# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=thumbv7-apple-ios -run-pass=if-converter %s -o - | FileCheck %s # Testcase with unanalyzable branches (that may fallthrough) in the BB # following the diamond/triangle. # Goal here is to showcase a problem seen in the IfConverter when # AnalyzeBranch is indicating that the branches couldn't be analyzed. Problem # was originally seen for an out-of-tree target, and here we use ARM and a # MBB with two conditional jumps to make AnalyzeBranch return false. # # The problem was that if-converter when analyzing branches was using a # variable named HasFallThrough, to remember that an MBB could fallthrough to # the textual successor. When HasFallThrough is set we know that there are # fallthrough exits, but the opposite is not guaranteed. If # HasFallThrough==false there could still be fallthrough exists in situations # when analyzeBranch found unanalyzable branches. There were however a couple # of places in the code that checked !HasFallThrough assuming that it would # imply that there was no fallthrough exit. # # As a consequence we could end up merging blocks at the end of a converted # diamond/triangle and while doing that we messed up when fixing up the CFG # related to fallthrough edges. For the test cases below we incorrectly ended # up with a fallthrough from the MBBs with two Bcc instructions to the MBB # with the STRH after if conversion. # --- name: avoidMergeBlockDiamond body: | ; CHECK-LABEL: name: avoidMergeBlockDiamond ; CHECK: bb.0: ; CHECK-NEXT: successors: %bb.1(0x80000000) ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: $sp = tADDspi $sp, 2, 1 /* CC::ne */, $cpsr ; CHECK-NEXT: $sp = tADDspi $sp, 1, 0 /* CC::eq */, $cpsr, implicit $sp ; CHECK-NEXT: $sp = tADDspi $sp, 3, 14 /* CC::al */, $noreg ; CHECK-NEXT: tBcc %bb.1, 1 /* CC::ne */, $cpsr ; CHECK-NEXT: tBcc %bb.1, 1 /* CC::ne */, $cpsr ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.1: ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: successors: %bb.2(0x80000000) ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: STRH $sp, $sp, $noreg, 0, 14 /* CC::al */, $noreg ; CHECK-NEXT: tB %bb.2, 14 /* CC::al */, $noreg bb.0: tBcc %bb.2, 1, $cpsr bb.1: $sp = tADDspi $sp, 1, 14, _ tB %bb.4, 14, $noreg bb.2: $sp = tADDspi $sp, 2, 14, _ tB %bb.4, 14, $noreg bb.3: STRH $sp, $sp, $noreg, 0, 14, $noreg tB %bb.3, 14, $noreg bb.4: $sp = tADDspi $sp, 3, 14, _ tBcc %bb.5, 1, $cpsr tBcc %bb.5, 1, $cpsr bb.5: successors: tBX_RET 14, _ ... # Similar to the above, but with a triangle. --- name: avoidMergeBlockTriangle body: | ; CHECK-LABEL: name: avoidMergeBlockTriangle ; CHECK: bb.0: ; CHECK-NEXT: successors: %bb.1(0x80000000) ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: $sp = tADDspi $sp, 1, 1 /* CC::ne */, $cpsr ; CHECK-NEXT: $sp = tADDspi $sp, 2, 14 /* CC::al */, $noreg ; CHECK-NEXT: tBcc %bb.1, 1 /* CC::ne */, $cpsr ; CHECK-NEXT: tBcc %bb.1, 1 /* CC::ne */, $cpsr ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.1: ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: successors: %bb.2(0x80000000) ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: STRH $sp, $sp, $noreg, 0, 14 /* CC::al */, $noreg ; CHECK-NEXT: tB %bb.2, 14 /* CC::al */, $noreg bb.0: tBcc %bb.1, 1, $cpsr tB %bb.3, 14, $noreg bb.1: $sp = tADDspi $sp, 1, 14, _ tB %bb.3, 14, $noreg bb.2: STRH $sp, $sp, $noreg, 0, 14, $noreg tB %bb.2, 14, $noreg bb.3: $sp = tADDspi $sp, 2, 14, _ tBcc %bb.4, 1, $cpsr tBcc %bb.4, 1, $cpsr bb.4: successors: tBX_RET 14, _ ...