Home | History | Annotate | Download | only in WebAssembly
      1 // WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*-
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief WebAssembly Memory operand code-gen constructs.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 // TODO:
     16 //  - HasAddr64
     17 //  - WebAssemblyTargetLowering having to do with atomics
     18 //  - Each has optional alignment.
     19 
     20 // WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16
     21 // local types. These memory-only types instead zero- or sign-extend into local
     22 // types when loading, and truncate when storing.
     23 
     24 // WebAssembly constant offsets are performed as unsigned with infinite
     25 // precision, so we need to check for NoUnsignedWrap so that we don't fold an
     26 // offset for an add that needs wrapping.
     27 def regPlusImm : PatFrag<(ops node:$off, node:$addr),
     28                          (add node:$addr, node:$off),
     29                          [{ return N->getFlags()->hasNoUnsignedWrap(); }]>;
     30 
     31 let Defs = [ARGUMENTS] in {
     32 
     33 // Basic load.
     34 def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
     35                  "i32.load\t$dst, ${off}(${addr})">;
     36 def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
     37                  "i64.load\t$dst, ${off}(${addr})">;
     38 def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr), [],
     39                  "f32.load\t$dst, ${off}(${addr})">;
     40 def LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr), [],
     41                  "f64.load\t$dst, ${off}(${addr})">;
     42 
     43 } // Defs = [ARGUMENTS]
     44 
     45 // Select loads with no constant offset.
     46 def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr)>;
     47 def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr)>;
     48 def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr)>;
     49 def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr)>;
     50 
     51 // Select loads with a constant offset.
     52 def : Pat<(i32 (load (regPlusImm imm:$off, I32:$addr))),
     53           (LOAD_I32 imm:$off, $addr)>;
     54 def : Pat<(i64 (load (regPlusImm imm:$off, I32:$addr))),
     55           (LOAD_I64 imm:$off, $addr)>;
     56 def : Pat<(f32 (load (regPlusImm imm:$off, I32:$addr))),
     57           (LOAD_F32 imm:$off, $addr)>;
     58 def : Pat<(f64 (load (regPlusImm imm:$off, I32:$addr))),
     59           (LOAD_F64 imm:$off, $addr)>;
     60 def : Pat<(i32 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
     61           (LOAD_I32 tglobaladdr:$off, $addr)>;
     62 def : Pat<(i64 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
     63           (LOAD_I64 tglobaladdr:$off, $addr)>;
     64 def : Pat<(f32 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
     65           (LOAD_F32 tglobaladdr:$off, $addr)>;
     66 def : Pat<(f64 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
     67           (LOAD_F64 tglobaladdr:$off, $addr)>;
     68 def : Pat<(i32 (load (regPlusImm texternalsym:$off, I32:$addr))),
     69           (LOAD_I32 texternalsym:$off, $addr)>;
     70 def : Pat<(i64 (load (regPlusImm texternalsym:$off, I32:$addr))),
     71           (LOAD_I64 texternalsym:$off, $addr)>;
     72 def : Pat<(f32 (load (regPlusImm texternalsym:$off, I32:$addr))),
     73           (LOAD_F32 texternalsym:$off, $addr)>;
     74 def : Pat<(f64 (load (regPlusImm texternalsym:$off, I32:$addr))),
     75           (LOAD_F64 texternalsym:$off, $addr)>;
     76 
     77 // Select loads with just a constant offset.
     78 def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0))>;
     79 def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0))>;
     80 def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0))>;
     81 def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0))>;
     82 def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))),
     83           (LOAD_I32 tglobaladdr:$off, (CONST_I32 0))>;
     84 def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))),
     85           (LOAD_I64 tglobaladdr:$off, (CONST_I32 0))>;
     86 def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))),
     87           (LOAD_F32 tglobaladdr:$off, (CONST_I32 0))>;
     88 def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))),
     89           (LOAD_F64 tglobaladdr:$off, (CONST_I32 0))>;
     90 def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))),
     91           (LOAD_I32 texternalsym:$off, (CONST_I32 0))>;
     92 def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))),
     93           (LOAD_I64 texternalsym:$off, (CONST_I32 0))>;
     94 def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))),
     95           (LOAD_F32 texternalsym:$off, (CONST_I32 0))>;
     96 def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))),
     97           (LOAD_F64 texternalsym:$off, (CONST_I32 0))>;
     98 
     99 let Defs = [ARGUMENTS] in {
    100 
    101 // Extending load.
    102 def LOAD8_S_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
    103                      "i32.load8_s\t$dst, ${off}(${addr})">;
    104 def LOAD8_U_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
    105                      "i32.load8_u\t$dst, ${off}(${addr})">;
    106 def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
    107                      "i32.load16_s\t$dst, ${off}(${addr})">;
    108 def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
    109                      "i32.load16_u\t$dst, ${off}(${addr})">;
    110 def LOAD8_S_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
    111                      "i64.load8_s\t$dst, ${off}(${addr})">;
    112 def LOAD8_U_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
    113                      "i64.load8_u\t$dst, ${off}(${addr})">;
    114 def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
    115                      "i64.load16_s\t$dst, ${off}(${addr})">;
    116 def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
    117                      "i64.load16_u\t$dst, ${off}(${addr})">;
    118 def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
    119                      "i64.load32_s\t$dst, ${off}(${addr})">;
    120 def LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
    121                      "i64.load32_u\t$dst, ${off}(${addr})">;
    122 
    123 } // Defs = [ARGUMENTS]
    124 
    125 // Select extending loads with no constant offset.
    126 def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr)>;
    127 def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>;
    128 def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr)>;
    129 def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>;
    130 def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr)>;
    131 def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>;
    132 def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr)>;
    133 def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>;
    134 def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr)>;
    135 def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>;
    136 
    137 // Select extending loads with a constant offset.
    138 def : Pat<(i32 (sextloadi8 (regPlusImm imm:$off, I32:$addr))),
    139           (LOAD8_S_I32 imm:$off, $addr)>;
    140 def : Pat<(i32 (zextloadi8 (regPlusImm imm:$off, I32:$addr))),
    141           (LOAD8_U_I32 imm:$off, $addr)>;
    142 def : Pat<(i32 (sextloadi16 (regPlusImm imm:$off, I32:$addr))),
    143           (LOAD16_S_I32 imm:$off, $addr)>;
    144 def : Pat<(i32 (zextloadi16 (regPlusImm imm:$off, I32:$addr))),
    145           (LOAD16_U_I32 imm:$off, $addr)>;
    146 def : Pat<(i64 (sextloadi8 (regPlusImm imm:$off, I32:$addr))),
    147           (LOAD8_S_I64 imm:$off, $addr)>;
    148 def : Pat<(i64 (zextloadi8 (regPlusImm imm:$off, I32:$addr))),
    149           (LOAD8_U_I64 imm:$off, $addr)>;
    150 def : Pat<(i64 (sextloadi16 (regPlusImm imm:$off, I32:$addr))),
    151           (LOAD16_S_I64 imm:$off, $addr)>;
    152 def : Pat<(i64 (zextloadi16 (regPlusImm imm:$off, I32:$addr))),
    153           (LOAD16_U_I64 imm:$off, $addr)>;
    154 def : Pat<(i64 (sextloadi32 (regPlusImm imm:$off, I32:$addr))),
    155           (LOAD32_S_I64 imm:$off, $addr)>;
    156 def : Pat<(i64 (zextloadi32 (regPlusImm imm:$off, I32:$addr))),
    157           (LOAD32_U_I64 imm:$off, $addr)>;
    158 def : Pat<(i32 (sextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
    159           (LOAD8_S_I32 tglobaladdr:$off, $addr)>;
    160 def : Pat<(i32 (zextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
    161           (LOAD8_U_I32 tglobaladdr:$off, $addr)>;
    162 def : Pat<(i32 (sextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
    163           (LOAD16_S_I32 tglobaladdr:$off, $addr)>;
    164 def : Pat<(i32 (zextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
    165           (LOAD16_U_I32 tglobaladdr:$off, $addr)>;
    166 def : Pat<(i64 (sextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
    167           (LOAD8_S_I64 tglobaladdr:$off, $addr)>;
    168 def : Pat<(i64 (zextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
    169           (LOAD8_U_I64 tglobaladdr:$off, $addr)>;
    170 def : Pat<(i64 (sextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
    171           (LOAD16_S_I64 tglobaladdr:$off, $addr)>;
    172 def : Pat<(i64 (zextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
    173           (LOAD16_U_I64 tglobaladdr:$off, $addr)>;
    174 def : Pat<(i64 (sextloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))),
    175           (LOAD32_S_I64 tglobaladdr:$off, $addr)>;
    176 def : Pat<(i64 (zextloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))),
    177           (LOAD32_U_I64 tglobaladdr:$off, $addr)>;
    178 def : Pat<(i32 (sextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
    179           (LOAD8_S_I32 texternalsym:$off, $addr)>;
    180 def : Pat<(i32 (zextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
    181           (LOAD8_U_I32 texternalsym:$off, $addr)>;
    182 def : Pat<(i32 (sextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
    183           (LOAD16_S_I32 texternalsym:$off, $addr)>;
    184 def : Pat<(i32 (zextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
    185           (LOAD16_U_I32 texternalsym:$off, $addr)>;
    186 def : Pat<(i64 (sextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
    187           (LOAD8_S_I64 texternalsym:$off, $addr)>;
    188 def : Pat<(i64 (zextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
    189           (LOAD8_U_I64 texternalsym:$off, $addr)>;
    190 def : Pat<(i64 (sextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
    191           (LOAD16_S_I64 texternalsym:$off, $addr)>;
    192 def : Pat<(i64 (zextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
    193           (LOAD16_U_I64 texternalsym:$off, $addr)>;
    194 def : Pat<(i64 (sextloadi32 (regPlusImm texternalsym:$off, I32:$addr))),
    195           (LOAD32_S_I64 texternalsym:$off, $addr)>;
    196 def : Pat<(i64 (zextloadi32 (regPlusImm texternalsym:$off, I32:$addr))),
    197           (LOAD32_U_I64 texternalsym:$off, $addr)>;
    198 
    199 // Select extending loads with just a constant offset.
    200 def : Pat<(i32 (sextloadi8 imm:$off)), (LOAD8_S_I32 imm:$off, (CONST_I32 0))>;
    201 def : Pat<(i32 (zextloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>;
    202 def : Pat<(i32 (sextloadi16 imm:$off)), (LOAD16_S_I32 imm:$off, (CONST_I32 0))>;
    203 def : Pat<(i32 (zextloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>;
    204 def : Pat<(i64 (sextloadi8 imm:$off)), (LOAD8_S_I64 imm:$off, (CONST_I32 0))>;
    205 def : Pat<(i64 (zextloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>;
    206 def : Pat<(i64 (sextloadi16 imm:$off)), (LOAD16_S_I64 imm:$off, (CONST_I32 0))>;
    207 def : Pat<(i64 (zextloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>;
    208 def : Pat<(i64 (sextloadi32 imm:$off)), (LOAD32_S_I64 imm:$off, (CONST_I32 0))>;
    209 def : Pat<(i64 (zextloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>;
    210 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    211           (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0))>;
    212 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    213           (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
    214 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    215           (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0))>;
    216 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    217           (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
    218 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    219           (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0))>;
    220 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    221           (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
    222 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    223           (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0))>;
    224 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    225           (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
    226 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
    227           (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0))>;
    228 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
    229           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
    230 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
    231           (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0))>;
    232 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
    233           (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>;
    234 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
    235           (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0))>;
    236 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
    237           (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>;
    238 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
    239           (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0))>;
    240 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
    241           (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>;
    242 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
    243           (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0))>;
    244 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
    245           (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>;
    246 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))),
    247           (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0))>;
    248 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))),
    249           (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0))>;
    250 
    251 // Resolve "don't care" extending loads to zero-extending loads. This is
    252 // somewhat arbitrary, but zero-extending is conceptually simpler.
    253 
    254 // Select "don't care" extending loads with no constant offset.
    255 def : Pat<(i32 (extloadi8 I32:$addr)),  (LOAD8_U_I32 0, $addr)>;
    256 def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>;
    257 def : Pat<(i64 (extloadi8 I32:$addr)),  (LOAD8_U_I64 0, $addr)>;
    258 def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>;
    259 def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>;
    260 
    261 // Select "don't care" extending loads with a constant offset.
    262 def : Pat<(i32 (extloadi8 (regPlusImm imm:$off, I32:$addr))),
    263           (LOAD8_U_I32 imm:$off, $addr)>;
    264 def : Pat<(i32 (extloadi16 (regPlusImm imm:$off, I32:$addr))),
    265           (LOAD16_U_I32 imm:$off, $addr)>;
    266 def : Pat<(i64 (extloadi8 (regPlusImm imm:$off, I32:$addr))),
    267           (LOAD8_U_I64 imm:$off, $addr)>;
    268 def : Pat<(i64 (extloadi16 (regPlusImm imm:$off, I32:$addr))),
    269           (LOAD16_U_I64 imm:$off, $addr)>;
    270 def : Pat<(i64 (extloadi32 (regPlusImm imm:$off, I32:$addr))),
    271           (LOAD32_U_I64 imm:$off, $addr)>;
    272 def : Pat<(i32 (extloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
    273           (LOAD8_U_I32 tglobaladdr:$off, $addr)>;
    274 def : Pat<(i32 (extloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
    275           (LOAD16_U_I32 tglobaladdr:$off, $addr)>;
    276 def : Pat<(i64 (extloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
    277           (LOAD8_U_I64 tglobaladdr:$off, $addr)>;
    278 def : Pat<(i64 (extloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
    279           (LOAD16_U_I64 tglobaladdr:$off, $addr)>;
    280 def : Pat<(i64 (extloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))),
    281           (LOAD32_U_I64 tglobaladdr:$off, $addr)>;
    282 def : Pat<(i32 (extloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
    283           (LOAD8_U_I32 texternalsym:$off, $addr)>;
    284 def : Pat<(i32 (extloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
    285           (LOAD16_U_I32 texternalsym:$off, $addr)>;
    286 def : Pat<(i64 (extloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
    287           (LOAD8_U_I64 texternalsym:$off, $addr)>;
    288 def : Pat<(i64 (extloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
    289           (LOAD16_U_I64 texternalsym:$off, $addr)>;
    290 def : Pat<(i64 (extloadi32 (regPlusImm texternalsym:$off, I32:$addr))),
    291           (LOAD32_U_I64 texternalsym:$off, $addr)>;
    292 
    293 // Select "don't care" extending loads with just a constant offset.
    294 def : Pat<(i32 (extloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>;
    295 def : Pat<(i32 (extloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>;
    296 def : Pat<(i64 (extloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>;
    297 def : Pat<(i64 (extloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>;
    298 def : Pat<(i64 (extloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>;
    299 def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    300           (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
    301 def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    302           (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
    303 def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    304           (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
    305 def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    306           (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
    307 def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))),
    308           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
    309 def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
    310           (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>;
    311 def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
    312           (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>;
    313 def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
    314           (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>;
    315 def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
    316           (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>;
    317 def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))),
    318           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
    319 
    320 let Defs = [ARGUMENTS] in {
    321 
    322 // Basic store.
    323 // Note that we split the patterns out of the instruction definitions because
    324 // WebAssembly's stores return their operand value, and tablegen doesn't like
    325 // instruction definition patterns that don't reference all of the output
    326 // operands.
    327 // Note: WebAssembly inverts SelectionDAG's usual operand order.
    328 def STORE_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [],
    329                    "i32.store\t$dst, ${off}(${addr}), $val">;
    330 def STORE_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
    331                    "i64.store\t$dst, ${off}(${addr}), $val">;
    332 def STORE_F32  : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, F32:$val), [],
    333                    "f32.store\t$dst, ${off}(${addr}), $val">;
    334 def STORE_F64  : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, F64:$val), [],
    335                    "f64.store\t$dst, ${off}(${addr}), $val">;
    336 
    337 } // Defs = [ARGUMENTS]
    338 
    339 // Select stores with no constant offset.
    340 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, I32:$val)>;
    341 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, I64:$val)>;
    342 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, F32:$val)>;
    343 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, F64:$val)>;
    344 
    345 // Select stores with a constant offset.
    346 def : Pat<(store I32:$val, (regPlusImm imm:$off, I32:$addr)),
    347           (STORE_I32 imm:$off, I32:$addr, I32:$val)>;
    348 def : Pat<(store I64:$val, (regPlusImm imm:$off, I32:$addr)),
    349           (STORE_I64 imm:$off, I32:$addr, I64:$val)>;
    350 def : Pat<(store F32:$val, (regPlusImm imm:$off, I32:$addr)),
    351           (STORE_F32 imm:$off, I32:$addr, F32:$val)>;
    352 def : Pat<(store F64:$val, (regPlusImm imm:$off, I32:$addr)),
    353           (STORE_F64 imm:$off, I32:$addr, F64:$val)>;
    354 def : Pat<(store I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    355           (STORE_I32 tglobaladdr:$off, I32:$addr, I32:$val)>;
    356 def : Pat<(store I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    357           (STORE_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
    358 def : Pat<(store F32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    359           (STORE_F32 tglobaladdr:$off, I32:$addr, F32:$val)>;
    360 def : Pat<(store F64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    361           (STORE_F64 tglobaladdr:$off, I32:$addr, F64:$val)>;
    362 def : Pat<(store I32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    363           (STORE_I32 texternalsym:$off, I32:$addr, I32:$val)>;
    364 def : Pat<(store I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    365           (STORE_I64 texternalsym:$off, I32:$addr, I64:$val)>;
    366 def : Pat<(store F32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    367           (STORE_F32 texternalsym:$off, I32:$addr, F32:$val)>;
    368 def : Pat<(store F64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    369           (STORE_F64 texternalsym:$off, I32:$addr, F64:$val)>;
    370 
    371 // Select stores with just a constant offset.
    372 def : Pat<(store I32:$val, imm:$off),
    373           (STORE_I32 imm:$off, (CONST_I32 0), I32:$val)>;
    374 def : Pat<(store I64:$val, imm:$off),
    375           (STORE_I64 imm:$off, (CONST_I32 0), I64:$val)>;
    376 def : Pat<(store F32:$val, imm:$off),
    377           (STORE_F32 imm:$off, (CONST_I32 0), F32:$val)>;
    378 def : Pat<(store F64:$val, imm:$off),
    379           (STORE_F64 imm:$off, (CONST_I32 0), F64:$val)>;
    380 def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    381           (STORE_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
    382 def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    383           (STORE_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
    384 def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    385           (STORE_F32 tglobaladdr:$off, (CONST_I32 0), F32:$val)>;
    386 def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    387           (STORE_F64 tglobaladdr:$off, (CONST_I32 0), F64:$val)>;
    388 def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)),
    389           (STORE_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>;
    390 def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)),
    391           (STORE_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
    392 def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)),
    393           (STORE_F32 texternalsym:$off, (CONST_I32 0), F32:$val)>;
    394 def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)),
    395           (STORE_F64 texternalsym:$off, (CONST_I32 0), F64:$val)>;
    396 
    397 let Defs = [ARGUMENTS] in {
    398 
    399 // Truncating store.
    400 def STORE8_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [],
    401                     "i32.store8\t$dst, ${off}(${addr}), $val">;
    402 def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [],
    403                     "i32.store16\t$dst, ${off}(${addr}), $val">;
    404 def STORE8_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
    405                     "i64.store8\t$dst, ${off}(${addr}), $val">;
    406 def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
    407                     "i64.store16\t$dst, ${off}(${addr}), $val">;
    408 def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
    409                     "i64.store32\t$dst, ${off}(${addr}), $val">;
    410 
    411 } // Defs = [ARGUMENTS]
    412 
    413 // Select truncating stores with no constant offset.
    414 def : Pat<(truncstorei8 I32:$val, I32:$addr),
    415           (STORE8_I32 0, I32:$addr, I32:$val)>;
    416 def : Pat<(truncstorei16 I32:$val, I32:$addr),
    417           (STORE16_I32 0, I32:$addr, I32:$val)>;
    418 def : Pat<(truncstorei8 I64:$val, I32:$addr),
    419           (STORE8_I64 0, I32:$addr, I64:$val)>;
    420 def : Pat<(truncstorei16 I64:$val, I32:$addr),
    421           (STORE16_I64 0, I32:$addr, I64:$val)>;
    422 def : Pat<(truncstorei32 I64:$val, I32:$addr),
    423           (STORE32_I64 0, I32:$addr, I64:$val)>;
    424 
    425 // Select truncating stores with a constant offset.
    426 def : Pat<(truncstorei8 I32:$val, (regPlusImm imm:$off, I32:$addr)),
    427           (STORE8_I32 imm:$off, I32:$addr, I32:$val)>;
    428 def : Pat<(truncstorei16 I32:$val, (regPlusImm imm:$off, I32:$addr)),
    429           (STORE16_I32 imm:$off, I32:$addr, I32:$val)>;
    430 def : Pat<(truncstorei8 I64:$val, (regPlusImm imm:$off, I32:$addr)),
    431           (STORE8_I64 imm:$off, I32:$addr, I64:$val)>;
    432 def : Pat<(truncstorei16 I64:$val, (regPlusImm imm:$off, I32:$addr)),
    433           (STORE16_I64 imm:$off, I32:$addr, I64:$val)>;
    434 def : Pat<(truncstorei32 I64:$val, (regPlusImm imm:$off, I32:$addr)),
    435           (STORE32_I64 imm:$off, I32:$addr, I64:$val)>;
    436 def : Pat<(truncstorei8 I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    437           (STORE8_I32 tglobaladdr:$off, I32:$addr, I32:$val)>;
    438 def : Pat<(truncstorei16 I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    439           (STORE16_I32 tglobaladdr:$off, I32:$addr, I32:$val)>;
    440 def : Pat<(truncstorei8 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    441           (STORE8_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
    442 def : Pat<(truncstorei16 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    443           (STORE16_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
    444 def : Pat<(truncstorei32 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
    445           (STORE32_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
    446 def : Pat<(truncstorei8 I32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    447           (STORE8_I32 texternalsym:$off, I32:$addr, I32:$val)>;
    448 def : Pat<(truncstorei16 I32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    449           (STORE16_I32 texternalsym:$off, I32:$addr, I32:$val)>;
    450 def : Pat<(truncstorei8 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    451           (STORE8_I64 texternalsym:$off, I32:$addr, I64:$val)>;
    452 def : Pat<(truncstorei16 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    453           (STORE16_I64 texternalsym:$off, I32:$addr, I64:$val)>;
    454 def : Pat<(truncstorei32 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
    455           (STORE32_I64 texternalsym:$off, I32:$addr, I64:$val)>;
    456 
    457 // Select truncating stores with just a constant offset.
    458 def : Pat<(truncstorei8 I32:$val, imm:$off),
    459           (STORE8_I32 imm:$off, (CONST_I32 0), I32:$val)>;
    460 def : Pat<(truncstorei16 I32:$val, imm:$off),
    461           (STORE16_I32 imm:$off, (CONST_I32 0), I32:$val)>;
    462 def : Pat<(truncstorei8 I64:$val, imm:$off),
    463           (STORE8_I64 imm:$off, (CONST_I32 0), I64:$val)>;
    464 def : Pat<(truncstorei16 I64:$val, imm:$off),
    465           (STORE16_I64 imm:$off, (CONST_I32 0), I64:$val)>;
    466 def : Pat<(truncstorei32 I64:$val, imm:$off),
    467           (STORE32_I64 imm:$off, (CONST_I32 0), I64:$val)>;
    468 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    469           (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
    470 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    471           (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
    472 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    473           (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
    474 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    475           (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
    476 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    477           (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
    478 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)),
    479           (STORE8_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>;
    480 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)),
    481           (STORE16_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>;
    482 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)),
    483           (STORE8_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
    484 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)),
    485           (STORE16_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
    486 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)),
    487           (STORE32_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
    488 
    489 let Defs = [ARGUMENTS] in {
    490 
    491 // Memory size.
    492 def MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins),
    493                         [(set I32:$dst, (int_wasm_memory_size))],
    494                         "memory_size\t$dst">,
    495                       Requires<[HasAddr32]>;
    496 def MEMORY_SIZE_I64 : I<(outs I64:$dst), (ins),
    497                         [(set I64:$dst, (int_wasm_memory_size))],
    498                         "memory_size\t$dst">,
    499                       Requires<[HasAddr64]>;
    500 
    501 // Grow memory.
    502 def GROW_MEMORY_I32 : I<(outs), (ins I32:$delta),
    503                         [(int_wasm_grow_memory I32:$delta)],
    504                         "grow_memory\t$delta">,
    505                       Requires<[HasAddr32]>;
    506 def GROW_MEMORY_I64 : I<(outs), (ins I64:$delta),
    507                         [(int_wasm_grow_memory I64:$delta)],
    508                         "grow_memory\t$delta">,
    509                       Requires<[HasAddr64]>;
    510 
    511 } // Defs = [ARGUMENTS]
    512