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:$addr, node:$off),
     28                          (add node:$addr, node:$off),
     29                          [{ return N->getFlags()->hasNoUnsignedWrap(); }]>;
     30 
     31 // Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
     32 def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
     33   if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
     34     return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
     35 
     36   APInt KnownZero0, KnownOne0;
     37   CurDAG->computeKnownBits(N->getOperand(0), KnownZero0, KnownOne0, 0);
     38   APInt KnownZero1, KnownOne1;
     39   CurDAG->computeKnownBits(N->getOperand(1), KnownZero1, KnownOne1, 0);
     40   return (~KnownZero0 & ~KnownZero1) == 0;
     41 }]>;
     42 
     43 // GlobalAddresses are conceptually unsigned values, so we can also fold them
     44 // into immediate values as long as their offsets are non-negative.
     45 def regPlusGA : PatFrag<(ops node:$addr, node:$off),
     46                         (add node:$addr, node:$off),
     47                         [{
     48   return N->getFlags()->hasNoUnsignedWrap() ||
     49          (N->getOperand(1)->getOpcode() == WebAssemblyISD::Wrapper &&
     50           isa<GlobalAddressSDNode>(N->getOperand(1)->getOperand(0)) &&
     51           cast<GlobalAddressSDNode>(N->getOperand(1)->getOperand(0))
     52              ->getOffset() >= 0);
     53 }]>;
     54 
     55 // We don't need a regPlusES because external symbols never have constant
     56 // offsets folded into them, so we can just use add.
     57 
     58 let Defs = [ARGUMENTS] in {
     59 
     60 // Basic load.
     61 def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
     62                                    P2Align:$p2align), [],
     63                  "i32.load\t$dst, ${off}(${addr})${p2align}">;
     64 def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
     65                                    P2Align:$p2align), [],
     66                  "i64.load\t$dst, ${off}(${addr})${p2align}">;
     67 def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr,
     68                                    P2Align:$p2align), [],
     69                  "f32.load\t$dst, ${off}(${addr})${p2align}">;
     70 def LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr,
     71                                    P2Align:$p2align), [],
     72                  "f64.load\t$dst, ${off}(${addr})${p2align}">;
     73 
     74 } // Defs = [ARGUMENTS]
     75 
     76 // Select loads with no constant offset.
     77 def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr, 0)>;
     78 def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr, 0)>;
     79 def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr, 0)>;
     80 def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr, 0)>;
     81 
     82 // Select loads with a constant offset.
     83 def : Pat<(i32 (load (regPlusImm I32:$addr, imm:$off))),
     84           (LOAD_I32 imm:$off, $addr, 0)>;
     85 def : Pat<(i64 (load (regPlusImm I32:$addr, imm:$off))),
     86           (LOAD_I64 imm:$off, $addr, 0)>;
     87 def : Pat<(f32 (load (regPlusImm I32:$addr, imm:$off))),
     88           (LOAD_F32 imm:$off, $addr, 0)>;
     89 def : Pat<(f64 (load (regPlusImm I32:$addr, imm:$off))),
     90           (LOAD_F64 imm:$off, $addr, 0)>;
     91 def : Pat<(i32 (load (or_is_add I32:$addr, imm:$off))),
     92           (LOAD_I32 imm:$off, $addr, 0)>;
     93 def : Pat<(i64 (load (or_is_add I32:$addr, imm:$off))),
     94           (LOAD_I64 imm:$off, $addr, 0)>;
     95 def : Pat<(f32 (load (or_is_add I32:$addr, imm:$off))),
     96           (LOAD_F32 imm:$off, $addr, 0)>;
     97 def : Pat<(f64 (load (or_is_add I32:$addr, imm:$off))),
     98           (LOAD_F64 imm:$off, $addr, 0)>;
     99 def : Pat<(i32 (load (regPlusGA I32:$addr,
    100                                 (WebAssemblywrapper tglobaladdr:$off)))),
    101           (LOAD_I32 tglobaladdr:$off, $addr, 0)>;
    102 def : Pat<(i64 (load (regPlusGA I32:$addr,
    103                                 (WebAssemblywrapper tglobaladdr:$off)))),
    104           (LOAD_I64 tglobaladdr:$off, $addr, 0)>;
    105 def : Pat<(f32 (load (regPlusGA I32:$addr,
    106                                 (WebAssemblywrapper tglobaladdr:$off)))),
    107           (LOAD_F32 tglobaladdr:$off, $addr, 0)>;
    108 def : Pat<(f64 (load (regPlusGA I32:$addr,
    109                                 (WebAssemblywrapper tglobaladdr:$off)))),
    110           (LOAD_F64 tglobaladdr:$off, $addr, 0)>;
    111 def : Pat<(i32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
    112           (LOAD_I32 texternalsym:$off, $addr, 0)>;
    113 def : Pat<(i64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
    114           (LOAD_I64 texternalsym:$off, $addr, 0)>;
    115 def : Pat<(f32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
    116           (LOAD_F32 texternalsym:$off, $addr, 0)>;
    117 def : Pat<(f64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
    118           (LOAD_F64 texternalsym:$off, $addr, 0)>;
    119 
    120 // Select loads with just a constant offset.
    121 def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0), 0)>;
    122 def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0), 0)>;
    123 def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0), 0)>;
    124 def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0), 0)>;
    125 def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))),
    126           (LOAD_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    127 def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))),
    128           (LOAD_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    129 def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))),
    130           (LOAD_F32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    131 def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))),
    132           (LOAD_F64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    133 def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))),
    134           (LOAD_I32 texternalsym:$off, (CONST_I32 0), 0)>;
    135 def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))),
    136           (LOAD_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    137 def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))),
    138           (LOAD_F32 texternalsym:$off, (CONST_I32 0), 0)>;
    139 def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))),
    140           (LOAD_F64 texternalsym:$off, (CONST_I32 0), 0)>;
    141 
    142 let Defs = [ARGUMENTS] in {
    143 
    144 // Extending load.
    145 def LOAD8_S_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
    146                                        P2Align:$p2align), [],
    147                      "i32.load8_s\t$dst, ${off}(${addr})${p2align}">;
    148 def LOAD8_U_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
    149                                        P2Align:$p2align), [],
    150                      "i32.load8_u\t$dst, ${off}(${addr})${p2align}">;
    151 def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
    152                                        P2Align:$p2align), [],
    153                      "i32.load16_s\t$dst, ${off}(${addr})${p2align}">;
    154 def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
    155                                        P2Align:$p2align), [],
    156                      "i32.load16_u\t$dst, ${off}(${addr})${p2align}">;
    157 def LOAD8_S_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    158                                        P2Align:$p2align), [],
    159                      "i64.load8_s\t$dst, ${off}(${addr})${p2align}">;
    160 def LOAD8_U_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    161                                        P2Align:$p2align), [],
    162                      "i64.load8_u\t$dst, ${off}(${addr})${p2align}">;
    163 def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    164                                        P2Align:$p2align), [],
    165                      "i64.load16_s\t$dst, ${off}(${addr})${p2align}">;
    166 def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    167                                        P2Align:$p2align), [],
    168                      "i64.load16_u\t$dst, ${off}(${addr})${p2align}">;
    169 def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    170                                        P2Align:$p2align), [],
    171                      "i64.load32_s\t$dst, ${off}(${addr})${p2align}">;
    172 def LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    173                                        P2Align:$p2align), [],
    174                      "i64.load32_u\t$dst, ${off}(${addr})${p2align}">;
    175 
    176 } // Defs = [ARGUMENTS]
    177 
    178 // Select extending loads with no constant offset.
    179 def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr, 0)>;
    180 def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr, 0)>;
    181 def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr, 0)>;
    182 def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>;
    183 def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr, 0)>;
    184 def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr, 0)>;
    185 def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr, 0)>;
    186 def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>;
    187 def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr, 0)>;
    188 def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>;
    189 
    190 // Select extending loads with a constant offset.
    191 def : Pat<(i32 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
    192           (LOAD8_S_I32 imm:$off, $addr, 0)>;
    193 def : Pat<(i32 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
    194           (LOAD8_U_I32 imm:$off, $addr, 0)>;
    195 def : Pat<(i32 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
    196           (LOAD16_S_I32 imm:$off, $addr, 0)>;
    197 def : Pat<(i32 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
    198           (LOAD16_U_I32 imm:$off, $addr, 0)>;
    199 def : Pat<(i64 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
    200           (LOAD8_S_I64 imm:$off, $addr, 0)>;
    201 def : Pat<(i64 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
    202           (LOAD8_U_I64 imm:$off, $addr, 0)>;
    203 def : Pat<(i64 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
    204           (LOAD16_S_I64 imm:$off, $addr, 0)>;
    205 def : Pat<(i64 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
    206           (LOAD16_U_I64 imm:$off, $addr, 0)>;
    207 def : Pat<(i64 (sextloadi32 (regPlusImm I32:$addr, imm:$off))),
    208           (LOAD32_S_I64 imm:$off, $addr, 0)>;
    209 def : Pat<(i64 (zextloadi32 (regPlusImm I32:$addr, imm:$off))),
    210           (LOAD32_U_I64 imm:$off, $addr, 0)>;
    211 def : Pat<(i32 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
    212           (LOAD8_S_I32 imm:$off, $addr, 0)>;
    213 def : Pat<(i32 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
    214           (LOAD8_U_I32 imm:$off, $addr, 0)>;
    215 def : Pat<(i32 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
    216           (LOAD16_S_I32 imm:$off, $addr, 0)>;
    217 def : Pat<(i32 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
    218           (LOAD16_U_I32 imm:$off, $addr, 0)>;
    219 def : Pat<(i64 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
    220           (LOAD8_S_I64 imm:$off, $addr, 0)>;
    221 def : Pat<(i64 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
    222           (LOAD8_U_I64 imm:$off, $addr, 0)>;
    223 def : Pat<(i64 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
    224           (LOAD16_S_I64 imm:$off, $addr, 0)>;
    225 def : Pat<(i64 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
    226           (LOAD16_U_I64 imm:$off, $addr, 0)>;
    227 def : Pat<(i64 (sextloadi32 (or_is_add I32:$addr, imm:$off))),
    228           (LOAD32_S_I64 imm:$off, $addr, 0)>;
    229 def : Pat<(i64 (zextloadi32 (or_is_add I32:$addr, imm:$off))),
    230           (LOAD32_U_I64 imm:$off, $addr, 0)>;
    231 def : Pat<(i32 (sextloadi8 (regPlusGA I32:$addr,
    232                                       (WebAssemblywrapper tglobaladdr:$off)))),
    233           (LOAD8_S_I32 tglobaladdr:$off, $addr, 0)>;
    234 def : Pat<(i32 (zextloadi8 (regPlusGA I32:$addr,
    235                                       (WebAssemblywrapper tglobaladdr:$off)))),
    236           (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>;
    237 def : Pat<(i32 (sextloadi16 (regPlusGA I32:$addr,
    238                                        (WebAssemblywrapper tglobaladdr:$off)))),
    239           (LOAD16_S_I32 tglobaladdr:$off, $addr, 0)>;
    240 def : Pat<(i32 (zextloadi16 (regPlusGA I32:$addr,
    241                                        (WebAssemblywrapper tglobaladdr:$off)))),
    242           (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>;
    243 def : Pat<(i64 (sextloadi8 (regPlusGA I32:$addr,
    244                                       (WebAssemblywrapper tglobaladdr:$off)))),
    245           (LOAD8_S_I64 tglobaladdr:$off, $addr, 0)>;
    246 def : Pat<(i64 (zextloadi8 (regPlusGA I32:$addr,
    247                                       (WebAssemblywrapper tglobaladdr:$off)))),
    248           (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>;
    249 def : Pat<(i64 (sextloadi16 (regPlusGA I32:$addr,
    250                                        (WebAssemblywrapper tglobaladdr:$off)))),
    251           (LOAD16_S_I64 tglobaladdr:$off, $addr, 0)>;
    252 def : Pat<(i64 (zextloadi16 (regPlusGA I32:$addr,
    253                                        (WebAssemblywrapper tglobaladdr:$off)))),
    254           (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>;
    255 def : Pat<(i64 (sextloadi32 (regPlusGA I32:$addr,
    256                                        (WebAssemblywrapper tglobaladdr:$off)))),
    257           (LOAD32_S_I64 tglobaladdr:$off, $addr, 0)>;
    258 def : Pat<(i64 (zextloadi32 (regPlusGA I32:$addr,
    259                                        (WebAssemblywrapper tglobaladdr:$off)))),
    260           (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>;
    261 def : Pat<(i32 (sextloadi8 (add I32:$addr,
    262                                 (WebAssemblywrapper texternalsym:$off)))),
    263           (LOAD8_S_I32 texternalsym:$off, $addr, 0)>;
    264 def : Pat<(i32 (zextloadi8 (add I32:$addr,
    265                                 (WebAssemblywrapper texternalsym:$off)))),
    266           (LOAD8_U_I32 texternalsym:$off, $addr, 0)>;
    267 def : Pat<(i32 (sextloadi16 (add I32:$addr,
    268                                  (WebAssemblywrapper texternalsym:$off)))),
    269           (LOAD16_S_I32 texternalsym:$off, $addr, 0)>;
    270 def : Pat<(i32 (zextloadi16 (add I32:$addr,
    271                                  (WebAssemblywrapper texternalsym:$off)))),
    272           (LOAD16_U_I32 texternalsym:$off, $addr, 0)>;
    273 def : Pat<(i64 (sextloadi8 (add I32:$addr,
    274                                 (WebAssemblywrapper texternalsym:$off)))),
    275           (LOAD8_S_I64 texternalsym:$off, $addr, 0)>;
    276 def : Pat<(i64 (zextloadi8 (add I32:$addr,
    277                                 (WebAssemblywrapper texternalsym:$off)))),
    278           (LOAD8_U_I64 texternalsym:$off, $addr, 0)>;
    279 def : Pat<(i64 (sextloadi16 (add I32:$addr,
    280                                  (WebAssemblywrapper texternalsym:$off)))),
    281           (LOAD16_S_I64 texternalsym:$off, $addr, 0)>;
    282 def : Pat<(i64 (zextloadi16 (add I32:$addr,
    283                                  (WebAssemblywrapper texternalsym:$off)))),
    284           (LOAD16_U_I64 texternalsym:$off, $addr, 0)>;
    285 def : Pat<(i64 (sextloadi32 (add I32:$addr,
    286                                  (WebAssemblywrapper texternalsym:$off)))),
    287           (LOAD32_S_I64 texternalsym:$off, $addr, 0)>;
    288 def : Pat<(i64 (zextloadi32 (add I32:$addr,
    289                                  (WebAssemblywrapper texternalsym:$off)))),
    290           (LOAD32_U_I64 texternalsym:$off, $addr, 0)>;
    291 
    292 // Select extending loads with just a constant offset.
    293 def : Pat<(i32 (sextloadi8 imm:$off)),
    294           (LOAD8_S_I32 imm:$off, (CONST_I32 0), 0)>;
    295 def : Pat<(i32 (zextloadi8 imm:$off)),
    296           (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>;
    297 def : Pat<(i32 (sextloadi16 imm:$off)),
    298           (LOAD16_S_I32 imm:$off, (CONST_I32 0), 0)>;
    299 def : Pat<(i32 (zextloadi16 imm:$off)),
    300           (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>;
    301 def : Pat<(i64 (sextloadi8 imm:$off)),
    302           (LOAD8_S_I64 imm:$off, (CONST_I32 0), 0)>;
    303 def : Pat<(i64 (zextloadi8 imm:$off)),
    304           (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>;
    305 def : Pat<(i64 (sextloadi16 imm:$off)),
    306           (LOAD16_S_I64 imm:$off, (CONST_I32 0), 0)>;
    307 def : Pat<(i64 (zextloadi16 imm:$off)),
    308           (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>;
    309 def : Pat<(i64 (sextloadi32 imm:$off)),
    310           (LOAD32_S_I64 imm:$off, (CONST_I32 0), 0)>;
    311 def : Pat<(i64 (zextloadi32 imm:$off)),
    312           (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>;
    313 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    314           (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    315 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    316           (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    317 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    318           (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    319 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    320           (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    321 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    322           (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    323 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    324           (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    325 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    326           (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    327 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    328           (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    329 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
    330           (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    331 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
    332           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    333 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
    334           (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0), 0)>;
    335 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
    336           (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
    337 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
    338           (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0), 0)>;
    339 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
    340           (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
    341 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
    342           (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    343 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
    344           (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    345 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
    346           (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    347 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
    348           (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    349 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))),
    350           (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    351 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))),
    352           (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    353 
    354 // Resolve "don't care" extending loads to zero-extending loads. This is
    355 // somewhat arbitrary, but zero-extending is conceptually simpler.
    356 
    357 // Select "don't care" extending loads with no constant offset.
    358 def : Pat<(i32 (extloadi8 I32:$addr)),  (LOAD8_U_I32 0, $addr, 0)>;
    359 def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>;
    360 def : Pat<(i64 (extloadi8 I32:$addr)),  (LOAD8_U_I64 0, $addr, 0)>;
    361 def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>;
    362 def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>;
    363 
    364 // Select "don't care" extending loads with a constant offset.
    365 def : Pat<(i32 (extloadi8 (regPlusImm I32:$addr, imm:$off))),
    366           (LOAD8_U_I32 imm:$off, $addr, 0)>;
    367 def : Pat<(i32 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
    368           (LOAD16_U_I32 imm:$off, $addr, 0)>;
    369 def : Pat<(i64 (extloadi8 (regPlusImm I32:$addr, imm:$off))),
    370           (LOAD8_U_I64 imm:$off, $addr, 0)>;
    371 def : Pat<(i64 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
    372           (LOAD16_U_I64 imm:$off, $addr, 0)>;
    373 def : Pat<(i64 (extloadi32 (regPlusImm I32:$addr, imm:$off))),
    374           (LOAD32_U_I64 imm:$off, $addr, 0)>;
    375 def : Pat<(i32 (extloadi8 (or_is_add I32:$addr, imm:$off))),
    376           (LOAD8_U_I32 imm:$off, $addr, 0)>;
    377 def : Pat<(i32 (extloadi16 (or_is_add I32:$addr, imm:$off))),
    378           (LOAD16_U_I32 imm:$off, $addr, 0)>;
    379 def : Pat<(i64 (extloadi8 (or_is_add I32:$addr, imm:$off))),
    380           (LOAD8_U_I64 imm:$off, $addr, 0)>;
    381 def : Pat<(i64 (extloadi16 (or_is_add I32:$addr, imm:$off))),
    382           (LOAD16_U_I64 imm:$off, $addr, 0)>;
    383 def : Pat<(i64 (extloadi32 (or_is_add I32:$addr, imm:$off))),
    384           (LOAD32_U_I64 imm:$off, $addr, 0)>;
    385 def : Pat<(i32 (extloadi8 (regPlusGA I32:$addr,
    386                                      (WebAssemblywrapper tglobaladdr:$off)))),
    387           (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>;
    388 def : Pat<(i32 (extloadi16 (regPlusGA I32:$addr,
    389                                       (WebAssemblywrapper tglobaladdr:$off)))),
    390           (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>;
    391 def : Pat<(i64 (extloadi8 (regPlusGA I32:$addr,
    392                                      (WebAssemblywrapper tglobaladdr:$off)))),
    393           (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>;
    394 def : Pat<(i64 (extloadi16 (regPlusGA I32:$addr,
    395                                       (WebAssemblywrapper tglobaladdr:$off)))),
    396           (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>;
    397 def : Pat<(i64 (extloadi32 (regPlusGA I32:$addr,
    398                                       (WebAssemblywrapper tglobaladdr:$off)))),
    399           (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>;
    400 def : Pat<(i32 (extloadi8 (add I32:$addr,
    401                                (WebAssemblywrapper texternalsym:$off)))),
    402           (LOAD8_U_I32 texternalsym:$off, $addr, 0)>;
    403 def : Pat<(i32 (extloadi16 (add I32:$addr,
    404                                 (WebAssemblywrapper texternalsym:$off)))),
    405           (LOAD16_U_I32 texternalsym:$off, $addr, 0)>;
    406 def : Pat<(i64 (extloadi8 (add I32:$addr,
    407                                (WebAssemblywrapper texternalsym:$off)))),
    408           (LOAD8_U_I64 texternalsym:$off, $addr, 0)>;
    409 def : Pat<(i64 (extloadi16 (add I32:$addr,
    410                                 (WebAssemblywrapper texternalsym:$off)))),
    411           (LOAD16_U_I64 texternalsym:$off, $addr, 0)>;
    412 def : Pat<(i64 (extloadi32 (add I32:$addr,
    413                                 (WebAssemblywrapper texternalsym:$off)))),
    414           (LOAD32_U_I64 texternalsym:$off, $addr, 0)>;
    415 
    416 // Select "don't care" extending loads with just a constant offset.
    417 def : Pat<(i32 (extloadi8 imm:$off)),
    418           (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>;
    419 def : Pat<(i32 (extloadi16 imm:$off)),
    420           (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>;
    421 def : Pat<(i64 (extloadi8 imm:$off)),
    422           (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>;
    423 def : Pat<(i64 (extloadi16 imm:$off)),
    424           (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>;
    425 def : Pat<(i64 (extloadi32 imm:$off)),
    426           (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>;
    427 def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    428           (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    429 def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    430           (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
    431 def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
    432           (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    433 def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
    434           (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    435 def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))),
    436           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    437 def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
    438           (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
    439 def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
    440           (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
    441 def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
    442           (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    443 def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
    444           (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
    445 def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))),
    446           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
    447 
    448 let Defs = [ARGUMENTS] in {
    449 
    450 // Basic store.
    451 // Note that we split the patterns out of the instruction definitions because
    452 // WebAssembly's stores return their operand value, and tablegen doesn't like
    453 // instruction definition patterns that don't reference all of the output
    454 // operands.
    455 // Note: WebAssembly inverts SelectionDAG's usual operand order.
    456 def STORE_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
    457                                      P2Align:$p2align, I32:$val), [],
    458                    "i32.store\t$dst, ${off}(${addr})${p2align}, $val">;
    459 def STORE_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    460                                      P2Align:$p2align, I64:$val), [],
    461                    "i64.store\t$dst, ${off}(${addr})${p2align}, $val">;
    462 def STORE_F32  : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr,
    463                                      P2Align:$p2align, F32:$val), [],
    464                    "f32.store\t$dst, ${off}(${addr})${p2align}, $val">;
    465 def STORE_F64  : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr,
    466                                      P2Align:$p2align, F64:$val), [],
    467                    "f64.store\t$dst, ${off}(${addr})${p2align}, $val">;
    468 
    469 } // Defs = [ARGUMENTS]
    470 
    471 // Select stores with no constant offset.
    472 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, 0, I32:$val)>;
    473 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, 0, I64:$val)>;
    474 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, 0, F32:$val)>;
    475 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, 0, F64:$val)>;
    476 
    477 // Select stores with a constant offset.
    478 def : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)),
    479           (STORE_I32 imm:$off, I32:$addr, 0, I32:$val)>;
    480 def : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)),
    481           (STORE_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    482 def : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)),
    483           (STORE_F32 imm:$off, I32:$addr, 0, F32:$val)>;
    484 def : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)),
    485           (STORE_F64 imm:$off, I32:$addr, 0, F64:$val)>;
    486 def : Pat<(store I32:$val, (or_is_add I32:$addr, imm:$off)),
    487           (STORE_I32 imm:$off, I32:$addr, 0, I32:$val)>;
    488 def : Pat<(store I64:$val, (or_is_add I32:$addr, imm:$off)),
    489           (STORE_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    490 def : Pat<(store F32:$val, (or_is_add I32:$addr, imm:$off)),
    491           (STORE_F32 imm:$off, I32:$addr, 0, F32:$val)>;
    492 def : Pat<(store F64:$val, (or_is_add I32:$addr, imm:$off)),
    493           (STORE_F64 imm:$off, I32:$addr, 0, F64:$val)>;
    494 def : Pat<(store I32:$val, (regPlusGA I32:$addr,
    495                                       (WebAssemblywrapper tglobaladdr:$off))),
    496           (STORE_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>;
    497 def : Pat<(store I64:$val, (regPlusGA I32:$addr,
    498                                       (WebAssemblywrapper tglobaladdr:$off))),
    499           (STORE_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
    500 def : Pat<(store F32:$val, (regPlusGA I32:$addr,
    501                                       (WebAssemblywrapper tglobaladdr:$off))),
    502           (STORE_F32 tglobaladdr:$off, I32:$addr, 0, F32:$val)>;
    503 def : Pat<(store F64:$val, (regPlusGA I32:$addr,
    504                                       (WebAssemblywrapper tglobaladdr:$off))),
    505           (STORE_F64 tglobaladdr:$off, I32:$addr, 0, F64:$val)>;
    506 def : Pat<(store I32:$val, (add I32:$addr,
    507                                 (WebAssemblywrapper texternalsym:$off))),
    508           (STORE_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>;
    509 def : Pat<(store I64:$val, (add I32:$addr,
    510                                 (WebAssemblywrapper texternalsym:$off))),
    511           (STORE_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
    512 def : Pat<(store F32:$val, (add I32:$addr,
    513                                 (WebAssemblywrapper texternalsym:$off))),
    514           (STORE_F32 texternalsym:$off, I32:$addr, 0, F32:$val)>;
    515 def : Pat<(store F64:$val, (add I32:$addr,
    516                                 (WebAssemblywrapper texternalsym:$off))),
    517           (STORE_F64 texternalsym:$off, I32:$addr, 0, F64:$val)>;
    518 
    519 // Select stores with just a constant offset.
    520 def : Pat<(store I32:$val, imm:$off),
    521           (STORE_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>;
    522 def : Pat<(store I64:$val, imm:$off),
    523           (STORE_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
    524 def : Pat<(store F32:$val, imm:$off),
    525           (STORE_F32 imm:$off, (CONST_I32 0), 0, F32:$val)>;
    526 def : Pat<(store F64:$val, imm:$off),
    527           (STORE_F64 imm:$off, (CONST_I32 0), 0, F64:$val)>;
    528 def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    529           (STORE_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>;
    530 def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    531           (STORE_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
    532 def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    533           (STORE_F32 tglobaladdr:$off, (CONST_I32 0), 0, F32:$val)>;
    534 def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    535           (STORE_F64 tglobaladdr:$off, (CONST_I32 0), 0, F64:$val)>;
    536 def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)),
    537           (STORE_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>;
    538 def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)),
    539           (STORE_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
    540 def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)),
    541           (STORE_F32 texternalsym:$off, (CONST_I32 0), 0, F32:$val)>;
    542 def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)),
    543           (STORE_F64 texternalsym:$off, (CONST_I32 0), 0, F64:$val)>;
    544 
    545 let Defs = [ARGUMENTS] in {
    546 
    547 // Truncating store.
    548 def STORE8_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
    549                                       P2Align:$p2align, I32:$val), [],
    550                     "i32.store8\t$dst, ${off}(${addr})${p2align}, $val">;
    551 def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
    552                                       P2Align:$p2align, I32:$val), [],
    553                     "i32.store16\t$dst, ${off}(${addr})${p2align}, $val">;
    554 def STORE8_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    555                                       P2Align:$p2align, I64:$val), [],
    556                     "i64.store8\t$dst, ${off}(${addr})${p2align}, $val">;
    557 def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    558                                       P2Align:$p2align, I64:$val), [],
    559                     "i64.store16\t$dst, ${off}(${addr})${p2align}, $val">;
    560 def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
    561                                       P2Align:$p2align, I64:$val), [],
    562                     "i64.store32\t$dst, ${off}(${addr})${p2align}, $val">;
    563 
    564 } // Defs = [ARGUMENTS]
    565 
    566 // Select truncating stores with no constant offset.
    567 def : Pat<(truncstorei8 I32:$val, I32:$addr),
    568           (STORE8_I32 0, I32:$addr, 0, I32:$val)>;
    569 def : Pat<(truncstorei16 I32:$val, I32:$addr),
    570           (STORE16_I32 0, I32:$addr, 0, I32:$val)>;
    571 def : Pat<(truncstorei8 I64:$val, I32:$addr),
    572           (STORE8_I64 0, I32:$addr, 0, I64:$val)>;
    573 def : Pat<(truncstorei16 I64:$val, I32:$addr),
    574           (STORE16_I64 0, I32:$addr, 0, I64:$val)>;
    575 def : Pat<(truncstorei32 I64:$val, I32:$addr),
    576           (STORE32_I64 0, I32:$addr, 0, I64:$val)>;
    577 
    578 // Select truncating stores with a constant offset.
    579 def : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)),
    580           (STORE8_I32 imm:$off, I32:$addr, 0, I32:$val)>;
    581 def : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)),
    582           (STORE16_I32 imm:$off, I32:$addr, 0, I32:$val)>;
    583 def : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)),
    584           (STORE8_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    585 def : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)),
    586           (STORE16_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    587 def : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)),
    588           (STORE32_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    589 def : Pat<(truncstorei8 I32:$val, (or_is_add I32:$addr, imm:$off)),
    590           (STORE8_I32 imm:$off, I32:$addr, 0, I32:$val)>;
    591 def : Pat<(truncstorei16 I32:$val, (or_is_add I32:$addr, imm:$off)),
    592           (STORE16_I32 imm:$off, I32:$addr, 0, I32:$val)>;
    593 def : Pat<(truncstorei8 I64:$val, (or_is_add I32:$addr, imm:$off)),
    594           (STORE8_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    595 def : Pat<(truncstorei16 I64:$val, (or_is_add I32:$addr, imm:$off)),
    596           (STORE16_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    597 def : Pat<(truncstorei32 I64:$val, (or_is_add I32:$addr, imm:$off)),
    598           (STORE32_I64 imm:$off, I32:$addr, 0, I64:$val)>;
    599 def : Pat<(truncstorei8 I32:$val,
    600                         (regPlusGA I32:$addr,
    601                                    (WebAssemblywrapper tglobaladdr:$off))),
    602           (STORE8_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>;
    603 def : Pat<(truncstorei16 I32:$val,
    604                          (regPlusGA I32:$addr,
    605                                     (WebAssemblywrapper tglobaladdr:$off))),
    606           (STORE16_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>;
    607 def : Pat<(truncstorei8 I64:$val,
    608                         (regPlusGA I32:$addr,
    609                                    (WebAssemblywrapper tglobaladdr:$off))),
    610           (STORE8_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
    611 def : Pat<(truncstorei16 I64:$val,
    612                          (regPlusGA I32:$addr,
    613                                     (WebAssemblywrapper tglobaladdr:$off))),
    614           (STORE16_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
    615 def : Pat<(truncstorei32 I64:$val,
    616                          (regPlusGA I32:$addr,
    617                                     (WebAssemblywrapper tglobaladdr:$off))),
    618           (STORE32_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
    619 def : Pat<(truncstorei8 I32:$val, (add I32:$addr,
    620                                        (WebAssemblywrapper texternalsym:$off))),
    621           (STORE8_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>;
    622 def : Pat<(truncstorei16 I32:$val,
    623                          (add I32:$addr,
    624                               (WebAssemblywrapper texternalsym:$off))),
    625           (STORE16_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>;
    626 def : Pat<(truncstorei8 I64:$val,
    627                         (add I32:$addr,
    628                              (WebAssemblywrapper texternalsym:$off))),
    629           (STORE8_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
    630 def : Pat<(truncstorei16 I64:$val,
    631                          (add I32:$addr,
    632                               (WebAssemblywrapper texternalsym:$off))),
    633           (STORE16_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
    634 def : Pat<(truncstorei32 I64:$val,
    635                          (add I32:$addr,
    636                               (WebAssemblywrapper texternalsym:$off))),
    637           (STORE32_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
    638 
    639 // Select truncating stores with just a constant offset.
    640 def : Pat<(truncstorei8 I32:$val, imm:$off),
    641           (STORE8_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>;
    642 def : Pat<(truncstorei16 I32:$val, imm:$off),
    643           (STORE16_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>;
    644 def : Pat<(truncstorei8 I64:$val, imm:$off),
    645           (STORE8_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
    646 def : Pat<(truncstorei16 I64:$val, imm:$off),
    647           (STORE16_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
    648 def : Pat<(truncstorei32 I64:$val, imm:$off),
    649           (STORE32_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
    650 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    651           (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>;
    652 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
    653           (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>;
    654 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    655           (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
    656 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    657           (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
    658 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
    659           (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
    660 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)),
    661           (STORE8_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>;
    662 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)),
    663           (STORE16_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>;
    664 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)),
    665           (STORE8_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
    666 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)),
    667           (STORE16_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
    668 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)),
    669           (STORE32_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
    670 
    671 let Defs = [ARGUMENTS] in {
    672 
    673 // Current memory size.
    674 def CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins),
    675                            [(set I32:$dst, (int_wasm_current_memory))],
    676                            "current_memory\t$dst">,
    677                          Requires<[HasAddr32]>;
    678 def CURRENT_MEMORY_I64 : I<(outs I64:$dst), (ins),
    679                            [(set I64:$dst, (int_wasm_current_memory))],
    680                            "current_memory\t$dst">,
    681                          Requires<[HasAddr64]>;
    682 
    683 // Grow memory.
    684 def GROW_MEMORY_I32 : I<(outs), (ins I32:$delta),
    685                         [(int_wasm_grow_memory I32:$delta)],
    686                         "grow_memory\t$delta">,
    687                       Requires<[HasAddr32]>;
    688 def GROW_MEMORY_I64 : I<(outs), (ins I64:$delta),
    689                         [(int_wasm_grow_memory I64:$delta)],
    690                         "grow_memory\t$delta">,
    691                       Requires<[HasAddr64]>;
    692 
    693 } // Defs = [ARGUMENTS]
    694