llvm.org GIT mirror llvm / a9143d4
[WebAssembly] Support constant offsets on loads and stores This is just prototype for load/store for i32 types. I'll add them to the rest of the types if we like this direction. Differential Revision: http://reviews.llvm.org/D15197 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254807 91177308-0d34-0410-b5e6-96231b3b80d8 Derek Schuff 4 years ago
11 changed file(s) with 128 addition(s) and 117 deletion(s). Raw diff Collapse all Expand all
2424 let Defs = [ARGUMENTS] in {
2525
2626 // Basic load.
27 def LOAD_I32 : I<(outs I32:$dst), (ins I32:$addr),
28 [(set I32:$dst, (load I32:$addr))],
29 "i32.load\t$dst, $addr">;
30 def LOAD_I64 : I<(outs I64:$dst), (ins I32:$addr),
31 [(set I64:$dst, (load I32:$addr))],
32 "i64.load\t$dst, $addr">;
33 def LOAD_F32 : I<(outs F32:$dst), (ins I32:$addr),
34 [(set F32:$dst, (load I32:$addr))],
35 "f32.load\t$dst, $addr">;
36 def LOAD_F64 : I<(outs F64:$dst), (ins I32:$addr),
37 [(set F64:$dst, (load I32:$addr))],
38 "f64.load\t$dst, $addr">;
27 def LOAD_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr), [],
28 "i32.load\t$dst, $off($addr)">;
29 def LOAD_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr), [],
30 "i64.load\t$dst, $off($addr)">;
31 def LOAD_F32 : I<(outs F32:$dst), (ins I32:$off, I32:$addr), [],
32 "f32.load\t$dst, $off($addr)">;
33 def LOAD_F64 : I<(outs F64:$dst), (ins I32:$off, I32:$addr), [],
34 "f64.load\t$dst, $off($addr)">;
3935
4036 // Extending load.
41 def LOAD8_S_I32 : I<(outs I32:$dst), (ins I32:$addr),
42 [(set I32:$dst, (sextloadi8 I32:$addr))],
43 "i32.load8_s\t$dst, $addr">;
44 def LOAD8_U_I32 : I<(outs I32:$dst), (ins I32:$addr),
45 [(set I32:$dst, (zextloadi8 I32:$addr))],
46 "i32.load8_u\t$dst, $addr">;
47 def LOAD16_S_I32 : I<(outs I32:$dst), (ins I32:$addr),
48 [(set I32:$dst, (sextloadi16 I32:$addr))],
49 "i32.load16_s\t$dst, $addr">;
50 def LOAD16_U_I32 : I<(outs I32:$dst), (ins I32:$addr),
51 [(set I32:$dst, (zextloadi16 I32:$addr))],
52 "i32.load16_u\t$dst, $addr">;
53 def LOAD8_S_I64 : I<(outs I64:$dst), (ins I32:$addr),
54 [(set I64:$dst, (sextloadi8 I32:$addr))],
55 "i64.load8_s\t$dst, $addr">;
56 def LOAD8_U_I64 : I<(outs I64:$dst), (ins I32:$addr),
57 [(set I64:$dst, (zextloadi8 I32:$addr))],
58 "i64.load8_u\t$dst, $addr">;
59 def LOAD16_S_I64 : I<(outs I64:$dst), (ins I32:$addr),
60 [(set I64:$dst, (sextloadi16 I32:$addr))],
61 "i64.load16_s\t$dst, $addr">;
62 def LOAD16_U_I64 : I<(outs I64:$dst), (ins I32:$addr),
63 [(set I64:$dst, (zextloadi16 I32:$addr))],
64 "i64.load16_u\t$dst, $addr">;
65 def LOAD32_S_I64 : I<(outs I64:$dst), (ins I32:$addr),
66 [(set I64:$dst, (sextloadi32 I32:$addr))],
67 "i64.load32_s\t$dst, $addr">;
68 def LOAD32_U_I64 : I<(outs I64:$dst), (ins I32:$addr),
69 [(set I64:$dst, (zextloadi32 I32:$addr))],
70 "i64.load32_u\t$dst, $addr">;
37 def LOAD8_S_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr), [],
38 "i32.load8_s\t$dst, $off($addr)">;
39 def LOAD8_U_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr), [],
40 "i32.load8_u\t$dst, $off($addr)">;
41 def LOAD16_S_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr), [],
42 "i32.load16_s\t$dst, $off($addr)">;
43 def LOAD16_U_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr), [],
44 "i32.load16_u\t$dst, $off($addr)">;
45 def LOAD8_S_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr), [],
46 "i64.load8_s\t$dst, $off($addr)">;
47 def LOAD8_U_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr), [],
48 "i64.load8_u\t$dst, $off($addr)">;
49 def LOAD16_S_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr), [],
50 "i64.load16_s\t$dst, $off($addr)">;
51 def LOAD16_U_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr), [],
52 "i64.load16_u\t$dst, $off($addr)">;
53 def LOAD32_S_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr), [],
54 "i64.load32_s\t$dst, $off($addr)">;
55 def LOAD32_U_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr), [],
56 "i64.load32_u\t$dst, $off($addr)">;
7157
7258 } // Defs = [ARGUMENTS]
7359
60 // Select loads with no constant offset.
61 def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr)>;
62 def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr)>;
63 def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr)>;
64 def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr)>;
65
66 // Select extending loads with no constant offset.
67 def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr)>;
68 def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>;
69 def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr)>;
70 def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>;
71 def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr)>;
72 def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>;
73 def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr)>;
74 def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>;
75 def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr)>;
76 def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>;
77
7478 // "Don't care" extending load become zero-extending load.
75 def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 $addr)>;
76 def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 $addr)>;
77 def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 $addr)>;
78 def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 $addr)>;
79 def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 $addr)>;
79 def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>;
80 def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>;
81 def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>;
82 def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>;
83 def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>;
8084
8185 let Defs = [ARGUMENTS] in {
8286
8690 // instruction definition patterns that don't reference all of the output
8791 // operands.
8892 // Note: WebAssembly inverts SelectionDAG's usual operand order.
89 def STORE_I32 : I<(outs I32:$dst), (ins I32:$addr, I32:$val), [],
90 "i32.store\t$dst, $addr, $val">;
91 def STORE_I64 : I<(outs I64:$dst), (ins I32:$addr, I64:$val), [],
92 "i64.store\t$dst, $addr, $val">;
93 def STORE_F32 : I<(outs F32:$dst), (ins I32:$addr, F32:$val), [],
94 "f32.store\t$dst, $addr, $val">;
95 def STORE_F64 : I<(outs F64:$dst), (ins I32:$addr, F64:$val), [],
96 "f64.store\t$dst, $addr, $val">;
93 def STORE_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr, I32:$val), [],
94 "i32.store\t$dst, $off($addr), $val">;
95 def STORE_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr, I64:$val), [],
96 "i64.store\t$dst, $off($addr), $val">;
97 def STORE_F32 : I<(outs F32:$dst), (ins I32:$off, I32:$addr, F32:$val), [],
98 "f32.store\t$dst, $off($addr), $val">;
99 def STORE_F64 : I<(outs F64:$dst), (ins I32:$off, I32:$addr, F64:$val), [],
100 "f64.store\t$dst, $off($addr), $val">;
97101
98102 } // Defs = [ARGUMENTS]
99103
100 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 I32:$addr, I32:$val)>;
101 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 I32:$addr, I64:$val)>;
102 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 I32:$addr, F32:$val)>;
103 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 I32:$addr, F64:$val)>;
104 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, I32:$val)>;
105 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, I64:$val)>;
106 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, F32:$val)>;
107 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, F64:$val)>;
108
109 // FIXME: This pattern matches an immediate to actually use the offset field
110 // in the store instruction; however only unsigned offsets are supported in
111 // wasm, so we need to constrain the immediate we match. This may require
112 // custom code rather than a simple pattern.
113 // def : Pat<(store I32:$val, (add I32:$addr, (i32 imm:$off))),
114 // (STORE_I32 imm:$off, I32:$addr, I32:$val)>;
104115
105116 let Defs = [ARGUMENTS] in {
106117
107118 // Truncating store.
108 def STORE8_I32 : I<(outs I32:$dst), (ins I32:$addr, I32:$val), [],
109 "i32.store8\t$dst, $addr, $val">;
110 def STORE16_I32 : I<(outs I32:$dst), (ins I32:$addr, I32:$val), [],
111 "i32.store16\t$dst, $addr, $val">;
112 def STORE8_I64 : I<(outs I64:$dst), (ins I32:$addr, I64:$val), [],
113 "i64.store8\t$dst, $addr, $val">;
114 def STORE16_I64 : I<(outs I64:$dst), (ins I32:$addr, I64:$val), [],
115 "i64.store16\t$dst, $addr, $val">;
116 def STORE32_I64 : I<(outs I64:$dst), (ins I32:$addr, I64:$val), [],
117 "i64.store32\t$dst, $addr, $val">;
119 def STORE8_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr, I32:$val), [],
120 "i32.store8\t$dst, $off($addr), $val">;
121 def STORE16_I32 : I<(outs I32:$dst), (ins I32:$off, I32:$addr, I32:$val), [],
122 "i32.store16\t$dst, $off($addr), $val">;
123 def STORE8_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr, I64:$val), [],
124 "i64.store8\t$dst, $off($addr), $val">;
125 def STORE16_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr, I64:$val), [],
126 "i64.store16\t$dst, $off($addr), $val">;
127 def STORE32_I64 : I<(outs I64:$dst), (ins I32:$off, I32:$addr, I64:$val), [],
128 "i64.store32\t$dst, $off($addr), $val">;
118129
119130 } // Defs = [ARGUMENTS]
120131
121132 def : Pat<(truncstorei8 I32:$val, I32:$addr),
122 (STORE8_I32 I32:$addr, I32:$val)>;
133 (STORE8_I32 0, I32:$addr, I32:$val)>;
123134 def : Pat<(truncstorei16 I32:$val, I32:$addr),
124 (STORE16_I32 I32:$addr, I32:$val)>;
135 (STORE16_I32 0, I32:$addr, I32:$val)>;
125136 def : Pat<(truncstorei8 I64:$val, I32:$addr),
126 (STORE8_I64 I32:$addr, I64:$val)>;
137 (STORE8_I64 0, I32:$addr, I64:$val)>;
127138 def : Pat<(truncstorei16 I64:$val, I32:$addr),
128 (STORE16_I64 I32:$addr, I64:$val)>;
139 (STORE16_I64 0, I32:$addr, I64:$val)>;
129140 def : Pat<(truncstorei32 I64:$val, I32:$addr),
130 (STORE32_I64 I32:$addr, I64:$val)>;
141 (STORE32_I64 0, I32:$addr, I64:$val)>;
131142
132143 let Defs = [ARGUMENTS] in {
133144
8787 case WebAssembly::STORE_I32:
8888 case WebAssembly::STORE_I64:
8989 unsigned ToReg = MI.getOperand(0).getReg();
90 unsigned FromReg = MI.getOperand(2).getReg();
90 unsigned FromReg = MI.getOperand(3).getReg();
9191 for (auto I = MRI.use_begin(FromReg), E = MRI.use_end(); I != E;) {
9292 MachineOperand &O = *I++;
9393 MachineInstr *Where = O.getParent();
183183 ; CHECK-LABEL: minimal_loop:
184184 ; CHECK-NOT: br
185185 ; CHECK: BB7_1:
186 ; CHECK: i32.store $discard=, $0, $pop{{[0-9]+}}{{$}}
186 ; CHECK: i32.store $discard=, 0($0), $pop{{[0-9]+}}{{$}}
187187 ; CHECK: br BB7_1{{$}}
188188 ; CHECK: BB7_2:
189189 define i32 @minimal_loop(i32* %p) {
1010
1111 ; CHECK: foo:
1212 ; CHECK: i32.const $push0=, answer{{$}}
13 ; CHECK-NEXT: i32.load $push1=, $pop0{{$}}
13 ; CHECK-NEXT: i32.load $push1=, 0($pop0){{$}}
1414 ; CHECK-NEXT: return $pop1{{$}}
1515 define i32 @foo() {
1616 %a = load i32, i32* @answer
55 target triple = "wasm32-unknown-unknown"
66
77 ; CHECK-LABEL: sext_i8_i32:
8 ; CHECK: i32.load8_s $push0=, $0{{$}}
8 ; CHECK: i32.load8_s $push0=, 0($0){{$}}
99 ; CHECK-NEXT: return $pop0{{$}}
1010 define i32 @sext_i8_i32(i8 *%p) {
1111 %v = load i8, i8* %p
1414 }
1515
1616 ; CHECK-LABEL: zext_i8_i32:
17 ; CHECK: i32.load8_u $push0=, $0{{$}}
17 ; CHECK: i32.load8_u $push0=, 0($0){{$}}
1818 ; CHECK-NEXT: return $pop0{{$}}
1919 define i32 @zext_i8_i32(i8 *%p) {
2020 %v = load i8, i8* %p
2323 }
2424
2525 ; CHECK-LABEL: sext_i16_i32:
26 ; CHECK: i32.load16_s $push0=, $0{{$}}
26 ; CHECK: i32.load16_s $push0=, 0($0){{$}}
2727 ; CHECK-NEXT: return $pop0{{$}}
2828 define i32 @sext_i16_i32(i16 *%p) {
2929 %v = load i16, i16* %p
3232 }
3333
3434 ; CHECK-LABEL: zext_i16_i32:
35 ; CHECK: i32.load16_u $push0=, $0{{$}}
35 ; CHECK: i32.load16_u $push0=, 0($0){{$}}
3636 ; CHECK-NEXT: return $pop0{{$}}
3737 define i32 @zext_i16_i32(i16 *%p) {
3838 %v = load i16, i16* %p
4141 }
4242
4343 ; CHECK-LABEL: sext_i8_i64:
44 ; CHECK: i64.load8_s $push0=, $0{{$}}
44 ; CHECK: i64.load8_s $push0=, 0($0){{$}}
4545 ; CHECK-NEXT: return $pop0{{$}}
4646 define i64 @sext_i8_i64(i8 *%p) {
4747 %v = load i8, i8* %p
5050 }
5151
5252 ; CHECK-LABEL: zext_i8_i64:
53 ; CHECK: i64.load8_u $push0=, $0{{$}}
53 ; CHECK: i64.load8_u $push0=, 0($0){{$}}
5454 ; CHECK-NEXT: return $pop0{{$}}
5555 define i64 @zext_i8_i64(i8 *%p) {
5656 %v = load i8, i8* %p
5959 }
6060
6161 ; CHECK-LABEL: sext_i16_i64:
62 ; CHECK: i64.load16_s $push0=, $0{{$}}
62 ; CHECK: i64.load16_s $push0=, 0($0){{$}}
6363 ; CHECK-NEXT: return $pop0{{$}}
6464 define i64 @sext_i16_i64(i16 *%p) {
6565 %v = load i16, i16* %p
6868 }
6969
7070 ; CHECK-LABEL: zext_i16_i64:
71 ; CHECK: i64.load16_u $push0=, $0{{$}}
71 ; CHECK: i64.load16_u $push0=, 0($0){{$}}
7272 ; CHECK-NEXT: return $pop0{{$}}
7373 define i64 @zext_i16_i64(i16 *%p) {
7474 %v = load i16, i16* %p
7777 }
7878
7979 ; CHECK-LABEL: sext_i32_i64:
80 ; CHECK: i64.load32_s $push0=, $0{{$}}
80 ; CHECK: i64.load32_s $push0=, 0($0){{$}}
8181 ; CHECK-NEXT: return $pop0{{$}}
8282 define i64 @sext_i32_i64(i32 *%p) {
8383 %v = load i32, i32* %p
8686 }
8787
8888 ; CHECK-LABEL: zext_i32_i64:
89 ; CHECK: i64.load32_u $push0=, $0{{$}}
89 ; CHECK: i64.load32_u $push0=, 0($0){{$}}
9090 ; CHECK: return $pop0{{$}}
9191 define i64 @zext_i32_i64(i32 *%p) {
9292 %v = load i32, i32* %p
55 target triple = "wasm32-unknown-unknown"
66
77 ; CHECK-LABEL: load_u_i1_i32:
8 ; CHECK: i32.load8_u $push[[NUM0:[0-9]+]]=, $0{{$}}
8 ; CHECK: i32.load8_u $push[[NUM0:[0-9]+]]=, 0($0){{$}}
99 ; CHECK-NEXT: return $pop[[NUM0]]{{$}}
1010 define i32 @load_u_i1_i32(i1* %p) {
1111 %v = load i1, i1* %p
1414 }
1515
1616 ; CHECK-LABEL: load_s_i1_i32:
17 ; CHECK: i32.load8_u $push[[NUM0:[0-9]+]]=, $0{{$}}
17 ; CHECK: i32.load8_u $push[[NUM0:[0-9]+]]=, 0($0){{$}}
1818 ; CHECK-NEXT: i32.const $[[NUM1:[0-9]+]]=, 31{{$}}
1919 ; CHECK-NEXT: shl $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $[[NUM1]]{{$}}
2020 ; CHECK-NEXT: shr_s $push[[NUM3:[0-9]+]]=, $pop[[NUM2]], $[[NUM1]]{{$}}
2626 }
2727
2828 ; CHECK-LABEL: load_u_i1_i64:
29 ; CHECK: i64.load8_u $push[[NUM0:[0-9]+]]=, $0{{$}}
29 ; CHECK: i64.load8_u $push[[NUM0:[0-9]+]]=, 0($0){{$}}
3030 ; CHECK-NEXT: return $pop[[NUM0]]{{$}}
3131 define i64 @load_u_i1_i64(i1* %p) {
3232 %v = load i1, i1* %p
3535 }
3636
3737 ; CHECK-LABEL: load_s_i1_i64:
38 ; CHECK: i64.load8_u $push[[NUM0:[0-9]+]]=, $0{{$}}
38 ; CHECK: i64.load8_u $push[[NUM0:[0-9]+]]=, 0($0){{$}}
3939 ; CHECK-NEXT: i64.const $[[NUM1:[0-9]+]]=, 63{{$}}
4040 ; CHECK-NEXT: shl $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $[[NUM1]]{{$}}
4141 ; CHECK-NEXT: shr_s $push[[NUM3:[0-9]+]]=, $pop[[NUM2]], $[[NUM1]]{{$}}
4949 ; CHECK-LABEL: store_i32_i1:
5050 ; CHECK: i32.const $push[[NUM0:[0-9]+]]=, 1{{$}}
5151 ; CHECK-NEXT: i32.and $push[[NUM1:[0-9]+]]=, $1, $pop[[NUM0]]{{$}}
52 ; CHECK-NEXT: i32.store8 $discard=, $0, $pop[[NUM1]]{{$}}
52 ; CHECK-NEXT: i32.store8 $discard=, 0($0), $pop[[NUM1]]{{$}}
5353 define void @store_i32_i1(i1* %p, i32 %v) {
5454 %t = trunc i32 %v to i1
5555 store i1 %t, i1* %p
5959 ; CHECK-LABEL: store_i64_i1:
6060 ; CHECK: i64.const $push[[NUM0:[0-9]+]]=, 1{{$}}
6161 ; CHECK-NEXT: i64.and $push[[NUM1:[0-9]+]]=, $1, $pop[[NUM0]]{{$}}
62 ; CHECK-NEXT: i64.store8 $discard=, $0, $pop[[NUM1]]{{$}}
62 ; CHECK-NEXT: i64.store8 $discard=, 0($0), $pop[[NUM1]]{{$}}
6363 define void @store_i64_i1(i1* %p, i64 %v) {
6464 %t = trunc i64 %v to i1
6565 store i1 %t, i1* %p
77 ; CHECK-LABEL: ldi32:
88 ; CHECK-NEXT: .param i32{{$}}
99 ; CHECK-NEXT: .result i32{{$}}
10 ; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, $0{{$}}
10 ; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
1111 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
1212 define i32 @ldi32(i32 *%p) {
1313 %v = load i32, i32* %p
1717 ; CHECK-LABEL: ldi64:
1818 ; CHECK-NEXT: .param i32{{$}}
1919 ; CHECK-NEXT: .result i64{{$}}
20 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, $0{{$}}
20 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
2121 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
2222 define i64 @ldi64(i64 *%p) {
2323 %v = load i64, i64* %p
2727 ; CHECK-LABEL: ldf32:
2828 ; CHECK-NEXT: .param i32{{$}}
2929 ; CHECK-NEXT: .result f32{{$}}
30 ; CHECK-NEXT: f32.load $push[[NUM:[0-9]+]]=, $0{{$}}
30 ; CHECK-NEXT: f32.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
3131 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
3232 define float @ldf32(float *%p) {
3333 %v = load float, float* %p
3737 ; CHECK-LABEL: ldf64:
3838 ; CHECK-NEXT: .param i32{{$}}
3939 ; CHECK-NEXT: .result f64{{$}}
40 ; CHECK-NEXT: f64.load $push[[NUM:[0-9]+]]=, $0{{$}}
40 ; CHECK-NEXT: f64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
4141 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
4242 define double @ldf64(double *%p) {
4343 %v = load double, double* %p
88 ; CHECK-LABEL: single_block:
99 ; CHECK-NOT: .local
1010 ; CHECK: i32.const $push{{[0-9]+}}=, 0
11 ; CHECK: i32.store $push[[STORE:[0-9]+]]=, $0, $pop{{[0-9]+}}
11 ; CHECK: i32.store $push[[STORE:[0-9]+]]=, 0($0), $pop{{[0-9]+}}
1212 ; CHECK: return $pop[[STORE]]{{$}}
1313 define i32 @single_block(i32* %p) {
1414 entry:
2525 @pos = global %class.Vec3 zeroinitializer, align 4
2626
2727 ; CHECK-LABEL: foo:
28 ; CHECK: i32.store $discard=, $pop0, $0
28 ; CHECK: i32.store $discard=, 0($pop0), $0
2929 define void @foo() {
3030 for.body.i:
3131 br label %for.body5.i
4343 }
4444
4545 ; CHECK-LABEL: bar:
46 ; CHECK: i32.store $discard=, $0, $pop0
46 ; CHECK: i32.store $discard=, 0($0), $pop0
4747 define void @bar() {
4848 for.body.i:
4949 br label %for.body5.i
55 target triple = "wasm32-unknown-unknown"
66
77 ; CHECK-LABEL: trunc_i8_i32:
8 ; CHECK: i32.store8 $discard=, $0, $1{{$}}
8 ; CHECK: i32.store8 $discard=, 0($0), $1{{$}}
99 define void @trunc_i8_i32(i8 *%p, i32 %v) {
1010 %t = trunc i32 %v to i8
1111 store i8 %t, i8* %p
1313 }
1414
1515 ; CHECK-LABEL: trunc_i16_i32:
16 ; CHECK: i32.store16 $discard=, $0, $1{{$}}
16 ; CHECK: i32.store16 $discard=, 0($0), $1{{$}}
1717 define void @trunc_i16_i32(i16 *%p, i32 %v) {
1818 %t = trunc i32 %v to i16
1919 store i16 %t, i16* %p
2121 }
2222
2323 ; CHECK-LABEL: trunc_i8_i64:
24 ; CHECK: i64.store8 $discard=, $0, $1{{$}}
24 ; CHECK: i64.store8 $discard=, 0($0), $1{{$}}
2525 define void @trunc_i8_i64(i8 *%p, i64 %v) {
2626 %t = trunc i64 %v to i8
2727 store i8 %t, i8* %p
2929 }
3030
3131 ; CHECK-LABEL: trunc_i16_i64:
32 ; CHECK: i64.store16 $discard=, $0, $1{{$}}
32 ; CHECK: i64.store16 $discard=, 0($0), $1{{$}}
3333 define void @trunc_i16_i64(i16 *%p, i64 %v) {
3434 %t = trunc i64 %v to i16
3535 store i16 %t, i16* %p
3737 }
3838
3939 ; CHECK-LABEL: trunc_i32_i64:
40 ; CHECK: i64.store32 $discard=, $0, $1{{$}}
40 ; CHECK: i64.store32 $discard=, 0($0), $1{{$}}
4141 define void @trunc_i32_i64(i32 *%p, i64 %v) {
4242 %t = trunc i64 %v to i32
4343 store i32 %t, i32* %p
66
77 ; CHECK-LABEL: sti32:
88 ; CHECK-NEXT: .param i32, i32{{$}}
9 ; CHECK-NEXT: i32.store $discard=, $0, $1{{$}}
9 ; CHECK-NEXT: i32.store $discard=, 0($0), $1{{$}}
1010 ; CHECK-NEXT: return{{$}}
1111 define void @sti32(i32 *%p, i32 %v) {
1212 store i32 %v, i32* %p
1515
1616 ; CHECK-LABEL: sti64:
1717 ; CHECK-NEXT: .param i32, i64{{$}}
18 ; CHECK-NEXT: i64.store $discard=, $0, $1{{$}}
18 ; CHECK-NEXT: i64.store $discard=, 0($0), $1{{$}}
1919 ; CHECK-NEXT: return{{$}}
2020 define void @sti64(i64 *%p, i64 %v) {
2121 store i64 %v, i64* %p
2424
2525 ; CHECK-LABEL: stf32:
2626 ; CHECK-NEXT: .param i32, f32{{$}}
27 ; CHECK-NEXT: f32.store $discard=, $0, $1{{$}}
27 ; CHECK-NEXT: f32.store $discard=, 0($0), $1{{$}}
2828 ; CHECK-NEXT: return{{$}}
2929 define void @stf32(float *%p, float %v) {
3030 store float %v, float* %p
3333
3434 ; CHECK-LABEL: stf64:
3535 ; CHECK-NEXT: .param i32, f64{{$}}
36 ; CHECK-NEXT: f64.store $discard=, $0, $1{{$}}
36 ; CHECK-NEXT: f64.store $discard=, 0($0), $1{{$}}
3737 ; CHECK-NEXT: return{{$}}
3838 define void @stf64(double *%p, double %v) {
3939 store double %v, double* %p
3131
3232 ; CHECK-LABEL: copy:
3333 ; CHECK-NEXT: .param i32, i32{{$}}
34 ; CHECK-NEXT: i32.load $push0=, $1{{$}}
35 ; CHECK-NEXT: i32.store $discard=, $0, $pop0{{$}}
34 ; CHECK-NEXT: i32.load $push0=, 0($1){{$}}
35 ; CHECK-NEXT: i32.store $discard=, 0($0), $pop0{{$}}
3636 ; CHECK-NEXT: return{{$}}
3737 define void @copy(i8** %ap, i8** %bp) {
3838 entry:
4848 ; CHECK-NEXT: .param i32{{$}}
4949 ; CHECK-NEXT: .result i32{{$}}
5050 ; CHECK-NEXT: .local i32{{$}}
51 ; CHECK-NEXT: i32.load $1=, $0{{$}}
51 ; CHECK-NEXT: i32.load $1=, 0($0){{$}}
5252 ; CHECK-NEXT: i32.const $push0=, 4{{$}}
5353 ; CHECK-NEXT: i32.add $push1=, $1, $pop0{{$}}
54 ; CHECK-NEXT: i32.store $discard=, $0, $pop1{{$}}
55 ; CHECK-NEXT: i32.load $push2=, $1{{$}}
54 ; CHECK-NEXT: i32.store $discard=, 0($0), $pop1{{$}}
55 ; CHECK-NEXT: i32.load $push2=, 0($1){{$}}
5656 ; CHECK-NEXT: return $pop2{{$}}
5757 define i8 @arg_i8(i8** %ap) {
5858 entry:
6666 ; CHECK-NEXT: .param i32{{$}}
6767 ; CHECK-NEXT: .result i32{{$}}
6868 ; CHECK-NEXT: .local i32{{$}}
69 ; CHECK-NEXT: i32.load $push0=, $0{{$}}
69 ; CHECK-NEXT: i32.load $push0=, 0($0){{$}}
7070 ; CHECK-NEXT: i32.const $push1=, 3{{$}}
7171 ; CHECK-NEXT: i32.add $push2=, $pop0, $pop1{{$}}
7272 ; CHECK-NEXT: i32.const $push3=, -4{{$}}
7373 ; CHECK-NEXT: i32.and $1=, $pop2, $pop3{{$}}
7474 ; CHECK-NEXT: i32.const $push4=, 4{{$}}
7575 ; CHECK-NEXT: i32.add $push5=, $1, $pop4{{$}}
76 ; CHECK-NEXT: i32.store $discard=, $0, $pop5{{$}}
77 ; CHECK-NEXT: i32.load $push6=, $1{{$}}
76 ; CHECK-NEXT: i32.store $discard=, 0($0), $pop5{{$}}
77 ; CHECK-NEXT: i32.load $push6=, 0($1){{$}}
7878 ; CHECK-NEXT: return $pop6{{$}}
7979 define i32 @arg_i32(i8** %ap) {
8080 entry: