330 lines · plain
1; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -asm-verbose=false | FileCheck %s2 3; These tests check for loop branching structure, and that the loop align4; directive is placed in the expected place.5 6; CodeGen should insert a branch into the middle of the loop in7; order to avoid a branch within the loop.8 9; CHECK-LABEL: simple:10; CHECK: align11; CHECK-NEXT: .LBB0_1:12; CHECK-NEXT: callq loop_header13; CHECK: js .LBB0_314; CHECK-NEXT: callq loop_latch15; CHECK-NEXT: jmp .LBB0_116; CHECK-NEXT: .LBB0_3:17; CHECK-NEXT: callq exit18 19define void @simple() nounwind {20entry:21 br label %loop22 23loop:24 call void @loop_header()25 %t0 = tail call i32 @get()26 %t1 = icmp slt i32 %t0, 027 br i1 %t1, label %done, label %bb28 29bb:30 call void @loop_latch()31 br label %loop32 33done:34 call void @exit()35 ret void36}37 38; CodeGen should move block_a to the top of the loop so that it39; falls through into the loop, avoiding a branch within the loop.40 41; CHECK-LABEL: slightly_more_involved:42; CHECK: jmp .LBB1_143; CHECK-NEXT: align44; CHECK-NEXT: .LBB1_4:45; CHECK-NEXT: callq bar9946; CHECK-NEXT: .LBB1_1:47; CHECK-NEXT: callq body48 49define void @slightly_more_involved() nounwind {50entry:51 br label %loop52 53loop:54 call void @body()55 %t0 = call i32 @get()56 %t1 = icmp slt i32 %t0, 257 br i1 %t1, label %block_a, label %bb58 59bb:60 %t2 = call i32 @get()61 %t3 = icmp slt i32 %t2, 9962 br i1 %t3, label %exit, label %loop63 64block_a:65 call void @bar99()66 br label %loop67 68exit:69 call void @exit()70 ret void71}72 73; Same as slightly_more_involved, but block_a is now a CFG diamond with74; fallthrough edges which should be preserved.75; "callq block_a_merge_func" is tail duped.76 77; CHECK-LABEL: yet_more_involved:78; CHECK: jmp .LBB2_179; CHECK-NEXT: align80 81; CHECK: .LBB2_1:82; CHECK-NEXT: callq body83; CHECK-NEXT: callq get84; CHECK-NEXT: cmpl $2, %eax85; CHECK-NEXT: jge .LBB2_286; CHECK-NEXT: callq bar9987; CHECK-NEXT: callq get88; CHECK-NEXT: cmpl $2999, %eax89; CHECK-NEXT: jg .LBB2_690; CHECK-NEXT: callq block_a_true_func91; CHECK-NEXT: callq block_a_merge_func92; CHECK-NEXT: jmp .LBB2_193; CHECK-NEXT: align94; CHECK-NEXT: .LBB2_6:95; CHECK-NEXT: callq block_a_false_func96; CHECK-NEXT: callq block_a_merge_func97; CHECK-NEXT: jmp .LBB2_198 99define void @yet_more_involved() nounwind {100entry:101 br label %loop102 103loop:104 call void @body()105 %t0 = call i32 @get()106 %t1 = icmp slt i32 %t0, 2107 br i1 %t1, label %block_a, label %bb108 109bb:110 %t2 = call i32 @get()111 %t3 = icmp slt i32 %t2, 99112 br i1 %t3, label %exit, label %loop113 114block_a:115 call void @bar99()116 %z0 = call i32 @get()117 %z1 = icmp slt i32 %z0, 3000118 br i1 %z1, label %block_a_true, label %block_a_false119 120block_a_true:121 call void @block_a_true_func()122 br label %block_a_merge123 124block_a_false:125 call void @block_a_false_func()126 br label %block_a_merge127 128block_a_merge:129 call void @block_a_merge_func()130 br label %loop131 132exit:133 call void @exit()134 ret void135}136 137; CodeGen should move the CFG islands that are part of the loop but don't138; conveniently fit anywhere so that they are at least contiguous with the139; loop.140 141; CHECK-LABEL: cfg_islands:142; CHECK: jmp .LBB3_1143; CHECK-NEXT: align144; CHECK-NEXT: .LBB3_7:145; CHECK-NEXT: callq bar100146; CHECK-NEXT: .LBB3_1:147; CHECK-NEXT: callq loop_header148; CHECK: jl .LBB3_7149; CHECK: jge .LBB3_3150; CHECK-NEXT: callq bar101151; CHECK-NEXT: jmp .LBB3_1152; CHECK-NEXT: align153; CHECK-NEXT: .LBB3_3:154; CHECK: jge .LBB3_4155; CHECK-NEXT: callq bar102156; CHECK-NEXT: jmp .LBB3_1157; CHECK-NEXT: .LBB3_4:158; CHECK: jl .LBB3_6159; CHECK-NEXT: callq loop_latch160; CHECK-NEXT: jmp .LBB3_1161; CHECK-NEXT: .LBB3_6:162 163define void @cfg_islands() nounwind {164entry:165 br label %loop166 167loop:168 call void @loop_header()169 %t0 = call i32 @get()170 %t1 = icmp slt i32 %t0, 100171 br i1 %t1, label %block100, label %bb172 173bb:174 %t2 = call i32 @get()175 %t3 = icmp slt i32 %t2, 101176 br i1 %t3, label %block101, label %bb1177 178bb1:179 %t4 = call i32 @get()180 %t5 = icmp slt i32 %t4, 102181 br i1 %t5, label %block102, label %bb2182 183bb2:184 %t6 = call i32 @get()185 %t7 = icmp slt i32 %t6, 103186 br i1 %t7, label %exit, label %bb3187 188bb3:189 call void @loop_latch()190 br label %loop191 192exit:193 call void @exit()194 ret void195 196block100:197 call void @bar100()198 br label %loop199 200block101:201 call void @bar101()202 br label %loop203 204block102:205 call void @bar102()206 br label %loop207}208 209; CHECK-LABEL: check_minsize:210; CHECK-NOT: align211; CHECK: .LBB4_1:212; CHECK-NEXT: callq loop_header213; CHECK: callq loop_latch214; CHECK: .LBB4_3:215; CHECK: callq exit216 217 218define void @check_minsize() minsize nounwind {219entry:220 br label %loop221 222loop:223 call void @loop_header()224 %t0 = tail call i32 @get()225 %t1 = icmp slt i32 %t0, 0226 br i1 %t1, label %done, label %bb227 228bb:229 call void @loop_latch()230 br label %loop231 232done:233 call void @exit()234 ret void235}236 237; This is exactly the same function as slightly_more_involved.238; The difference is that when optimising for size, we do not want239; to see this reordering.240 241; CHECK-LABEL: slightly_more_involved_2:242; CHECK-NOT: jmp .LBB5_1243; CHECK: .LBB5_1:244; CHECK-NEXT: callq body245 246define void @slightly_more_involved_2() #0 {247entry:248 br label %loop249 250loop:251 call void @body()252 %t0 = call i32 @get()253 %t1 = icmp slt i32 %t0, 2254 br i1 %t1, label %block_a, label %bb255 256bb:257 %t2 = call i32 @get()258 %t3 = icmp slt i32 %t2, 99259 br i1 %t3, label %exit, label %loop260 261block_a:262 call void @bar99()263 br label %loop264 265exit:266 call void @exit()267 ret void268}269 270attributes #0 = { minsize norecurse nounwind optsize readnone uwtable }271 272; CHECK-LABEL: slightly_more_involved_2_pgso:273; CHECK-NOT: jmp .LBB6_1274; CHECK: .LBB6_1:275; CHECK-NEXT: callq body276 277define void @slightly_more_involved_2_pgso() norecurse nounwind readnone uwtable !prof !14 {278entry:279 br label %loop280 281loop:282 call void @body()283 %t0 = call i32 @get()284 %t1 = icmp slt i32 %t0, 2285 br i1 %t1, label %block_a, label %bb286 287bb:288 %t2 = call i32 @get()289 %t3 = icmp slt i32 %t2, 99290 br i1 %t3, label %exit, label %loop291 292block_a:293 call void @bar99()294 br label %loop295 296exit:297 call void @exit()298 ret void299}300 301declare void @bar99() nounwind302declare void @bar100() nounwind303declare void @bar101() nounwind304declare void @bar102() nounwind305declare void @body() nounwind306declare void @exit() nounwind307declare void @loop_header() nounwind308declare void @loop_latch() nounwind309declare i32 @get() nounwind310declare void @block_a_true_func() nounwind311declare void @block_a_false_func() nounwind312declare void @block_a_merge_func() nounwind313 314!llvm.module.flags = !{!0}315!0 = !{i32 1, !"ProfileSummary", !1}316!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}317!2 = !{!"ProfileFormat", !"InstrProf"}318!3 = !{!"TotalCount", i64 10000}319!4 = !{!"MaxCount", i64 10}320!5 = !{!"MaxInternalCount", i64 1}321!6 = !{!"MaxFunctionCount", i64 1000}322!7 = !{!"NumCounts", i64 3}323!8 = !{!"NumFunctions", i64 3}324!9 = !{!"DetailedSummary", !10}325!10 = !{!11, !12, !13}326!11 = !{i32 10000, i64 100, i32 1}327!12 = !{i32 999000, i64 100, i32 1}328!13 = !{i32 999999, i64 1, i32 2}329!14 = !{!"function_entry_count", i64 0}330