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-LABEL: 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 17 define void @simple() nounwind { 18 entry: 19 br label %loop 20 21 loop: 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 27 bb: 28 call void @loop_latch() 29 br label %loop 30 31 done: 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-LABEL: 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 47 define void @slightly_more_involved() nounwind { 48 entry: 49 br label %loop 50 51 loop: 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 57 bb: 58 %t2 = call i32 @get() 59 %t3 = icmp slt i32 %t2, 99 60 br i1 %t3, label %exit, label %loop 61 62 block_a: 63 call void @bar99() 64 br label %loop 65 66 exit: 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-LABEL: yet_more_involved: 76 ; CHECK: jmp .LBB2_1 77 ; CHECK-NEXT: align 78 ; CHECK-NEXT: .LBB2_5: 79 ; CHECK-NEXT: callq block_a_true_func 80 ; CHECK-NEXT: callq block_a_merge_func 81 ; CHECK-NEXT: .LBB2_1: 82 ; CHECK-NEXT: callq body 83 ; 84 ; LBB2_4 85 ; CHECK: callq bar99 86 ; CHECK-NEXT: callq get 87 ; CHECK-NEXT: cmpl $2999, %eax 88 ; CHECK-NEXT: jle .LBB2_5 89 ; CHECK-NEXT: callq block_a_false_func 90 ; CHECK-NEXT: callq block_a_merge_func 91 ; CHECK-NEXT: jmp .LBB2_1 92 93 define void @yet_more_involved() nounwind { 94 entry: 95 br label %loop 96 97 loop: 98 call void @body() 99 %t0 = call i32 @get() 100 %t1 = icmp slt i32 %t0, 2 101 br i1 %t1, label %block_a, label %bb 102 103 bb: 104 %t2 = call i32 @get() 105 %t3 = icmp slt i32 %t2, 99 106 br i1 %t3, label %exit, label %loop 107 108 block_a: 109 call void @bar99() 110 %z0 = call i32 @get() 111 %z1 = icmp slt i32 %z0, 3000 112 br i1 %z1, label %block_a_true, label %block_a_false 113 114 block_a_true: 115 call void @block_a_true_func() 116 br label %block_a_merge 117 118 block_a_false: 119 call void @block_a_false_func() 120 br label %block_a_merge 121 122 block_a_merge: 123 call void @block_a_merge_func() 124 br label %loop 125 126 exit: 127 call void @exit() 128 ret void 129 } 130 131 ; CodeGen should move the CFG islands that are part of the loop but don't 132 ; conveniently fit anywhere so that they are at least contiguous with the 133 ; loop. 134 135 ; CHECK-LABEL: cfg_islands: 136 ; CHECK: jmp .LBB3_1 137 ; CHECK-NEXT: align 138 ; CHECK-NEXT: .LBB3_7: 139 ; CHECK-NEXT: callq bar100 140 ; CHECK-NEXT: .LBB3_1: 141 ; CHECK-NEXT: callq loop_header 142 ; CHECK: jl .LBB3_7 143 ; CHECK: jge .LBB3_3 144 ; CHECK-NEXT: callq bar101 145 ; CHECK-NEXT: jmp .LBB3_1 146 ; CHECK-NEXT: align 147 ; CHECK-NEXT: .LBB3_3: 148 ; CHECK: jge .LBB3_4 149 ; CHECK-NEXT: callq bar102 150 ; CHECK-NEXT: jmp .LBB3_1 151 ; CHECK-NEXT: .LBB3_4: 152 ; CHECK: jl .LBB3_6 153 ; CHECK-NEXT: callq loop_latch 154 ; CHECK-NEXT: jmp .LBB3_1 155 ; CHECK-NEXT: .LBB3_6: 156 157 define void @cfg_islands() nounwind { 158 entry: 159 br label %loop 160 161 loop: 162 call void @loop_header() 163 %t0 = call i32 @get() 164 %t1 = icmp slt i32 %t0, 100 165 br i1 %t1, label %block100, label %bb 166 167 bb: 168 %t2 = call i32 @get() 169 %t3 = icmp slt i32 %t2, 101 170 br i1 %t3, label %block101, label %bb1 171 172 bb1: 173 %t4 = call i32 @get() 174 %t5 = icmp slt i32 %t4, 102 175 br i1 %t5, label %block102, label %bb2 176 177 bb2: 178 %t6 = call i32 @get() 179 %t7 = icmp slt i32 %t6, 103 180 br i1 %t7, label %exit, label %bb3 181 182 bb3: 183 call void @loop_latch() 184 br label %loop 185 186 exit: 187 call void @exit() 188 ret void 189 190 block100: 191 call void @bar100() 192 br label %loop 193 194 block101: 195 call void @bar101() 196 br label %loop 197 198 block102: 199 call void @bar102() 200 br label %loop 201 } 202 203 declare void @bar99() nounwind 204 declare void @bar100() nounwind 205 declare void @bar101() nounwind 206 declare void @bar102() nounwind 207 declare void @body() nounwind 208 declare void @exit() nounwind 209 declare void @loop_header() nounwind 210 declare void @loop_latch() nounwind 211 declare i32 @get() nounwind 212 declare void @block_a_true_func() nounwind 213 declare void @block_a_false_func() nounwind 214 declare void @block_a_merge_func() nounwind 215