diff --git a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll --- a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll +++ b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll @@ -17,6 +17,39 @@ ret void } +define void @foo_switch(i64 %C, ptr %P) { +; CHECK-LABEL: @foo_switch( +; CHECK-NEXT: switch i64 [[C:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: common.ret: +; CHECK-NEXT: ret void +; CHECK: bb0: +; CHECK-NEXT: store i32 7, ptr [[P:%.*]], align 4 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] +; CHECK: bb1: +; CHECK-NEXT: store i32 7, ptr [[P]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: bb2: +; CHECK-NEXT: store i32 7, ptr [[P]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] +; + switch i64 %C, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: ; preds = %0 + store i32 7, ptr %P + ret void +bb1: ; preds = %0 + store i32 7, ptr %P + ret void +bb2: ; preds = %0 + store i32 7, ptr %P + ret void +} + define float @PR39535min(float %x) { ; CHECK-LABEL: @PR39535min( ; CHECK-NEXT: entry: @@ -38,3 +71,38 @@ %cond = phi fast float [ 0.0, %cond.true ], [ %x, %cond.false ] ret float %cond } + +define float @PR39535min_switch(i64 %i, float %x) { +; CHECK-LABEL: @PR39535min_switch( +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i64 [[I:%.*]], label [[END:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb1: +; CHECK-NEXT: br label [[END]] +; CHECK: bb2: +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[COND:%.*]] = phi fast float [ [[X:%.*]], [[BB1]] ], [ [[X]], [[BB2]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret float [[COND]] +; +entry: + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] + +bb0: + br label %end + +bb1: + br label %end + +bb2: + br label %end + +end: + %cond = phi fast float [ 0.0, %bb0 ], [ %x, %bb1 ], [ %x, %bb2 ] + ret float %cond +} diff --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll @@ -0,0 +1,99 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes='simplifycfg' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s + +define i1 @common_instr_with_unreachable(i64 %a, i64 %b, i64 %c) { +; CHECK-LABEL: @common_instr_with_unreachable( +; CHECK-NEXT: start: +; CHECK-NEXT: switch i64 [[A:%.*]], label [[UNREACHABLE:%.*]] [ +; CHECK-NEXT: i64 0, label [[BB0:%.*]] +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: unreachable: +; CHECK-NEXT: unreachable +; CHECK: bb0: +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ] +; CHECK-NEXT: ret i1 [[RESULT]] +; +start: + switch i64 %a, label %unreachable [ + i64 0, label %bb0 + i64 1, label %bb1 + i64 2, label %bb2 + ] + +unreachable: + unreachable + +bb0: ; preds = %start + %0 = icmp eq i64 %b, %c + br label %exit + +bb1: ; preds = %start + %1 = icmp eq i64 %b, %c + br label %exit + +bb2: ; preds = %start + %2 = icmp eq i64 %b, %c + br label %exit + +exit: ; preds = %bb2, %bb1, %bb0 + %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ] + ret i1 %result +} + +define i1 @common_instr_with_unreachable_2(i64 %a, i64 %b, i64 %c) { +; CHECK-LABEL: @common_instr_with_unreachable_2( +; CHECK-NEXT: start: +; CHECK-NEXT: switch i64 [[A:%.*]], label [[BB1:%.*]] [ +; CHECK-NEXT: i64 0, label [[BB0:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ] +; CHECK-NEXT: ret i1 [[RESULT]] +; +start: + switch i64 %a, label %bb1 [ + i64 0, label %bb0 + i64 1, label %unreachable + i64 2, label %bb2 + ] + +unreachable: + unreachable + +bb0: ; preds = %start + %0 = icmp eq i64 %b, %c + br label %exit + +bb1: ; preds = %start + %1 = icmp eq i64 %b, %c + br label %exit + +bb2: ; preds = %start + %2 = icmp eq i64 %b, %c + br label %exit + +exit: ; preds = %bb2, %bb1, %bb0 + %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ] + ret i1 %result +} diff --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll --- a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll +++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll @@ -24,3 +24,133 @@ ret void } +define void @test_switch(i64 %i, ptr %Q) { +; CHECK-LABEL: @test_switch( +; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: common.ret: +; CHECK-NEXT: ret void +; CHECK: bb0: +; CHECK-NEXT: store i32 1, ptr [[Q:%.*]], align 4 +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[Q]], align 4 +; CHECK-NEXT: call void @bar(i32 [[A]]) +; CHECK-NEXT: br label [[COMMON_RET:%.*]] +; CHECK: bb1: +; CHECK-NEXT: store i32 1, ptr [[Q]], align 4 +; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Q]], align 4 +; CHECK-NEXT: call void @bar(i32 [[B]]) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: bb2: +; CHECK-NEXT: store i32 1, ptr [[Q]], align 4 +; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[Q]], align 4 +; CHECK-NEXT: call void @bar(i32 [[C]]) +; CHECK-NEXT: br label [[COMMON_RET]] +; + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: ; preds = %0 + store i32 1, ptr %Q + %A = load i32, ptr %Q ; [#uses=1] + call void @bar( i32 %A ) + ret void +bb1: ; preds = %0 + store i32 1, ptr %Q + %B = load i32, ptr %Q ; [#uses=1] + call void @bar( i32 %B ) + ret void +bb2: ; preds = %0 + store i32 1, ptr %Q + %C = load i32, ptr %Q ; [#uses=1] + call void @bar( i32 %C ) + ret void +} + +define i1 @common_instr_on_switch(i64 %a, i64 %b, i64 %c) unnamed_addr { +; CHECK-LABEL: @common_instr_on_switch( +; CHECK-NEXT: start: +; CHECK-NEXT: switch i64 [[A:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ] +; CHECK-NEXT: ret i1 [[RESULT]] +; +start: + switch i64 %a, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] + +bb0: ; preds = %start + %0 = icmp eq i64 %b, %c + br label %exit + +bb1: ; preds = %start + %1 = icmp eq i64 %b, %c + br label %exit + +bb2: ; preds = %start + %2 = icmp eq i64 %b, %c + br label %exit + +exit: ; preds = %bb2, %bb1, %bb0 + %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ] + ret i1 %result +} + +define i1 @partial_common_instr_on_switch(i64 %a, i64 %b, i64 %c) unnamed_addr { +; CHECK-LABEL: @partial_common_instr_on_switch( +; CHECK-NEXT: start: +; CHECK-NEXT: switch i64 [[A:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ] +; CHECK-NEXT: ret i1 [[RESULT]] +; +start: + switch i64 %a, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] + +bb0: ; preds = %start + %0 = icmp eq i64 %b, %c + br label %exit + +bb1: ; preds = %start + %1 = icmp ne i64 %b, %c + br label %exit + +bb2: ; preds = %start + %2 = icmp eq i64 %b, %c + br label %exit + +exit: ; preds = %bb2, %bb1, %bb0 + %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ] + ret i1 %result +} diff --git a/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll b/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll --- a/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll +++ b/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll @@ -19,10 +19,45 @@ ret void } +define void @hoist_range_switch(i64 %i, ptr %p) { +; CHECK-LABEL: @hoist_range_switch( +; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !range [[RNG1:![0-9]+]] +; CHECK-NEXT: br label [[OUT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG2:![0-9]+]] +; CHECK-NEXT: br label [[OUT]] +; CHECK: bb2: +; CHECK-NEXT: [[F:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG3:![0-9]+]] +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret void +; + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: + %t = load i8, ptr %p, !range !0 + br label %out +bb1: + %e = load i8, ptr %p, !range !1 + br label %out +bb2: + %f = load i8, ptr %p, !range !3 + br label %out +out: + ret void +} + define void @hoist_both_noundef(i1 %c, ptr %p) { ; CHECK-LABEL: @hoist_both_noundef( ; CHECK-NEXT: if: -; CHECK-NEXT: [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !1 +; CHECK-NEXT: [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !4 ; CHECK-NEXT: ret void ; if: @@ -40,6 +75,42 @@ ret void } + +define void @hoist_both_noundef_switch(i64 %i, ptr %p) { +; CHECK-LABEL: @hoist_both_noundef_switch( +; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !4 +; CHECK-NEXT: br label [[OUT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[P]], align 1, !noundef !4 +; CHECK-NEXT: br label [[OUT]] +; CHECK: bb2: +; CHECK-NEXT: [[F:%.*]] = load i8, ptr [[P]], align 1, !noundef !4 +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret void +; + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: + %t = load i8, ptr %p, !noundef !2 + br label %out +bb1: + %e = load i8, ptr %p, !noundef !2 + br label %out +bb2: + %f = load i8, ptr %p, !noundef !2 + br label %out +out: + ret void +} + define void @hoist_one_noundef(i1 %c, ptr %p) { ; CHECK-LABEL: @hoist_one_noundef( ; CHECK-NEXT: if: @@ -61,10 +132,45 @@ ret void } +define void @hoist_one_noundef_switch(i64 %i, ptr %p) { +; CHECK-LABEL: @hoist_one_noundef_switch( +; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !4 +; CHECK-NEXT: br label [[OUT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: br label [[OUT]] +; CHECK: bb2: +; CHECK-NEXT: [[F:%.*]] = load i8, ptr [[P]], align 1, !noundef !4 +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret void +; + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: + %t = load i8, ptr %p, !noundef !2 + br label %out +bb1: + %e = load i8, ptr %p + br label %out +bb2: + %f = load i8, ptr %p, !noundef !2 + br label %out +out: + ret void +} + define void @hoist_dereferenceable(i1 %c, ptr %p) { ; CHECK-LABEL: @hoist_dereferenceable( ; CHECK-NEXT: if: -; CHECK-NEXT: [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !2 +; CHECK-NEXT: [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !5 ; CHECK-NEXT: ret void ; if: @@ -79,10 +185,45 @@ ret void } +define void @hoist_dereferenceable_switch(i64 %i, ptr %p) { +; CHECK-LABEL: @hoist_dereferenceable_switch( +; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !5 +; CHECK-NEXT: br label [[OUT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[E:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !6 +; CHECK-NEXT: br label [[OUT]] +; CHECK: bb2: +; CHECK-NEXT: [[F:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !7 +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret void +; + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: + %t = load ptr, ptr %p, !dereferenceable !{i64 10} + br label %out +bb1: + %e = load ptr, ptr %p, !dereferenceable !{i64 20} + br label %out +bb2: + %f = load ptr, ptr %p, !dereferenceable !{i64 30} + br label %out +out: + ret void +} + define void @hoist_dereferenceable_or_null(i1 %c, ptr %p) { ; CHECK-LABEL: @hoist_dereferenceable_or_null( ; CHECK-NEXT: if: -; CHECK-NEXT: [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable_or_null !2 +; CHECK-NEXT: [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable_or_null !5 ; CHECK-NEXT: ret void ; if: @@ -97,11 +238,46 @@ ret void } +define void @hoist_dereferenceable_or_null_switch(i64 %i, ptr %p) { +; CHECK-LABEL: @hoist_dereferenceable_or_null_switch( +; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable_or_null !6 +; CHECK-NEXT: br label [[OUT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[E:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null !5 +; CHECK-NEXT: br label [[OUT]] +; CHECK: bb2: +; CHECK-NEXT: [[F:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null !7 +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret void +; + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: + %t = load ptr, ptr %p, !dereferenceable_or_null !{i64 20} + br label %out +bb1: + %e = load ptr, ptr %p, !dereferenceable_or_null !{i64 10} + br label %out +bb2: + %f = load ptr, ptr %p, !dereferenceable_or_null !{i64 30} + br label %out +out: + ret void +} + ; !range violation only returns poison, and is thus safe to speculate. define i32 @speculate_range(i1 %c, ptr dereferenceable(8) align 8 %p) { ; CHECK-LABEL: @speculate_range( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG3:![0-9]+]] +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG8:![0-9]+]] ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 [[V]], i32 0 ; CHECK-NEXT: ret i32 [[SPEC_SELECT]] ; @@ -122,7 +298,7 @@ define ptr @speculate_nonnull(i1 %c, ptr dereferenceable(8) align 8 %p) { ; CHECK-LABEL: @speculate_nonnull( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !nonnull !1 +; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !nonnull !4 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], ptr [[V]], ptr null ; CHECK-NEXT: ret ptr [[SPEC_SELECT]] ; @@ -143,7 +319,7 @@ define ptr @speculate_align(i1 %c, ptr dereferenceable(8) align 8 %p) { ; CHECK-LABEL: @speculate_align( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align !4 +; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align !9 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], ptr [[V]], ptr null ; CHECK-NEXT: ret ptr [[SPEC_SELECT]] ; @@ -162,7 +338,7 @@ define void @hoist_fpmath(i1 %c, double %x) { ; CHECK-LABEL: @hoist_fpmath( ; CHECK-NEXT: if: -; CHECK-NEXT: [[T:%.*]] = fadd double [[X:%.*]], 1.000000e+00, !fpmath !5 +; CHECK-NEXT: [[T:%.*]] = fadd double [[X:%.*]], 1.000000e+00, !fpmath !10 ; CHECK-NEXT: ret void ; if: @@ -177,14 +353,57 @@ ret void } +define void @hoist_fpmath_switch(i64 %i, double %x) { +; CHECK-LABEL: @hoist_fpmath_switch( +; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb0: +; CHECK-NEXT: [[T:%.*]] = fadd double [[X:%.*]], 1.000000e+00, !fpmath !10 +; CHECK-NEXT: br label [[OUT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[E:%.*]] = fadd double [[X]], 1.000000e+00, !fpmath !11 +; CHECK-NEXT: br label [[OUT]] +; CHECK: bb2: +; CHECK-NEXT: [[F:%.*]] = fadd double [[X]], 1.000000e+00, !fpmath !12 +; CHECK-NEXT: br label [[OUT]] +; CHECK: out: +; CHECK-NEXT: ret void +; + switch i64 %i, label %bb0 [ + i64 1, label %bb1 + i64 2, label %bb2 + ] +bb0: + %t = fadd double %x, 1.0, !fpmath !{ float 2.5 } + br label %out +bb1: + %e = fadd double %x, 1.0, !fpmath !{ float 5.0 } + br label %out +bb2: + %f = fadd double %x, 1.0, !fpmath !{ float 7.5 } + br label %out +out: + ret void +} + !0 = !{ i8 0, i8 1 } !1 = !{ i8 3, i8 5 } !2 = !{} +!3 = !{ i8 7, i8 9 } ;. ; CHECK: [[RNG0]] = !{i8 0, i8 1, i8 3, i8 5} -; CHECK: [[META1:![0-9]+]] = !{} -; CHECK: [[META2:![0-9]+]] = !{i64 10} -; CHECK: [[RNG3]] = !{i32 0, i32 10} -; CHECK: [[META4:![0-9]+]] = !{i64 4} -; CHECK: [[META5:![0-9]+]] = !{float 2.500000e+00} +; CHECK: [[RNG1]] = !{i8 0, i8 1} +; CHECK: [[RNG2]] = !{i8 3, i8 5} +; CHECK: [[RNG3]] = !{i8 7, i8 9} +; CHECK: [[META4:![0-9]+]] = !{} +; CHECK: [[META5:![0-9]+]] = !{i64 10} +; CHECK: [[META6:![0-9]+]] = !{i64 20} +; CHECK: [[META7:![0-9]+]] = !{i64 30} +; CHECK: [[RNG8]] = !{i32 0, i32 10} +; CHECK: [[META9:![0-9]+]] = !{i64 4} +; CHECK: [[META10:![0-9]+]] = !{float 2.500000e+00} +; CHECK: [[META11:![0-9]+]] = !{float 5.000000e+00} +; CHECK: [[META12:![0-9]+]] = !{float 7.500000e+00} ;.