diff options
5 files changed, 1009 insertions, 289 deletions
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll index 14b9a1999cc..520d7c2b66c 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -1,74 +1,104 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -correlated-propagation -S | FileCheck %s ; PR2581 +define i32 @test1(i1 %C) { ; CHECK-LABEL: @test1( -define i32 @test1(i1 %C) nounwind { - br i1 %C, label %exit, label %body +; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[BODY:%.*]] +; CHECK: body: +; CHECK-NEXT: ret i32 11 +; CHECK: exit: +; CHECK-NEXT: ret i32 10 +; + br i1 %C, label %exit, label %body body: ; preds = %0 -; CHECK-NOT: select - %A = select i1 %C, i32 10, i32 11 ; <i32> [#uses=1] -; CHECK: ret i32 11 - ret i32 %A + %A = select i1 %C, i32 10, i32 11 + ret i32 %A exit: ; preds = %0 -; CHECK: ret i32 10 - ret i32 10 + ret i32 10 } ; PR4420 declare i1 @ext() -; CHECK-LABEL: @test2( define i1 @test2() { +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND:%.*]] = tail call i1 @ext() +; CHECK-NEXT: br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[COND2:%.*]] = tail call i1 @ext() +; CHECK-NEXT: br i1 [[COND2]], label [[BB3:%.*]], label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: ret i1 false +; CHECK: bb3: +; CHECK-NEXT: [[RES:%.*]] = tail call i1 @ext() +; CHECK-NEXT: ret i1 [[RES]] +; entry: - %cond = tail call i1 @ext() ; <i1> [#uses=2] - br i1 %cond, label %bb1, label %bb2 - -bb1: ; preds = %entry - %cond2 = tail call i1 @ext() ; <i1> [#uses=1] - br i1 %cond2, label %bb3, label %bb2 - -bb2: ; preds = %bb1, %entry -; CHECK-NOT: phi i1 - %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ] ; <i1> [#uses=1] -; CHECK: ret i1 false - ret i1 %cond_merge - -bb3: ; preds = %bb1 - %res = tail call i1 @ext() ; <i1> [#uses=1] -; CHECK: ret i1 %res - ret i1 %res + %cond = tail call i1 @ext() + br i1 %cond, label %bb1, label %bb2 + +bb1: + %cond2 = tail call i1 @ext() + br i1 %cond2, label %bb3, label %bb2 + +bb2: + %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ] + ret i1 %cond_merge + +bb3: + %res = tail call i1 @ext() + ret i1 %res } ; PR4855 @gv = internal constant i8 7 -; CHECK-LABEL: @test3( define i8 @test3(i8* %a) nounwind { +; CHECK-LABEL: @test3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND:%.*]] = icmp eq i8* [[A:%.*]], @gv +; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret i8 0 +; CHECK: bb2: +; CHECK-NEXT: [[SHOULD_BE_CONST:%.*]] = load i8, i8* @gv +; CHECK-NEXT: ret i8 [[SHOULD_BE_CONST]] +; entry: - %cond = icmp eq i8* %a, @gv - br i1 %cond, label %bb2, label %bb + %cond = icmp eq i8* %a, @gv + br i1 %cond, label %bb2, label %bb -bb: ; preds = %entry - ret i8 0 +bb: + ret i8 0 -bb2: ; preds = %entry -; CHECK: %should_be_const = load i8, i8* @gv - %should_be_const = load i8, i8* %a - ret i8 %should_be_const +bb2: + %should_be_const = load i8, i8* %a + ret i8 %should_be_const } ; PR1757 -; CHECK-LABEL: @test4( define i32 @test4(i32) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: EntryBlock: +; CHECK-NEXT: [[DOTDEMORGAN:%.*]] = icmp sgt i32 [[TMP0:%.*]], 2 +; CHECK-NEXT: br i1 [[DOTDEMORGAN]], label [[GREATERTHANTWO:%.*]], label [[LESSTHANOREQUALTOTWO:%.*]] +; CHECK: GreaterThanTwo: +; CHECK-NEXT: br i1 false, label [[IMPOSSIBLE:%.*]], label [[NOTTWOANDGREATERTHANTWO:%.*]] +; CHECK: NotTwoAndGreaterThanTwo: +; CHECK-NEXT: ret i32 2 +; CHECK: Impossible: +; CHECK-NEXT: ret i32 1 +; CHECK: LessThanOrEqualToTwo: +; CHECK-NEXT: ret i32 0 +; EntryBlock: -; CHECK: icmp sgt i32 %0, 2 - %.demorgan = icmp sgt i32 %0, 2 + %.demorgan = icmp sgt i32 %0, 2 br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo GreaterThanTwo: -; CHECK-NOT: icmp eq i32 %0, 2 icmp eq i32 %0, 2 -; CHECK: br i1 false br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo NotTwoAndGreaterThanTwo: @@ -84,13 +114,25 @@ LessThanOrEqualToTwo: declare i32* @f(i32*) define void @test5(i32* %x, i32* %y) { ; CHECK-LABEL: @test5( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PRE:%.*]] = icmp eq i32* [[X:%.*]], null +; CHECK-NEXT: br i1 [[PRE]], label [[RETURN:%.*]], label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[F]] = tail call i32* @f(i32* [[PHI]]) +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32* [[F]], [[Y:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32* [[F]], i32* null +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32* [[SEL]], null +; CHECK-NEXT: br i1 [[CMP2]], label [[RETURN]], label [[LOOP]] +; CHECK: return: +; CHECK-NEXT: ret void +; entry: %pre = icmp eq i32* %x, null br i1 %pre, label %return, label %loop loop: %phi = phi i32* [ %sel, %loop ], [ %x, %entry ] -; CHECK: %phi = phi i32* [ %f, %loop ], [ %x, %entry ] %f = tail call i32* @f(i32* %phi) %cmp1 = icmp ne i32* %f, %y %sel = select i1 %cmp1, i32* %f, i32* null @@ -103,25 +145,32 @@ return: define i32 @switch1(i32 %s) { ; CHECK-LABEL: @switch1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[S:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[NEGATIVE:%.*]], label [[OUT:%.*]] +; CHECK: negative: +; CHECK-NEXT: switch i32 [[S]], label [[OUT]] [ +; CHECK-NEXT: i32 -2, label [[NEXT:%.*]] +; CHECK-NEXT: i32 -1, label [[NEXT]] +; CHECK-NEXT: ] +; CHECK: out: +; CHECK-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ -1, [[NEGATIVE]] ] +; CHECK-NEXT: ret i32 [[P]] +; CHECK: next: +; CHECK-NEXT: ret i32 0 +; entry: %cmp = icmp slt i32 %s, 0 br i1 %cmp, label %negative, label %out negative: switch i32 %s, label %out [ -; CHECK: switch i32 %s, label %out - i32 0, label %out -; CHECK-NOT: i32 0 - i32 1, label %out -; CHECK-NOT: i32 1 - i32 -1, label %next -; CHECK-DAG: i32 -1, label %next - i32 -2, label %next -; CHECK-DAG: i32 -2, label %next - i32 2, label %out -; CHECK-NOT: i32 2 - i32 3, label %out -; CHECK-NOT: i32 3 + i32 0, label %out + i32 1, label %out + i32 -1, label %next + i32 -2, label %next + i32 2, label %out + i32 3, label %out ] out: @@ -135,17 +184,27 @@ next: define i32 @switch2(i32 %s) { ; CHECK-LABEL: @switch2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]] +; CHECK: positive: +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ] +; CHECK-NEXT: ret i32 [[P]] +; CHECK: next: +; CHECK-NEXT: ret i32 0 +; entry: %cmp = icmp sgt i32 %s, 0 br i1 %cmp, label %positive, label %out positive: switch i32 %s, label %out [ - i32 0, label %out - i32 -1, label %next - i32 -2, label %next + i32 0, label %out + i32 -1, label %next + i32 -2, label %next ] -; CHECK: br label %out out: %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ] @@ -158,17 +217,27 @@ next: define i32 @switch3(i32 %s) { ; CHECK-LABEL: @switch3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]] +; CHECK: positive: +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ] +; CHECK-NEXT: ret i32 [[P]] +; CHECK: next: +; CHECK-NEXT: ret i32 0 +; entry: %cmp = icmp sgt i32 %s, 0 br i1 %cmp, label %positive, label %out positive: switch i32 %s, label %out [ - i32 -1, label %out - i32 -2, label %next - i32 -3, label %next + i32 -1, label %out + i32 -2, label %next + i32 -3, label %next ] -; CHECK: br label %out out: %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ] @@ -181,17 +250,26 @@ next: define void @switch4(i32 %s) { ; CHECK-LABEL: @switch4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[S:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[ZERO:%.*]], label [[OUT:%.*]] +; CHECK: zero: +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: out: +; CHECK-NEXT: ret void +; CHECK: next: +; CHECK-NEXT: ret void +; entry: %cmp = icmp eq i32 %s, 0 br i1 %cmp, label %zero, label %out zero: switch i32 %s, label %out [ - i32 0, label %next - i32 1, label %out - i32 -1, label %out + i32 0, label %next + i32 1, label %out + i32 -1, label %out ] -; CHECK: br label %next out: ret void @@ -202,7 +280,10 @@ next: define i1 @arg_attribute(i8* nonnull %a) { ; CHECK-LABEL: @arg_attribute( -; CHECK: ret i1 false +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 false +; %cmp = icmp eq i8* %a, null br label %exit @@ -213,7 +294,12 @@ exit: declare nonnull i8* @return_nonnull() define i1 @call_attribute() { ; CHECK-LABEL: @call_attribute( -; CHECK: ret i1 false +; CHECK-NEXT: [[A:%.*]] = call i8* @return_nonnull() +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[A]], null +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 false +; %a = call i8* @return_nonnull() %cmp = icmp eq i8* %a, null br label %exit @@ -224,6 +310,22 @@ exit: define i1 @umin(i32 %a, i32 %b) { ; CHECK-LABEL: @umin( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20 +; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] +; CHECK: b_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ult i32 [[A]], [[B]] +; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MIN]], 7 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp ult i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -238,8 +340,6 @@ b_guard: %res = icmp eq i32 %min, 7 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -247,6 +347,22 @@ out: define i1 @smin(i32 %a, i32 %b) { ; CHECK-LABEL: @smin( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20 +; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] +; CHECK: b_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sle i32 [[A]], [[B]] +; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MIN]], 7 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp ult i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -261,8 +377,6 @@ b_guard: %res = icmp eq i32 %min, 7 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -270,6 +384,22 @@ out: define i1 @smax(i32 %a, i32 %b) { ; CHECK-LABEL: @smax( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20 +; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] +; CHECK: b_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sge i32 [[A]], [[B]] +; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MAX]], 7 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp sgt i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -284,8 +414,6 @@ b_guard: %res = icmp eq i32 %max, 7 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -293,6 +421,22 @@ out: define i1 @umax(i32 %a, i32 %b) { ; CHECK-LABEL: @umax( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20 +; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] +; CHECK: b_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]] +; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MAX]], 7 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp sgt i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -307,8 +451,6 @@ b_guard: %res = icmp eq i32 %max, 7 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -316,6 +458,20 @@ out: define i1 @clamp_low1(i32 %a) { ; CHECK-LABEL: @clamp_low1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], -1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]] +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp sge i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -327,8 +483,6 @@ a_guard: %res = icmp eq i32 %sel, 4 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -336,6 +490,20 @@ out: define i1 @clamp_low2(i32 %a) { ; CHECK-LABEL: @clamp_low2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], -1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp sge i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -347,8 +515,6 @@ a_guard: %res = icmp eq i32 %sel, 4 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -356,6 +522,20 @@ out: define i1 @clamp_high1(i32 %a) { ; CHECK-LABEL: @clamp_high1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]] +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp sle i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -367,8 +547,6 @@ a_guard: %res = icmp eq i32 %sel, 6 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -376,6 +554,20 @@ out: define i1 @clamp_high2(i32 %a) { ; CHECK-LABEL: @clamp_high2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp sle i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -387,8 +579,6 @@ a_guard: %res = icmp eq i32 %sel, 6 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false @@ -397,6 +587,20 @@ out: ; Just showing arbitrary constants work, not really a clamp define i1 @clamp_high3(i32 %a) { ; CHECK-LABEL: @clamp_high3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 100 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 105 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; entry: %cmp = icmp sle i32 %a, 5 br i1 %cmp, label %a_guard, label %out @@ -408,16 +612,20 @@ a_guard: %res = icmp eq i32 %sel, 105 br label %next next: -; CHECK: next: -; CHECK: ret i1 false ret i1 %res out: ret i1 false } define i1 @zext_unknown(i8 %a) { -; CHECK-LABEL: @zext_unknown -; CHECK: ret i1 true +; CHECK-LABEL: @zext_unknown( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A32:%.*]] = zext i8 [[A:%.*]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 256 +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 true +; entry: %a32 = zext i8 %a to i32 %cmp = icmp sle i32 %a32, 256 @@ -427,8 +635,15 @@ exit: } define i1 @trunc_unknown(i32 %a) { -; CHECK-LABEL: @trunc_unknown -; CHECK: ret i1 true +; CHECK-LABEL: @trunc_unknown( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A8:%.*]] = trunc i32 [[A:%.*]] to i8 +; CHECK-NEXT: [[A32:%.*]] = sext i8 [[A8]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 128 +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 true +; entry: %a8 = trunc i32 %a to i8 %a32 = sext i8 %a8 to i32 @@ -439,11 +654,16 @@ exit: } ; TODO: missed optimization -; Make sure we exercise non-integer inputs to unary operators (i.e. crash -; check). +; Make sure we exercise non-integer inputs to unary operators (i.e. crash check). define i1 @bitcast_unknown(float %a) { -; CHECK-LABEL: @bitcast_unknown -; CHECK: ret i1 %cmp +; CHECK-LABEL: @bitcast_unknown( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A32:%.*]] = bitcast float [[A:%.*]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 128 +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 [[CMP]] +; entry: %a32 = bitcast float %a to i32 %cmp = icmp sle i32 %a32, 128 @@ -453,8 +673,14 @@ exit: } define i1 @bitcast_unknown2(i8* %p) { -; CHECK-LABEL: @bitcast_unknown2 -; CHECK: ret i1 %cmp +; CHECK-LABEL: @bitcast_unknown2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P64:%.*]] = ptrtoint i8* [[P:%.*]] to i64 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[P64]], 128 +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 [[CMP]] +; entry: %p64 = ptrtoint i8* %p to i64 %cmp = icmp sle i64 %p64, 128 @@ -465,8 +691,14 @@ exit: define i1 @and_unknown(i32 %a) { -; CHECK-LABEL: @and_unknown -; CHECK: ret i1 true +; CHECK-LABEL: @and_unknown( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 128 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[AND]], 128 +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 true +; entry: %and = and i32 %a, 128 %cmp = icmp sle i32 %and, 128 @@ -476,8 +708,14 @@ exit: } define i1 @lshr_unknown(i32 %a) { -; CHECK-LABEL: @lshr_unknown -; CHECK: ret i1 true +; CHECK-LABEL: @lshr_unknown( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[A:%.*]], 30 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[AND]], 128 +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 true +; entry: %and = lshr i32 %a, 30 %cmp = icmp sle i32 %and, 128 diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/conflict.ll b/llvm/test/Transforms/CorrelatedValuePropagation/conflict.ll index ef566856ed7..d9d655328e0 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/conflict.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/conflict.ll @@ -1,19 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -correlated-propagation -S < %s | FileCheck %s -; Checks that we don't crash on conflicting facts about a value + +; Checks that we don't crash on conflicting facts about a value ; (i.e. unreachable code) ; Test that we can handle conflict edge facts + define i8 @test(i8 %a) { -; CHECK-LABEL: @test +; CHECK-LABEL: @test( +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP1]], label [[NEXT:%.*]], label [[EXIT:%.*]] +; CHECK: next: +; CHECK-NEXT: br i1 false, label [[DEAD:%.*]], label [[EXIT]] +; CHECK: dead: +; CHECK-NEXT: ret i8 5 +; CHECK: exit: +; CHECK-NEXT: ret i8 0 +; %cmp1 = icmp eq i8 %a, 5 br i1 %cmp1, label %next, label %exit next: %cmp2 = icmp eq i8 %a, 3 -; CHECK: br i1 false, label %dead, label %exit br i1 %cmp2, label %dead, label %exit dead: -; CHECK-LABEL: dead: -; CHECK: ret i8 5 ; NOTE: undef, or 3 would be equal valid ret i8 %a exit: @@ -23,12 +32,20 @@ exit: declare void @llvm.assume(i1) ; Test that we can handle conflicting assume vs edge facts + define i8 @test2(i8 %a) { -; CHECK-LABEL: @test2 +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A:%.*]], 5 +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) +; CHECK-NEXT: br i1 false, label [[DEAD:%.*]], label [[EXIT:%.*]] +; CHECK: dead: +; CHECK-NEXT: ret i8 5 +; CHECK: exit: +; CHECK-NEXT: ret i8 0 +; %cmp1 = icmp eq i8 %a, 5 call void @llvm.assume(i1 %cmp1) %cmp2 = icmp eq i8 %a, 3 -; CHECK: br i1 false, label %dead, label %exit br i1 %cmp2, label %dead, label %exit dead: ret i8 %a @@ -37,14 +54,22 @@ exit: } define i8 @test3(i8 %a) { -; CHECK-LABEL: @test3 +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP1]], label [[DEAD:%.*]], label [[EXIT:%.*]] +; CHECK: dead: +; CHECK-NEXT: call void @llvm.assume(i1 false) +; CHECK-NEXT: ret i8 5 +; CHECK: exit: +; CHECK-NEXT: ret i8 0 +; %cmp1 = icmp eq i8 %a, 5 br i1 %cmp1, label %dead, label %exit dead: %cmp2 = icmp eq i8 %a, 3 -; CHECK: call void @llvm.assume(i1 false) call void @llvm.assume(i1 %cmp2) ret i8 %a exit: ret i8 0 } + diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll index a8c7f20ad7c..de97e858b58 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll @@ -1,20 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -correlated-propagation -S %s | FileCheck %s ; RUN: opt -passes=correlated-propagation -S %s | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" -; Function Attrs: noreturn declare void @check1(i1) #1 - -; Function Attrs: noreturn declare void @check2(i1) #1 ; Make sure we propagate the value of %tmp35 to the true/false cases -; CHECK-LABEL: @test1 -; CHECK: call void @check1(i1 false) -; CHECK: call void @check2(i1 true) + define void @test1(i64 %tmp35) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP36:%.*]] = icmp sgt i64 [[TMP35:%.*]], 0 +; CHECK-NEXT: br i1 [[TMP36]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]] +; CHECK: bb_true: +; CHECK-NEXT: tail call void @check1(i1 false) #0 +; CHECK-NEXT: unreachable +; CHECK: bb_false: +; CHECK-NEXT: tail call void @check2(i1 true) #0 +; CHECK-NEXT: unreachable +; bb: %tmp36 = icmp sgt i64 %tmp35, 0 br i1 %tmp36, label %bb_true, label %bb_false @@ -30,13 +37,27 @@ bb_false: unreachable } -; Function Attrs: noreturn ; This is the same as test1 but with a diamond to ensure we ; get %tmp36 from both true and false BBs. -; CHECK-LABEL: @test2 -; CHECK: call void @check1(i1 false) -; CHECK: call void @check2(i1 true) + define void @test2(i64 %tmp35, i1 %inner_cmp) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP36:%.*]] = icmp sgt i64 [[TMP35:%.*]], 0 +; CHECK-NEXT: br i1 [[TMP36]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]] +; CHECK: bb_true: +; CHECK-NEXT: br i1 [[INNER_CMP:%.*]], label [[INNER_TRUE:%.*]], label [[INNER_FALSE:%.*]] +; CHECK: inner_true: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: inner_false: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: tail call void @check1(i1 false) +; CHECK-NEXT: unreachable +; CHECK: bb_false: +; CHECK-NEXT: tail call void @check2(i1 true) #0 +; CHECK-NEXT: unreachable +; bb: %tmp36 = icmp sgt i64 %tmp35, 0 br i1 %tmp36, label %bb_true, label %bb_false @@ -62,8 +83,23 @@ bb_false: } ; Make sure binary operator transfer functions are run when RHS is non-constant -; CHECK-LABEL: @test3 + define i1 @test3(i32 %x, i32 %y) #0 { +; CHECK-LABEL: @test3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10 +; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] +; CHECK: cont1: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10 +; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] +; CHECK: cont2: +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], [[Y]] +; CHECK-NEXT: br label [[CONT3:%.*]] +; CHECK: cont3: +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret i1 true +; entry: %cmp1 = icmp ult i32 %x, 10 br i1 %cmp1, label %cont1, label %out @@ -82,13 +118,29 @@ cont3: out: %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ] -; CHECK: ret i1 true ret i1 %ret } ; Same as previous but make sure nobody gets over-zealous -; CHECK-LABEL: @test4 + define i1 @test4(i32 %x, i32 %y) #0 { +; CHECK-LABEL: @test4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10 +; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] +; CHECK: cont1: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10 +; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] +; CHECK: cont2: +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], [[Y]] +; CHECK-NEXT: br label [[CONT3:%.*]] +; CHECK: cont3: +; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[ADD]], 15 +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: [[RET:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ true, [[CONT1]] ], [ [[CMP3]], [[CONT3]] ] +; CHECK-NEXT: ret i1 [[RET]] +; entry: %cmp1 = icmp ult i32 %x, 10 br i1 %cmp1, label %cont1, label %out @@ -107,13 +159,27 @@ cont3: out: %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ] -; CHECK-NOT: ret i1 true ret i1 %ret } ; Make sure binary operator transfer functions are run when RHS is non-constant -; CHECK-LABEL: @test5 + define i1 @test5(i32 %x, i32 %y) #0 { +; CHECK-LABEL: @test5( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] +; CHECK: cont1: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] +; CHECK: cont2: +; CHECK-NEXT: [[SHIFTED:%.*]] = shl i32 [[X]], [[Y]] +; CHECK-NEXT: br label [[CONT3:%.*]] +; CHECK: cont3: +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret i1 true +; entry: %cmp1 = icmp ult i32 %x, 5 br i1 %cmp1, label %cont1, label %out @@ -132,13 +198,29 @@ cont3: out: %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ] -; CHECK: ret i1 true ret i1 %ret } ; Same as previous but make sure nobody gets over-zealous -; CHECK-LABEL: @test6 + define i1 @test6(i32 %x, i32 %y) #0 { +; CHECK-LABEL: @test6( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] +; CHECK: cont1: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 15 +; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] +; CHECK: cont2: +; CHECK-NEXT: [[SHIFTED:%.*]] = shl i32 [[X]], [[Y]] +; CHECK-NEXT: br label [[CONT3:%.*]] +; CHECK: cont3: +; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[SHIFTED]], 65536 +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: [[RET:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ true, [[CONT1]] ], [ [[CMP3]], [[CONT3]] ] +; CHECK-NEXT: ret i1 [[RET]] +; entry: %cmp1 = icmp ult i32 %x, 5 br i1 %cmp1, label %cont1, label %out @@ -157,7 +239,6 @@ cont3: out: %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ] -; CHECK-NOT: ret i1 true ret i1 %ret } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/non-null.ll b/llvm/test/Transforms/CorrelatedValuePropagation/non-null.ll index a5cd90524fa..d86031d312f 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/non-null.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/non-null.ll @@ -1,193 +1,287 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -correlated-propagation -S | FileCheck %s define void @test1(i8* %ptr) { -; CHECK: test1 +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[A:%.*]] = load i8, i8* [[PTR:%.*]] +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret void +; %A = load i8, i8* %ptr br label %bb bb: icmp ne i8* %ptr, null -; CHECK-NOT: icmp ret void } define void @test1_no_null_opt(i8* %ptr) #0 { -; CHECK: test1_no_null_opt +; CHECK-LABEL: @test1_no_null_opt( +; CHECK-NEXT: [[A:%.*]] = load i8, i8* [[PTR:%.*]] +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[PTR]], null +; CHECK-NEXT: ret void +; %A = load i8, i8* %ptr br label %bb bb: icmp ne i8* %ptr, null -; CHECK: icmp ne i8* %ptr, null ret void } define void @test2(i8* %ptr) { -; CHECK: test2 +; CHECK-LABEL: @test2( +; CHECK-NEXT: store i8 0, i8* [[PTR:%.*]] +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret void +; store i8 0, i8* %ptr br label %bb bb: icmp ne i8* %ptr, null -; CHECK-NOT: icmp ret void } define void @test2_no_null_opt(i8* %ptr) #0 { -; CHECK: test2_no_null_opt +; CHECK-LABEL: @test2_no_null_opt( +; CHECK-NEXT: store i8 0, i8* [[PTR:%.*]] +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[PTR]], null +; CHECK-NEXT: ret void +; store i8 0, i8* %ptr br label %bb bb: icmp ne i8* %ptr, null -; CHECK: icmp ne i8* %ptr, null ret void } define void @test3() { -; CHECK: test3 +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[PTR:%.*]] = alloca i8 +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret void +; %ptr = alloca i8 br label %bb bb: icmp ne i8* %ptr, null -; CHECK-NOT: icmp ret void } ;; OK to remove icmp here since ptr is coming from alloca. + define void @test3_no_null_opt() #0 { -; CHECK: test3 +; CHECK-LABEL: @test3_no_null_opt( +; CHECK-NEXT: [[PTR:%.*]] = alloca i8 +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret void +; %ptr = alloca i8 br label %bb bb: icmp ne i8* %ptr, null -; CHECK-NOT: icmp ret void } declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1) + define void @test4(i8* %dest, i8* %src) { -; CHECK: test4 +; CHECK-LABEL: @test4( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret void +; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) br label %bb bb: icmp ne i8* %dest, null icmp ne i8* %src, null -; CHECK-NOT: icmp ret void } define void @test4_no_null_opt(i8* %dest, i8* %src) #0 { -; CHECK: test4_no_null_opt +; CHECK-LABEL: @test4_no_null_opt( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[DEST]], null +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8* [[SRC]], null +; CHECK-NEXT: ret void +; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) br label %bb bb: icmp ne i8* %dest, null icmp ne i8* %src, null -; CHECK: icmp ne i8* %dest, null -; CHECK: icmp ne i8* %src, null ret void } declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i1) define void @test5(i8* %dest, i8* %src) { -; CHECK: test5 +; CHECK-LABEL: @test5( +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret void +; call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) br label %bb bb: icmp ne i8* %dest, null icmp ne i8* %src, null -; CHECK-NOT: icmp ret void } define void @test5_no_null_opt(i8* %dest, i8* %src) #0 { -; CHECK: test5_no_null_opt +; CHECK-LABEL: @test5_no_null_opt( +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[DEST]], null +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8* [[SRC]], null +; CHECK-NEXT: ret void +; call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) br label %bb bb: icmp ne i8* %dest, null icmp ne i8* %src, null -; CHECK: icmp ne i8* %dest, null -; CHECK: icmp ne i8* %src, null ret void } declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i1) define void @test6(i8* %dest) { -; CHECK: test6 +; CHECK-LABEL: @test6( +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[DEST:%.*]], i8 -1, i32 1, i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: ret void +; call void @llvm.memset.p0i8.i32(i8* %dest, i8 255, i32 1, i1 false) br label %bb bb: icmp ne i8* %dest, null -; CHECK-NOT: icmp ret void } define void @test6_no_null_opt(i8* %dest) #0 { -; CHECK: test6_no_null_opt +; CHECK-LABEL: @test6_no_null_opt( +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[DEST:%.*]], i8 -1, i32 1, i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[DEST]], null +; CHECK-NEXT: ret void +; call void @llvm.memset.p0i8.i32(i8* %dest, i8 255, i32 1, i1 false) br label %bb bb: icmp ne i8* %dest, null -; CHECK: icmp ne i8* %dest, null ret void } define void @test7(i8* %dest, i8* %src, i32 %len) { -; CHECK: test7 +; CHECK-LABEL: @test7( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 [[LEN:%.*]], i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[KEEP1:%.*]] = icmp ne i8* [[DEST]], null +; CHECK-NEXT: [[KEEP2:%.*]] = icmp ne i8* [[SRC]], null +; CHECK-NEXT: ret void +; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false) br label %bb bb: %KEEP1 = icmp ne i8* %dest, null -; CHECK: KEEP1 %KEEP2 = icmp ne i8* %src, null -; CHECK: KEEP2 ret void } declare void @llvm.memcpy.p1i8.p1i8.i32(i8 addrspace(1) *, i8 addrspace(1) *, i32, i1) define void @test8(i8 addrspace(1) * %dest, i8 addrspace(1) * %src) { -; CHECK: test8 +; CHECK-LABEL: @test8( +; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i32(i8 addrspace(1)* [[DEST:%.*]], i8 addrspace(1)* [[SRC:%.*]], i32 1, i1 false) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[KEEP1:%.*]] = icmp ne i8 addrspace(1)* [[DEST]], null +; CHECK-NEXT: [[KEEP2:%.*]] = icmp ne i8 addrspace(1)* [[SRC]], null +; CHECK-NEXT: ret void +; call void @llvm.memcpy.p1i8.p1i8.i32(i8 addrspace(1) * %dest, i8 addrspace(1) * %src, i32 1, i1 false) br label %bb bb: %KEEP1 = icmp ne i8 addrspace(1) * %dest, null -; CHECK: KEEP1 %KEEP2 = icmp ne i8 addrspace(1) * %src, null -; CHECK: KEEP2 ret void } define void @test9(i8* %dest, i8* %src) { -; CHECK: test9 +; CHECK-LABEL: @test9( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 true) +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[KEEP1:%.*]] = icmp ne i8* [[DEST]], null +; CHECK-NEXT: [[KEEP2:%.*]] = icmp ne i8* [[SRC]], null +; CHECK-NEXT: ret void +; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 true) br label %bb bb: %KEEP1 = icmp ne i8* %dest, null -; CHECK: KEEP1 %KEEP2 = icmp ne i8* %src, null -; CHECK: KEEP2 ret void } declare void @test10_helper(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) + define void @test10(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) { -; CHECK-LABEL: @test10 +; CHECK-LABEL: @test10( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8* [[ARG1:%.*]], null +; CHECK-NEXT: br i1 [[IS_NULL]], label [[NULL:%.*]], label [[NON_NULL:%.*]] +; CHECK: non_null: +; CHECK-NEXT: call void @test10_helper(i8* nonnull [[ARG1]], i8* [[ARG2:%.*]], i32 [[NON_POINTER_ARG:%.*]]) +; CHECK-NEXT: br label [[NULL]] +; CHECK: null: +; CHECK-NEXT: call void @test10_helper(i8* [[ARG1]], i8* [[ARG2]], i32 [[NON_POINTER_ARG]]) +; CHECK-NEXT: ret void +; entry: %is_null = icmp eq i8* %arg1, null br i1 %is_null, label %null, label %non_null non_null: call void @test10_helper(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) - ; CHECK: call void @test10_helper(i8* nonnull %arg1, i8* %arg2, i32 %non-pointer-arg) br label %null null: call void @test10_helper(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) - ; CHECK: call void @test10_helper(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) ret void } declare void @test11_helper(i8* %arg) + define void @test11(i8* %arg1, i8** %arg2) { -; CHECK-LABEL: @test11 +; CHECK-LABEL: @test11( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8* [[ARG1:%.*]], null +; CHECK-NEXT: br i1 [[IS_NULL]], label [[NULL:%.*]], label [[NON_NULL:%.*]] +; CHECK: non_null: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: null: +; CHECK-NEXT: [[ANOTHER_ARG:%.*]] = alloca i8 +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: [[MERGED_ARG:%.*]] = phi i8* [ [[ANOTHER_ARG]], [[NULL]] ], [ [[ARG1]], [[NON_NULL]] ] +; CHECK-NEXT: call void @test11_helper(i8* nonnull [[MERGED_ARG]]) +; CHECK-NEXT: ret void +; entry: %is_null = icmp eq i8* %arg1, null br i1 %is_null, label %null, label %non_null @@ -202,13 +296,26 @@ null: merge: %merged_arg = phi i8* [%another_arg, %null], [%arg1, %non_null] call void @test11_helper(i8* %merged_arg) - ; CHECK: call void @test11_helper(i8* nonnull %merged_arg) ret void } declare void @test12_helper(i8* %arg) + define void @test12(i8* %arg1, i8** %arg2) { -; CHECK-LABEL: @test12 +; CHECK-LABEL: @test12( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8* [[ARG1:%.*]], null +; CHECK-NEXT: br i1 [[IS_NULL]], label [[NULL:%.*]], label [[NON_NULL:%.*]] +; CHECK: non_null: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: null: +; CHECK-NEXT: [[ANOTHER_ARG:%.*]] = load i8*, i8** [[ARG2:%.*]], !nonnull !0 +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: [[MERGED_ARG:%.*]] = phi i8* [ [[ANOTHER_ARG]], [[NULL]] ], [ [[ARG1]], [[NON_NULL]] ] +; CHECK-NEXT: call void @test12_helper(i8* nonnull [[MERGED_ARG]]) +; CHECK-NEXT: ret void +; entry: %is_null = icmp eq i8* %arg1, null br i1 %is_null, label %null, label %non_null @@ -223,7 +330,6 @@ null: merge: %merged_arg = phi i8* [%another_arg, %null], [%arg1, %non_null] call void @test12_helper(i8* %merged_arg) - ; CHECK: call void @test12_helper(i8* nonnull %merged_arg) ret void } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll index 002dfc5a544..0e6915a289b 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll @@ -1,8 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -correlated-propagation -S < %s | FileCheck %s declare i32 @foo() define i32 @test1(i32 %a) nounwind { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: br i1 false, label [[END:%.*]], label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %a.off = add i32 %a, -8 %cmp = icmp ult i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -16,13 +28,20 @@ else: end: ret i32 2 - -; CHECK-LABEL: @test1( -; CHECK: then: -; CHECK-NEXT: br i1 false, label %end, label %else } define i32 @test2(i32 %a) nounwind { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: br i1 false, label [[END:%.*]], label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %a.off = add i32 %a, -8 %cmp = icmp ult i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -36,14 +55,26 @@ else: end: ret i32 2 - -; CHECK-LABEL: @test2( -; CHECK: then: -; CHECK-NEXT: br i1 false, label %end, label %else } -; CHECK-LABEL: @test3( define i32 @test3(i32 %c) nounwind { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[C:%.*]], 2 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i32 1 +; CHECK: if.end: +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[C]], 3 +; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END8:%.*]] +; CHECK: if.then2: +; CHECK-NEXT: br i1 true, label [[IF_THEN4:%.*]], label [[IF_END6:%.*]] +; CHECK: if.end6: +; CHECK-NEXT: ret i32 2 +; CHECK: if.then4: +; CHECK-NEXT: ret i32 3 +; CHECK: if.end8: +; CHECK-NEXT: ret i32 4 +; %cmp = icmp slt i32 %c, 2 br i1 %cmp, label %if.then, label %if.end @@ -54,13 +85,10 @@ if.end: %cmp1 = icmp slt i32 %c, 3 br i1 %cmp1, label %if.then2, label %if.end8 -; CHECK: if.then2 if.then2: %cmp2 = icmp eq i32 %c, 2 -; CHECK: br i1 true br i1 %cmp2, label %if.then4, label %if.end6 -; CHECK: if.end6 if.end6: ret i32 2 @@ -71,18 +99,33 @@ if.end8: ret i32 4 } -; CHECK-LABEL: @test4( define i32 @test4(i32 %c) nounwind { +; CHECK-LABEL: @test4( +; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 1, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB]] +; CHECK-NEXT: i32 4, label [[SW_BB]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: br label [[RETURN:%.*]] +; CHECK: if.end: +; CHECK-NEXT: br label [[RETURN]] +; CHECK: sw.default: +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 42, [[SW_DEFAULT]] ], [ 4, [[IF_THEN]] ], [ 9, [[IF_END]] ] +; CHECK-NEXT: ret i32 [[RETVAL_0]] +; switch i32 %c, label %sw.default [ - i32 1, label %sw.bb - i32 2, label %sw.bb - i32 4, label %sw.bb + i32 1, label %sw.bb + i32 2, label %sw.bb + i32 4, label %sw.bb ] -; CHECK: sw.bb sw.bb: %cmp = icmp sge i32 %c, 1 -; CHECK: br i1 true br i1 %cmp, label %if.then, label %if.end if.then: @@ -99,8 +142,20 @@ return: ret i32 %retval.0 } -; CHECK-LABEL: @test5( define i1 @test5(i32 %c) nounwind { +; CHECK-LABEL: @test5( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[C:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[C]], 4 +; CHECK-NEXT: br i1 [[CMP1]], label [[IF_END]], label [[IF_END8:%.*]] +; CHECK: if.end: +; CHECK-NEXT: ret i1 true +; CHECK: if.end8: +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[C]], 3 +; CHECK-NEXT: [[OR:%.*]] = or i1 false, false +; CHECK-NEXT: ret i1 [[CMP2]] +; %cmp = icmp slt i32 %c, 5 br i1 %cmp, label %if.then, label %if.end @@ -115,23 +170,29 @@ if.end8: %cmp2 = icmp eq i32 %c, 3 %cmp3 = icmp eq i32 %c, 4 %cmp4 = icmp eq i32 %c, 6 -; CHECK: %or = or i1 false, false %or = or i1 %cmp3, %cmp4 -; CHECK: ret i1 %cmp2 ret i1 %cmp2 } -; CHECK-LABEL: @test6( define i1 @test6(i32 %c) nounwind { +; CHECK-LABEL: @test6( +; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[C:%.*]], 7 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[C]], 6 +; CHECK-NEXT: br i1 [[COND]], label [[SW_BB:%.*]], label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret i1 true +; CHECK: sw.bb: +; CHECK-NEXT: ret i1 true +; %cmp = icmp ule i32 %c, 7 br i1 %cmp, label %if.then, label %if.end if.then: -; CHECK: icmp eq i32 %c, 6 -; CHECK: br i1 switch i32 %c, label %if.end [ - i32 6, label %sw.bb - i32 8, label %sw.bb + i32 6, label %sw.bb + i32 8, label %sw.bb ] if.end: @@ -139,52 +200,72 @@ if.end: sw.bb: %cmp2 = icmp eq i32 %c, 6 -; CHECK: ret i1 true ret i1 %cmp2 } -; CHECK-LABEL: @test7( define i1 @test7(i32 %c) nounwind { +; CHECK-LABEL: @test7( +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 6, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 7, label [[SW_BB]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: ret i1 true +; CHECK: sw.default: +; CHECK-NEXT: [[CMP5:%.*]] = icmp eq i32 [[C]], 5 +; CHECK-NEXT: [[CMP8:%.*]] = icmp eq i32 [[C]], 8 +; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP5]], false +; CHECK-NEXT: [[OR2:%.*]] = or i1 false, [[CMP8]] +; CHECK-NEXT: ret i1 false +; entry: - switch i32 %c, label %sw.default [ - i32 6, label %sw.bb - i32 7, label %sw.bb - ] + switch i32 %c, label %sw.default [ + i32 6, label %sw.bb + i32 7, label %sw.bb + ] sw.bb: - ret i1 true + ret i1 true sw.default: - %cmp5 = icmp eq i32 %c, 5 - %cmp6 = icmp eq i32 %c, 6 - %cmp7 = icmp eq i32 %c, 7 - %cmp8 = icmp eq i32 %c, 8 -; CHECK: %or = or i1 %cmp5, false - %or = or i1 %cmp5, %cmp6 -; CHECK: %or2 = or i1 false, %cmp8 - %or2 = or i1 %cmp7, %cmp8 - ret i1 false + %cmp5 = icmp eq i32 %c, 5 + %cmp6 = icmp eq i32 %c, 6 + %cmp7 = icmp eq i32 %c, 7 + %cmp8 = icmp eq i32 %c, 8 + %or = or i1 %cmp5, %cmp6 + %or2 = or i1 %cmp7, %cmp8 + ret i1 false } define i1 @test8(i64* %p) { -; CHECK-LABEL: @test8 -; CHECK: ret i1 false +; CHECK-LABEL: @test8( +; CHECK-NEXT: [[A:%.*]] = load i64, i64* [[P:%.*]], !range !0 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i64 [[A]], 0 +; CHECK-NEXT: ret i1 false +; %a = load i64, i64* %p, !range !{i64 4, i64 255} %res = icmp eq i64 %a, 0 ret i1 %res } define i1 @test9(i64* %p) { -; CHECK-LABEL: @test9 -; CHECK: ret i1 true +; CHECK-LABEL: @test9( +; CHECK-NEXT: [[A:%.*]] = load i64, i64* [[P:%.*]], !range !1 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i64 [[A]], 0 +; CHECK-NEXT: ret i1 true +; %a = load i64, i64* %p, !range !{i64 0, i64 1} %res = icmp eq i64 %a, 0 ret i1 %res } define i1 @test10(i64* %p) { -; CHECK-LABEL: @test10 -; CHECK: ret i1 false +; CHECK-LABEL: @test10( +; CHECK-NEXT: [[A:%.*]] = load i64, i64* [[P:%.*]], !range !2 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i64 [[A]], 0 +; CHECK-NEXT: ret i1 false +; %a = load i64, i64* %p, !range !{i64 4, i64 8, i64 15, i64 20} %res = icmp eq i64 %a, 0 ret i1 %res @@ -193,8 +274,14 @@ define i1 @test10(i64* %p) { @g = external global i32 define i1 @test11() { -; CHECK: @test11 -; CHECK: ret i1 true +; CHECK-LABEL: @test11( +; CHECK-NEXT: [[POSITIVE:%.*]] = load i32, i32* @g, !range !3 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[POSITIVE]], 1 +; CHECK-NEXT: [[TEST:%.*]] = icmp sgt i32 [[ADD]], 0 +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: ret i1 true +; %positive = load i32, i32* @g, !range !{i32 1, i32 2048} %add = add i32 %positive, 1 %test = icmp sgt i32 %add, 0 @@ -206,8 +293,15 @@ next: define i32 @test12(i32 %a, i32 %b) { ; CHECK-LABEL: @test12( -; CHECK: then: -; CHECK-NEXT: br i1 false, label %end, label %else +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: br i1 false, label [[END:%.*]], label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %cmp = icmp ult i32 %a, %b br i1 %cmp, label %then, label %else @@ -224,8 +318,15 @@ end: define i32 @test12_swap(i32 %a, i32 %b) { ; CHECK-LABEL: @test12_swap( -; CHECK: then: -; CHECK-NEXT: br i1 false, label %end, label %else +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: br i1 false, label [[END:%.*]], label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %cmp = icmp ugt i32 %b, %a br i1 %cmp, label %then, label %else @@ -240,11 +341,20 @@ end: ret i32 2 } -define i32 @test12_neg(i32 %a, i32 %b) { ; The same as @test12 but the second check is on the false path + +define i32 @test12_neg(i32 %a, i32 %b) { ; CHECK-LABEL: @test12_neg( -; CHECK: else: -; CHECK-NEXT: %alive = icmp eq i32 %a, -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: else: +; CHECK-NEXT: [[ALIVE:%.*]] = icmp eq i32 [[A]], -1 +; CHECK-NEXT: br i1 [[ALIVE]], label [[END:%.*]], label [[THEN]] +; CHECK: then: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %cmp = icmp ult i32 %a, %b br i1 %cmp, label %then, label %else @@ -259,11 +369,19 @@ end: ret i32 2 } -define i32 @test12_signed(i32 %a, i32 %b) { ; The same as @test12 but with signed comparison + +define i32 @test12_signed(i32 %a, i32 %b) { ; CHECK-LABEL: @test12_signed( -; CHECK: then: -; CHECK-NEXT: br i1 false, label %end, label %else +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: br i1 false, label [[END:%.*]], label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %cmp = icmp slt i32 %a, %b br i1 %cmp, label %then, label %else @@ -280,8 +398,16 @@ end: define i32 @test13(i32 %a, i32 %b) { ; CHECK-LABEL: @test13( -; CHECK: then: -; CHECK-NEXT: br i1 false, label %end, label %else +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A_OFF]], [[B:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: br i1 false, label [[END:%.*]], label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %a.off = add i32 %a, -8 %cmp = icmp ult i32 %a.off, %b br i1 %cmp, label %then, label %else @@ -299,8 +425,16 @@ end: define i32 @test13_swap(i32 %a, i32 %b) { ; CHECK-LABEL: @test13_swap( -; CHECK: then: -; CHECK-NEXT: br i1 false, label %end, label %else +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[B:%.*]], [[A_OFF]] +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: br i1 false, label [[END:%.*]], label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret i32 1 +; CHECK: end: +; CHECK-NEXT: ret i32 2 +; %a.off = add i32 %a, -8 %cmp = icmp ugt i32 %b, %a.off br i1 %cmp, label %then, label %else @@ -318,8 +452,15 @@ end: define i1 @test14_slt(i32 %a) { ; CHECK-LABEL: @test14_slt( -; CHECK: then: -; CHECK-NEXT: %result = or i1 false, false +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, false +; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %a.off = add i32 %a, -8 %cmp = icmp slt i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -336,9 +477,16 @@ else: define i1 @test14_sle(i32 %a) { ; CHECK-LABEL: @test14_sle( -; CHECK: then: -; CHECK-NEXT: %alive = icmp eq i32 %a, 16 -; CHECK-NEXT: %result = or i1 false, %alive +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[ALIVE:%.*]] = icmp eq i32 [[A]], 16 +; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, [[ALIVE]] +; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %a.off = add i32 %a, -8 %cmp = icmp sle i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -355,8 +503,15 @@ else: define i1 @test14_sgt(i32 %a) { ; CHECK-LABEL: @test14_sgt( -; CHECK: then: -; CHECK-NEXT: %result = or i1 false, false +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, false +; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %a.off = add i32 %a, -8 %cmp = icmp sgt i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -373,9 +528,16 @@ else: define i1 @test14_sge(i32 %a) { ; CHECK-LABEL: @test14_sge( -; CHECK: then: -; CHECK-NEXT: %alive = icmp eq i32 %a, 16 -; CHECK-NEXT: %result = or i1 false, %alive +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[ALIVE:%.*]] = icmp eq i32 [[A]], 16 +; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, [[ALIVE]] +; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %a.off = add i32 %a, -8 %cmp = icmp sge i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -392,9 +554,16 @@ else: define i1 @test14_ule(i32 %a) { ; CHECK-LABEL: @test14_ule( -; CHECK: then: -; CHECK-NEXT: %alive = icmp eq i32 %a, 16 -; CHECK-NEXT: %result = or i1 false, %alive +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[ALIVE:%.*]] = icmp eq i32 [[A]], 16 +; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, [[ALIVE]] +; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %a.off = add i32 %a, -8 %cmp = icmp ule i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -411,8 +580,15 @@ else: define i1 @test14_ugt(i32 %a) { ; CHECK-LABEL: @test14_ugt( -; CHECK: then: -; CHECK-NEXT: %result = or i1 false, false +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, false +; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %a.off = add i32 %a, -8 %cmp = icmp ugt i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -429,9 +605,16 @@ else: define i1 @test14_uge(i32 %a) { ; CHECK-LABEL: @test14_uge( -; CHECK: then: -; CHECK-NEXT: %alive = icmp eq i32 %a, 16 -; CHECK-NEXT: %result = or i1 false, %alive +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[ALIVE:%.*]] = icmp eq i32 [[A]], 16 +; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, [[ALIVE]] +; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %a.off = add i32 %a, -8 %cmp = icmp uge i32 %a.off, 8 br i1 %cmp, label %then, label %else @@ -449,8 +632,14 @@ else: @limit = external global i32 define i1 @test15(i32 %a) { ; CHECK-LABEL: @test15( -; CHECK: then: -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: [[LIMIT:%.*]] = load i32, i32* @limit, !range !4 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[LIMIT]] +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: ret i1 false +; CHECK: else: +; CHECK-NEXT: ret i1 false +; %limit = load i32, i32* @limit, !range !{i32 0, i32 256} %cmp = icmp ult i32 %a, %limit br i1 %cmp, label %then, label %else @@ -464,6 +653,16 @@ else: } define i32 @test16(i8 %a) { +; CHECK-LABEL: @test16( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = zext i8 [[A:%.*]] to i32 +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 93 +; CHECK-NEXT: br i1 [[CMP]], label [[TARGET93:%.*]], label [[DISPATCH]] +; CHECK: target93: +; CHECK-NEXT: ret i32 93 +; entry: %b = zext i8 %a to i32 br label %dispatch @@ -472,14 +671,20 @@ dispatch: %cmp = icmp eq i8 %a, 93 br i1 %cmp, label %target93, label %dispatch -; CHECK-LABEL: @test16( -; CHECK: target93: -; CHECK-NEXT: ret i32 93 target93: ret i32 %b } define i32 @test16_i1(i1 %a) { +; CHECK-LABEL: @test16_i1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A:%.*]] to i32 +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: br i1 [[A]], label [[TRUE:%.*]], label [[DISPATCH]] +; CHECK: true: +; CHECK-NEXT: ret i32 1 +; entry: %b = zext i1 %a to i32 br label %dispatch @@ -487,14 +692,21 @@ entry: dispatch: br i1 %a, label %true, label %dispatch -; CHECK-LABEL: @test16_i1( -; CHECK: true: -; CHECK-NEXT: ret i32 1 true: ret i32 %b } define i8 @test17(i8 %a) { +; CHECK-LABEL: @test17( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C:%.*]] = add i8 [[A:%.*]], 3 +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 93 +; CHECK-NEXT: br i1 [[CMP]], label [[TARGET93:%.*]], label [[DISPATCH]] +; CHECK: target93: +; CHECK-NEXT: ret i8 96 +; entry: %c = add i8 %a, 3 br label %dispatch @@ -503,14 +715,21 @@ dispatch: %cmp = icmp eq i8 %a, 93 br i1 %cmp, label %target93, label %dispatch -; CHECK-LABEL: @test17( -; CHECK: target93: -; CHECK-NEXT: ret i8 96 target93: ret i8 %c } define i8 @test17_2(i8 %a) { +; CHECK-LABEL: @test17_2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C:%.*]] = add i8 [[A:%.*]], [[A]] +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 93 +; CHECK-NEXT: br i1 [[CMP]], label [[TARGET93:%.*]], label [[DISPATCH]] +; CHECK: target93: +; CHECK-NEXT: ret i8 -70 +; entry: %c = add i8 %a, %a br label %dispatch @@ -519,14 +738,20 @@ dispatch: %cmp = icmp eq i8 %a, 93 br i1 %cmp, label %target93, label %dispatch -; CHECK-LABEL: @test17_2( -; CHECK: target93: -; CHECK-NEXT: ret i8 -70 target93: ret i8 %c } define i1 @test17_i1(i1 %a) { +; CHECK-LABEL: @test17_i1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C:%.*]] = and i1 [[A:%.*]], true +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: br i1 [[A]], label [[TRUE:%.*]], label [[DISPATCH]] +; CHECK: true: +; CHECK-NEXT: ret i1 true +; entry: %c = and i1 %a, true br label %dispatch @@ -534,58 +759,92 @@ entry: dispatch: br i1 %a, label %true, label %dispatch -; CHECK-LABEL: @test17_i1( -; CHECK: true: -; CHECK-NEXT: ret i1 true true: ret i1 %c } define i32 @test18(i8 %a) { +; CHECK-LABEL: @test18( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = zext i8 [[A:%.*]] to i32 +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: switch i8 [[A]], label [[DISPATCH]] [ +; CHECK-NEXT: i8 93, label [[TARGET93:%.*]] +; CHECK-NEXT: i8 -111, label [[DISPATCH]] +; CHECK-NEXT: ] +; CHECK: target93: +; CHECK-NEXT: ret i32 93 +; entry: %b = zext i8 %a to i32 br label %dispatch dispatch: switch i8 %a, label %dispatch [ - i8 93, label %target93 - i8 -111, label %dispatch + i8 93, label %target93 + i8 -111, label %dispatch ] -; CHECK-LABEL: @test18( -; CHECK: target93: -; CHECK-NEXT: ret i32 93 target93: ret i32 %b } define i8 @test19(i8 %a) { +; CHECK-LABEL: @test19( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C:%.*]] = add i8 [[A:%.*]], 3 +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: switch i8 [[A]], label [[DISPATCH]] [ +; CHECK-NEXT: i8 93, label [[TARGET93:%.*]] +; CHECK-NEXT: i8 -111, label [[DISPATCH]] +; CHECK-NEXT: ] +; CHECK: target93: +; CHECK-NEXT: ret i8 96 +; entry: %c = add i8 %a, 3 br label %dispatch dispatch: switch i8 %a, label %dispatch [ - i8 93, label %target93 - i8 -111, label %dispatch + i8 93, label %target93 + i8 -111, label %dispatch ] -; CHECK-LABEL: @test19( -; CHECK: target93: -; CHECK-NEXT: ret i8 96 target93: ret i8 %c } +; Negative test. Shouldn't be incorrectly optimized to "ret i1 false". + define i1 @test20(i64 %a) { +; CHECK-LABEL: @test20( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = and i64 [[A:%.*]], 7 +; CHECK-NEXT: br label [[DISPATCH:%.*]] +; CHECK: dispatch: +; CHECK-NEXT: switch i64 [[A]], label [[DEFAULT:%.*]] [ +; CHECK-NEXT: i64 0, label [[EXIT2:%.*]] +; CHECK-NEXT: i64 -2147483647, label [[EXIT2]] +; CHECK-NEXT: ] +; CHECK: default: +; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[B]], 0 +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i1 [[C]] +; CHECK: exit2: +; CHECK-NEXT: ret i1 false +; entry: %b = and i64 %a, 7 br label %dispatch dispatch: switch i64 %a, label %default [ - i64 0, label %exit2 - i64 -2147483647, label %exit2 + i64 0, label %exit2 + i64 -2147483647, label %exit2 ] default: @@ -593,11 +852,6 @@ default: br label %exit exit: -; Negative test. Shouldn't be incorrectly optimized to "ret i1 false". -; CHECK-LABEL: @test20( -; CHECK: exit: -; CHECK-NOT: ret i1 false -; CHECK: exit2: ret i1 %c exit2: @@ -606,7 +860,11 @@ exit2: define i1 @slt(i8 %a, i8 %b) { ; CHECK-LABEL: @slt( -; CHECK: ret i1 true +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: ret i1 true +; entry: %cmp = icmp slt i8 %a, %b call void @llvm.assume(i1 %cmp) @@ -616,7 +874,11 @@ entry: define i1 @sgt(i8 %a, i8 %b) { ; CHECK-LABEL: @sgt( -; CHECK: ret i1 true +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: ret i1 true +; entry: %cmp = icmp sgt i8 %a, %b call void @llvm.assume(i1 %cmp) @@ -626,7 +888,11 @@ entry: define i1 @ult(i8 %a, i8 %b) { ; CHECK-LABEL: @ult( -; CHECK: ret i1 true +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: ret i1 true +; entry: %cmp = icmp ult i8 %a, %b call void @llvm.assume(i1 %cmp) @@ -636,7 +902,11 @@ entry: define i1 @ugt(i8 %a, i8 %b) { ; CHECK-LABEL: @ugt( -; CHECK: ret i1 true +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: ret i1 true +; entry: %cmp = icmp ugt i8 %a, %b call void @llvm.assume(i1 %cmp) |

