WebAssemblyInstrMemory.td revision 296417
11638Srgrimes// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*- 250476Speter// 31638Srgrimes// The LLVM Compiler Infrastructure 43470Srgrimes// 53470Srgrimes// This file is distributed under the University of Illinois Open Source 61638Srgrimes// License. See LICENSE.TXT for details. 774942Sru// 823559Swosch//===----------------------------------------------------------------------===// 91638Srgrimes/// 1023559Swosch/// \file 1123559Swosch/// \brief WebAssembly Memory operand code-gen constructs. 1223559Swosch/// 1323559Swosch//===----------------------------------------------------------------------===// 1423559Swosch 1523559Swosch// TODO: 1623559Swosch// - HasAddr64 1723559Swosch// - WebAssemblyTargetLowering having to do with atomics 1823559Swosch// - Each has optional alignment. 1923559Swosch 2023559Swosch// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16 2123559Swosch// local types. These memory-only types instead zero- or sign-extend into local 2223559Swosch// types when loading, and truncate when storing. 2323559Swosch 2423559Swosch// WebAssembly constant offsets are performed as unsigned with infinite 2523559Swosch// precision, so we need to check for NoUnsignedWrap so that we don't fold an 2623559Swosch// offset for an add that needs wrapping. 271638Srgrimesdef regPlusImm : PatFrag<(ops node:$addr, node:$off), 281638Srgrimes (add node:$addr, node:$off), 291638Srgrimes [{ return N->getFlags()->hasNoUnsignedWrap(); }]>; 3023578Swosch 3123578Swosch// GlobalAddresses are conceptually unsigned values, so we can also fold them 3223578Swosch// into immediate values as long as their offsets are non-negative. 331638Srgrimesdef regPlusGA : PatFrag<(ops node:$addr, node:$off), 341638Srgrimes (add node:$addr, node:$off), 351638Srgrimes [{ 361638Srgrimes return N->getFlags()->hasNoUnsignedWrap() || 371638Srgrimes (N->getOperand(1)->getOpcode() == WebAssemblyISD::Wrapper && 381638Srgrimes isa<GlobalAddressSDNode>(N->getOperand(1)->getOperand(0)) && 391638Srgrimes cast<GlobalAddressSDNode>(N->getOperand(1)->getOperand(0)) 401638Srgrimes ->getOffset() >= 0); 411638Srgrimes}]>; 421638Srgrimes 431638Srgrimes// We don't need a regPlusES because external symbols never have constant 441638Srgrimes// offsets folded into them, so we can just use add. 451638Srgrimes 461638Srgrimeslet Defs = [ARGUMENTS] in { 471638Srgrimes 481638Srgrimes// Basic load. 491638Srgrimesdef LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 501638Srgrimes "i32.load\t$dst, ${off}(${addr})">; 511638Srgrimesdef LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 521638Srgrimes "i64.load\t$dst, ${off}(${addr})">; 531638Srgrimesdef LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr), [], 541638Srgrimes "f32.load\t$dst, ${off}(${addr})">; 551638Srgrimesdef LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr), [], 561638Srgrimes "f64.load\t$dst, ${off}(${addr})">; 571638Srgrimes 581638Srgrimes} // Defs = [ARGUMENTS] 591638Srgrimes 601638Srgrimes// Select loads with no constant offset. 611638Srgrimesdef : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr)>; 621638Srgrimesdef : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr)>; 631638Srgrimesdef : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr)>; 641638Srgrimesdef : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr)>; 651638Srgrimes 661638Srgrimes// Select loads with a constant offset. 671638Srgrimesdef : Pat<(i32 (load (regPlusImm I32:$addr, imm:$off))), 681638Srgrimes (LOAD_I32 imm:$off, $addr)>; 691638Srgrimesdef : Pat<(i64 (load (regPlusImm I32:$addr, imm:$off))), 701638Srgrimes (LOAD_I64 imm:$off, $addr)>; 711638Srgrimesdef : Pat<(f32 (load (regPlusImm I32:$addr, imm:$off))), 721638Srgrimes (LOAD_F32 imm:$off, $addr)>; 731638Srgrimesdef : Pat<(f64 (load (regPlusImm I32:$addr, imm:$off))), 741638Srgrimes (LOAD_F64 imm:$off, $addr)>; 751638Srgrimesdef : Pat<(i32 (load (regPlusGA I32:$addr, 761638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 771638Srgrimes (LOAD_I32 tglobaladdr:$off, $addr)>; 781638Srgrimesdef : Pat<(i64 (load (regPlusGA I32:$addr, 791638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 801638Srgrimes (LOAD_I64 tglobaladdr:$off, $addr)>; 811638Srgrimesdef : Pat<(f32 (load (regPlusGA I32:$addr, 821638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 831638Srgrimes (LOAD_F32 tglobaladdr:$off, $addr)>; 841638Srgrimesdef : Pat<(f64 (load (regPlusGA I32:$addr, 851638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 861638Srgrimes (LOAD_F64 tglobaladdr:$off, $addr)>; 871638Srgrimesdef : Pat<(i32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 881638Srgrimes (LOAD_I32 texternalsym:$off, $addr)>; 891638Srgrimesdef : Pat<(i64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 901638Srgrimes (LOAD_I64 texternalsym:$off, $addr)>; 911638Srgrimesdef : Pat<(f32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 921638Srgrimes (LOAD_F32 texternalsym:$off, $addr)>; 9383075Srudef : Pat<(f64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 941638Srgrimes (LOAD_F64 texternalsym:$off, $addr)>; 9583075Sru 9683075Sru// Select loads with just a constant offset. 971638Srgrimesdef : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0))>; 9883075Srudef : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0))>; 9983075Srudef : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0))>; 10083075Srudef : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0))>; 1011638Srgrimesdef : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))), 1021638Srgrimes (LOAD_I32 tglobaladdr:$off, (CONST_I32 0))>; 1031638Srgrimesdef : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))), 1041638Srgrimes (LOAD_I64 tglobaladdr:$off, (CONST_I32 0))>; 1051638Srgrimesdef : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))), 1061638Srgrimes (LOAD_F32 tglobaladdr:$off, (CONST_I32 0))>; 1071638Srgrimesdef : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))), 1081638Srgrimes (LOAD_F64 tglobaladdr:$off, (CONST_I32 0))>; 1091638Srgrimesdef : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))), 1101638Srgrimes (LOAD_I32 texternalsym:$off, (CONST_I32 0))>; 1111638Srgrimesdef : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))), 1121638Srgrimes (LOAD_I64 texternalsym:$off, (CONST_I32 0))>; 1131638Srgrimesdef : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))), 1141638Srgrimes (LOAD_F32 texternalsym:$off, (CONST_I32 0))>; 11574942Srudef : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))), 1161638Srgrimes (LOAD_F64 texternalsym:$off, (CONST_I32 0))>; 11758494Sru 1181638Srgrimeslet Defs = [ARGUMENTS] in { 1191638Srgrimes 1201638Srgrimes// Extending load. 12174942Srudef LOAD8_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 12274942Sru "i32.load8_s\t$dst, ${off}(${addr})">; 1231638Srgrimesdef LOAD8_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 1241638Srgrimes "i32.load8_u\t$dst, ${off}(${addr})">; 1251638Srgrimesdef LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 1261638Srgrimes "i32.load16_s\t$dst, ${off}(${addr})">; 1271638Srgrimesdef LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 1281638Srgrimes "i32.load16_u\t$dst, ${off}(${addr})">; 1291638Srgrimesdef LOAD8_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 1301638Srgrimes "i64.load8_s\t$dst, ${off}(${addr})">; 1311638Srgrimesdef LOAD8_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 1321638Srgrimes "i64.load8_u\t$dst, ${off}(${addr})">; 1331638Srgrimesdef LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 1341638Srgrimes "i64.load16_s\t$dst, ${off}(${addr})">; 1351638Srgrimesdef LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 1361638Srgrimes "i64.load16_u\t$dst, ${off}(${addr})">; 1371638Srgrimesdef LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 1381638Srgrimes "i64.load32_s\t$dst, ${off}(${addr})">; 1391638Srgrimesdef LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 1401638Srgrimes "i64.load32_u\t$dst, ${off}(${addr})">; 1411638Srgrimes 1421638Srgrimes} // Defs = [ARGUMENTS] 1431638Srgrimes 1441638Srgrimes// Select extending loads with no constant offset. 1451638Srgrimesdef : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr)>; 1461638Srgrimesdef : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>; 1471638Srgrimesdef : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr)>; 1481638Srgrimesdef : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>; 1491638Srgrimesdef : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr)>; 1501638Srgrimesdef : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>; 1511638Srgrimesdef : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr)>; 1521638Srgrimesdef : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>; 1531638Srgrimesdef : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr)>; 1541638Srgrimesdef : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>; 1551638Srgrimes 1561638Srgrimes// Select extending loads with a constant offset. 1571638Srgrimesdef : Pat<(i32 (sextloadi8 (regPlusImm I32:$addr, imm:$off))), 1581638Srgrimes (LOAD8_S_I32 imm:$off, $addr)>; 1591638Srgrimesdef : Pat<(i32 (zextloadi8 (regPlusImm I32:$addr, imm:$off))), 1601638Srgrimes (LOAD8_U_I32 imm:$off, $addr)>; 1611638Srgrimesdef : Pat<(i32 (sextloadi16 (regPlusImm I32:$addr, imm:$off))), 1621638Srgrimes (LOAD16_S_I32 imm:$off, $addr)>; 1631638Srgrimesdef : Pat<(i32 (zextloadi16 (regPlusImm I32:$addr, imm:$off))), 1641638Srgrimes (LOAD16_U_I32 imm:$off, $addr)>; 1651638Srgrimesdef : Pat<(i64 (sextloadi8 (regPlusImm I32:$addr, imm:$off))), 1661638Srgrimes (LOAD8_S_I64 imm:$off, $addr)>; 1671638Srgrimesdef : Pat<(i64 (zextloadi8 (regPlusImm I32:$addr, imm:$off))), 1681638Srgrimes (LOAD8_U_I64 imm:$off, $addr)>; 1691638Srgrimesdef : Pat<(i64 (sextloadi16 (regPlusImm I32:$addr, imm:$off))), 1701638Srgrimes (LOAD16_S_I64 imm:$off, $addr)>; 1711638Srgrimesdef : Pat<(i64 (zextloadi16 (regPlusImm I32:$addr, imm:$off))), 1721638Srgrimes (LOAD16_U_I64 imm:$off, $addr)>; 1731638Srgrimesdef : Pat<(i64 (sextloadi32 (regPlusImm I32:$addr, imm:$off))), 1741638Srgrimes (LOAD32_S_I64 imm:$off, $addr)>; 1751638Srgrimesdef : Pat<(i64 (zextloadi32 (regPlusImm I32:$addr, imm:$off))), 1761638Srgrimes (LOAD32_U_I64 imm:$off, $addr)>; 1771638Srgrimesdef : Pat<(i32 (sextloadi8 (regPlusGA I32:$addr, 1781638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 1791638Srgrimes (LOAD8_S_I32 tglobaladdr:$off, $addr)>; 1801638Srgrimesdef : Pat<(i32 (zextloadi8 (regPlusGA I32:$addr, 1811638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 1821638Srgrimes (LOAD8_U_I32 tglobaladdr:$off, $addr)>; 1831638Srgrimesdef : Pat<(i32 (sextloadi16 (regPlusGA I32:$addr, 1841638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 1851638Srgrimes (LOAD16_S_I32 tglobaladdr:$off, $addr)>; 1861638Srgrimesdef : Pat<(i32 (zextloadi16 (regPlusGA I32:$addr, 1871638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 1881638Srgrimes (LOAD16_U_I32 tglobaladdr:$off, $addr)>; 1891638Srgrimesdef : Pat<(i64 (sextloadi8 (regPlusGA I32:$addr, 1901638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 1911638Srgrimes (LOAD8_S_I64 tglobaladdr:$off, $addr)>; 1921638Srgrimesdef : Pat<(i64 (zextloadi8 (regPlusGA I32:$addr, 19316437Sphk (WebAssemblywrapper tglobaladdr:$off)))), 19416437Sphk (LOAD8_U_I64 tglobaladdr:$off, $addr)>; 19516437Sphkdef : Pat<(i64 (sextloadi16 (regPlusGA I32:$addr, 1961638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 1971638Srgrimes (LOAD16_S_I64 tglobaladdr:$off, $addr)>; 1981638Srgrimesdef : Pat<(i64 (zextloadi16 (regPlusGA I32:$addr, 1991638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 2001638Srgrimes (LOAD16_U_I64 tglobaladdr:$off, $addr)>; 2011638Srgrimesdef : Pat<(i64 (sextloadi32 (regPlusGA I32:$addr, 2021638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 2031638Srgrimes (LOAD32_S_I64 tglobaladdr:$off, $addr)>; 2041638Srgrimesdef : Pat<(i64 (zextloadi32 (regPlusGA I32:$addr, 2051638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 2061638Srgrimes (LOAD32_U_I64 tglobaladdr:$off, $addr)>; 2071638Srgrimesdef : Pat<(i32 (sextloadi8 (add I32:$addr, 2081638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 2091638Srgrimes (LOAD8_S_I32 texternalsym:$off, $addr)>; 2101638Srgrimesdef : Pat<(i32 (zextloadi8 (add I32:$addr, 2111638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 2121638Srgrimes (LOAD8_U_I32 texternalsym:$off, $addr)>; 2131638Srgrimesdef : Pat<(i32 (sextloadi16 (add I32:$addr, 2141638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 2151638Srgrimes (LOAD16_S_I32 texternalsym:$off, $addr)>; 2161638Srgrimesdef : Pat<(i32 (zextloadi16 (add I32:$addr, 2171638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 21874942Sru (LOAD16_U_I32 texternalsym:$off, $addr)>; 21974942Srudef : Pat<(i64 (sextloadi8 (add I32:$addr, 2201638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 2211638Srgrimes (LOAD8_S_I64 texternalsym:$off, $addr)>; 2221638Srgrimesdef : Pat<(i64 (zextloadi8 (add I32:$addr, 2231638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 22475083Sru (LOAD8_U_I64 texternalsym:$off, $addr)>; 22575083Srudef : Pat<(i64 (sextloadi16 (add I32:$addr, 22675083Sru (WebAssemblywrapper texternalsym:$off)))), 22753965Smharo (LOAD16_S_I64 texternalsym:$off, $addr)>; 2281638Srgrimesdef : Pat<(i64 (zextloadi16 (add I32:$addr, 2291638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 2301638Srgrimes (LOAD16_U_I64 texternalsym:$off, $addr)>; 2311638Srgrimesdef : Pat<(i64 (sextloadi32 (add I32:$addr, 2321638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 2331638Srgrimes (LOAD32_S_I64 texternalsym:$off, $addr)>; 2341638Srgrimesdef : Pat<(i64 (zextloadi32 (add I32:$addr, 2351638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 23614701Sbde (LOAD32_U_I64 texternalsym:$off, $addr)>; 23714701Sbde 23814701Sbde// Select extending loads with just a constant offset. 23914701Sbdedef : Pat<(i32 (sextloadi8 imm:$off)), (LOAD8_S_I32 imm:$off, (CONST_I32 0))>; 2401638Srgrimesdef : Pat<(i32 (zextloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>; 24114701Sbdedef : Pat<(i32 (sextloadi16 imm:$off)), (LOAD16_S_I32 imm:$off, (CONST_I32 0))>; 24214701Sbdedef : Pat<(i32 (zextloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>; 24314701Sbdedef : Pat<(i64 (sextloadi8 imm:$off)), (LOAD8_S_I64 imm:$off, (CONST_I32 0))>; 24414701Sbdedef : Pat<(i64 (zextloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>; 24514701Sbdedef : Pat<(i64 (sextloadi16 imm:$off)), (LOAD16_S_I64 imm:$off, (CONST_I32 0))>; 24614701Sbdedef : Pat<(i64 (zextloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>; 24714701Sbdedef : Pat<(i64 (sextloadi32 imm:$off)), (LOAD32_S_I64 imm:$off, (CONST_I32 0))>; 24814701Sbdedef : Pat<(i64 (zextloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>; 2491638Srgrimesdef : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 2501638Srgrimes (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0))>; 2511638Srgrimesdef : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 2521638Srgrimes (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 2531638Srgrimesdef : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 2541638Srgrimes (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0))>; 2551638Srgrimesdef : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 2561638Srgrimes (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 25775284Srudef : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 25875284Sru (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0))>; 25975284Srudef : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 26075284Sru (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 26175284Srudef : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 26274942Sru (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0))>; 26374942Srudef : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 2641638Srgrimes (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 2651638Srgrimesdef : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))), 2661638Srgrimes (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0))>; 2671638Srgrimesdef : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))), 2681638Srgrimes (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 2691638Srgrimesdef : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), 2701638Srgrimes (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0))>; 2711638Srgrimesdef : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), 2721638Srgrimes (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>; 2731638Srgrimesdef : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), 2741638Srgrimes (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0))>; 27558494Srudef : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), 2761638Srgrimes (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>; 2771638Srgrimesdef : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), 2781638Srgrimes (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0))>; 2791638Srgrimesdef : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), 2801638Srgrimes (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>; 2811638Srgrimesdef : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), 2821638Srgrimes (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0))>; 2831638Srgrimesdef : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), 2841638Srgrimes (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>; 2851638Srgrimesdef : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))), 2861638Srgrimes (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0))>; 2871638Srgrimesdef : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))), 2881638Srgrimes (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0))>; 2891638Srgrimes 2901638Srgrimes// Resolve "don't care" extending loads to zero-extending loads. This is 2911638Srgrimes// somewhat arbitrary, but zero-extending is conceptually simpler. 2921638Srgrimes 2931638Srgrimes// Select "don't care" extending loads with no constant offset. 2941638Srgrimesdef : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>; 2951638Srgrimesdef : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>; 2961638Srgrimesdef : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>; 2971638Srgrimesdef : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>; 2981638Srgrimesdef : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>; 2991638Srgrimes 3001638Srgrimes// Select "don't care" extending loads with a constant offset. 3011638Srgrimesdef : Pat<(i32 (extloadi8 (regPlusImm I32:$addr, imm:$off))), 3021638Srgrimes (LOAD8_U_I32 imm:$off, $addr)>; 3031638Srgrimesdef : Pat<(i32 (extloadi16 (regPlusImm I32:$addr, imm:$off))), 3041638Srgrimes (LOAD16_U_I32 imm:$off, $addr)>; 3051638Srgrimesdef : Pat<(i64 (extloadi8 (regPlusImm I32:$addr, imm:$off))), 3061638Srgrimes (LOAD8_U_I64 imm:$off, $addr)>; 3071638Srgrimesdef : Pat<(i64 (extloadi16 (regPlusImm I32:$addr, imm:$off))), 3081638Srgrimes (LOAD16_U_I64 imm:$off, $addr)>; 3091638Srgrimesdef : Pat<(i64 (extloadi32 (regPlusImm I32:$addr, imm:$off))), 3101638Srgrimes (LOAD32_U_I64 imm:$off, $addr)>; 3111638Srgrimesdef : Pat<(i32 (extloadi8 (regPlusGA I32:$addr, 3121638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 3131638Srgrimes (LOAD8_U_I32 tglobaladdr:$off, $addr)>; 3141638Srgrimesdef : Pat<(i32 (extloadi16 (regPlusGA I32:$addr, 3151638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 31674942Sru (LOAD16_U_I32 tglobaladdr:$off, $addr)>; 3171638Srgrimesdef : Pat<(i64 (extloadi8 (regPlusGA I32:$addr, 3181638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 3191638Srgrimes (LOAD8_U_I64 tglobaladdr:$off, $addr)>; 3201638Srgrimesdef : Pat<(i64 (extloadi16 (regPlusGA I32:$addr, 3211638Srgrimes (WebAssemblywrapper tglobaladdr:$off)))), 3221638Srgrimes (LOAD16_U_I64 tglobaladdr:$off, $addr)>; 32374942Srudef : Pat<(i64 (extloadi32 (regPlusGA I32:$addr, 32474942Sru (WebAssemblywrapper tglobaladdr:$off)))), 3251638Srgrimes (LOAD32_U_I64 tglobaladdr:$off, $addr)>; 3261638Srgrimesdef : Pat<(i32 (extloadi8 (add I32:$addr, 3271638Srgrimes (WebAssemblywrapper texternalsym:$off)))), 3281638Srgrimes (LOAD8_U_I32 texternalsym:$off, $addr)>; 3291638Srgrimesdef : Pat<(i32 (extloadi16 (add I32:$addr, 330 (WebAssemblywrapper texternalsym:$off)))), 331 (LOAD16_U_I32 texternalsym:$off, $addr)>; 332def : Pat<(i64 (extloadi8 (add I32:$addr, 333 (WebAssemblywrapper texternalsym:$off)))), 334 (LOAD8_U_I64 texternalsym:$off, $addr)>; 335def : Pat<(i64 (extloadi16 (add I32:$addr, 336 (WebAssemblywrapper texternalsym:$off)))), 337 (LOAD16_U_I64 texternalsym:$off, $addr)>; 338def : Pat<(i64 (extloadi32 (add I32:$addr, 339 (WebAssemblywrapper texternalsym:$off)))), 340 (LOAD32_U_I64 texternalsym:$off, $addr)>; 341 342// Select "don't care" extending loads with just a constant offset. 343def : Pat<(i32 (extloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>; 344def : Pat<(i32 (extloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>; 345def : Pat<(i64 (extloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>; 346def : Pat<(i64 (extloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>; 347def : Pat<(i64 (extloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>; 348def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), 349 (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 350def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), 351 (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 352def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), 353 (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 354def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), 355 (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 356def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))), 357 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 358def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))), 359 (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>; 360def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))), 361 (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>; 362def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))), 363 (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>; 364def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))), 365 (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>; 366def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))), 367 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 368 369let Defs = [ARGUMENTS] in { 370 371// Basic store. 372// Note that we split the patterns out of the instruction definitions because 373// WebAssembly's stores return their operand value, and tablegen doesn't like 374// instruction definition patterns that don't reference all of the output 375// operands. 376// Note: WebAssembly inverts SelectionDAG's usual operand order. 377def STORE_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], 378 "i32.store\t$dst, ${off}(${addr}), $val">; 379def STORE_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 380 "i64.store\t$dst, ${off}(${addr}), $val">; 381def STORE_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, F32:$val), [], 382 "f32.store\t$dst, ${off}(${addr}), $val">; 383def STORE_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, F64:$val), [], 384 "f64.store\t$dst, ${off}(${addr}), $val">; 385 386} // Defs = [ARGUMENTS] 387 388// Select stores with no constant offset. 389def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, I32:$val)>; 390def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, I64:$val)>; 391def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, F32:$val)>; 392def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, F64:$val)>; 393 394// Select stores with a constant offset. 395def : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)), 396 (STORE_I32 imm:$off, I32:$addr, I32:$val)>; 397def : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)), 398 (STORE_I64 imm:$off, I32:$addr, I64:$val)>; 399def : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)), 400 (STORE_F32 imm:$off, I32:$addr, F32:$val)>; 401def : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)), 402 (STORE_F64 imm:$off, I32:$addr, F64:$val)>; 403def : Pat<(store I32:$val, (regPlusGA I32:$addr, 404 (WebAssemblywrapper tglobaladdr:$off))), 405 (STORE_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; 406def : Pat<(store I64:$val, (regPlusGA I32:$addr, 407 (WebAssemblywrapper tglobaladdr:$off))), 408 (STORE_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 409def : Pat<(store F32:$val, (regPlusGA I32:$addr, 410 (WebAssemblywrapper tglobaladdr:$off))), 411 (STORE_F32 tglobaladdr:$off, I32:$addr, F32:$val)>; 412def : Pat<(store F64:$val, (regPlusGA I32:$addr, 413 (WebAssemblywrapper tglobaladdr:$off))), 414 (STORE_F64 tglobaladdr:$off, I32:$addr, F64:$val)>; 415def : Pat<(store I32:$val, (add I32:$addr, 416 (WebAssemblywrapper texternalsym:$off))), 417 (STORE_I32 texternalsym:$off, I32:$addr, I32:$val)>; 418def : Pat<(store I64:$val, (add I32:$addr, 419 (WebAssemblywrapper texternalsym:$off))), 420 (STORE_I64 texternalsym:$off, I32:$addr, I64:$val)>; 421def : Pat<(store F32:$val, (add I32:$addr, 422 (WebAssemblywrapper texternalsym:$off))), 423 (STORE_F32 texternalsym:$off, I32:$addr, F32:$val)>; 424def : Pat<(store F64:$val, (add I32:$addr, 425 (WebAssemblywrapper texternalsym:$off))), 426 (STORE_F64 texternalsym:$off, I32:$addr, F64:$val)>; 427 428// Select stores with just a constant offset. 429def : Pat<(store I32:$val, imm:$off), 430 (STORE_I32 imm:$off, (CONST_I32 0), I32:$val)>; 431def : Pat<(store I64:$val, imm:$off), 432 (STORE_I64 imm:$off, (CONST_I32 0), I64:$val)>; 433def : Pat<(store F32:$val, imm:$off), 434 (STORE_F32 imm:$off, (CONST_I32 0), F32:$val)>; 435def : Pat<(store F64:$val, imm:$off), 436 (STORE_F64 imm:$off, (CONST_I32 0), F64:$val)>; 437def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 438 (STORE_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 439def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 440 (STORE_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 441def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)), 442 (STORE_F32 tglobaladdr:$off, (CONST_I32 0), F32:$val)>; 443def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)), 444 (STORE_F64 tglobaladdr:$off, (CONST_I32 0), F64:$val)>; 445def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)), 446 (STORE_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; 447def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)), 448 (STORE_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 449def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)), 450 (STORE_F32 texternalsym:$off, (CONST_I32 0), F32:$val)>; 451def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)), 452 (STORE_F64 texternalsym:$off, (CONST_I32 0), F64:$val)>; 453 454let Defs = [ARGUMENTS] in { 455 456// Truncating store. 457def STORE8_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], 458 "i32.store8\t$dst, ${off}(${addr}), $val">; 459def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], 460 "i32.store16\t$dst, ${off}(${addr}), $val">; 461def STORE8_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 462 "i64.store8\t$dst, ${off}(${addr}), $val">; 463def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 464 "i64.store16\t$dst, ${off}(${addr}), $val">; 465def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 466 "i64.store32\t$dst, ${off}(${addr}), $val">; 467 468} // Defs = [ARGUMENTS] 469 470// Select truncating stores with no constant offset. 471def : Pat<(truncstorei8 I32:$val, I32:$addr), 472 (STORE8_I32 0, I32:$addr, I32:$val)>; 473def : Pat<(truncstorei16 I32:$val, I32:$addr), 474 (STORE16_I32 0, I32:$addr, I32:$val)>; 475def : Pat<(truncstorei8 I64:$val, I32:$addr), 476 (STORE8_I64 0, I32:$addr, I64:$val)>; 477def : Pat<(truncstorei16 I64:$val, I32:$addr), 478 (STORE16_I64 0, I32:$addr, I64:$val)>; 479def : Pat<(truncstorei32 I64:$val, I32:$addr), 480 (STORE32_I64 0, I32:$addr, I64:$val)>; 481 482// Select truncating stores with a constant offset. 483def : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)), 484 (STORE8_I32 imm:$off, I32:$addr, I32:$val)>; 485def : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)), 486 (STORE16_I32 imm:$off, I32:$addr, I32:$val)>; 487def : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)), 488 (STORE8_I64 imm:$off, I32:$addr, I64:$val)>; 489def : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)), 490 (STORE16_I64 imm:$off, I32:$addr, I64:$val)>; 491def : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)), 492 (STORE32_I64 imm:$off, I32:$addr, I64:$val)>; 493def : Pat<(truncstorei8 I32:$val, 494 (regPlusGA I32:$addr, 495 (WebAssemblywrapper tglobaladdr:$off))), 496 (STORE8_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; 497def : Pat<(truncstorei16 I32:$val, 498 (regPlusGA I32:$addr, 499 (WebAssemblywrapper tglobaladdr:$off))), 500 (STORE16_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; 501def : Pat<(truncstorei8 I64:$val, 502 (regPlusGA I32:$addr, 503 (WebAssemblywrapper tglobaladdr:$off))), 504 (STORE8_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 505def : Pat<(truncstorei16 I64:$val, 506 (regPlusGA I32:$addr, 507 (WebAssemblywrapper tglobaladdr:$off))), 508 (STORE16_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 509def : Pat<(truncstorei32 I64:$val, 510 (regPlusGA I32:$addr, 511 (WebAssemblywrapper tglobaladdr:$off))), 512 (STORE32_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 513def : Pat<(truncstorei8 I32:$val, (add I32:$addr, 514 (WebAssemblywrapper texternalsym:$off))), 515 (STORE8_I32 texternalsym:$off, I32:$addr, I32:$val)>; 516def : Pat<(truncstorei16 I32:$val, 517 (add I32:$addr, 518 (WebAssemblywrapper texternalsym:$off))), 519 (STORE16_I32 texternalsym:$off, I32:$addr, I32:$val)>; 520def : Pat<(truncstorei8 I64:$val, 521 (add I32:$addr, 522 (WebAssemblywrapper texternalsym:$off))), 523 (STORE8_I64 texternalsym:$off, I32:$addr, I64:$val)>; 524def : Pat<(truncstorei16 I64:$val, 525 (add I32:$addr, 526 (WebAssemblywrapper texternalsym:$off))), 527 (STORE16_I64 texternalsym:$off, I32:$addr, I64:$val)>; 528def : Pat<(truncstorei32 I64:$val, 529 (add I32:$addr, 530 (WebAssemblywrapper texternalsym:$off))), 531 (STORE32_I64 texternalsym:$off, I32:$addr, I64:$val)>; 532 533// Select truncating stores with just a constant offset. 534def : Pat<(truncstorei8 I32:$val, imm:$off), 535 (STORE8_I32 imm:$off, (CONST_I32 0), I32:$val)>; 536def : Pat<(truncstorei16 I32:$val, imm:$off), 537 (STORE16_I32 imm:$off, (CONST_I32 0), I32:$val)>; 538def : Pat<(truncstorei8 I64:$val, imm:$off), 539 (STORE8_I64 imm:$off, (CONST_I32 0), I64:$val)>; 540def : Pat<(truncstorei16 I64:$val, imm:$off), 541 (STORE16_I64 imm:$off, (CONST_I32 0), I64:$val)>; 542def : Pat<(truncstorei32 I64:$val, imm:$off), 543 (STORE32_I64 imm:$off, (CONST_I32 0), I64:$val)>; 544def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 545 (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 546def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 547 (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 548def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 549 (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 550def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 551 (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 552def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 553 (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 554def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)), 555 (STORE8_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; 556def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)), 557 (STORE16_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; 558def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)), 559 (STORE8_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 560def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)), 561 (STORE16_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 562def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)), 563 (STORE32_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 564 565let Defs = [ARGUMENTS] in { 566 567// Memory size. 568def MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins), 569 [(set I32:$dst, (int_wasm_memory_size))], 570 "memory_size\t$dst">, 571 Requires<[HasAddr32]>; 572def MEMORY_SIZE_I64 : I<(outs I64:$dst), (ins), 573 [(set I64:$dst, (int_wasm_memory_size))], 574 "memory_size\t$dst">, 575 Requires<[HasAddr64]>; 576 577// Grow memory. 578def GROW_MEMORY_I32 : I<(outs), (ins I32:$delta), 579 [(int_wasm_grow_memory I32:$delta)], 580 "grow_memory\t$delta">, 581 Requires<[HasAddr32]>; 582def GROW_MEMORY_I64 : I<(outs), (ins I64:$delta), 583 [(int_wasm_grow_memory I64:$delta)], 584 "grow_memory\t$delta">, 585 Requires<[HasAddr64]>; 586 587} // Defs = [ARGUMENTS] 588