1; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -asm-verbose=false | FileCheck %s 2 3; These tests check for loop branching structure, and that the loop align 4; directive is placed in the expected place. 5 6; CodeGen should insert a branch into the middle of the loop in 7; order to avoid a branch within the loop. 8 9; CHECK: simple: 10; CHECK: jmp .LBB0_1 11; CHECK-NEXT: align 12; CHECK-NEXT: .LBB0_2: 13; CHECK-NEXT: callq loop_latch 14; CHECK-NEXT: .LBB0_1: 15; CHECK-NEXT: callq loop_header 16 17define void @simple() nounwind { 18entry: 19 br label %loop 20 21loop: 22 call void @loop_header() 23 %t0 = tail call i32 @get() 24 %t1 = icmp slt i32 %t0, 0 25 br i1 %t1, label %done, label %bb 26 27bb: 28 call void @loop_latch() 29 br label %loop 30 31done: 32 call void @exit() 33 ret void 34} 35 36; CodeGen should move block_a to the top of the loop so that it 37; falls through into the loop, avoiding a branch within the loop. 38 39; CHECK: slightly_more_involved: 40; CHECK: jmp .LBB1_1 41; CHECK-NEXT: align 42; CHECK-NEXT: .LBB1_4: 43; CHECK-NEXT: callq bar99 44; CHECK-NEXT: .LBB1_1: 45; CHECK-NEXT: callq body 46 47define void @slightly_more_involved() nounwind { 48entry: 49 br label %loop 50 51loop: 52 call void @body() 53 %t0 = call i32 @get() 54 %t1 = icmp slt i32 %t0, 2 55 br i1 %t1, label %block_a, label %bb 56 57bb: 58 %t2 = call i32 @get() 59 %t3 = icmp slt i32 %t2, 99 60 br i1 %t3, label %exit, label %loop 61 62block_a: 63 call void @bar99() 64 br label %loop 65 66exit: 67 call void @exit() 68 ret void 69} 70 71; Same as slightly_more_involved, but block_a is now a CFG diamond with 72; fallthrough edges which should be preserved. 73; "callq block_a_merge_func" is tail duped. 74 75; CHECK: yet_more_involved: 76; CHECK: jmp .LBB2_1 77; CHECK-NEXT: align 78; CHECK-NEXT: .LBB2_4: 79; CHECK-NEXT: callq bar99 80; CHECK-NEXT: callq get 81; CHECK-NEXT: cmpl $2999, %eax 82; CHECK-NEXT: jle .LBB2_5 83; CHECK-NEXT: callq block_a_false_func 84; CHECK-NEXT: callq block_a_merge_func 85; CHECK-NEXT: jmp .LBB2_1 86; CHECK-NEXT: .LBB2_5: 87; CHECK-NEXT: callq block_a_true_func 88; CHECK-NEXT: callq block_a_merge_func 89; CHECK-NEXT: .LBB2_1: 90; CHECK-NEXT: callq body 91 92define void @yet_more_involved() nounwind { 93entry: 94 br label %loop 95 96loop: 97 call void @body() 98 %t0 = call i32 @get() 99 %t1 = icmp slt i32 %t0, 2 100 br i1 %t1, label %block_a, label %bb 101 102bb: 103 %t2 = call i32 @get() 104 %t3 = icmp slt i32 %t2, 99 105 br i1 %t3, label %exit, label %loop 106 107block_a: 108 call void @bar99() 109 %z0 = call i32 @get() 110 %z1 = icmp slt i32 %z0, 3000 111 br i1 %z1, label %block_a_true, label %block_a_false 112 113block_a_true: 114 call void @block_a_true_func() 115 br label %block_a_merge 116 117block_a_false: 118 call void @block_a_false_func() 119 br label %block_a_merge 120 121block_a_merge: 122 call void @block_a_merge_func() 123 br label %loop 124 125exit: 126 call void @exit() 127 ret void 128} 129 130; CodeGen should move the CFG islands that are part of the loop but don't 131; conveniently fit anywhere so that they are at least contiguous with the 132; loop. 133 134; CHECK: cfg_islands: 135; CHECK: jmp .LBB3_1 136; CHECK-NEXT: align 137; CHECK-NEXT: .LBB3_7: 138; CHECK-NEXT: callq bar100 139; CHECK-NEXT: jmp .LBB3_1 140; CHECK-NEXT: .LBB3_8: 141; CHECK-NEXT: callq bar101 142; CHECK-NEXT: jmp .LBB3_1 143; CHECK-NEXT: .LBB3_9: 144; CHECK-NEXT: callq bar102 145; CHECK-NEXT: jmp .LBB3_1 146; CHECK-NEXT: .LBB3_5: 147; CHECK-NEXT: callq loop_latch 148; CHECK-NEXT: .LBB3_1: 149; CHECK-NEXT: callq loop_header 150 151define void @cfg_islands() nounwind { 152entry: 153 br label %loop 154 155loop: 156 call void @loop_header() 157 %t0 = call i32 @get() 158 %t1 = icmp slt i32 %t0, 100 159 br i1 %t1, label %block100, label %bb 160 161bb: 162 %t2 = call i32 @get() 163 %t3 = icmp slt i32 %t2, 101 164 br i1 %t3, label %block101, label %bb1 165 166bb1: 167 %t4 = call i32 @get() 168 %t5 = icmp slt i32 %t4, 102 169 br i1 %t5, label %block102, label %bb2 170 171bb2: 172 %t6 = call i32 @get() 173 %t7 = icmp slt i32 %t6, 103 174 br i1 %t7, label %exit, label %bb3 175 176bb3: 177 call void @loop_latch() 178 br label %loop 179 180exit: 181 call void @exit() 182 ret void 183 184block100: 185 call void @bar100() 186 br label %loop 187 188block101: 189 call void @bar101() 190 br label %loop 191 192block102: 193 call void @bar102() 194 br label %loop 195} 196 197declare void @bar99() nounwind 198declare void @bar100() nounwind 199declare void @bar101() nounwind 200declare void @bar102() nounwind 201declare void @body() nounwind 202declare void @exit() nounwind 203declare void @loop_header() nounwind 204declare void @loop_latch() nounwind 205declare i32 @get() nounwind 206declare void @block_a_true_func() nounwind 207declare void @block_a_false_func() nounwind 208declare void @block_a_merge_func() nounwind 209