llvm.org GIT mirror llvm / d3d0477
[AVR] Insert unconditional branch when inserting MBBs between blocks with fallthrough This updates the AVR Select8/Select16 expansion code so that, when inserting the two basic blocks for true and false conditions, any existing fallthrough on the previous block is preserved. Prior to this patch, if the block before the Select pseudo fell through to the subsequent block, two new basic blocks would be inserted at the prior fallthrough point, changing the fallthrough destination. The predecessor or successor lists were not updated, causing the BranchFolding pass at -O1 and above the rearrange basic blocks, causing an infinite loop. Not to mention the unconditional fallthrough to the true block is incorrect in of itself. This patch modifies the Select8/16 expansion so that, if inserting true and false basic blocks at a fallthrough point, the implicit branch is preserved by means of an explicit, unconditional branch to the previous fallthrough destination. Thanks to Carl Peto for reporting this bug. This fixes avr-rust bug https://github.com/avr-rust/rust/issues/123. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351721 91177308-0d34-0410-b5e6-96231b3b80d8 Dylan McKay 1 year, 10 months ago
2 changed file(s) with 83 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
16331633
16341634 MachineFunction *MF = MBB->getParent();
16351635 const BasicBlock *LLVM_BB = MBB->getBasicBlock();
1636 MachineBasicBlock *FallThrough = MBB->getFallThrough();
1637
1638 // If the current basic block falls through to another basic block,
1639 // we must insert an unconditional branch to the fallthrough destination
1640 // if we are to insert basic blocks at the prior fallthrough point.
1641 if (FallThrough != nullptr) {
1642 BuildMI(MBB, dl, TII.get(AVR::RJMPk)).addMBB(FallThrough);
1643 }
1644
16361645 MachineBasicBlock *trueMBB = MF->CreateMachineBasicBlock(LLVM_BB);
16371646 MachineBasicBlock *falseMBB = MF->CreateMachineBasicBlock(LLVM_BB);
16381647
0 ; RUN: llc -O1 < %s -march=avr | FileCheck %s
1
2 ; This test ensures that the Select8/Select16 expansion
3 ; pass inserts an unconditional branch to the previous adjacent
4 ; basic block when inserting new basic blocks when the
5 ; prior block has a fallthrough.
6 ;
7 ; Before this bug was fixed, Select8/Select16 expansion
8 ; would leave a dangling fallthrough to an undefined block.
9 ;
10 ; The BranchFolding pass would later rearrange the basic
11 ; blocks based on predecessor/successor list assumptions
12 ; which were made incorrect due to the invalid Select
13 ; expansion.
14
15 ; More information in
16 ; https://github.com/avr-rust/rust/issues/123.
17
18 %UInt8 = type <{ i8 }>
19 %UInt32 = type <{ i32 }>
20 %Sb = type <{ i1 }>
21
22 @delayFactor = hidden global %UInt8 zeroinitializer, align 1
23 @delay = hidden global %UInt32 zeroinitializer, align 4
24 @flag = hidden global %Sb zeroinitializer, align 1
25
26 declare void @eeprom_write(i16, i8)
27
28 ; CHECK-LABEL: update_register
29 define hidden void @update_register(i8 %arg, i8 %arg1) {
30 entry:
31 ; CHECK: push [[PRELUDER:r[0-9]+]]
32 ; CHECK: cpi r24, 7
33 switch i8 %arg, label %bb7 [
34 i8 6, label %bb
35 i8 7, label %bb6
36 ]
37
38 ; CHECK-NOT: ret
39 bb: ; preds = %entry
40 %tmp = icmp ugt i8 %arg1, 90
41 %tmp2 = icmp ult i8 %arg1, 5
42 %. = select i1 %tmp2, i8 5, i8 %arg1
43 %tmp3 = select i1 %tmp, i8 90, i8 %.
44 ; CHECK: sts delayFactor, r{{[0-9]+}}
45 store i8 %tmp3, i8* getelementptr inbounds (%UInt8, %UInt8* @delayFactor, i64 0, i32 0), align 1
46 %tmp4 = zext i8 %tmp3 to i32
47 %tmp5 = mul nuw nsw i32 %tmp4, 100
48 ; CHECK: sts delay+3, r{{[0-9]+}}
49 ; CHECK-NEXT: sts delay+2, r{{[0-9]+}}
50 ; CHECK-NEXT: sts delay+1, r{{[0-9]+}}
51 ; CHECK-NEXT: sts delay, r{{[0-9]+}}
52 store i32 %tmp5, i32* getelementptr inbounds (%UInt32, %UInt32* @delay, i64 0, i32 0), align 4
53 tail call void @eeprom_write(i16 34, i8 %tmp3)
54 br label %bb7
55
56 bb6: ; preds = %entry
57 %not. = icmp ne i8 %arg1, 0
58 %.2 = zext i1 %not. to i8
59 store i1 %not., i1* getelementptr inbounds (%Sb, %Sb* @flag, i64 0, i32 0), align 1
60
61 ; CHECK: call eeprom_write
62 tail call void @eeprom_write(i16 35, i8 %.2)
63 br label %bb7
64
65 ; CHECK: LBB0_{{[0-9]+}}
66 ; CHECK: pop [[PRELUDER]]
67 ; CHECK-NEXT: ret
68 bb7: ; preds = %bb6, %bb, %entry
69 ret void
70 }
71 ; CHECK-NOT: LBB0_{{[0-9]+}}:
72 ; CHECK-LABEL: .Lfunc_end0
73 ; CHECK: .size update_register, .Lfunc_end0-update_register