Home | History | Annotate | Download | only in WebAssembly
      1 ; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
      2 
      3 ; Test loads and stores with custom alignment values.
      4 
      5 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
      6 target triple = "wasm32-unknown-unknown"
      7 
      8 ;===----------------------------------------------------------------------------
      9 ; Loads
     10 ;===----------------------------------------------------------------------------
     11 
     12 ; CHECK-LABEL: ldi32_a1:
     13 ; CHECK-NEXT: .param i32{{$}}
     14 ; CHECK-NEXT: .result i32{{$}}
     15 ; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
     16 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     17 define i32 @ldi32_a1(i32 *%p) {
     18   %v = load i32, i32* %p, align 1
     19   ret i32 %v
     20 }
     21 
     22 ; CHECK-LABEL: ldi32_a2:
     23 ; CHECK-NEXT: .param i32{{$}}
     24 ; CHECK-NEXT: .result i32{{$}}
     25 ; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
     26 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     27 define i32 @ldi32_a2(i32 *%p) {
     28   %v = load i32, i32* %p, align 2
     29   ret i32 %v
     30 }
     31 
     32 ; 4 is the default alignment for i32 so no attribute is needed.
     33 
     34 ; CHECK-LABEL: ldi32_a4:
     35 ; CHECK-NEXT: .param i32{{$}}
     36 ; CHECK-NEXT: .result i32{{$}}
     37 ; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
     38 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     39 define i32 @ldi32_a4(i32 *%p) {
     40   %v = load i32, i32* %p, align 4
     41   ret i32 %v
     42 }
     43 
     44 ; The default alignment in LLVM is the same as the defualt alignment in wasm.
     45 
     46 ; CHECK-LABEL: ldi32:
     47 ; CHECK-NEXT: .param i32{{$}}
     48 ; CHECK-NEXT: .result i32{{$}}
     49 ; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
     50 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     51 define i32 @ldi32(i32 *%p) {
     52   %v = load i32, i32* %p
     53   ret i32 %v
     54 }
     55 
     56 ; 8 is greater than the default alignment so it is ignored.
     57 
     58 ; CHECK-LABEL: ldi32_a8:
     59 ; CHECK-NEXT: .param i32{{$}}
     60 ; CHECK-NEXT: .result i32{{$}}
     61 ; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
     62 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     63 define i32 @ldi32_a8(i32 *%p) {
     64   %v = load i32, i32* %p, align 8
     65   ret i32 %v
     66 }
     67 
     68 ;===----------------------------------------------------------------------------
     69 ; Extending loads
     70 ;===----------------------------------------------------------------------------
     71 
     72 ; CHECK-LABEL: ldi8_a1:
     73 ; CHECK-NEXT: .param i32{{$}}
     74 ; CHECK-NEXT: .result i32{{$}}
     75 ; CHECK-NEXT: i32.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
     76 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     77 define i8 @ldi8_a1(i8 *%p) {
     78   %v = load i8, i8* %p, align 1
     79   ret i8 %v
     80 }
     81 
     82 ; CHECK-LABEL: ldi8_a2:
     83 ; CHECK-NEXT: .param i32{{$}}
     84 ; CHECK-NEXT: .result i32{{$}}
     85 ; CHECK-NEXT: i32.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
     86 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     87 define i8 @ldi8_a2(i8 *%p) {
     88   %v = load i8, i8* %p, align 2
     89   ret i8 %v
     90 }
     91 
     92 ; CHECK-LABEL: ldi16_a1:
     93 ; CHECK-NEXT: .param i32{{$}}
     94 ; CHECK-NEXT: .result i32{{$}}
     95 ; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
     96 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     97 define i16 @ldi16_a1(i16 *%p) {
     98   %v = load i16, i16* %p, align 1
     99   ret i16 %v
    100 }
    101 
    102 ; CHECK-LABEL: ldi16_a2:
    103 ; CHECK-NEXT: .param i32{{$}}
    104 ; CHECK-NEXT: .result i32{{$}}
    105 ; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
    106 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    107 define i16 @ldi16_a2(i16 *%p) {
    108   %v = load i16, i16* %p, align 2
    109   ret i16 %v
    110 }
    111 
    112 ; CHECK-LABEL: ldi16_a4:
    113 ; CHECK-NEXT: .param i32{{$}}
    114 ; CHECK-NEXT: .result i32{{$}}
    115 ; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
    116 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    117 define i16 @ldi16_a4(i16 *%p) {
    118   %v = load i16, i16* %p, align 4
    119   ret i16 %v
    120 }
    121 
    122 ;===----------------------------------------------------------------------------
    123 ; Stores
    124 ;===----------------------------------------------------------------------------
    125 
    126 ; CHECK-LABEL: sti32_a1:
    127 ; CHECK-NEXT: .param i32, i32{{$}}
    128 ; CHECK-NEXT: i32.store 0($0):p2align=0, $1{{$}}
    129 ; CHECK-NEXT: return{{$}}
    130 define void @sti32_a1(i32 *%p, i32 %v) {
    131   store i32 %v, i32* %p, align 1
    132   ret void
    133 }
    134 
    135 ; CHECK-LABEL: sti32_a2:
    136 ; CHECK-NEXT: .param i32, i32{{$}}
    137 ; CHECK-NEXT: i32.store 0($0):p2align=1, $1{{$}}
    138 ; CHECK-NEXT: return{{$}}
    139 define void @sti32_a2(i32 *%p, i32 %v) {
    140   store i32 %v, i32* %p, align 2
    141   ret void
    142 }
    143 
    144 ; 4 is the default alignment for i32 so no attribute is needed.
    145 
    146 ; CHECK-LABEL: sti32_a4:
    147 ; CHECK-NEXT: .param i32, i32{{$}}
    148 ; CHECK-NEXT: i32.store 0($0), $1{{$}}
    149 ; CHECK-NEXT: return{{$}}
    150 define void @sti32_a4(i32 *%p, i32 %v) {
    151   store i32 %v, i32* %p, align 4
    152   ret void
    153 }
    154 
    155 ; The default alignment in LLVM is the same as the defualt alignment in wasm.
    156 
    157 ; CHECK-LABEL: sti32:
    158 ; CHECK-NEXT: .param i32, i32{{$}}
    159 ; CHECK-NEXT: i32.store 0($0), $1{{$}}
    160 ; CHECK-NEXT: return{{$}}
    161 define void @sti32(i32 *%p, i32 %v) {
    162   store i32 %v, i32* %p
    163   ret void
    164 }
    165 
    166 ; CHECK-LABEL: sti32_a8:
    167 ; CHECK-NEXT: .param i32, i32{{$}}
    168 ; CHECK-NEXT: i32.store 0($0), $1{{$}}
    169 ; CHECK-NEXT: return{{$}}
    170 define void @sti32_a8(i32 *%p, i32 %v) {
    171   store i32 %v, i32* %p, align 8
    172   ret void
    173 }
    174 
    175 ;===----------------------------------------------------------------------------
    176 ; Truncating stores
    177 ;===----------------------------------------------------------------------------
    178 
    179 ; CHECK-LABEL: sti8_a1:
    180 ; CHECK-NEXT: .param i32, i32{{$}}
    181 ; CHECK-NEXT: i32.store8 0($0), $1{{$}}
    182 ; CHECK-NEXT: return{{$}}
    183 define void @sti8_a1(i8 *%p, i8 %v) {
    184   store i8 %v, i8* %p, align 1
    185   ret void
    186 }
    187 
    188 ; CHECK-LABEL: sti8_a2:
    189 ; CHECK-NEXT: .param i32, i32{{$}}
    190 ; CHECK-NEXT: i32.store8 0($0), $1{{$}}
    191 ; CHECK-NEXT: return{{$}}
    192 define void @sti8_a2(i8 *%p, i8 %v) {
    193   store i8 %v, i8* %p, align 2
    194   ret void
    195 }
    196 
    197 ; CHECK-LABEL: sti16_a1:
    198 ; CHECK-NEXT: .param i32, i32{{$}}
    199 ; CHECK-NEXT: i32.store16 0($0):p2align=0, $1{{$}}
    200 ; CHECK-NEXT: return{{$}}
    201 define void @sti16_a1(i16 *%p, i16 %v) {
    202   store i16 %v, i16* %p, align 1
    203   ret void
    204 }
    205 
    206 ; CHECK-LABEL: sti16_a2:
    207 ; CHECK-NEXT: .param i32, i32{{$}}
    208 ; CHECK-NEXT: i32.store16 0($0), $1{{$}}
    209 ; CHECK-NEXT: return{{$}}
    210 define void @sti16_a2(i16 *%p, i16 %v) {
    211   store i16 %v, i16* %p, align 2
    212   ret void
    213 }
    214 
    215 ; CHECK-LABEL: sti16_a4:
    216 ; CHECK-NEXT: .param i32, i32{{$}}
    217 ; CHECK-NEXT: i32.store16 0($0), $1{{$}}
    218 ; CHECK-NEXT: return{{$}}
    219 define void @sti16_a4(i16 *%p, i16 %v) {
    220   store i16 %v, i16* %p, align 4
    221   ret void
    222 }
    223 
    224 ;===----------------------------------------------------------------------------
    225 ; Atomic loads
    226 ;===----------------------------------------------------------------------------
    227 
    228 ; Wasm atomics have the alignment field, but it must always have the type's
    229 ; natural alignment.
    230 
    231 ; CHECK-LABEL: ldi32_atomic_a4:
    232 ; CHECK-NEXT: .param i32{{$}}
    233 ; CHECK-NEXT: .result i32{{$}}
    234 ; CHECK-NEXT: i32.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
    235 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    236 define i32 @ldi32_atomic_a4(i32 *%p) {
    237   %v = load atomic i32, i32* %p seq_cst, align 4
    238   ret i32 %v
    239 }
    240 
    241 ; 8 is greater than the default alignment so it is ignored.
    242 
    243 ; CHECK-LABEL: ldi32_atomic_a8:
    244 ; CHECK-NEXT: .param i32{{$}}
    245 ; CHECK-NEXT: .result i32{{$}}
    246 ; CHECK-NEXT: i32.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
    247 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    248 define i32 @ldi32_atomic_a8(i32 *%p) {
    249   %v = load atomic i32, i32* %p seq_cst, align 8
    250   ret i32 %v
    251 }
    252 
    253 ;===----------------------------------------------------------------------------
    254 ; Atomic stores
    255 ;===----------------------------------------------------------------------------
    256 
    257 ; CHECK-LABEL: sti32_atomic_a4:
    258 ; CHECK-NEXT: .param i32, i32{{$}}
    259 ; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}
    260 ; CHECK-NEXT: return{{$}}
    261 define void @sti32_atomic_a4(i32 *%p, i32 %v) {
    262  store atomic i32 %v, i32* %p seq_cst, align 4
    263  ret void
    264 }
    265 
    266 ; 8 is greater than the default alignment so it is ignored.
    267 
    268 ; CHECK-LABEL: sti32_atomic_a8:
    269 ; CHECK-NEXT: .param i32, i32{{$}}
    270 ; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}
    271 ; CHECK-NEXT: return{{$}}
    272 define void @sti32_atomic_a8(i32 *%p, i32 %v) {
    273  store atomic i32 %v, i32* %p seq_cst, align 8
    274  ret void
    275 }
    276