summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/SpeculateAroundPHIs/basic-x86.ll
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Transforms/SpeculateAroundPHIs/basic-x86.ll')
-rw-r--r--llvm/test/Transforms/SpeculateAroundPHIs/basic-x86.ll595
1 files changed, 595 insertions, 0 deletions
diff --git a/llvm/test/Transforms/SpeculateAroundPHIs/basic-x86.ll b/llvm/test/Transforms/SpeculateAroundPHIs/basic-x86.ll
new file mode 100644
index 00000000000..1edba0e5e98
--- /dev/null
+++ b/llvm/test/Transforms/SpeculateAroundPHIs/basic-x86.ll
@@ -0,0 +1,595 @@
+; Test the basic functionality of speculating around PHI nodes based on reduced
+; cost of the constant operands to the PHI nodes using the x86 cost model.
+;
+; REQUIRES: x86-registered-target
+; RUN: opt -S -passes=spec-phis < %s | FileCheck %s
+
+target triple = "x86_64-unknown-unknown"
+
+define i32 @test_basic(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_basic(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 7
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg, 11
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %sum = add i32 %arg, %p
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+; Check that we handle commuted operands and get the constant onto the RHS.
+define i32 @test_commuted(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_commuted(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 7
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg, 11
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %sum = add i32 %p, %arg
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+define i32 @test_split_crit_edge(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_split_crit_edge(
+entry:
+ br i1 %flag, label %exit, label %a
+; CHECK: entry:
+; CHECK-NEXT: br i1 %flag, label %[[ENTRY_SPLIT:.*]], label %a
+;
+; CHECK: [[ENTRY_SPLIT]]:
+; CHECK-NEXT: %[[SUM_ENTRY_SPLIT:.*]] = add i32 %arg, 7
+; CHECK-NEXT: br label %exit
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 11
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %entry ], [ 11, %a ]
+ %sum = add i32 %arg, %p
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_ENTRY_SPLIT]], %[[ENTRY_SPLIT]] ], [ %[[SUM_A]], %a ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+define i32 @test_no_spec_dominating_inst(i1 %flag, i32* %ptr) {
+; CHECK-LABEL: define i32 @test_no_spec_dominating_inst(
+entry:
+ %load = load i32, i32* %ptr
+ br i1 %flag, label %a, label %b
+; CHECK: %[[LOAD:.*]] = load i32, i32* %ptr
+; CHECK-NEXT: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %[[LOAD]], 7
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %[[LOAD]], 11
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %sum = add i32 %load, %p
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+; We have special logic handling PHI nodes, make sure it doesn't get confused
+; by a dominating PHI.
+define i32 @test_no_spec_dominating_phi(i1 %flag1, i1 %flag2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_no_spec_dominating_phi(
+entry:
+ br i1 %flag1, label %x.block, label %y.block
+; CHECK: entry:
+; CHECK-NEXT: br i1 %flag1, label %x.block, label %y.block
+
+x.block:
+ br label %merge
+; CHECK: x.block:
+; CHECK-NEXT: br label %merge
+
+y.block:
+ br label %merge
+; CHECK: y.block:
+; CHECK-NEXT: br label %merge
+
+merge:
+ %xy.phi = phi i32 [ %x, %x.block ], [ %y, %y.block ]
+ br i1 %flag2, label %a, label %b
+; CHECK: merge:
+; CHECK-NEXT: %[[XY_PHI:.*]] = phi i32 [ %x, %x.block ], [ %y, %y.block ]
+; CHECK-NEXT: br i1 %flag2, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %[[XY_PHI]], 7
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %[[XY_PHI]], 11
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %sum = add i32 %xy.phi, %p
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[SUM_PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT: ret i32 %[[SUM_PHI]]
+}
+
+; Ensure that we will speculate some number of "free" instructions on the given
+; architecture even though they are unrelated to the PHI itself.
+define i32 @test_speculate_free_insts(i1 %flag, i64 %arg) {
+; CHECK-LABEL: define i32 @test_speculate_free_insts(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[T1_A:.*]] = trunc i64 %arg to i48
+; CHECK-NEXT: %[[T2_A:.*]] = trunc i48 %[[T1_A]] to i32
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %[[T2_A]], 7
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[T1_B:.*]] = trunc i64 %arg to i48
+; CHECK-NEXT: %[[T2_B:.*]] = trunc i48 %[[T1_B]] to i32
+; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %[[T2_B]], 11
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %t1 = trunc i64 %arg to i48
+ %t2 = trunc i48 %t1 to i32
+ %sum = add i32 %t2, %p
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+define i32 @test_speculate_free_phis(i1 %flag, i32 %arg1, i32 %arg2) {
+; CHECK-LABEL: define i32 @test_speculate_free_phis(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg1, 7
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg2, 11
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p1 = phi i32 [ 7, %a ], [ 11, %b ]
+ %p2 = phi i32 [ %arg1, %a ], [ %arg2, %b ]
+ %sum = add i32 %p2, %p1
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; We don't DCE the now unused PHI node...
+; CHECK-NEXT: %{{.*}} = phi i32 [ %arg1, %a ], [ %arg2, %b ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+; We shouldn't speculate multiple uses even if each individually looks
+; profitable because of the total cost.
+define i32 @test_no_spec_multi_uses(i1 %flag, i32 %arg1, i32 %arg2, i32 %arg3) {
+; CHECK-LABEL: define i32 @test_no_spec_multi_uses(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %add1 = add i32 %arg1, %p
+ %add2 = add i32 %arg2, %p
+ %add3 = add i32 %arg3, %p
+ %sum1 = add i32 %add1, %add2
+ %sum2 = add i32 %sum1, %add3
+ ret i32 %sum2
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT: %[[ADD1:.*]] = add i32 %arg1, %[[PHI]]
+; CHECK-NEXT: %[[ADD2:.*]] = add i32 %arg2, %[[PHI]]
+; CHECK-NEXT: %[[ADD3:.*]] = add i32 %arg3, %[[PHI]]
+; CHECK-NEXT: %[[SUM1:.*]] = add i32 %[[ADD1]], %[[ADD2]]
+; CHECK-NEXT: %[[SUM2:.*]] = add i32 %[[SUM1]], %[[ADD3]]
+; CHECK-NEXT: ret i32 %[[SUM2]]
+}
+
+define i32 @test_multi_phis1(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_multi_phis1(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A1:.*]] = add i32 %arg, 1
+; CHECK-NEXT: %[[SUM_A2:.*]] = add i32 %[[SUM_A1]], 3
+; CHECK-NEXT: %[[SUM_A3:.*]] = add i32 %[[SUM_A2]], 5
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B1:.*]] = add i32 %arg, 2
+; CHECK-NEXT: %[[SUM_B2:.*]] = add i32 %[[SUM_B1]], 4
+; CHECK-NEXT: %[[SUM_B3:.*]] = add i32 %[[SUM_B2]], 6
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p1 = phi i32 [ 1, %a ], [ 2, %b ]
+ %p2 = phi i32 [ 3, %a ], [ 4, %b ]
+ %p3 = phi i32 [ 5, %a ], [ 6, %b ]
+ %sum1 = add i32 %arg, %p1
+ %sum2 = add i32 %sum1, %p2
+ %sum3 = add i32 %sum2, %p3
+ ret i32 %sum3
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A3]], %a ], [ %[[SUM_B3]], %b ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+; Check that the order of the PHIs doesn't impact the behavior.
+define i32 @test_multi_phis2(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_multi_phis2(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: br i1 %flag, label %a, label %b
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A1:.*]] = add i32 %arg, 1
+; CHECK-NEXT: %[[SUM_A2:.*]] = add i32 %[[SUM_A1]], 3
+; CHECK-NEXT: %[[SUM_A3:.*]] = add i32 %[[SUM_A2]], 5
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B1:.*]] = add i32 %arg, 2
+; CHECK-NEXT: %[[SUM_B2:.*]] = add i32 %[[SUM_B1]], 4
+; CHECK-NEXT: %[[SUM_B3:.*]] = add i32 %[[SUM_B2]], 6
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p3 = phi i32 [ 5, %a ], [ 6, %b ]
+ %p2 = phi i32 [ 3, %a ], [ 4, %b ]
+ %p1 = phi i32 [ 1, %a ], [ 2, %b ]
+ %sum1 = add i32 %arg, %p1
+ %sum2 = add i32 %sum1, %p2
+ %sum3 = add i32 %sum2, %p3
+ ret i32 %sum3
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A3]], %a ], [ %[[SUM_B3]], %b ]
+; CHECK-NEXT: ret i32 %[[PHI]]
+}
+
+define i32 @test_no_spec_indirectbr(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_no_spec_indirectbr(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: entry:
+; CHECK-NEXT: br i1 %flag, label %a, label %b
+
+a:
+ indirectbr i8* undef, [label %exit]
+; CHECK: a:
+; CHECK-NEXT: indirectbr i8* undef, [label %exit]
+
+b:
+ indirectbr i8* undef, [label %exit]
+; CHECK: b:
+; CHECK-NEXT: indirectbr i8* undef, [label %exit]
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %sum = add i32 %arg, %p
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT: %[[SUM:.*]] = add i32 %arg, %[[PHI]]
+; CHECK-NEXT: ret i32 %[[SUM]]
+}
+
+declare void @g()
+
+declare i32 @__gxx_personality_v0(...)
+
+; FIXME: We should be able to handle this case -- only the exceptional edge is
+; impossible to split.
+define i32 @test_no_spec_invoke_continue(i1 %flag, i32 %arg) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-LABEL: define i32 @test_no_spec_invoke_continue(
+entry:
+ br i1 %flag, label %a, label %b
+; CHECK: entry:
+; CHECK-NEXT: br i1 %flag, label %a, label %b
+
+a:
+ invoke void @g()
+ to label %exit unwind label %lpad
+; CHECK: a:
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT: to label %exit unwind label %lpad
+
+b:
+ invoke void @g()
+ to label %exit unwind label %lpad
+; CHECK: b:
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT: to label %exit unwind label %lpad
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %sum = add i32 %arg, %p
+ ret i32 %sum
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT: %[[SUM:.*]] = add i32 %arg, %[[PHI]]
+; CHECK-NEXT: ret i32 %[[SUM]]
+
+lpad:
+ %lp = landingpad { i8*, i32 }
+ cleanup
+ resume { i8*, i32 } undef
+}
+
+define i32 @test_no_spec_landingpad(i32 %arg, i32* %ptr) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-LABEL: define i32 @test_no_spec_landingpad(
+entry:
+ invoke void @g()
+ to label %invoke.cont unwind label %lpad
+; CHECK: entry:
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT: to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+ invoke void @g()
+ to label %exit unwind label %lpad
+; CHECK: invoke.cont:
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT: to label %exit unwind label %lpad
+
+lpad:
+ %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+ %lp = landingpad { i8*, i32 }
+ cleanup
+ %sum = add i32 %arg, %p
+ store i32 %sum, i32* %ptr
+ resume { i8*, i32 } undef
+; CHECK: lpad:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+
+exit:
+ ret i32 0
+}
+
+declare i32 @__CxxFrameHandler3(...)
+
+define i32 @test_no_spec_cleanuppad(i32 %arg, i32* %ptr) personality i32 (...)* @__CxxFrameHandler3 {
+; CHECK-LABEL: define i32 @test_no_spec_cleanuppad(
+entry:
+ invoke void @g()
+ to label %invoke.cont unwind label %lpad
+; CHECK: entry:
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT: to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+ invoke void @g()
+ to label %exit unwind label %lpad
+; CHECK: invoke.cont:
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT: to label %exit unwind label %lpad
+
+lpad:
+ %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+ %cp = cleanuppad within none []
+ %sum = add i32 %arg, %p
+ store i32 %sum, i32* %ptr
+ cleanupret from %cp unwind to caller
+; CHECK: lpad:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+
+exit:
+ ret i32 0
+}
+
+; Check that we don't fall over when confronted with seemingly reasonable code
+; for us to handle but in an unreachable region and with non-PHI use-def
+; cycles.
+define i32 @test_unreachable_non_phi_cycles(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_unreachable_non_phi_cycles(
+entry:
+ ret i32 42
+; CHECK: entry:
+; CHECK-NEXT: ret i32 42
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i32 [ 7, %a ], [ 11, %b ]
+ %zext = zext i32 %sum to i64
+ %trunc = trunc i64 %zext to i32
+ %sum = add i32 %trunc, %p
+ br i1 %flag, label %a, label %b
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT: %[[ZEXT:.*]] = zext i32 %[[SUM:.*]] to i64
+; CHECK-NEXT: %[[TRUNC:.*]] = trunc i64 %[[ZEXT]] to i32
+; CHECK-NEXT: %[[SUM]] = add i32 %[[TRUNC]], %[[PHI]]
+; CHECK-NEXT: br i1 %flag, label %a, label %b
+}
+
+; Check that we don't speculate in the face of an expensive immediate. There
+; are two reasons this should never speculate. First, even a local analysis
+; should fail because it makes some paths (%a) potentially more expensive due
+; to multiple uses of the immediate. Additionally, when we go to speculate the
+; instructions, their cost will also be too high.
+; FIXME: The goal is really to test the first property, but there doesn't
+; happen to be any way to use free-to-speculate instructions here so that it
+; would be the only interesting property.
+define i64 @test_expensive_imm(i32 %flag, i64 %arg) {
+; CHECK-LABEL: define i64 @test_expensive_imm(
+entry:
+ switch i32 %flag, label %a [
+ i32 1, label %b
+ i32 2, label %c
+ i32 3, label %d
+ ]
+; CHECK: switch i32 %flag, label %a [
+; CHECK-NEXT: i32 1, label %b
+; CHECK-NEXT: i32 2, label %c
+; CHECK-NEXT: i32 3, label %d
+; CHECK-NEXT: ]
+
+a:
+ br label %exit
+; CHECK: a:
+; CHECK-NEXT: br label %exit
+
+b:
+ br label %exit
+; CHECK: b:
+; CHECK-NEXT: br label %exit
+
+c:
+ br label %exit
+; CHECK: c:
+; CHECK-NEXT: br label %exit
+
+d:
+ br label %exit
+; CHECK: d:
+; CHECK-NEXT: br label %exit
+
+exit:
+ %p = phi i64 [ 4294967296, %a ], [ 1, %b ], [ 1, %c ], [ 1, %d ]
+ %sum1 = add i64 %arg, %p
+ %sum2 = add i64 %sum1, %p
+ ret i64 %sum2
+; CHECK: exit:
+; CHECK-NEXT: %[[PHI:.*]] = phi i64 [ {{[0-9]+}}, %a ], [ 1, %b ], [ 1, %c ], [ 1, %d ]
+; CHECK-NEXT: %[[SUM1:.*]] = add i64 %arg, %[[PHI]]
+; CHECK-NEXT: %[[SUM2:.*]] = add i64 %[[SUM1]], %[[PHI]]
+; CHECK-NEXT: ret i64 %[[SUM2]]
+}
+
+define i32 @test_no_spec_non_postdominating_uses(i1 %flag1, i1 %flag2, i32 %arg) {
+; CHECK-LABEL: define i32 @test_no_spec_non_postdominating_uses(
+entry:
+ br i1 %flag1, label %a, label %b
+; CHECK: br i1 %flag1, label %a, label %b
+
+a:
+ br label %merge
+; CHECK: a:
+; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 7
+; CHECK-NEXT: br label %merge
+
+b:
+ br label %merge
+; CHECK: b:
+; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg, 11
+; CHECK-NEXT: br label %merge
+
+merge:
+ %p1 = phi i32 [ 7, %a ], [ 11, %b ]
+ %p2 = phi i32 [ 13, %a ], [ 42, %b ]
+ %sum1 = add i32 %arg, %p1
+ br i1 %flag2, label %exit1, label %exit2
+; CHECK: merge:
+; CHECK-NEXT: %[[PHI1:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT: %[[PHI2:.*]] = phi i32 [ 13, %a ], [ 42, %b ]
+; CHECK-NEXT: br i1 %flag2, label %exit1, label %exit2
+
+exit1:
+ ret i32 %sum1
+; CHECK: exit1:
+; CHECK-NEXT: ret i32 %[[PHI1]]
+
+exit2:
+ %sum2 = add i32 %arg, %p2
+ ret i32 %sum2
+; CHECK: exit2:
+; CHECK-NEXT: %[[SUM2:.*]] = add i32 %arg, %[[PHI2]]
+; CHECK-NEXT: ret i32 %[[SUM2]]
+}
OpenPOWER on IntegriCloud