[WebAssembly] Make CFG stackification independent of basic-block labels.
[oota-llvm.git] / test / CodeGen / WebAssembly / reg-stackify.ll
1 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
2
3 ; Test the register stackifier pass.
4
5 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6 target triple = "wasm32-unknown-unknown"
7
8 ; No because of pointer aliasing.
9
10 ; CHECK-LABEL: no0:
11 ; CHECK: return $1{{$}}
12 define i32 @no0(i32* %p, i32* %q) {
13   %t = load i32, i32* %q
14   store i32 0, i32* %p
15   ret i32 %t
16 }
17
18 ; No because of side effects.
19
20 ; CHECK-LABEL: no1:
21 ; CHECK: return $1{{$}}
22 define i32 @no1(i32* %p, i32* dereferenceable(4) %q) {
23   %t = load volatile i32, i32* %q, !invariant.load !0
24   store volatile i32 0, i32* %p
25   ret i32 %t
26 }
27
28 ; Yes because of invariant load and no side effects.
29
30 ; CHECK-LABEL: yes0:
31 ; CHECK: return $pop0{{$}}
32 define i32 @yes0(i32* %p, i32* dereferenceable(4) %q) {
33   %t = load i32, i32* %q, !invariant.load !0
34   store i32 0, i32* %p
35   ret i32 %t
36 }
37
38 ; Yes because of no intervening side effects.
39
40 ; CHECK-LABEL: yes1:
41 ; CHECK: return $pop0{{$}}
42 define i32 @yes1(i32* %q) {
43   %t = load volatile i32, i32* %q
44   ret i32 %t
45 }
46
47 ; Don't schedule stack uses into the stack. To reduce register pressure, the
48 ; scheduler might be tempted to move the definition of $2 down. However, this
49 ; would risk getting incorrect liveness if the instructions are later
50 ; rearranged to make the stack contiguous.
51
52 ; CHECK-LABEL: stack_uses:
53 ; CHECK-NEXT: .param i32, i32, i32, i32{{$}}
54 ; CHECK-NEXT: .result i32{{$}}
55 ; CHECK-NEXT: .local i32, i32{{$}}
56 ; CHECK-NEXT: i32.const   $5=, 2{{$}}
57 ; CHECK-NEXT: i32.const   $4=, 1{{$}}
58 ; CHECK-NEXT: block{{$}}
59 ; CHECK-NEXT: i32.lt_s    $push0=, $0, $4{{$}}
60 ; CHECK-NEXT: i32.lt_s    $push1=, $1, $5{{$}}
61 ; CHECK-NEXT: i32.xor     $push4=, $pop0, $pop1{{$}}
62 ; CHECK-NEXT: i32.lt_s    $push2=, $2, $4{{$}}
63 ; CHECK-NEXT: i32.lt_s    $push3=, $3, $5{{$}}
64 ; CHECK-NEXT: i32.xor     $push5=, $pop2, $pop3{{$}}
65 ; CHECK-NEXT: i32.xor     $push6=, $pop4, $pop5{{$}}
66 ; CHECK-NEXT: i32.ne      $push7=, $pop6, $4{{$}}
67 ; CHECK-NEXT: br_if       $pop7, 0{{$}}
68 ; CHECK-NEXT: i32.const   $push8=, 0{{$}}
69 ; CHECK-NEXT: return      $pop8{{$}}
70 ; CHECK-NEXT: .LBB4_2:
71 ; CHECK-NEXT: end_block{{$}}
72 ; CHECK-NEXT: return      $4{{$}}
73 define i32 @stack_uses(i32 %x, i32 %y, i32 %z, i32 %w) {
74 entry:
75   %c = icmp sle i32 %x, 0
76   %d = icmp sle i32 %y, 1
77   %e = icmp sle i32 %z, 0
78   %f = icmp sle i32 %w, 1
79   %g = xor i1 %c, %d
80   %h = xor i1 %e, %f
81   %i = xor i1 %g, %h
82   br i1 %i, label %true, label %false
83 true:
84   ret i32 0
85 false:
86   ret i32 1
87 }
88
89 ; Test an interesting case where the load has multiple uses and cannot
90 ; be trivially stackified.
91
92 ; CHECK-LABEL: multiple_uses:
93 ; CHECK-NEXT: .param       i32, i32, i32{{$}}
94 ; CHECK-NEXT: .local       i32{{$}}
95 ; CHECK-NEXT: i32.load    $3=, 0($2){{$}}
96 ; CHECK-NEXT: block{{$}}
97 ; CHECK-NEXT: i32.ge_u    $push0=, $3, $1{{$}}
98 ; CHECK-NEXT: br_if       $pop0, 0{{$}}
99 ; CHECK-NEXT: i32.lt_u    $push1=, $3, $0{{$}}
100 ; CHECK-NEXT: br_if       $pop1, 0{{$}}
101 ; CHECK-NEXT: i32.store   $discard=, 0($2), $3{{$}}
102 ; CHECK-NEXT: .LBB5_3:
103 ; CHECK-NEXT: end_block{{$}}
104 ; CHECK-NEXT: return{{$}}
105 define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind {
106 bb:
107   br label %loop
108
109 loop:
110   %tmp7 = load i32, i32* %arg2
111   %tmp8 = inttoptr i32 %tmp7 to i32*
112   %tmp9 = icmp uge i32* %tmp8, %arg1
113   %tmp10 = icmp ult i32* %tmp8, %arg0
114   %tmp11 = or i1 %tmp9, %tmp10
115   br i1 %tmp11, label %back, label %then
116
117 then:
118   store i32 %tmp7, i32* %arg2
119   br label %back
120
121 back:
122   br i1 undef, label %return, label %loop
123
124 return:
125   ret void
126 }
127
128 !0 = !{}