diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll b/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll new file mode 100644 index 0000000000000..370f41f6b95c2 --- /dev/null +++ b/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll @@ -0,0 +1,293 @@ +; 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, i1} @llvm.usub.with.overflow.i16(i16, i16) + +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: [[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) + %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_longer_chain(i16 %x) { +; CHECK-LABEL: @sel_true_cond_longer_chain( +; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) +; CHECK-NEXT: [[EXTRA:%.*]] = mul i16 [[SUB]], 3 +; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42 +; CHECK-NEXT: ret i16 [[SEL]] +; + %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) + %extra = mul i16 %sub, 3 + %cmp = icmp uge i16 %x, 10 + %sel = select i1 %cmp, i16 %extra, i16 42 + 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: [[CMP:%.*]] = icmp ult 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 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: [[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 [[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, 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 +} + +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: [[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 [[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, 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 +} + +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_NEXT:%.*]], [[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: [[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 +}