diff options
Diffstat (limited to 'llvm/lib/Target')
16 files changed, 489 insertions, 246 deletions
diff --git a/llvm/lib/Target/WebAssembly/CMakeLists.txt b/llvm/lib/Target/WebAssembly/CMakeLists.txt index 46c61d89841..7f595e0a077 100644 --- a/llvm/lib/Target/WebAssembly/CMakeLists.txt +++ b/llvm/lib/Target/WebAssembly/CMakeLists.txt @@ -29,6 +29,7 @@ add_llvm_target(WebAssemblyCodeGen WebAssemblyRegNumbering.cpp WebAssemblyRegStackify.cpp WebAssemblySelectionDAGInfo.cpp + WebAssemblySetP2AlignOperands.cpp WebAssemblyStoreResults.cpp WebAssemblySubtarget.cpp WebAssemblyTargetMachine.cpp diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp index 0143b10c0ab..15dab1ec6c7 100644 --- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -93,6 +93,7 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction( const MCOperandInfo &Info = Desc.OpInfo[i]; switch (Info.OperandType) { case MCOI::OPERAND_IMMEDIATE: + case WebAssembly::OPERAND_P2ALIGN: case WebAssembly::OPERAND_BASIC_BLOCK: { if (Pos + sizeof(uint64_t) > Bytes.size()) return MCDisassembler::Fail; diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index 9a95150cb55..2ecf9be2398 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -172,6 +172,16 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } } +void +WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI, + unsigned OpNo, + raw_ostream &O) { + int64_t Imm = MI->getOperand(OpNo).getImm(); + if (Imm == WebAssembly::GetDefaultP2Align(MI->getOpcode())) + return; + O << ":p2align=" << Imm; +} + const char *llvm::WebAssembly::TypeToString(MVT Ty) { switch (Ty.SimpleTy) { case MVT::i32: diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h index 50e8ede85f8..a67ecaa2e6b 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h @@ -36,6 +36,8 @@ public: // Used by tblegen code. void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O); // Autogenerated by tblgen. void printInstruction(const MCInst *MI, raw_ostream &O); diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index a87d743fed5..df541f8c499 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -45,7 +45,9 @@ enum OperandType { /// Basic block label in a branch construct. OPERAND_BASIC_BLOCK = MCOI::OPERAND_FIRST_TARGET, /// Floating-point immediate. - OPERAND_FPIMM + OPERAND_FPIMM, + /// p2align immediate for load and store address alignment. + OPERAND_P2ALIGN }; /// WebAssembly-specific directive identifiers. @@ -86,4 +88,47 @@ enum { #define GET_SUBTARGETINFO_ENUM #include "WebAssemblyGenSubtargetInfo.inc" +namespace llvm { +namespace WebAssembly { + +/// Return the default p2align value for a load or store with the given opcode. +inline unsigned GetDefaultP2Align(unsigned Opcode) { + switch (Opcode) { + case WebAssembly::LOAD8_S_I32: + case WebAssembly::LOAD8_U_I32: + case WebAssembly::LOAD8_S_I64: + case WebAssembly::LOAD8_U_I64: + case WebAssembly::STORE8_I32: + case WebAssembly::STORE8_I64: + return 0; + case WebAssembly::LOAD16_S_I32: + case WebAssembly::LOAD16_U_I32: + case WebAssembly::LOAD16_S_I64: + case WebAssembly::LOAD16_U_I64: + case WebAssembly::STORE16_I32: + case WebAssembly::STORE16_I64: + return 1; + case WebAssembly::LOAD_I32: + case WebAssembly::LOAD_F32: + case WebAssembly::STORE_I32: + case WebAssembly::STORE_F32: + case WebAssembly::LOAD32_S_I64: + case WebAssembly::LOAD32_U_I64: + case WebAssembly::STORE32_I64: + return 2; + case WebAssembly::LOAD_I64: + case WebAssembly::LOAD_F64: + case WebAssembly::STORE_I64: + case WebAssembly::STORE_F64: + return 3; + default: llvm_unreachable("Only loads and stores have p2align values"); + } +} + +/// The operand number of the stored value in a store instruction. +static const unsigned StoreValueOperandNo = 4; + +} // end namespace WebAssembly +} // end namespace llvm + #endif diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h b/llvm/lib/Target/WebAssembly/WebAssembly.h index b4a3750de95..6ac0db84ecb 100644 --- a/llvm/lib/Target/WebAssembly/WebAssembly.h +++ b/llvm/lib/Target/WebAssembly/WebAssembly.h @@ -28,6 +28,7 @@ FunctionPass *createWebAssemblyOptimizeReturned(); FunctionPass *createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, CodeGenOpt::Level OptLevel); FunctionPass *createWebAssemblyArgumentMove(); +FunctionPass *createWebAssemblySetP2AlignOperands(); FunctionPass *createWebAssemblyStoreResults(); FunctionPass *createWebAssemblyRegStackify(); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp index 43d9b53adaf..5ea532e13c9 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -84,6 +84,7 @@ static void adjustStackPointer(unsigned StackSize, BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg) .addImm(0) .addReg(SPReg) + .addImm(2) // p2align .addMemOperand(LoadMMO); // Add/Subtract the frame size unsigned OffsetReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); @@ -102,6 +103,7 @@ static void adjustStackPointer(unsigned StackSize, BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), WebAssembly::SP32) .addImm(0) .addReg(OffsetReg) + .addImm(2) // p2align .addReg(WebAssembly::SP32) .addMemOperand(MMO); } @@ -169,6 +171,7 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), WebAssembly::SP32) .addImm(0) .addReg(OffsetReg) + .addImm(2) // p2align .addReg(WebAssembly::SP32) .addMemOperand(MMO); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index e9933b09298..3906b9d5387 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -285,6 +285,20 @@ bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL, return true; } +bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses( + EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/, + bool *Fast) const { + // WebAssembly supports unaligned accesses, though it should be declared + // with the p2align attribute on loads and stores which do so, and there + // may be a performance impact. We tell LLVM they're "fast" because + // for the kinds of things that LLVM uses this for (merging agacent stores + // of constants, etc.), WebAssembly implementations will either want the + // unaligned access or they'll split anyway. + if (Fast) + *Fast = true; + return true; +} + //===----------------------------------------------------------------------===// // WebAssembly Lowering private implementation. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h index e7232a042e1..b56f602effe 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -56,6 +56,8 @@ private: bool isCheapToSpeculateCtlz() const override; bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS) const override; + bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace, unsigned Align, + bool *Fast) const override; SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const override; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index 75b76565c3f..f761606f2e8 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -76,6 +76,12 @@ def f32imm_op : Operand<f32>; def f64imm_op : Operand<f64>; } // OperandType = "OPERAND_FPIMM" +let OperandType = "OPERAND_P2ALIGN" in { +def P2Align : Operand<i32> { + let PrintMethod = "printWebAssemblyP2AlignOperand"; +} +} // OperandType = "OPERAND_P2ALIGN" + } // OperandNamespace = "WebAssembly" //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td index b39ac5212f8..096d1875492 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td @@ -46,325 +46,354 @@ def regPlusGA : PatFrag<(ops node:$addr, node:$off), let Defs = [ARGUMENTS] in { // Basic load. -def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], - "i32.load\t$dst, ${off}(${addr})">; -def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], - "i64.load\t$dst, ${off}(${addr})">; -def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr), [], - "f32.load\t$dst, ${off}(${addr})">; -def LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr), [], - "f64.load\t$dst, ${off}(${addr})">; +def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i32.load\t$dst, ${off}(${addr})${p2align}">; +def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i64.load\t$dst, ${off}(${addr})${p2align}">; +def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "f32.load\t$dst, ${off}(${addr})${p2align}">; +def LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "f64.load\t$dst, ${off}(${addr})${p2align}">; } // Defs = [ARGUMENTS] // Select loads with no constant offset. -def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr)>; -def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr)>; -def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr)>; -def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr)>; +def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr, 0)>; +def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr, 0)>; +def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr, 0)>; +def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr, 0)>; // Select loads with a constant offset. def : Pat<(i32 (load (regPlusImm I32:$addr, imm:$off))), - (LOAD_I32 imm:$off, $addr)>; + (LOAD_I32 imm:$off, $addr, 0)>; def : Pat<(i64 (load (regPlusImm I32:$addr, imm:$off))), - (LOAD_I64 imm:$off, $addr)>; + (LOAD_I64 imm:$off, $addr, 0)>; def : Pat<(f32 (load (regPlusImm I32:$addr, imm:$off))), - (LOAD_F32 imm:$off, $addr)>; + (LOAD_F32 imm:$off, $addr, 0)>; def : Pat<(f64 (load (regPlusImm I32:$addr, imm:$off))), - (LOAD_F64 imm:$off, $addr)>; + (LOAD_F64 imm:$off, $addr, 0)>; def : Pat<(i32 (load (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD_I32 tglobaladdr:$off, $addr)>; + (LOAD_I32 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (load (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD_I64 tglobaladdr:$off, $addr)>; + (LOAD_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(f32 (load (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD_F32 tglobaladdr:$off, $addr)>; + (LOAD_F32 tglobaladdr:$off, $addr, 0)>; def : Pat<(f64 (load (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD_F64 tglobaladdr:$off, $addr)>; + (LOAD_F64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD_I32 texternalsym:$off, $addr)>; + (LOAD_I32 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD_I64 texternalsym:$off, $addr)>; + (LOAD_I64 texternalsym:$off, $addr, 0)>; def : Pat<(f32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD_F32 texternalsym:$off, $addr)>; + (LOAD_F32 texternalsym:$off, $addr, 0)>; def : Pat<(f64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD_F64 texternalsym:$off, $addr)>; + (LOAD_F64 texternalsym:$off, $addr, 0)>; // Select loads with just a constant offset. -def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0))>; -def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0))>; +def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))), - (LOAD_I32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))), - (LOAD_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))), - (LOAD_F32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD_F32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))), - (LOAD_F64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD_F64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))), - (LOAD_I32 texternalsym:$off, (CONST_I32 0))>; + (LOAD_I32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))), - (LOAD_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))), - (LOAD_F32 texternalsym:$off, (CONST_I32 0))>; + (LOAD_F32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))), - (LOAD_F64 texternalsym:$off, (CONST_I32 0))>; + (LOAD_F64 texternalsym:$off, (CONST_I32 0), 0)>; let Defs = [ARGUMENTS] in { // Extending load. -def LOAD8_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], - "i32.load8_s\t$dst, ${off}(${addr})">; -def LOAD8_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], - "i32.load8_u\t$dst, ${off}(${addr})">; -def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], - "i32.load16_s\t$dst, ${off}(${addr})">; -def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], - "i32.load16_u\t$dst, ${off}(${addr})">; -def LOAD8_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], - "i64.load8_s\t$dst, ${off}(${addr})">; -def LOAD8_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], - "i64.load8_u\t$dst, ${off}(${addr})">; -def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], - "i64.load16_s\t$dst, ${off}(${addr})">; -def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], - "i64.load16_u\t$dst, ${off}(${addr})">; -def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], - "i64.load32_s\t$dst, ${off}(${addr})">; -def LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], - "i64.load32_u\t$dst, ${off}(${addr})">; +def LOAD8_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i32.load8_s\t$dst, ${off}(${addr})${p2align}">; +def LOAD8_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i32.load8_u\t$dst, ${off}(${addr})${p2align}">; +def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i32.load16_s\t$dst, ${off}(${addr})${p2align}">; +def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i32.load16_u\t$dst, ${off}(${addr})${p2align}">; +def LOAD8_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i64.load8_s\t$dst, ${off}(${addr})${p2align}">; +def LOAD8_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i64.load8_u\t$dst, ${off}(${addr})${p2align}">; +def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i64.load16_s\t$dst, ${off}(${addr})${p2align}">; +def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i64.load16_u\t$dst, ${off}(${addr})${p2align}">; +def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i64.load32_s\t$dst, ${off}(${addr})${p2align}">; +def LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align), [], + "i64.load32_u\t$dst, ${off}(${addr})${p2align}">; } // Defs = [ARGUMENTS] // Select extending loads with no constant offset. -def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr)>; -def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>; -def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr)>; -def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>; -def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr)>; -def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>; -def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr)>; -def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>; -def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr)>; -def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>; +def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr, 0)>; +def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr, 0)>; +def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr, 0)>; +def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>; +def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr, 0)>; +def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr, 0)>; +def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr, 0)>; +def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>; +def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr, 0)>; +def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>; // Select extending loads with a constant offset. def : Pat<(i32 (sextloadi8 (regPlusImm I32:$addr, imm:$off))), - (LOAD8_S_I32 imm:$off, $addr)>; + (LOAD8_S_I32 imm:$off, $addr, 0)>; def : Pat<(i32 (zextloadi8 (regPlusImm I32:$addr, imm:$off))), - (LOAD8_U_I32 imm:$off, $addr)>; + (LOAD8_U_I32 imm:$off, $addr, 0)>; def : Pat<(i32 (sextloadi16 (regPlusImm I32:$addr, imm:$off))), - (LOAD16_S_I32 imm:$off, $addr)>; + (LOAD16_S_I32 imm:$off, $addr, 0)>; def : Pat<(i32 (zextloadi16 (regPlusImm I32:$addr, imm:$off))), - (LOAD16_U_I32 imm:$off, $addr)>; + (LOAD16_U_I32 imm:$off, $addr, 0)>; def : Pat<(i64 (sextloadi8 (regPlusImm I32:$addr, imm:$off))), - (LOAD8_S_I64 imm:$off, $addr)>; + (LOAD8_S_I64 imm:$off, $addr, 0)>; def : Pat<(i64 (zextloadi8 (regPlusImm I32:$addr, imm:$off))), - (LOAD8_U_I64 imm:$off, $addr)>; + (LOAD8_U_I64 imm:$off, $addr, 0)>; def : Pat<(i64 (sextloadi16 (regPlusImm I32:$addr, imm:$off))), - (LOAD16_S_I64 imm:$off, $addr)>; + (LOAD16_S_I64 imm:$off, $addr, 0)>; def : Pat<(i64 (zextloadi16 (regPlusImm I32:$addr, imm:$off))), - (LOAD16_U_I64 imm:$off, $addr)>; + (LOAD16_U_I64 imm:$off, $addr, 0)>; def : Pat<(i64 (sextloadi32 (regPlusImm I32:$addr, imm:$off))), - (LOAD32_S_I64 imm:$off, $addr)>; + (LOAD32_S_I64 imm:$off, $addr, 0)>; def : Pat<(i64 (zextloadi32 (regPlusImm I32:$addr, imm:$off))), - (LOAD32_U_I64 imm:$off, $addr)>; + (LOAD32_U_I64 imm:$off, $addr, 0)>; def : Pat<(i32 (sextloadi8 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD8_S_I32 tglobaladdr:$off, $addr)>; + (LOAD8_S_I32 tglobaladdr:$off, $addr, 0)>; def : Pat<(i32 (zextloadi8 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD8_U_I32 tglobaladdr:$off, $addr)>; + (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>; def : Pat<(i32 (sextloadi16 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD16_S_I32 tglobaladdr:$off, $addr)>; + (LOAD16_S_I32 tglobaladdr:$off, $addr, 0)>; def : Pat<(i32 (zextloadi16 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD16_U_I32 tglobaladdr:$off, $addr)>; + (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (sextloadi8 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD8_S_I64 tglobaladdr:$off, $addr)>; + (LOAD8_S_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (zextloadi8 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD8_U_I64 tglobaladdr:$off, $addr)>; + (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (sextloadi16 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD16_S_I64 tglobaladdr:$off, $addr)>; + (LOAD16_S_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (zextloadi16 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD16_U_I64 tglobaladdr:$off, $addr)>; + (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (sextloadi32 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD32_S_I64 tglobaladdr:$off, $addr)>; + (LOAD32_S_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (zextloadi32 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD32_U_I64 tglobaladdr:$off, $addr)>; + (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i32 (sextloadi8 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD8_S_I32 texternalsym:$off, $addr)>; + (LOAD8_S_I32 texternalsym:$off, $addr, 0)>; def : Pat<(i32 (zextloadi8 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD8_U_I32 texternalsym:$off, $addr)>; + (LOAD8_U_I32 texternalsym:$off, $addr, 0)>; def : Pat<(i32 (sextloadi16 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD16_S_I32 texternalsym:$off, $addr)>; + (LOAD16_S_I32 texternalsym:$off, $addr, 0)>; def : Pat<(i32 (zextloadi16 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD16_U_I32 texternalsym:$off, $addr)>; + (LOAD16_U_I32 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (sextloadi8 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD8_S_I64 texternalsym:$off, $addr)>; + (LOAD8_S_I64 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (zextloadi8 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD8_U_I64 texternalsym:$off, $addr)>; + (LOAD8_U_I64 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (sextloadi16 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD16_S_I64 texternalsym:$off, $addr)>; + (LOAD16_S_I64 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (zextloadi16 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD16_U_I64 texternalsym:$off, $addr)>; + (LOAD16_U_I64 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (sextloadi32 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD32_S_I64 texternalsym:$off, $addr)>; + (LOAD32_S_I64 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (zextloadi32 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD32_U_I64 texternalsym:$off, $addr)>; + (LOAD32_U_I64 texternalsym:$off, $addr, 0)>; // Select extending loads with just a constant offset. -def : Pat<(i32 (sextloadi8 imm:$off)), (LOAD8_S_I32 imm:$off, (CONST_I32 0))>; -def : Pat<(i32 (zextloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>; -def : Pat<(i32 (sextloadi16 imm:$off)), (LOAD16_S_I32 imm:$off, (CONST_I32 0))>; -def : Pat<(i32 (zextloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (sextloadi8 imm:$off)), (LOAD8_S_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (zextloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (sextloadi16 imm:$off)), (LOAD16_S_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (zextloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (sextloadi32 imm:$off)), (LOAD32_S_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (zextloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>; +def : Pat<(i32 (sextloadi8 imm:$off)), + (LOAD8_S_I32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i32 (zextloadi8 imm:$off)), + (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i32 (sextloadi16 imm:$off)), + (LOAD16_S_I32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i32 (zextloadi16 imm:$off)), + (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (sextloadi8 imm:$off)), + (LOAD8_S_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (zextloadi8 imm:$off)), + (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (sextloadi16 imm:$off)), + (LOAD16_S_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (zextloadi16 imm:$off)), + (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (sextloadi32 imm:$off)), + (LOAD32_S_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (zextloadi32 imm:$off)), + (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), - (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0))>; + (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), - (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>; + (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), - (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0))>; + (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), - (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>; + (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), - (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), - (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), - (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), - (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))), - (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))), - (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; // Resolve "don't care" extending loads to zero-extending loads. This is // somewhat arbitrary, but zero-extending is conceptually simpler. // Select "don't care" extending loads with no constant offset. -def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>; -def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>; -def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>; -def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>; -def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>; +def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr, 0)>; +def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>; +def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr, 0)>; +def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>; +def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>; // Select "don't care" extending loads with a constant offset. def : Pat<(i32 (extloadi8 (regPlusImm I32:$addr, imm:$off))), - (LOAD8_U_I32 imm:$off, $addr)>; + (LOAD8_U_I32 imm:$off, $addr, 0)>; def : Pat<(i32 (extloadi16 (regPlusImm I32:$addr, imm:$off))), - (LOAD16_U_I32 imm:$off, $addr)>; + (LOAD16_U_I32 imm:$off, $addr, 0)>; def : Pat<(i64 (extloadi8 (regPlusImm I32:$addr, imm:$off))), - (LOAD8_U_I64 imm:$off, $addr)>; + (LOAD8_U_I64 imm:$off, $addr, 0)>; def : Pat<(i64 (extloadi16 (regPlusImm I32:$addr, imm:$off))), - (LOAD16_U_I64 imm:$off, $addr)>; + (LOAD16_U_I64 imm:$off, $addr, 0)>; def : Pat<(i64 (extloadi32 (regPlusImm I32:$addr, imm:$off))), - (LOAD32_U_I64 imm:$off, $addr)>; + (LOAD32_U_I64 imm:$off, $addr, 0)>; def : Pat<(i32 (extloadi8 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD8_U_I32 tglobaladdr:$off, $addr)>; + (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>; def : Pat<(i32 (extloadi16 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD16_U_I32 tglobaladdr:$off, $addr)>; + (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (extloadi8 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD8_U_I64 tglobaladdr:$off, $addr)>; + (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (extloadi16 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD16_U_I64 tglobaladdr:$off, $addr)>; + (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i64 (extloadi32 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), - (LOAD32_U_I64 tglobaladdr:$off, $addr)>; + (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>; def : Pat<(i32 (extloadi8 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD8_U_I32 texternalsym:$off, $addr)>; + (LOAD8_U_I32 texternalsym:$off, $addr, 0)>; def : Pat<(i32 (extloadi16 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD16_U_I32 texternalsym:$off, $addr)>; + (LOAD16_U_I32 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (extloadi8 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD8_U_I64 texternalsym:$off, $addr)>; + (LOAD8_U_I64 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (extloadi16 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD16_U_I64 texternalsym:$off, $addr)>; + (LOAD16_U_I64 texternalsym:$off, $addr, 0)>; def : Pat<(i64 (extloadi32 (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), - (LOAD32_U_I64 texternalsym:$off, $addr)>; + (LOAD32_U_I64 texternalsym:$off, $addr, 0)>; // Select "don't care" extending loads with just a constant offset. -def : Pat<(i32 (extloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>; -def : Pat<(i32 (extloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (extloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (extloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>; -def : Pat<(i64 (extloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>; +def : Pat<(i32 (extloadi8 imm:$off)), + (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i32 (extloadi16 imm:$off)), + (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (extloadi8 imm:$off)), + (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (extloadi16 imm:$off)), + (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>; +def : Pat<(i64 (extloadi32 imm:$off)), + (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))), - (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))), - (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>; + (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))), - (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>; + (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))), - (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))), - (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>; + (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))), - (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; + (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; let Defs = [ARGUMENTS] in { @@ -374,193 +403,202 @@ let Defs = [ARGUMENTS] in { // instruction definition patterns that don't reference all of the output // operands. // Note: WebAssembly inverts SelectionDAG's usual operand order. -def STORE_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], - "i32.store\t$dst, ${off}(${addr}), $val">; -def STORE_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], - "i64.store\t$dst, ${off}(${addr}), $val">; -def STORE_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, F32:$val), [], - "f32.store\t$dst, ${off}(${addr}), $val">; -def STORE_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, F64:$val), [], - "f64.store\t$dst, ${off}(${addr}), $val">; +def STORE_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I32:$val), [], + "i32.store\t$dst, ${off}(${addr})${p2align}, $val">; +def STORE_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store\t$dst, ${off}(${addr})${p2align}, $val">; +def STORE_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, F32:$val), [], + "f32.store\t$dst, ${off}(${addr})${p2align}, $val">; +def STORE_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, F64:$val), [], + "f64.store\t$dst, ${off}(${addr})${p2align}, $val">; } // Defs = [ARGUMENTS] // Select stores with no constant offset. -def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, I32:$val)>; -def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, I64:$val)>; -def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, F32:$val)>; -def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, F64:$val)>; +def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, 0, I32:$val)>; +def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, 0, I64:$val)>; +def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, 0, F32:$val)>; +def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, 0, F64:$val)>; // Select stores with a constant offset. def : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE_I32 imm:$off, I32:$addr, I32:$val)>; + (STORE_I32 imm:$off, I32:$addr, 0, I32:$val)>; def : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE_I64 imm:$off, I32:$addr, I64:$val)>; + (STORE_I64 imm:$off, I32:$addr, 0, I64:$val)>; def : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE_F32 imm:$off, I32:$addr, F32:$val)>; + (STORE_F32 imm:$off, I32:$addr, 0, F32:$val)>; def : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE_F64 imm:$off, I32:$addr, F64:$val)>; + (STORE_F64 imm:$off, I32:$addr, 0, F64:$val)>; def : Pat<(store I32:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; + (STORE_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>; def : Pat<(store I64:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; + (STORE_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; def : Pat<(store F32:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE_F32 tglobaladdr:$off, I32:$addr, F32:$val)>; + (STORE_F32 tglobaladdr:$off, I32:$addr, 0, F32:$val)>; def : Pat<(store F64:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE_F64 tglobaladdr:$off, I32:$addr, F64:$val)>; + (STORE_F64 tglobaladdr:$off, I32:$addr, 0, F64:$val)>; def : Pat<(store I32:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE_I32 texternalsym:$off, I32:$addr, I32:$val)>; + (STORE_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>; def : Pat<(store I64:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE_I64 texternalsym:$off, I32:$addr, I64:$val)>; + (STORE_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>; def : Pat<(store F32:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE_F32 texternalsym:$off, I32:$addr, F32:$val)>; + (STORE_F32 texternalsym:$off, I32:$addr, 0, F32:$val)>; def : Pat<(store F64:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE_F64 texternalsym:$off, I32:$addr, F64:$val)>; + (STORE_F64 texternalsym:$off, I32:$addr, 0, F64:$val)>; // Select stores with just a constant offset. def : Pat<(store I32:$val, imm:$off), - (STORE_I32 imm:$off, (CONST_I32 0), I32:$val)>; + (STORE_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(store I64:$val, imm:$off), - (STORE_I64 imm:$off, (CONST_I32 0), I64:$val)>; + (STORE_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(store F32:$val, imm:$off), - (STORE_F32 imm:$off, (CONST_I32 0), F32:$val)>; + (STORE_F32 imm:$off, (CONST_I32 0), 0, F32:$val)>; def : Pat<(store F64:$val, imm:$off), - (STORE_F64 imm:$off, (CONST_I32 0), F64:$val)>; + (STORE_F64 imm:$off, (CONST_I32 0), 0, F64:$val)>; def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; + (STORE_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; + (STORE_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE_F32 tglobaladdr:$off, (CONST_I32 0), F32:$val)>; + (STORE_F32 tglobaladdr:$off, (CONST_I32 0), 0, F32:$val)>; def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE_F64 tglobaladdr:$off, (CONST_I32 0), F64:$val)>; + (STORE_F64 tglobaladdr:$off, (CONST_I32 0), 0, F64:$val)>; def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; + (STORE_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; + (STORE_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE_F32 texternalsym:$off, (CONST_I32 0), F32:$val)>; + (STORE_F32 texternalsym:$off, (CONST_I32 0), 0, F32:$val)>; def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE_F64 texternalsym:$off, (CONST_I32 0), F64:$val)>; + (STORE_F64 texternalsym:$off, (CONST_I32 0), 0, F64:$val)>; let Defs = [ARGUMENTS] in { // Truncating store. -def STORE8_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], - "i32.store8\t$dst, ${off}(${addr}), $val">; -def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], - "i32.store16\t$dst, ${off}(${addr}), $val">; -def STORE8_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], - "i64.store8\t$dst, ${off}(${addr}), $val">; -def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], - "i64.store16\t$dst, ${off}(${addr}), $val">; -def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], - "i64.store32\t$dst, ${off}(${addr}), $val">; +def STORE8_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I32:$val), [], + "i32.store8\t$dst, ${off}(${addr})${p2align}, $val">; +def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I32:$val), [], + "i32.store16\t$dst, ${off}(${addr})${p2align}, $val">; +def STORE8_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store8\t$dst, ${off}(${addr})${p2align}, $val">; +def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store16\t$dst, ${off}(${addr})${p2align}, $val">; +def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store32\t$dst, ${off}(${addr})${p2align}, $val">; } // Defs = [ARGUMENTS] // Select truncating stores with no constant offset. def : Pat<(truncstorei8 I32:$val, I32:$addr), - (STORE8_I32 0, I32:$addr, I32:$val)>; + (STORE8_I32 0, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei16 I32:$val, I32:$addr), - (STORE16_I32 0, I32:$addr, I32:$val)>; + (STORE16_I32 0, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei8 I64:$val, I32:$addr), - (STORE8_I64 0, I32:$addr, I64:$val)>; + (STORE8_I64 0, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei16 I64:$val, I32:$addr), - (STORE16_I64 0, I32:$addr, I64:$val)>; + (STORE16_I64 0, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei32 I64:$val, I32:$addr), - (STORE32_I64 0, I32:$addr, I64:$val)>; + (STORE32_I64 0, I32:$addr, 0, I64:$val)>; // Select truncating stores with a constant offset. def : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE8_I32 imm:$off, I32:$addr, I32:$val)>; + (STORE8_I32 imm:$off, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE16_I32 imm:$off, I32:$addr, I32:$val)>; + (STORE16_I32 imm:$off, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE8_I64 imm:$off, I32:$addr, I64:$val)>; + (STORE8_I64 imm:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE16_I64 imm:$off, I32:$addr, I64:$val)>; + (STORE16_I64 imm:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)), - (STORE32_I64 imm:$off, I32:$addr, I64:$val)>; + (STORE32_I64 imm:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei8 I32:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE8_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; + (STORE8_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei16 I32:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE16_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; + (STORE16_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei8 I64:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE8_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; + (STORE8_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei16 I64:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE16_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; + (STORE16_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei32 I64:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), - (STORE32_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; + (STORE32_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei8 I32:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE8_I32 texternalsym:$off, I32:$addr, I32:$val)>; + (STORE8_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei16 I32:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE16_I32 texternalsym:$off, I32:$addr, I32:$val)>; + (STORE16_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>; def : Pat<(truncstorei8 I64:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE8_I64 texternalsym:$off, I32:$addr, I64:$val)>; + (STORE8_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei16 I64:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE16_I64 texternalsym:$off, I32:$addr, I64:$val)>; + (STORE16_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>; def : Pat<(truncstorei32 I64:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), - (STORE32_I64 texternalsym:$off, I32:$addr, I64:$val)>; + (STORE32_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>; // Select truncating stores with just a constant offset. def : Pat<(truncstorei8 I32:$val, imm:$off), - (STORE8_I32 imm:$off, (CONST_I32 0), I32:$val)>; + (STORE8_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(truncstorei16 I32:$val, imm:$off), - (STORE16_I32 imm:$off, (CONST_I32 0), I32:$val)>; + (STORE16_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(truncstorei8 I64:$val, imm:$off), - (STORE8_I64 imm:$off, (CONST_I32 0), I64:$val)>; + (STORE8_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei16 I64:$val, imm:$off), - (STORE16_I64 imm:$off, (CONST_I32 0), I64:$val)>; + (STORE16_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei32 I64:$val, imm:$off), - (STORE32_I64 imm:$off, (CONST_I32 0), I64:$val)>; + (STORE32_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; + (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; + (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; + (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; + (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), - (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; + (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE8_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; + (STORE8_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE16_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; + (STORE16_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>; def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE8_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; + (STORE8_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE16_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; + (STORE16_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)), - (STORE32_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; + (STORE32_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; let Defs = [ARGUMENTS] in { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h index 6a60280900a..53f80ea1858 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -58,6 +58,11 @@ public: VRegStackified.resize(TargetRegisterInfo::virtReg2Index(VReg) + 1); VRegStackified.set(TargetRegisterInfo::virtReg2Index(VReg)); } + void unstackifyVReg(unsigned VReg) { + if (TargetRegisterInfo::virtReg2Index(VReg) >= VRegStackified.size()) + return; + VRegStackified.reset(TargetRegisterInfo::virtReg2Index(VReg)); + } bool isVRegStackified(unsigned VReg) const { if (TargetRegisterInfo::virtReg2Index(VReg) >= VRegStackified.size()) return false; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp index 86532651f59..76ef5c061d6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp @@ -70,8 +70,10 @@ bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) { MachineOperand &MO = MI.getOperand(0); unsigned OldReg = MO.getReg(); // TODO: Handle SP/physregs - if (OldReg == MI.getOperand(3).getReg() && - TargetRegisterInfo::isVirtualRegister(MI.getOperand(3).getReg())) { + if (OldReg == + MI.getOperand(WebAssembly::StoreValueOperandNo).getReg() && + TargetRegisterInfo::isVirtualRegister( + MI.getOperand(WebAssembly::StoreValueOperandNo).getReg())) { Changed = true; unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg)); MO.setReg(NewReg); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp b/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp new file mode 100644 index 00000000000..9ffd04e581d --- /dev/null +++ b/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp @@ -0,0 +1,108 @@ +//=- WebAssemblySetP2AlignOperands.cpp - Set alignments on loads and stores -=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file sets the p2align operands on load and store instructions. +/// +//===----------------------------------------------------------------------===// + +#include "WebAssembly.h" +#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "WebAssemblyMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "wasm-set-p2align-operands" + +namespace { +class WebAssemblySetP2AlignOperands final : public MachineFunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + WebAssemblySetP2AlignOperands() : MachineFunctionPass(ID) {} + + const char *getPassName() const override { + return "WebAssembly Set p2align Operands"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + AU.addPreserved<MachineBlockFrequencyInfo>(); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) override; +}; +} // end anonymous namespace + +char WebAssemblySetP2AlignOperands::ID = 0; +FunctionPass *llvm::createWebAssemblySetP2AlignOperands() { + return new WebAssemblySetP2AlignOperands(); +} + +bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { + DEBUG({ + dbgs() << "********** Set p2align Operands **********\n" + << "********** Function: " << MF.getName() << '\n'; + }); + + bool Changed = false; + + for (auto &MBB : MF) { + for (auto &MI : MBB) { + switch (MI.getOpcode()) { + case WebAssembly::LOAD_I32: + case WebAssembly::LOAD_I64: + case WebAssembly::LOAD_F32: + case WebAssembly::LOAD_F64: + case WebAssembly::LOAD8_S_I32: + case WebAssembly::LOAD8_U_I32: + case WebAssembly::LOAD16_S_I32: + case WebAssembly::LOAD16_U_I32: + case WebAssembly::LOAD8_S_I64: + case WebAssembly::LOAD8_U_I64: + case WebAssembly::LOAD16_S_I64: + case WebAssembly::LOAD16_U_I64: + case WebAssembly::LOAD32_S_I64: + case WebAssembly::LOAD32_U_I64: + case WebAssembly::STORE_I32: + case WebAssembly::STORE_I64: + case WebAssembly::STORE_F32: + case WebAssembly::STORE_F64: + case WebAssembly::STORE8_I32: + case WebAssembly::STORE16_I32: + case WebAssembly::STORE8_I64: + case WebAssembly::STORE16_I64: + case WebAssembly::STORE32_I64: + assert(MI.getOperand(3).getImm() == 0 && + "ISel should set p2align operands to 0"); + assert(MI.hasOneMemOperand() && + "Load and store instructions have exactly one mem operand"); + assert((*MI.memoperands_begin())->getSize() == + (UINT64_C(1) + << WebAssembly::GetDefaultP2Align(MI.getOpcode())) && + "Default p2align value should be natural"); + assert(MI.getDesc().OpInfo[3].OperandType == + WebAssembly::OPERAND_P2ALIGN && + "Load and store instructions should have a p2align operand"); + MI.getOperand(3).setImm( + Log2_64((*MI.memoperands_begin())->getAlignment())); + break; + default: + break; + } + } + } + + return Changed; +} diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp index 4e08b2b079e..a32fb171555 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp @@ -91,7 +91,8 @@ bool WebAssemblyStoreResults::runOnMachineFunction(MachineFunction &MF) { case WebAssembly::STORE_I32: case WebAssembly::STORE_I64: unsigned ToReg = MI.getOperand(0).getReg(); - unsigned FromReg = MI.getOperand(3).getReg(); + unsigned FromReg = + MI.getOperand(WebAssembly::StoreValueOperandNo).getReg(); for (auto I = MRI.use_begin(FromReg), E = MRI.use_end(); I != E;) { MachineOperand &O = *I++; MachineInstr *Where = O.getParent(); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp index 9228ecb87cf..25f009d2fb3 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -154,6 +154,10 @@ bool WebAssemblyPassConfig::addInstSelector() { // so that we can fix up the ARGUMENT instructions before anything else // sees them in the wrong place. addPass(createWebAssemblyArgumentMove()); + // Set the p2align operands. This information is present during ISel, however + // it's inconvenient to collect. Collect it now, and update the immediate + // operands. + addPass(createWebAssemblySetP2AlignOperands()); return false; } |