diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
7 files changed, 64 insertions, 88 deletions
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 0fc65e5a836..c7d6efb794f 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -134,9 +134,12 @@ inline unsigned GetDefaultP2Align(unsigned Opcode) { } /// The operand number of the load or store address in load/store instructions. -static const unsigned MemOpAddressOperandNo = 2; -/// The operand number of the stored value in a store instruction. -static const unsigned StoreValueOperandNo = 4; +static const unsigned LoadAddressOperandNo = 2; +static const unsigned StoreAddressOperandNo = 1; + +/// The operand number of the load or store p2align in load/store instructions. +static const unsigned LoadP2AlignOperandNo = 3; +static const unsigned StoreP2AlignOperandNo = 2; } // end namespace WebAssembly } // end namespace llvm diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 2f409622795..64d4dae9647 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -1092,34 +1092,27 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) { return false; unsigned Opc; - const TargetRegisterClass *RC; bool VTIsi1 = false; switch (getSimpleType(Store->getValueOperand()->getType())) { case MVT::i1: VTIsi1 = true; case MVT::i8: Opc = WebAssembly::STORE8_I32; - RC = &WebAssembly::I32RegClass; break; case MVT::i16: Opc = WebAssembly::STORE16_I32; - RC = &WebAssembly::I32RegClass; break; case MVT::i32: Opc = WebAssembly::STORE_I32; - RC = &WebAssembly::I32RegClass; break; case MVT::i64: Opc = WebAssembly::STORE_I64; - RC = &WebAssembly::I64RegClass; break; case MVT::f32: Opc = WebAssembly::STORE_F32; - RC = &WebAssembly::F32RegClass; break; case MVT::f64: Opc = WebAssembly::STORE_F64; - RC = &WebAssembly::F64RegClass; break; default: return false; } @@ -1132,9 +1125,7 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) { if (VTIsi1) ValueReg = maskI1Value(ValueReg, Store->getValueOperand()); - unsigned ResultReg = createResultReg(RC); - auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), - ResultReg); + auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store)); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp index 99205402653..6523ea55966 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -88,7 +88,6 @@ static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, const TargetRegisterClass *PtrRC = MRI.getTargetRegisterInfo()->getPointerRegClass(MF); unsigned Zero = MRI.createVirtualRegister(PtrRC); - unsigned Drop = MRI.createVirtualRegister(PtrRC); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), Zero) @@ -96,7 +95,7 @@ static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, MachineMemOperand *MMO = MF.getMachineMemOperand( MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)), MachineMemOperand::MOStore, 4, 4); - BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32), Drop) + BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32)) .addExternalSymbol(SPSymbol) .addReg(Zero) .addImm(2) // p2align diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td index 7535ece1c2d..2a96aa04ca3 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td @@ -446,23 +446,19 @@ def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))), let Defs = [ARGUMENTS] in { // Basic store. -// Note that we split the patterns out of the instruction definitions because -// WebAssembly's stores return their operand value, and tablegen doesn't like -// 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, - P2Align:$p2align, I32:$val), [], - "i32.store\t$dst, ${off}(${addr})${p2align}, $val", 0x33>; -def STORE_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, I64:$val), [], - "i64.store\t$dst, ${off}(${addr})${p2align}, $val", 0x34>; -def STORE_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, F32:$val), [], - "f32.store\t$dst, ${off}(${addr})${p2align}, $val", 0x35>; -def STORE_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, F64:$val), [], - "f64.store\t$dst, ${off}(${addr})${p2align}, $val", 0x36>; +def STORE_I32 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I32:$val), [], + "i32.store\t${off}(${addr})${p2align}, $val", 0x33>; +def STORE_I64 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store\t${off}(${addr})${p2align}, $val", 0x34>; +def STORE_F32 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, F32:$val), [], + "f32.store\t${off}(${addr})${p2align}, $val", 0x35>; +def STORE_F64 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, F64:$val), [], + "f64.store\t${off}(${addr})${p2align}, $val", 0x36>; } // Defs = [ARGUMENTS] @@ -543,21 +539,21 @@ def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)), let Defs = [ARGUMENTS] in { // Truncating store. -def STORE8_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, I32:$val), [], - "i32.store8\t$dst, ${off}(${addr})${p2align}, $val", 0x2e>; -def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, I32:$val), [], - "i32.store16\t$dst, ${off}(${addr})${p2align}, $val", 0x2f>; -def STORE8_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, I64:$val), [], - "i64.store8\t$dst, ${off}(${addr})${p2align}, $val", 0x30>; -def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, I64:$val), [], - "i64.store16\t$dst, ${off}(${addr})${p2align}, $val", 0x31>; -def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, - P2Align:$p2align, I64:$val), [], - "i64.store32\t$dst, ${off}(${addr})${p2align}, $val", 0x32>; +def STORE8_I32 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I32:$val), [], + "i32.store8\t${off}(${addr})${p2align}, $val", 0x2e>; +def STORE16_I32 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I32:$val), [], + "i32.store16\t${off}(${addr})${p2align}, $val", 0x2f>; +def STORE8_I64 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store8\t${off}(${addr})${p2align}, $val", 0x30>; +def STORE16_I64 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store16\t${off}(${addr})${p2align}, $val", 0x31>; +def STORE32_I64 : I<(outs), (ins i32imm:$off, I32:$addr, + P2Align:$p2align, I64:$val), [], + "i64.store32\t${off}(${addr})${p2align}, $val", 0x32>; } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp index 0120431c639..a9e970c399d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp @@ -119,25 +119,6 @@ bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) { switch (MI.getOpcode()) { default: break; - case WebAssembly::STORE8_I32: - case WebAssembly::STORE16_I32: - case WebAssembly::STORE8_I64: - case WebAssembly::STORE16_I64: - case WebAssembly::STORE32_I64: - case WebAssembly::STORE_F32: - case WebAssembly::STORE_F64: - case WebAssembly::STORE_I32: - case WebAssembly::STORE_I64: { - // Store instructions return their value operand. If we ended up using - // the same register for both, replace it with a dead def so that it - // can use $drop instead. - MachineOperand &MO = MI.getOperand(0); - unsigned OldReg = MO.getReg(); - unsigned NewReg = - MI.getOperand(WebAssembly::StoreValueOperandNo).getReg(); - Changed |= MaybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI); - break; - } case WebAssembly::CALL_I32: case WebAssembly::CALL_I64: { MachineOperand &Op1 = MI.getOperand(1); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp index bb8fe9ae996..9367464c806 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp @@ -71,9 +71,10 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex( // If this is the address operand of a load or store, make it relative to SP // and fold the frame offset directly in. - if (MI.mayLoadOrStore() && FIOperandNum == WebAssembly::MemOpAddressOperandNo) { - assert(FrameOffset >= 0 && MI.getOperand(1).getImm() >= 0); - int64_t Offset = MI.getOperand(1).getImm() + FrameOffset; + if ((MI.mayLoad() && FIOperandNum == WebAssembly::LoadAddressOperandNo) || + (MI.mayStore() && FIOperandNum == WebAssembly::StoreAddressOperandNo)) { + assert(FrameOffset >= 0 && MI.getOperand(FIOperandNum - 1).getImm() >= 0); + int64_t Offset = MI.getOperand(FIOperandNum - 1).getImm() + FrameOffset; if (static_cast<uint64_t>(Offset) <= std::numeric_limits<uint32_t>::max()) { MI.getOperand(FIOperandNum - 1).setImm(Offset); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp b/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp index 8e0356f12f5..2441ead7cb2 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp @@ -50,6 +50,27 @@ FunctionPass *llvm::createWebAssemblySetP2AlignOperands() { return new WebAssemblySetP2AlignOperands(); } +static void RewriteP2Align(MachineInstr &MI, unsigned OperandNo) { + assert(MI.getOperand(OperandNo).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[OperandNo].OperandType == + WebAssembly::OPERAND_P2ALIGN && + "Load and store instructions should have a p2align operand"); + uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment()); + + // WebAssembly does not currently support supernatural alignment. + P2Align = std::min( + P2Align, uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode()))); + + MI.getOperand(OperandNo).setImm(P2Align); +} + bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { DEBUG({ dbgs() << "********** Set p2align Operands **********\n" @@ -75,6 +96,8 @@ bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { case WebAssembly::LOAD16_U_I64: case WebAssembly::LOAD32_S_I64: case WebAssembly::LOAD32_U_I64: + RewriteP2Align(MI, WebAssembly::LoadP2AlignOperandNo); + break; case WebAssembly::STORE_I32: case WebAssembly::STORE_I64: case WebAssembly::STORE_F32: @@ -83,27 +106,9 @@ bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { 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"); - uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment()); - - // WebAssembly does not currently support supernatural alignment. - P2Align = std::min( - P2Align, uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode()))); - - MI.getOperand(3).setImm(P2Align); + case WebAssembly::STORE32_I64: + RewriteP2Align(MI, WebAssembly::StoreP2AlignOperandNo); break; - } default: break; } |

