Home | History | Annotate | Download | only in WebAssembly
      1 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
      2 
      3 ; Test constant load and store address offsets.
      4 
      5 target datalayout = "e-p:32:32-i64:64-n32:64-S128"
      6 target triple = "wasm32-unknown-unknown"
      7 
      8 ; With an nuw add, we can fold an offset.
      9 
     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
     17   ret i32 %t
     18 }
     19 
     20 ; Without nuw, and even with nsw, we can't fold an offset.
     21 
     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
     31   ret i32 %t
     32 }
     33 
     34 ; Same as above but with i64.
     35 
     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
     43   ret i64 %t
     44 }
     45 
     46 ; Same as above but with i64.
     47 
     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
     57   ret i64 %t
     58 }
     59 
     60 ; Same as above but with store.
     61 
     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*
     68   store i32 0, i32* %s
     69   ret void
     70 }
     71 
     72 ; Same as above but with store.
     73 
     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*
     82   store i32 0, i32* %s
     83   ret void
     84 }
     85 
     86 ; Same as above but with store with i64.
     87 
     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*
     94   store i64 0, i64* %s
     95   ret void
     96 }
     97 
     98 ; Same as above but with store with i64.
     99 
    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*
    108   store i64 0, i64* %s
    109   ret void
    110 }
    111 
    112 ; When loading from a fixed address, materialize a zero.
    113 
    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
    120   ret i32 %t
    121 }
    122 
    123 ; CHECK-LABEL: load_i32_from_global_address
    124 ; CHECK: i32.const $push0=, 0{{$}}
    125 ; CHECK: i32.load  $push1=, gv($pop0){{$}}
    126 @gv = global i32 0
    127 define i32 @load_i32_from_global_address() {
    128   %t = load i32, i32* @gv
    129   ret i32 %t
    130 }
    131 
    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*
    137   store i32 0, i32* %s
    138   ret void
    139 }
    140 
    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
    146   ret void
    147 }
    148 
    149 ; Fold an offset into a sign-extending load.
    150 
    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*
    157   %t = load i8, i8* %s
    158   %u = sext i8 %t to i32
    159   ret i32 %u
    160 }
    161 
    162 ; Fold an offset into a zero-extending load.
    163 
    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*
    170   %t = load i8, i8* %s
    171   %u = zext i8 %t to i32
    172   ret i32 %u
    173 }
    174 
    175 ; Fold an offset into a truncating store.
    176 
    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*
    183   store i8 0, i8* %s
    184   ret void
    185 }
    186