diff options
Diffstat (limited to 'test/Transforms/SimplifyCFG/indirectbr.ll')
-rw-r--r-- | test/Transforms/SimplifyCFG/indirectbr.ll | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/test/Transforms/SimplifyCFG/indirectbr.ll b/test/Transforms/SimplifyCFG/indirectbr.ll index de4f5b6..7fb4def 100644 --- a/test/Transforms/SimplifyCFG/indirectbr.ll +++ b/test/Transforms/SimplifyCFG/indirectbr.ll @@ -62,3 +62,121 @@ entry: BB0: ret void } + + +; Make sure the blocks in the next few tests aren't trivially removable as +; successors by taking their addresses. + +@anchor = constant [13 x i8*] [ + i8* blockaddress(@indbrtest3, %L1), i8* blockaddress(@indbrtest3, %L2), i8* blockaddress(@indbrtest3, %L3), + i8* blockaddress(@indbrtest4, %L1), i8* blockaddress(@indbrtest4, %L2), i8* blockaddress(@indbrtest4, %L3), + i8* blockaddress(@indbrtest5, %L1), i8* blockaddress(@indbrtest5, %L2), i8* blockaddress(@indbrtest5, %L3), i8* blockaddress(@indbrtest5, %L4), + i8* blockaddress(@indbrtest6, %L1), i8* blockaddress(@indbrtest6, %L2), i8* blockaddress(@indbrtest6, %L3) +] + +; SimplifyCFG should turn the indirectbr into a conditional branch on the +; condition of the select. + +; CHECK: @indbrtest3 +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 %cond, label %L1, label %L2 +; CHECK-NOT: indirectbr +; CHECK-NOT: br +; CHECK-NOT: L3: +define void @indbrtest3(i1 %cond, i8* %address) nounwind { +entry: + %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest3, %L1), i8* blockaddress(@indbrtest3, %L2) + indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3] + +L1: + call void @A() + ret void +L2: + call void @C() + ret void +L3: + call void @foo() + ret void +} + +; SimplifyCFG should turn the indirectbr into an unconditional branch to the +; only possible destination. +; As in @indbrtest1, it should really remove the branch entirely, but it doesn't +; because it's in the entry block. + +; CHECK: @indbrtest4 +; CHECK-NEXT: entry: +; CHECK-NEXT: br label %L1 +define void @indbrtest4(i1 %cond) nounwind { +entry: + %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest4, %L1), i8* blockaddress(@indbrtest4, %L1) + indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3] + +L1: + call void @A() + ret void +L2: + call void @C() + ret void +L3: + call void @foo() + ret void +} + +; SimplifyCFG should turn the indirectbr into an unreachable because neither +; destination is listed as a successor. + +; CHECK: @indbrtest5 +; CHECK-NEXT: entry: +; CHECK-NEXT: unreachable +; CHECK-NEXT: } +define void @indbrtest5(i1 %cond, i8* %anchor) nounwind { +entry: + %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest5, %L1), i8* blockaddress(@indbrtest5, %L2) +; This needs to have more than one successor for this test, otherwise it gets +; replaced with an unconditional branch to the single successor. + indirectbr i8* %indirect.goto.dest, [label %L3, label %L4] + +L1: + call void @A() + ret void +L2: + call void @C() + ret void +L3: + call void @foo() + ret void +L4: + call void @foo() + +; This keeps blockaddresses not otherwise listed as successors from being zapped +; before SimplifyCFG even looks at the indirectbr. + indirectbr i8* %anchor, [label %L1, label %L2] +} + +; The same as above, except the selected addresses are equal. + +; CHECK: @indbrtest6 +; CHECK-NEXT: entry: +; CHECK-NEXT: unreachable +; CHECK-NEXT: } +define void @indbrtest6(i1 %cond, i8* %anchor) nounwind { +entry: + %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest6, %L1), i8* blockaddress(@indbrtest6, %L1) +; This needs to have more than one successor for this test, otherwise it gets +; replaced with an unconditional branch to the single successor. + indirectbr i8* %indirect.goto.dest, [label %L2, label %L3] + +L1: + call void @A() + ret void +L2: + call void @C() + ret void +L3: + call void @foo() + +; This keeps blockaddresses not otherwise listed as successors from being zapped +; before SimplifyCFG even looks at the indirectbr. + indirectbr i8* %anchor, [label %L1, label %L2] +} |