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 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: 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: 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 92 define void @yet_more_involved() nounwind { 93 entry: 94 br label %loop 95 96 loop: 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 102 bb: 103 %t2 = call i32 @get() 104 %t3 = icmp slt i32 %t2, 99 105 br i1 %t3, label %exit, label %loop 106 107 block_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 113 block_a_true: 114 call void @block_a_true_func() 115 br label %block_a_merge 116 117 block_a_false: 118 call void @block_a_false_func() 119 br label %block_a_merge 120 121 block_a_merge: 122 call void @block_a_merge_func() 123 br label %loop 124 125 exit: 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 151 define void @cfg_islands() nounwind { 152 entry: 153 br label %loop 154 155 loop: 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 161 bb: 162 %t2 = call i32 @get() 163 %t3 = icmp slt i32 %t2, 101 164 br i1 %t3, label %block101, label %bb1 165 166 bb1: 167 %t4 = call i32 @get() 168 %t5 = icmp slt i32 %t4, 102 169 br i1 %t5, label %block102, label %bb2 170 171 bb2: 172 %t6 = call i32 @get() 173 %t7 = icmp slt i32 %t6, 103 174 br i1 %t7, label %exit, label %bb3 175 176 bb3: 177 call void @loop_latch() 178 br label %loop 179 180 exit: 181 call void @exit() 182 ret void 183 184 block100: 185 call void @bar100() 186 br label %loop 187 188 block101: 189 call void @bar101() 190 br label %loop 191 192 block102: 193 call void @bar102() 194 br label %loop 195 } 196 197 declare void @bar99() nounwind 198 declare void @bar100() nounwind 199 declare void @bar101() nounwind 200 declare void @bar102() nounwind 201 declare void @body() nounwind 202 declare void @exit() nounwind 203 declare void @loop_header() nounwind 204 declare void @loop_latch() nounwind 205 declare i32 @get() nounwind 206 declare void @block_a_true_func() nounwind 207 declare void @block_a_false_func() nounwind 208 declare void @block_a_merge_func() nounwind 209