1 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
3 ; Test constant load and store address offsets.
5 target datalayout = "e-p:32:32-i64:64-n32:64-S128"
6 target triple = "wasm32-unknown-unknown"
8 ; With an nuw add, we can fold an offset.
10 ; CHECK-LABEL: load_i32_with_folded_offset:
11 ; CHECK: i32.load $push0=, 24($0){{$}}
12 define i32 @load_i32_with_folded_offset(i32* %p) {
13 %q = ptrtoint i32* %p to i32
14 %r = add nuw i32 %q, 24
15 %s = inttoptr i32 %r to i32*
16 %t = load i32, i32* %s
20 ; Without nuw, and even with nsw, we can't fold an offset.
22 ; CHECK-LABEL: load_i32_with_unfolded_offset:
23 ; CHECK: i32.const $push0=, 24{{$}}
24 ; CHECK: i32.add $push1=, $0, $pop0{{$}}
25 ; CHECK: i32.load $push2=, 0($pop1){{$}}
26 define i32 @load_i32_with_unfolded_offset(i32* %p) {
27 %q = ptrtoint i32* %p to i32
28 %r = add nsw i32 %q, 24
29 %s = inttoptr i32 %r to i32*
30 %t = load i32, i32* %s
34 ; Same as above but with i64.
36 ; CHECK-LABEL: load_i64_with_folded_offset:
37 ; CHECK: i64.load $push0=, 24($0){{$}}
38 define i64 @load_i64_with_folded_offset(i64* %p) {
39 %q = ptrtoint i64* %p to i32
40 %r = add nuw i32 %q, 24
41 %s = inttoptr i32 %r to i64*
42 %t = load i64, i64* %s
46 ; Same as above but with i64.
48 ; CHECK-LABEL: load_i64_with_unfolded_offset:
49 ; CHECK: i32.const $push0=, 24{{$}}
50 ; CHECK: i32.add $push1=, $0, $pop0{{$}}
51 ; CHECK: i64.load $push2=, 0($pop1){{$}}
52 define i64 @load_i64_with_unfolded_offset(i64* %p) {
53 %q = ptrtoint i64* %p to i32
54 %r = add nsw i32 %q, 24
55 %s = inttoptr i32 %r to i64*
56 %t = load i64, i64* %s
60 ; Same as above but with store.
62 ; CHECK-LABEL: store_i32_with_folded_offset:
63 ; CHECK: i32.store $discard=, 24($0), $pop0{{$}}
64 define void @store_i32_with_folded_offset(i32* %p) {
65 %q = ptrtoint i32* %p to i32
66 %r = add nuw i32 %q, 24
67 %s = inttoptr i32 %r to i32*
72 ; Same as above but with store.
74 ; CHECK-LABEL: store_i32_with_unfolded_offset:
75 ; CHECK: i32.const $push0=, 24{{$}}
76 ; CHECK: i32.add $push1=, $0, $pop0{{$}}
77 ; CHECK: i32.store $discard=, 0($pop1), $pop2{{$}}
78 define void @store_i32_with_unfolded_offset(i32* %p) {
79 %q = ptrtoint i32* %p to i32
80 %r = add nsw i32 %q, 24
81 %s = inttoptr i32 %r to i32*
86 ; Same as above but with store with i64.
88 ; CHECK-LABEL: store_i64_with_folded_offset:
89 ; CHECK: i64.store $discard=, 24($0), $pop0{{$}}
90 define void @store_i64_with_folded_offset(i64* %p) {
91 %q = ptrtoint i64* %p to i32
92 %r = add nuw i32 %q, 24
93 %s = inttoptr i32 %r to i64*
98 ; Same as above but with store with i64.
100 ; CHECK-LABEL: store_i64_with_unfolded_offset:
101 ; CHECK: i32.const $push0=, 24{{$}}
102 ; CHECK: i32.add $push1=, $0, $pop0{{$}}
103 ; CHECK: i64.store $discard=, 0($pop1), $pop2{{$}}
104 define void @store_i64_with_unfolded_offset(i64* %p) {
105 %q = ptrtoint i64* %p to i32
106 %r = add nsw i32 %q, 24
107 %s = inttoptr i32 %r to i64*
112 ; When loading from a fixed address, materialize a zero.
114 ; CHECK-LABEL: load_i32_from_numeric_address
115 ; CHECK: i32.const $push0=, 0{{$}}
116 ; CHECK: i32.load $push1=, 42($pop0){{$}}
117 define i32 @load_i32_from_numeric_address() {
118 %s = inttoptr i32 42 to i32*
119 %t = load i32, i32* %s
123 ; CHECK-LABEL: load_i32_from_global_address
124 ; CHECK: i32.const $push0=, 0{{$}}
125 ; CHECK: i32.load $push1=, gv($pop0){{$}}
127 define i32 @load_i32_from_global_address() {
128 %t = load i32, i32* @gv
132 ; CHECK-LABEL: store_i32_to_numeric_address:
133 ; CHECK: i32.const $0=, 0{{$}}
134 ; CHECK: i32.store $discard=, 42($0), $0{{$}}
135 define void @store_i32_to_numeric_address() {
136 %s = inttoptr i32 42 to i32*
141 ; CHECK-LABEL: store_i32_to_global_address:
142 ; CHECK: i32.const $0=, 0{{$}}
143 ; CHECK: i32.store $discard=, gv($0), $0{{$}}
144 define void @store_i32_to_global_address() {
145 store i32 0, i32* @gv
149 ; Fold an offset into a sign-extending load.
151 ; CHECK-LABEL: load_i8_s_with_folded_offset:
152 ; CHECK: i32.load8_s $push0=, 24($0){{$}}
153 define i32 @load_i8_s_with_folded_offset(i8* %p) {
154 %q = ptrtoint i8* %p to i32
155 %r = add nuw i32 %q, 24
156 %s = inttoptr i32 %r to i8*
158 %u = sext i8 %t to i32
162 ; Fold an offset into a zero-extending load.
164 ; CHECK-LABEL: load_i8_u_with_folded_offset:
165 ; CHECK: i32.load8_u $push0=, 24($0){{$}}
166 define i32 @load_i8_u_with_folded_offset(i8* %p) {
167 %q = ptrtoint i8* %p to i32
168 %r = add nuw i32 %q, 24
169 %s = inttoptr i32 %r to i8*
171 %u = zext i8 %t to i32
175 ; Fold an offset into a truncating store.
177 ; CHECK-LABEL: store_i8_with_folded_offset:
178 ; CHECK: i32.store8 $discard=, 24($0), $pop0{{$}}
179 define void @store_i8_with_folded_offset(i8* %p) {
180 %q = ptrtoint i8* %p to i32
181 %r = add nuw i32 %q, 24
182 %s = inttoptr i32 %r to i8*