| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s |
| |
| declare void @use.i16(i16) |
| declare i16 @llvm.usub.sat.i16(i16, i16) |
| declare i16 @llvm.uadd.sat.i16(i16, i16) |
| declare i16 @llvm.umin.i16(i16, i16) |
| declare i16 @llvm.abs.i16(i16, i1) |
| |
| define i16 @sel_true_cond(i16 noundef %x) { |
| ; CHECK-LABEL: @sel_true_cond( |
| ; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 |
| ; 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) |
| %cmp = icmp uge i16 %x, 10 |
| %sel = select i1 %cmp, i16 %sub, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @sel_true_cond_insufficient(i16 %x) { |
| ; CHECK-LABEL: @sel_true_cond_insufficient( |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 9 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp uge i16 %x, 9 |
| %sel = select i1 %cmp, i16 %sub, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @sel_true_cond_wrong_swap(i16 %x) { |
| ; CHECK-LABEL: @sel_true_cond_wrong_swap( |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB]] |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp uge i16 %x, 10 |
| %sel = select i1 %cmp, i16 42, i16 %sub |
| ret i16 %sel |
| } |
| |
| define i16 @sel_true_cond_wrong_op(i16 %x, i16 %y) { |
| ; CHECK-LABEL: @sel_true_cond_wrong_op( |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[Y:%.*]], 10 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp uge i16 %y, 10 |
| %sel = select i1 %cmp, i16 %sub, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @sel_true_cond_extra_use(i16 %x) { |
| ; CHECK-LABEL: @sel_true_cond_extra_use( |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: call void @use.i16(i16 [[SUB]]) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| call void @use.i16(i16 %sub) |
| %cmp = icmp uge i16 %x, 10 |
| %sel = select i1 %cmp, i16 %sub, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @sel_true_cond_chain_speculatable(i16 noundef %x) { |
| ; CHECK-LABEL: @sel_true_cond_chain_speculatable( |
| ; 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]] |
| ; |
| %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1) |
| %extra = mul i16 %sub, 3 |
| %cmp = icmp ne i16 %x, -1 |
| %sel = select i1 %cmp, i16 %extra, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @sel_true_cond_chain_non_speculatable(i16 %x) { |
| ; CHECK-LABEL: @sel_true_cond_chain_non_speculatable( |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1) |
| ; CHECK-NEXT: [[EXTRA:%.*]] = udiv i16 3, [[SUB]] |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -1 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1) |
| %extra = udiv i16 3, %sub |
| %cmp = icmp ne i16 %x, -1 |
| %sel = select i1 %cmp, i16 %extra, i16 42 |
| ret i16 %sel |
| } |
| |
| ; TODO: We could handle this case by raising the limit on the number of |
| ; instructions we look through. |
| define i16 @sel_true_cond_longer_chain(i16 %x) { |
| ; CHECK-LABEL: @sel_true_cond_longer_chain( |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1) |
| ; CHECK-NEXT: [[EXTRA:%.*]] = mul i16 [[SUB]], 3 |
| ; CHECK-NEXT: [[EXTRA2:%.*]] = xor i16 [[SUB]], 7 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -1 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA2]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1) |
| %extra = mul i16 %sub, 3 |
| %extra2 = xor i16 %sub, 7 |
| %cmp = icmp ne i16 %x, -1 |
| %sel = select i1 %cmp, i16 %extra2, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @sel_false_cond(i16 noundef %x) { |
| ; CHECK-LABEL: @sel_false_cond( |
| ; 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 [[SUB1]] |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp ult i16 %x, 10 |
| %sel = select i1 %cmp, i16 42, i16 %sub |
| ret i16 %sel |
| } |
| |
| define i16 @sel_false_cond_insufficient(i16 %x) { |
| ; CHECK-LABEL: @sel_false_cond_insufficient( |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 9 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB]] |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp ult i16 %x, 9 |
| %sel = select i1 %cmp, i16 42, i16 %sub |
| ret i16 %sel |
| } |
| |
| define i16 @phi_true_cond(i16 %x) { |
| ; CHECK-LABEL: @phi_true_cond( |
| ; CHECK-NEXT: entry: |
| ; 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 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ] |
| ; CHECK-NEXT: ret i16 [[PHI]] |
| ; |
| entry: |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp uge i16 %x, 10 |
| br i1 %cmp, label %join, label %split |
| |
| split: |
| br label %join |
| |
| join: |
| %phi = phi i16 [ %sub, %entry ], [ 42, %split ] |
| ret i16 %phi |
| } |
| |
| define i16 @phi_true_cond_insufficient(i16 %x) { |
| ; CHECK-LABEL: @phi_true_cond_insufficient( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 9 |
| ; 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: ret i16 [[PHI]] |
| ; |
| entry: |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp uge i16 %x, 9 |
| br i1 %cmp, label %join, label %split |
| |
| split: |
| br label %join |
| |
| join: |
| %phi = phi i16 [ %sub, %entry ], [ 42, %split ] |
| ret i16 %phi |
| } |
| |
| ; TODO: We could handle this by using conditions that are not directly on the |
| ; phi edge. |
| define i16 @phi_true_cond_non_local(i16 %x) { |
| ; CHECK-LABEL: @phi_true_cond_non_local( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp uge 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]], [[SPLIT]] ], [ 42, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: ret i16 [[PHI]] |
| ; |
| entry: |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp uge i16 %x, 10 |
| br i1 %cmp, label %split, label %join |
| |
| split: |
| br label %join |
| |
| join: |
| %phi = phi i16 [ %sub, %split ], [ 42, %entry ] |
| ret i16 %phi |
| } |
| |
| define i16 @phi_false_cond(i16 %x) { |
| ; CHECK-LABEL: @phi_false_cond( |
| ; CHECK-NEXT: entry: |
| ; 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 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ] |
| ; CHECK-NEXT: ret i16 [[PHI]] |
| ; |
| entry: |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp ult i16 %x, 10 |
| br i1 %cmp, label %split, label %join |
| |
| split: |
| br label %join |
| |
| join: |
| %phi = phi i16 [ %sub, %entry ], [ 42, %split ] |
| ret i16 %phi |
| } |
| |
| define i16 @phi_false_cond_insufficient(i16 %x) { |
| ; CHECK-LABEL: @phi_false_cond_insufficient( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 9 |
| ; 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: ret i16 [[PHI]] |
| ; |
| entry: |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp ult i16 %x, 9 |
| br i1 %cmp, label %split, label %join |
| |
| split: |
| br label %join |
| |
| join: |
| %phi = phi i16 [ %sub, %entry ], [ 42, %split ] |
| ret i16 %phi |
| } |
| |
| ; TODO: We could handle this by using conditions that are not directly on the |
| ; phi edge. |
| define i16 @phi_false_cond_non_local(i16 %x) { |
| ; CHECK-LABEL: @phi_false_cond_non_local( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult 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]], [[SPLIT]] ], [ 42, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: ret i16 [[PHI]] |
| ; |
| entry: |
| %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) |
| %cmp = icmp ult i16 %x, 10 |
| br i1 %cmp, label %join, label %split |
| |
| split: |
| br label %join |
| |
| join: |
| %phi = phi i16 [ %sub, %split ], [ 42, %entry ] |
| ret i16 %phi |
| } |
| |
| define i16 @loop_cond() { |
| ; CHECK-LABEL: @loop_cond( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: 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_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: |
| ; CHECK-NEXT: ret i16 [[COUNT]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i16 [ 1000, %entry ], [ %iv.next, %loop ] |
| %count = phi i16 [ 0, %entry ], [ %count.next, %loop ] |
| %cmp = icmp eq i16 %iv, 0 |
| %iv.next = call i16 @llvm.usub.sat.i16(i16 %iv, i16 1) |
| %count.next = add i16 %count, 1 |
| br i1 %cmp, label %exit, label %loop |
| |
| exit: |
| ret i16 %count |
| } |
| |
| define i16 @urem_elide(i16 noundef %x) { |
| ; CHECK-LABEL: @urem_elide( |
| ; 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 |
| %cmp = icmp ult i16 %x, 42 |
| %sel = select i1 %cmp, i16 %urem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @urem_expand(i16 noundef %x) { |
| ; CHECK-LABEL: @urem_expand( |
| ; CHECK-NEXT: [[UREM_UREM:%.*]] = sub nuw i16 [[X:%.*]], 42 |
| ; CHECK-NEXT: [[UREM_CMP:%.*]] = icmp ult i16 [[X]], 42 |
| ; CHECK-NEXT: [[UREM:%.*]] = select i1 [[UREM_CMP]], i16 [[X]], 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]] |
| ; |
| %urem = urem i16 %x, 42 |
| %cmp = icmp ult i16 %x, 84 |
| %sel = select i1 %cmp, i16 %urem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @urem_narrow(i16 noundef %x) { |
| ; CHECK-LABEL: @urem_narrow( |
| ; 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_ZEXT]], i16 24 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %urem = urem i16 %x, 42 |
| %cmp = icmp ult i16 %x, 85 |
| %sel = select i1 %cmp, i16 %urem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @urem_insufficient(i16 %x) { |
| ; CHECK-LABEL: @urem_insufficient( |
| ; CHECK-NEXT: [[UREM:%.*]] = urem i16 [[X:%.*]], 42 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 257 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %urem = urem i16 %x, 42 |
| %cmp = icmp ult i16 %x, 257 |
| %sel = select i1 %cmp, i16 %urem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @srem_elide(i16 noundef %x) { |
| ; CHECK-LABEL: @srem_elide( |
| ; 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 [[X]], i16 24 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %srem = srem i16 %x, 42 |
| %cmp1 = icmp slt i16 %x, 42 |
| %cmp2 = icmp sgt i16 %x, -42 |
| %and = and i1 %cmp1, %cmp2 |
| %sel = select i1 %and, i16 %srem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @srem_narrow(i16 noundef %x) { |
| ; CHECK-LABEL: @srem_narrow( |
| ; 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_SEXT]], i16 24 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %srem = srem i16 %x, 42 |
| %cmp1 = icmp slt i16 %x, 43 |
| %cmp2 = icmp sgt i16 %x, -43 |
| %and = and i1 %cmp1, %cmp2 |
| %sel = select i1 %and, i16 %srem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @srem_convert(i16 noundef %x) { |
| ; CHECK-LABEL: @srem_convert( |
| ; 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 [[SREM1_NEG]], i16 24 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %srem = srem i16 %x, 42 |
| %cmp = icmp slt i16 %x, 0 |
| %sel = select i1 %cmp, i16 %srem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @sdiv_convert(i16 noundef %x) { |
| ; CHECK-LABEL: @sdiv_convert( |
| ; 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 [[SREM1_NEG]], i16 24 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %srem = sdiv i16 %x, 42 |
| %cmp = icmp slt i16 %x, 0 |
| %sel = select i1 %cmp, i16 %srem, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @abs_elide(i16 %x) { |
| ; CHECK-LABEL: @abs_elide( |
| ; CHECK-NEXT: [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i16 [[X]], -32768 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %abs = call i16 @llvm.abs.i16(i16 %x, i1 false) |
| %cmp = icmp ule i16 %x, 32768 |
| %sel = select i1 %cmp, i16 %abs, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @abs_elide2(i16 %x) { |
| ; CHECK-LABEL: @abs_elide2( |
| ; CHECK-NEXT: [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i16 [[X]], 0 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %abs = call i16 @llvm.abs.i16(i16 %x, i1 false) |
| %cmp = icmp sle i16 %x, 0 |
| %sel = select i1 %cmp, i16 %abs, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @abs_not_int_min(i16 %x) { |
| ; CHECK-LABEL: @abs_not_int_min( |
| ; CHECK-NEXT: [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -32768 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %abs = call i16 @llvm.abs.i16(i16 %x, i1 false) |
| %cmp = icmp ne i16 %x, 32768 |
| %sel = select i1 %cmp, i16 %abs, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @umin_elide(i16 %x) { |
| ; CHECK-LABEL: @umin_elide( |
| ; CHECK-NEXT: [[MIN:%.*]] = call i16 @llvm.umin.i16(i16 [[X:%.*]], i16 10) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i16 [[X]], 10 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[MIN]], i16 42 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %min = call i16 @llvm.umin.i16(i16 %x, i16 10) |
| %cmp = icmp ule i16 %x, 10 |
| %sel = select i1 %cmp, i16 %min, i16 42 |
| ret i16 %sel |
| } |
| |
| define i16 @ashr_convert(i16 noundef %x, i16 %y) { |
| ; CHECK-LABEL: @ashr_convert( |
| ; 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]] |
| ; |
| %ashr = ashr i16 %x, %y |
| %cmp = icmp sge i16 %x, 0 |
| %sel = select i1 %cmp, i16 %ashr, i16 24 |
| ret i16 %sel |
| } |
| |
| define i32 @sext_convert(i16 noundef %x) { |
| ; CHECK-LABEL: @sext_convert( |
| ; 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]] |
| ; |
| %ext = sext i16 %x to i32 |
| %cmp = icmp sge i16 %x, 0 |
| %sel = select i1 %cmp, i32 %ext, i32 24 |
| ret i32 %sel |
| } |
| |
| define i16 @infer_flags(i16 %x) { |
| ; CHECK-LABEL: @infer_flags( |
| ; CHECK-NEXT: [[ADD:%.*]] = add i16 [[X:%.*]], 42 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 100 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ADD]], i16 24 |
| ; CHECK-NEXT: ret i16 [[SEL]] |
| ; |
| %add = add i16 %x, 42 |
| %cmp = icmp ult i16 %x, 100 |
| %sel = select i1 %cmp, i16 %add, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @and_elide(i16 noundef %x) { |
| ; CHECK-LABEL: @and_elide( |
| ; 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 |
| %cmp = icmp ult i16 %x, 8 |
| %sel = select i1 %cmp, i16 %and, i16 24 |
| ret i16 %sel |
| } |
| |
| define i16 @cond_value_may_not_well_defined(i16 %x) { |
| ; CHECK-LABEL: @cond_value_may_not_well_defined( |
| ; 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: ret i16 [[SEL]] |
| ; |
| %and = and i16 %x, 7 |
| %cmp = icmp ult i16 %x, 8 |
| %sel = select i1 %cmp, i16 %and, i16 24 |
| ret i16 %sel |
| } |