Home | History | Annotate | Download | only in WebAssembly
      1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | 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 ; CHECK-LABEL: ldi64_a1:
      9 ; CHECK-NEXT: .param i32{{$}}
     10 ; CHECK-NEXT: .result i64{{$}}
     11 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
     12 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     13 define i64 @ldi64_a1(i64 *%p) {
     14   %v = load i64, i64* %p, align 1
     15   ret i64 %v
     16 }
     17 
     18 ; CHECK-LABEL: ldi64_a2:
     19 ; CHECK-NEXT: .param i32{{$}}
     20 ; CHECK-NEXT: .result i64{{$}}
     21 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
     22 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     23 define i64 @ldi64_a2(i64 *%p) {
     24   %v = load i64, i64* %p, align 2
     25   ret i64 %v
     26 }
     27 
     28 ; CHECK-LABEL: ldi64_a4:
     29 ; CHECK-NEXT: .param i32{{$}}
     30 ; CHECK-NEXT: .result i64{{$}}
     31 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=2{{$}}
     32 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     33 define i64 @ldi64_a4(i64 *%p) {
     34   %v = load i64, i64* %p, align 4
     35   ret i64 %v
     36 }
     37 
     38 ; 8 is the default alignment for i64 so no attribute is needed.
     39 
     40 ; CHECK-LABEL: ldi64_a8:
     41 ; CHECK-NEXT: .param i32{{$}}
     42 ; CHECK-NEXT: .result i64{{$}}
     43 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
     44 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     45 define i64 @ldi64_a8(i64 *%p) {
     46   %v = load i64, i64* %p, align 8
     47   ret i64 %v
     48 }
     49 
     50 ; The default alignment in LLVM is the same as the defualt alignment in wasm.
     51 
     52 ; CHECK-LABEL: ldi64:
     53 ; CHECK-NEXT: .param i32{{$}}
     54 ; CHECK-NEXT: .result i64{{$}}
     55 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
     56 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     57 define i64 @ldi64(i64 *%p) {
     58   %v = load i64, i64* %p
     59   ret i64 %v
     60 }
     61 
     62 ; 16 is greater than the default alignment so it is ignored.
     63 
     64 ; CHECK-LABEL: ldi64_a16:
     65 ; CHECK-NEXT: .param i32{{$}}
     66 ; CHECK-NEXT: .result i64{{$}}
     67 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
     68 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     69 define i64 @ldi64_a16(i64 *%p) {
     70   %v = load i64, i64* %p, align 16
     71   ret i64 %v
     72 }
     73 
     74 ; Extending loads.
     75 
     76 ; CHECK-LABEL: ldi8_a1:
     77 ; CHECK-NEXT: .param i32{{$}}
     78 ; CHECK-NEXT: .result i64{{$}}
     79 ; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
     80 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     81 define i64 @ldi8_a1(i8 *%p) {
     82   %v = load i8, i8* %p, align 1
     83   %w = zext i8 %v to i64
     84   ret i64 %w
     85 }
     86 
     87 ; CHECK-LABEL: ldi8_a2:
     88 ; CHECK-NEXT: .param i32{{$}}
     89 ; CHECK-NEXT: .result i64{{$}}
     90 ; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
     91 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
     92 define i64 @ldi8_a2(i8 *%p) {
     93   %v = load i8, i8* %p, align 2
     94   %w = zext i8 %v to i64
     95   ret i64 %w
     96 }
     97 
     98 ; CHECK-LABEL: ldi16_a1:
     99 ; CHECK-NEXT: .param i32{{$}}
    100 ; CHECK-NEXT: .result i64{{$}}
    101 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
    102 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    103 define i64 @ldi16_a1(i16 *%p) {
    104   %v = load i16, i16* %p, align 1
    105   %w = zext i16 %v to i64
    106   ret i64 %w
    107 }
    108 
    109 ; CHECK-LABEL: ldi16_a2:
    110 ; CHECK-NEXT: .param i32{{$}}
    111 ; CHECK-NEXT: .result i64{{$}}
    112 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
    113 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    114 define i64 @ldi16_a2(i16 *%p) {
    115   %v = load i16, i16* %p, align 2
    116   %w = zext i16 %v to i64
    117   ret i64 %w
    118 }
    119 
    120 ; CHECK-LABEL: ldi16_a4:
    121 ; CHECK-NEXT: .param i32{{$}}
    122 ; CHECK-NEXT: .result i64{{$}}
    123 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
    124 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    125 define i64 @ldi16_a4(i16 *%p) {
    126   %v = load i16, i16* %p, align 4
    127   %w = zext i16 %v to i64
    128   ret i64 %w
    129 }
    130 
    131 ; CHECK-LABEL: ldi32_a1:
    132 ; CHECK-NEXT: .param i32{{$}}
    133 ; CHECK-NEXT: .result i64{{$}}
    134 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
    135 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    136 define i64 @ldi32_a1(i32 *%p) {
    137   %v = load i32, i32* %p, align 1
    138   %w = zext i32 %v to i64
    139   ret i64 %w
    140 }
    141 
    142 ; CHECK-LABEL: ldi32_a2:
    143 ; CHECK-NEXT: .param i32{{$}}
    144 ; CHECK-NEXT: .result i64{{$}}
    145 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
    146 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    147 define i64 @ldi32_a2(i32 *%p) {
    148   %v = load i32, i32* %p, align 2
    149   %w = zext i32 %v to i64
    150   ret i64 %w
    151 }
    152 
    153 ; CHECK-LABEL: ldi32_a4:
    154 ; CHECK-NEXT: .param i32{{$}}
    155 ; CHECK-NEXT: .result i64{{$}}
    156 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
    157 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    158 define i64 @ldi32_a4(i32 *%p) {
    159   %v = load i32, i32* %p, align 4
    160   %w = zext i32 %v to i64
    161   ret i64 %w
    162 }
    163 
    164 ; CHECK-LABEL: ldi32_a8:
    165 ; CHECK-NEXT: .param i32{{$}}
    166 ; CHECK-NEXT: .result i64{{$}}
    167 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
    168 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
    169 define i64 @ldi32_a8(i32 *%p) {
    170   %v = load i32, i32* %p, align 8
    171   %w = zext i32 %v to i64
    172   ret i64 %w
    173 }
    174 
    175 ; Stores.
    176 
    177 ; CHECK-LABEL: sti64_a1:
    178 ; CHECK-NEXT: .param i32, i64{{$}}
    179 ; CHECK-NEXT: i64.store $drop=, 0($0):p2align=0, $1{{$}}
    180 ; CHECK-NEXT: return{{$}}
    181 define void @sti64_a1(i64 *%p, i64 %v) {
    182   store i64 %v, i64* %p, align 1
    183   ret void
    184 }
    185 
    186 ; CHECK-LABEL: sti64_a2:
    187 ; CHECK-NEXT: .param i32, i64{{$}}
    188 ; CHECK-NEXT: i64.store $drop=, 0($0):p2align=1, $1{{$}}
    189 ; CHECK-NEXT: return{{$}}
    190 define void @sti64_a2(i64 *%p, i64 %v) {
    191   store i64 %v, i64* %p, align 2
    192   ret void
    193 }
    194 
    195 ; CHECK-LABEL: sti64_a4:
    196 ; CHECK-NEXT: .param i32, i64{{$}}
    197 ; CHECK-NEXT: i64.store $drop=, 0($0):p2align=2, $1{{$}}
    198 ; CHECK-NEXT: return{{$}}
    199 define void @sti64_a4(i64 *%p, i64 %v) {
    200   store i64 %v, i64* %p, align 4
    201   ret void
    202 }
    203 
    204 ; 8 is the default alignment for i32 so no attribute is needed.
    205 
    206 ; CHECK-LABEL: sti64_a8:
    207 ; CHECK-NEXT: .param i32, i64{{$}}
    208 ; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}}
    209 ; CHECK-NEXT: return{{$}}
    210 define void @sti64_a8(i64 *%p, i64 %v) {
    211   store i64 %v, i64* %p, align 8
    212   ret void
    213 }
    214 
    215 ; The default alignment in LLVM is the same as the defualt alignment in wasm.
    216 
    217 ; CHECK-LABEL: sti64:
    218 ; CHECK-NEXT: .param i32, i64{{$}}
    219 ; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}}
    220 ; CHECK-NEXT: return{{$}}
    221 define void @sti64(i64 *%p, i64 %v) {
    222   store i64 %v, i64* %p
    223   ret void
    224 }
    225 
    226 ; CHECK-LABEL: sti64_a16:
    227 ; CHECK-NEXT: .param i32, i64{{$}}
    228 ; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}}
    229 ; CHECK-NEXT: return{{$}}
    230 define void @sti64_a16(i64 *%p, i64 %v) {
    231   store i64 %v, i64* %p, align 16
    232   ret void
    233 }
    234 
    235 ; Truncating stores.
    236 
    237 ; CHECK-LABEL: sti8_a1:
    238 ; CHECK-NEXT: .param i32, i64{{$}}
    239 ; CHECK-NEXT: i64.store8 $drop=, 0($0), $1{{$}}
    240 ; CHECK-NEXT: return{{$}}
    241 define void @sti8_a1(i8 *%p, i64 %w) {
    242   %v = trunc i64 %w to i8
    243   store i8 %v, i8* %p, align 1
    244   ret void
    245 }
    246 
    247 ; CHECK-LABEL: sti8_a2:
    248 ; CHECK-NEXT: .param i32, i64{{$}}
    249 ; CHECK-NEXT: i64.store8 $drop=, 0($0), $1{{$}}
    250 ; CHECK-NEXT: return{{$}}
    251 define void @sti8_a2(i8 *%p, i64 %w) {
    252   %v = trunc i64 %w to i8
    253   store i8 %v, i8* %p, align 2
    254   ret void
    255 }
    256 
    257 ; CHECK-LABEL: sti16_a1:
    258 ; CHECK-NEXT: .param i32, i64{{$}}
    259 ; CHECK-NEXT: i64.store16 $drop=, 0($0):p2align=0, $1{{$}}
    260 ; CHECK-NEXT: return{{$}}
    261 define void @sti16_a1(i16 *%p, i64 %w) {
    262   %v = trunc i64 %w to i16
    263   store i16 %v, i16* %p, align 1
    264   ret void
    265 }
    266 
    267 ; CHECK-LABEL: sti16_a2:
    268 ; CHECK-NEXT: .param i32, i64{{$}}
    269 ; CHECK-NEXT: i64.store16 $drop=, 0($0), $1{{$}}
    270 ; CHECK-NEXT: return{{$}}
    271 define void @sti16_a2(i16 *%p, i64 %w) {
    272   %v = trunc i64 %w to i16
    273   store i16 %v, i16* %p, align 2
    274   ret void
    275 }
    276 
    277 ; CHECK-LABEL: sti16_a4:
    278 ; CHECK-NEXT: .param i32, i64{{$}}
    279 ; CHECK-NEXT: i64.store16 $drop=, 0($0), $1{{$}}
    280 ; CHECK-NEXT: return{{$}}
    281 define void @sti16_a4(i16 *%p, i64 %w) {
    282   %v = trunc i64 %w to i16
    283   store i16 %v, i16* %p, align 4
    284   ret void
    285 }
    286 
    287 ; CHECK-LABEL: sti32_a1:
    288 ; CHECK-NEXT: .param i32, i64{{$}}
    289 ; CHECK-NEXT: i64.store32 $drop=, 0($0):p2align=0, $1{{$}}
    290 ; CHECK-NEXT: return{{$}}
    291 define void @sti32_a1(i32 *%p, i64 %w) {
    292   %v = trunc i64 %w to i32
    293   store i32 %v, i32* %p, align 1
    294   ret void
    295 }
    296 
    297 ; CHECK-LABEL: sti32_a2:
    298 ; CHECK-NEXT: .param i32, i64{{$}}
    299 ; CHECK-NEXT: i64.store32 $drop=, 0($0):p2align=1, $1{{$}}
    300 ; CHECK-NEXT: return{{$}}
    301 define void @sti32_a2(i32 *%p, i64 %w) {
    302   %v = trunc i64 %w to i32
    303   store i32 %v, i32* %p, align 2
    304   ret void
    305 }
    306 
    307 ; CHECK-LABEL: sti32_a4:
    308 ; CHECK-NEXT: .param i32, i64{{$}}
    309 ; CHECK-NEXT: i64.store32 $drop=, 0($0), $1{{$}}
    310 ; CHECK-NEXT: return{{$}}
    311 define void @sti32_a4(i32 *%p, i64 %w) {
    312   %v = trunc i64 %w to i32
    313   store i32 %v, i32* %p, align 4
    314   ret void
    315 }
    316 
    317 ; CHECK-LABEL: sti32_a8:
    318 ; CHECK-NEXT: .param i32, i64{{$}}
    319 ; CHECK-NEXT: i64.store32 $drop=, 0($0), $1{{$}}
    320 ; CHECK-NEXT: return{{$}}
    321 define void @sti32_a8(i32 *%p, i64 %w) {
    322   %v = trunc i64 %w to i32
    323   store i32 %v, i32* %p, align 8
    324   ret void
    325 }
    326