define i16 @sel_true_cond(i16 %x) {
; CHECK-LABEL: @sel_true_cond(
-; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
+; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB1]], i16 42
; CHECK-NEXT: ret i16 [[SEL]]
;
%sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
define i16 @sel_true_cond_chain_speculatable(i16 %x) {
; CHECK-LABEL: @sel_true_cond_chain_speculatable(
-; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1)
-; CHECK-NEXT: [[EXTRA:%.*]] = mul i16 [[SUB]], 3
+; CHECK-NEXT: [[SUB1:%.*]] = add nuw i16 [[X:%.*]], 1
+; CHECK-NEXT: [[EXTRA:%.*]] = mul i16 [[SUB1]], 3
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -1
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42
; CHECK-NEXT: ret i16 [[SEL]]
define i16 @sel_false_cond(i16 %x) {
; CHECK-LABEL: @sel_false_cond(
-; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
+; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 10
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB1]]
; CHECK-NEXT: ret i16 [[SEL]]
;
%sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
define i16 @phi_true_cond(i16 %x) {
; CHECK-LABEL: @phi_true_cond(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
+; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10
; CHECK-NEXT: br i1 [[CMP]], label [[JOIN:%.*]], label [[SPLIT:%.*]]
; CHECK: split:
; CHECK-NEXT: br label [[JOIN]]
; CHECK: join:
-; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
+; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
; CHECK-NEXT: ret i16 [[PHI]]
;
entry:
define i16 @phi_false_cond(i16 %x) {
; CHECK-LABEL: @phi_false_cond(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
+; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 10
; CHECK-NEXT: br i1 [[CMP]], label [[SPLIT:%.*]], label [[JOIN:%.*]]
; CHECK: split:
; CHECK-NEXT: br label [[JOIN]]
; CHECK: join:
-; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
+; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
; CHECK-NEXT: ret i16 [[PHI]]
;
entry:
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 1000, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 1000, [[ENTRY:%.*]] ], [ [[IV_NEXT1:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[COUNT:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[COUNT_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[IV]], 0
-; CHECK-NEXT: [[IV_NEXT]] = call i16 @llvm.usub.sat.i16(i16 [[IV]], i16 1)
+; CHECK-NEXT: [[IV_NEXT1]] = sub nuw i16 [[IV]], 1
; CHECK-NEXT: [[COUNT_NEXT]] = add i16 [[COUNT]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
define i16 @urem_elide(i16 %x) {
; CHECK-LABEL: @urem_elide(
-; CHECK-NEXT: [[UREM:%.*]] = urem i16 [[X:%.*]], 42
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 42
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X:%.*]], 42
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
;
%urem = urem i16 %x, 42
define i16 @urem_expand(i16 %x) {
; CHECK-LABEL: @urem_expand(
-; CHECK-NEXT: [[UREM:%.*]] = urem i16 [[X:%.*]], 42
+; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i16 [[X:%.*]]
+; CHECK-NEXT: [[UREM_UREM:%.*]] = sub nuw i16 [[X_FROZEN]], 42
+; CHECK-NEXT: [[UREM_CMP:%.*]] = icmp ult i16 [[X_FROZEN]], 42
+; CHECK-NEXT: [[UREM:%.*]] = select i1 [[UREM_CMP]], i16 [[X_FROZEN]], i16 [[UREM_UREM]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 84
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
define i16 @urem_narrow(i16 %x) {
; CHECK-LABEL: @urem_narrow(
-; CHECK-NEXT: [[UREM:%.*]] = urem i16 [[X:%.*]], 42
+; CHECK-NEXT: [[UREM_LHS_TRUNC:%.*]] = trunc i16 [[X:%.*]] to i8
+; CHECK-NEXT: [[UREM1:%.*]] = urem i8 [[UREM_LHS_TRUNC]], 42
+; CHECK-NEXT: [[UREM_ZEXT:%.*]] = zext i8 [[UREM1]] to i16
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 85
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM_ZEXT]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
;
%urem = urem i16 %x, 42
define i16 @srem_elide(i16 %x) {
; CHECK-LABEL: @srem_elide(
-; CHECK-NEXT: [[SREM:%.*]] = srem i16 [[X:%.*]], 42
-; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i16 [[X]], 42
+; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i16 [[X:%.*]], 42
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i16 [[X]], -42
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i16 [[SREM]], i16 24
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i16 [[X]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
;
%srem = srem i16 %x, 42
define i16 @srem_narrow(i16 %x) {
; CHECK-LABEL: @srem_narrow(
-; CHECK-NEXT: [[SREM:%.*]] = srem i16 [[X:%.*]], 42
+; CHECK-NEXT: [[SREM_LHS_TRUNC:%.*]] = trunc i16 [[X:%.*]] to i8
+; CHECK-NEXT: [[SREM1:%.*]] = srem i8 [[SREM_LHS_TRUNC]], 42
+; CHECK-NEXT: [[SREM_SEXT:%.*]] = sext i8 [[SREM1]] to i16
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i16 [[X]], 43
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i16 [[X]], -43
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i16 [[SREM]], i16 24
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i16 [[SREM_SEXT]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
;
%srem = srem i16 %x, 42
define i16 @srem_convert(i16 %x) {
; CHECK-LABEL: @srem_convert(
-; CHECK-NEXT: [[SREM:%.*]] = srem i16 [[X:%.*]], 42
+; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i16 0, [[X:%.*]]
+; CHECK-NEXT: [[SREM1:%.*]] = urem i16 [[X_NONNEG]], 42
+; CHECK-NEXT: [[SREM1_NEG:%.*]] = sub i16 0, [[SREM1]]
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[X]], 0
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM]], i16 24
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM1_NEG]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
;
%srem = srem i16 %x, 42
define i16 @sdiv_convert(i16 %x) {
; CHECK-LABEL: @sdiv_convert(
-; CHECK-NEXT: [[SREM:%.*]] = sdiv i16 [[X:%.*]], 42
+; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i16 0, [[X:%.*]]
+; CHECK-NEXT: [[SREM1:%.*]] = udiv i16 [[X_NONNEG]], 42
+; CHECK-NEXT: [[SREM1_NEG:%.*]] = sub i16 0, [[SREM1]]
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[X]], 0
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM]], i16 24
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM1_NEG]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
;
%srem = sdiv i16 %x, 42
define i16 @ashr_convert(i16 %x, i16 %y) {
; CHECK-LABEL: @ashr_convert(
-; CHECK-NEXT: [[ASHR:%.*]] = ashr i16 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[ASHR:%.*]] = lshr i16 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i16 [[X]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ASHR]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
define i32 @sext_convert(i16 %x) {
; CHECK-LABEL: @sext_convert(
-; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[X:%.*]] to i32
+; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[X:%.*]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i16 [[X]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[EXT]], i32 24
; CHECK-NEXT: ret i32 [[SEL]]
define i16 @and_elide(i16 %x) {
; CHECK-LABEL: @and_elide(
-; CHECK-NEXT: [[AND:%.*]] = and i16 [[X:%.*]], 7
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 8
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[AND]], i16 24
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X:%.*]], 8
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24
; CHECK-NEXT: ret i16 [[SEL]]
;
%and = and i16 %x, 7