1; RUN: llc < %s -asm-verbose=false | FileCheck %s 2 3; Test the CFG stackifier pass. 4 5target datalayout = "e-p:32:32-i64:64-n32:64-S128" 6target triple = "wasm32-unknown-unknown" 7 8declare void @something() 9 10; Test that loops are made contiguous, even in the presence of split backedges. 11 12; CHECK-LABEL: test0: 13; CHECK: loop 14; CHECK: add 15; CHECK: br_if 16; CHECK: call 17; CHECK: br $BB0_1{{$}} 18; CHECK: return{{$}} 19define void @test0(i32 %n) { 20entry: 21 br label %header 22 23header: 24 %i = phi i32 [ 0, %entry ], [ %i.next, %back ] 25 %i.next = add i32 %i, 1 26 27 %c = icmp slt i32 %i.next, %n 28 br i1 %c, label %back, label %exit 29 30exit: 31 ret void 32 33back: 34 call void @something() 35 br label %header 36} 37 38; Same as test0, but the branch condition is reversed. 39 40; CHECK-LABEL: test1: 41; CHECK: loop 42; CHECK: add 43; CHECK: br_if 44; CHECK: call 45; CHECK: br $BB1_1{{$}} 46; CHECK: return{{$}} 47define void @test1(i32 %n) { 48entry: 49 br label %header 50 51header: 52 %i = phi i32 [ 0, %entry ], [ %i.next, %back ] 53 %i.next = add i32 %i, 1 54 55 %c = icmp sge i32 %i.next, %n 56 br i1 %c, label %exit, label %back 57 58exit: 59 ret void 60 61back: 62 call void @something() 63 br label %header 64} 65 66; Test that a simple loop is handled as expected. 67 68; CHECK-LABEL: test2: 69; CHECK: block $BB2_2{{$}} 70; CHECK: br_if $BB2_2, {{.*}} 71; CHECK: BB2_1: 72; CHECK: br_if $BB2_1, (get_local 16){{$}} 73; CHECK: BB2_2: 74; CHECK: return{{$}} 75define void @test2(double* nocapture %p, i32 %n) { 76entry: 77 %cmp.4 = icmp sgt i32 %n, 0 78 br i1 %cmp.4, label %for.body.preheader, label %for.end 79 80for.body.preheader: 81 br label %for.body 82 83for.body: 84 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ] 85 %arrayidx = getelementptr inbounds double, double* %p, i32 %i.05 86 %0 = load double, double* %arrayidx, align 8 87 %mul = fmul double %0, 3.200000e+00 88 store double %mul, double* %arrayidx, align 8 89 %inc = add nuw nsw i32 %i.05, 1 90 %exitcond = icmp eq i32 %inc, %n 91 br i1 %exitcond, label %for.end.loopexit, label %for.body 92 93for.end.loopexit: 94 br label %for.end 95 96for.end: 97 ret void 98} 99 100; CHECK-LABEL: doublediamond: 101; CHECK: block $BB3_5{{$}} 102; CHECK: block $BB3_4{{$}} 103; CHECK: block $BB3_2{{$}} 104; CHECK: br_if $BB3_2, (get_local 7){{$}} 105; CHECK: br $BB3_5{{$}} 106; CHECK: BB3_2: 107; CHECK: br_if $BB3_4, (get_local 10){{$}} 108; CHECK: br $BB3_5{{$}} 109; CHECK: BB3_4: 110; CHECK: BB3_5: 111; CHECK: return (get_local 6){{$}} 112define i32 @doublediamond(i32 %a, i32 %b, i32* %p) { 113entry: 114 %c = icmp eq i32 %a, 0 115 %d = icmp eq i32 %b, 0 116 store volatile i32 0, i32* %p 117 br i1 %c, label %true, label %false 118true: 119 store volatile i32 1, i32* %p 120 br label %exit 121false: 122 store volatile i32 2, i32* %p 123 br i1 %d, label %ft, label %ff 124ft: 125 store volatile i32 3, i32* %p 126 br label %exit 127ff: 128 store volatile i32 4, i32* %p 129 br label %exit 130exit: 131 store volatile i32 5, i32* %p 132 ret i32 0 133} 134 135; CHECK-LABEL: triangle: 136; CHECK: block $BB4_2{{$}} 137; CHECK: br_if $BB4_2, (get_local 5){{$}} 138; CHECK: BB4_2: 139; CHECK: return (get_local 4){{$}} 140define i32 @triangle(i32* %p, i32 %a) { 141entry: 142 %c = icmp eq i32 %a, 0 143 store volatile i32 0, i32* %p 144 br i1 %c, label %true, label %exit 145true: 146 store volatile i32 1, i32* %p 147 br label %exit 148exit: 149 store volatile i32 2, i32* %p 150 ret i32 0 151} 152 153; CHECK-LABEL: diamond: 154; CHECK: block $BB5_3{{$}} 155; CHECK: block $BB5_2{{$}} 156; CHECK: br_if $BB5_2, (get_local 5){{$}} 157; CHECK: br $BB5_3{{$}} 158; CHECK: BB5_2: 159; CHECK: BB5_3: 160; CHECK: return (get_local 4){{$}} 161define i32 @diamond(i32* %p, i32 %a) { 162entry: 163 %c = icmp eq i32 %a, 0 164 store volatile i32 0, i32* %p 165 br i1 %c, label %true, label %false 166true: 167 store volatile i32 1, i32* %p 168 br label %exit 169false: 170 store volatile i32 2, i32* %p 171 br label %exit 172exit: 173 store volatile i32 3, i32* %p 174 ret i32 0 175} 176 177; CHECK-LABEL: single_block: 178; CHECK-NOT: br 179; CHECK: return (get_local 2){{$}} 180define i32 @single_block(i32* %p) { 181entry: 182 store volatile i32 0, i32* %p 183 ret i32 0 184} 185 186; CHECK-LABEL: minimal_loop: 187; CHECK-NOT: br 188; CHECK: BB7_1: 189; CHECK: i32.store (get_local 1), (get_local 3){{$}} 190; CHECK: br $BB7_1{{$}} 191define i32 @minimal_loop(i32* %p) { 192entry: 193 store volatile i32 0, i32* %p 194 br label %loop 195loop: 196 store volatile i32 1, i32* %p 197 br label %loop 198} 199 200; CHECK-LABEL: simple_loop: 201; CHECK-NOT: br 202; CHECK: BB8_1: 203; CHECK: loop $BB8_2{{$}} 204; CHECK: br_if $BB8_1, (get_local 6){{$}} 205; CHECK: return (get_local 4){{$}} 206define i32 @simple_loop(i32* %p, i32 %a) { 207entry: 208 %c = icmp eq i32 %a, 0 209 store volatile i32 0, i32* %p 210 br label %loop 211loop: 212 store volatile i32 1, i32* %p 213 br i1 %c, label %loop, label %exit 214exit: 215 store volatile i32 2, i32* %p 216 ret i32 0 217} 218 219; CHECK-LABEL: doubletriangle: 220; CHECK: block $BB9_4{{$}} 221; CHECK: block $BB9_3{{$}} 222; CHECK: br_if $BB9_4, (get_local 7){{$}} 223; CHECK: br_if $BB9_3, (get_local 10){{$}} 224; CHECK: BB9_3: 225; CHECK: BB9_4: 226; CHECK: return (get_local 6){{$}} 227define i32 @doubletriangle(i32 %a, i32 %b, i32* %p) { 228entry: 229 %c = icmp eq i32 %a, 0 230 %d = icmp eq i32 %b, 0 231 store volatile i32 0, i32* %p 232 br i1 %c, label %true, label %exit 233true: 234 store volatile i32 2, i32* %p 235 br i1 %d, label %tt, label %tf 236tt: 237 store volatile i32 3, i32* %p 238 br label %tf 239tf: 240 store volatile i32 4, i32* %p 241 br label %exit 242exit: 243 store volatile i32 5, i32* %p 244 ret i32 0 245} 246 247; CHECK-LABEL: ifelse_earlyexits: 248; CHECK: block $BB10_4{{$}} 249; CHECK: block $BB10_2{{$}} 250; CHECK: br_if $BB10_2, (get_local 7){{$}} 251; CHECK: br $BB10_4{{$}} 252; CHECK: BB10_2: 253; CHECK: br_if $BB10_4, (get_local 10){{$}} 254; CHECK: BB10_4: 255; CHECK: return (get_local 6){{$}} 256define i32 @ifelse_earlyexits(i32 %a, i32 %b, i32* %p) { 257entry: 258 %c = icmp eq i32 %a, 0 259 %d = icmp eq i32 %b, 0 260 store volatile i32 0, i32* %p 261 br i1 %c, label %true, label %false 262true: 263 store volatile i32 1, i32* %p 264 br label %exit 265false: 266 store volatile i32 2, i32* %p 267 br i1 %d, label %ft, label %exit 268ft: 269 store volatile i32 3, i32* %p 270 br label %exit 271exit: 272 store volatile i32 4, i32* %p 273 ret i32 0 274} 275 276; Test that nested loops are handled. 277 278declare void @bar() 279 280define void @test3(i32 %w) { 281entry: 282 br i1 undef, label %outer.ph, label %exit 283 284outer.ph: 285 br label %outer 286 287outer: 288 %tobool = icmp eq i32 undef, 0 289 br i1 %tobool, label %inner, label %unreachable 290 291unreachable: 292 unreachable 293 294inner: 295 %c = icmp eq i32 undef, %w 296 br i1 %c, label %if.end, label %inner 297 298exit: 299 ret void 300 301if.end: 302 call void @bar() 303 br label %outer 304} 305