From dda6181a826cf07e6468588b440c43cb87a9c954 Mon Sep 17 00:00:00 2001 From: Lucas Ste <38472950+LucasSte@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:16:35 -0300 Subject: [PATCH] [SOL] New encoding for memory instructions (#118) --- llvm/lib/Target/SBF/BTFDebug.cpp | 26 +- .../SBF/Disassembler/SBFDisassembler.cpp | 23 + llvm/lib/Target/SBF/SBFInstrFormats.td | 12 + llvm/lib/Target/SBF/SBFInstrInfo.cpp | 45 +- llvm/lib/Target/SBF/SBFInstrInfo.h | 3 +- llvm/lib/Target/SBF/SBFInstrInfo.td | 432 +++++++++++++++--- llvm/lib/Target/SBF/SBFMIPeephole.cpp | 33 +- .../lib/Target/SBF/SBFMISimplifyPatchable.cpp | 73 ++- llvm/lib/Target/SBF/SBFSubtarget.cpp | 3 +- llvm/lib/Target/SBF/SBFSubtarget.h | 4 + llvm/lib/Target/SBF/SBFTargetFeatures.td | 3 + .../CodeGen/SBF/32-bit-subreg-load-store.ll | 2 + .../CodeGen/SBF/CORE/field-reloc-st-imm.ll | 1 + llvm/test/CodeGen/SBF/load.ll | 1 + llvm/test/CodeGen/SBF/many_args_new_conv.ll | 1 + llvm/test/CodeGen/SBF/memcpy_16.ll | 1 + llvm/test/CodeGen/SBF/preprocess-loads.ll | 1 + llvm/test/CodeGen/SBF/remove_truncate_3.ll | 1 + llvm/test/CodeGen/SBF/store-imm.ll | 24 + llvm/test/CodeGen/SBF/undef.ll | 1 + .../test/MC/Disassembler/SBF/sbf-ldst-new.txt | 62 +++ llvm/test/MC/SBF/sbf-ldst-new.s | 91 ++++ 22 files changed, 713 insertions(+), 130 deletions(-) create mode 100644 llvm/test/MC/Disassembler/SBF/sbf-ldst-new.txt create mode 100644 llvm/test/MC/SBF/sbf-ldst-new.s diff --git a/llvm/lib/Target/SBF/BTFDebug.cpp b/llvm/lib/Target/SBF/BTFDebug.cpp index 474307284de661..de238e6f4685a7 100644 --- a/llvm/lib/Target/SBF/BTFDebug.cpp +++ b/llvm/lib/Target/SBF/BTFDebug.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include +#include "SBFSubtarget.h" using namespace llvm; using namespace BTFX; @@ -1309,6 +1310,15 @@ void BTFDebug::processGlobalValue(const MachineOperand &MO) { } } +static bool isCoreLoadOrStore(unsigned OpCode, bool NewMemEncoding) { + if (NewMemEncoding) + return OpCode == SBF::CORE_LD64_V2 || OpCode == SBF::CORE_LD32_V2 || + OpCode == SBF::CORE_ST_V2; + + return OpCode == SBF::CORE_LD64_V1 || OpCode == SBF::CORE_LD32_V1 || + OpCode == SBF::CORE_ST_V1; +} + void BTFDebug::beginInstruction(const MachineInstr *MI) { DebugHandlerBase::beginInstruction(MI); @@ -1329,6 +1339,10 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) { return; } + bool NewMemEncoding = MI->getParent() + ->getParent() + ->getSubtarget() + .getNewMemEncoding(); if (MI->getOpcode() == SBF::LD_imm64) { // If the insn is "r2 = LD_imm64 @", // add this insn into the .BTF.ext FieldReloc subsection. @@ -1345,9 +1359,7 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) { // If the insn is "r2 = LD_imm64 @", // The LD_imm64 result will be replaced with a btf type id. processGlobalValue(MI->getOperand(1)); - } else if (MI->getOpcode() == SBF::CORE_LD64 || - MI->getOpcode() == SBF::CORE_LD32 || - MI->getOpcode() == SBF::CORE_ST || + } else if (isCoreLoadOrStore(MI->getOpcode(), NewMemEncoding) || MI->getOpcode() == SBF::CORE_SHIFT) { // relocation insn is a load, store or shift insn. processGlobalValue(MI->getOperand(3)); @@ -1496,6 +1508,10 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) { /// Emit proper patchable instructions. bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { + bool NewMemEncoding = MI->getParent() + ->getParent() + ->getSubtarget() + .getNewMemEncoding(); if (MI->getOpcode() == SBF::LD_imm64) { const MachineOperand &MO = MI->getOperand(1); if (MO.isGlobal()) { @@ -1525,9 +1541,7 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { return true; } } - } else if (MI->getOpcode() == SBF::CORE_LD64 || - MI->getOpcode() == SBF::CORE_LD32 || - MI->getOpcode() == SBF::CORE_ST || + } else if (isCoreLoadOrStore(MI->getOpcode(), NewMemEncoding) || MI->getOpcode() == SBF::CORE_SHIFT) { const MachineOperand &MO = MI->getOperand(3); if (MO.isGlobal()) { diff --git a/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp b/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp index a5881c01087924..f9489bc85df3eb 100644 --- a/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp +++ b/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp @@ -68,6 +68,7 @@ class SBFDisassembler : public MCDisassembler { uint8_t getInstSize(uint64_t Inst) const { return (Inst >> 59) & 0x3; }; uint8_t getInstMode(uint64_t Inst) const { return (Inst >> 61) & 0x7; }; bool isMov32(uint64_t Inst) const { return (Inst >> 56) == 0xb4; } + bool isNewMem(uint64_t Inst) const; }; } // end anonymous namespace @@ -158,6 +159,18 @@ static DecodeStatus readInstruction64(ArrayRef Bytes, uint64_t Address, return MCDisassembler::Success; } +bool SBFDisassembler::isNewMem(uint64_t Inst) const { + uint8_t OpCode = Inst >> 56; + + uint8_t LSB = OpCode & 0xf; + if (LSB != 0x7 && LSB != 0xc && LSB != 0xf) + return false; + + uint8_t MSB = OpCode >> 4; + + return MSB == 0x2 || MSB == 0x3 || MSB == 0x8 || MSB == 0x9; +} + DecodeStatus SBFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef Bytes, uint64_t Address, @@ -183,6 +196,16 @@ DecodeStatus SBFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, STI.hasFeature(SBF::FeatureDisableLddw)) Result = decodeInstruction(DecoderTableSBFv264, Instr, Insn, Address, this, STI); + else if (isNewMem(Insn) && (Insn >> 60) != 0x9 && + STI.hasFeature(SBF::FeatureNewMemEncoding) && + STI.hasFeature(SBF::ALU32)) + Result = + decodeInstruction(DecoderTableSBFALU32MEMv264, + Instr, Insn, Address, this, STI); + else if (isNewMem(Insn) && STI.hasFeature(SBF::FeatureNewMemEncoding)) + Result = + decodeInstruction(DecoderTableSBFv264, + Instr, Insn, Address, this, STI); else Result = decodeInstruction(DecoderTableSBF64, Instr, Insn, Address, this, STI); diff --git a/llvm/lib/Target/SBF/SBFInstrFormats.td b/llvm/lib/Target/SBF/SBFInstrFormats.td index 8a772e3bf1cc6e..ae49010b6772fb 100644 --- a/llvm/lib/Target/SBF/SBFInstrFormats.td +++ b/llvm/lib/Target/SBF/SBFInstrFormats.td @@ -19,6 +19,9 @@ def SBF_JMP : SBFOpClass<0x5>; def SBF_PQR : SBFOpClass<0x6>; def SBF_ALU64 : SBFOpClass<0x7>; +def SBF_LD_V2 : SBFOpClass<0x4>; +def SBF_ST_V2 : SBFOpClass<0x7>; + class SBFSrcType val> { bits<1> Value = val; } @@ -92,6 +95,15 @@ def SBF_H : SBFWidthModifer<0x1>; def SBF_B : SBFWidthModifer<0x2>; def SBF_DW : SBFWidthModifer<0x3>; +class SBFSizeModifier val> { + bits<4> Value = val; +} + +def SBF_B_V2 : SBFSizeModifier<0x2>; +def SBF_H_V2 : SBFSizeModifier<0x3>; +def SBF_W_V2 : SBFSizeModifier<0x8>; +def SBF_DW_V2 : SBFSizeModifier<0x9>; + class SBFModeModifer val> { bits<3> Value = val; } diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.cpp b/llvm/lib/Target/SBF/SBFInstrInfo.cpp index 9e7cc61e854727..b001fd9cdce8a8 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.cpp +++ b/llvm/lib/Target/SBF/SBFInstrInfo.cpp @@ -28,8 +28,9 @@ using namespace llvm; SBFInstrInfo::SBFInstrInfo() : SBFGenInstrInfo(SBF::ADJCALLSTACKDOWN, SBF::ADJCALLSTACKUP) {} -void SBFInstrInfo::setHasExplicitSignExt(bool HasExplicitSext) { +void SBFInstrInfo::initializeTargetFeatures(bool HasExplicitSext, bool NewMemEncoding) { this->HasExplicitSignExt = HasExplicitSext; + this->NewMemEncoding = NewMemEncoding; } void SBFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, @@ -60,24 +61,24 @@ void SBFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const { DebugLoc dl = MI->getDebugLoc(); unsigned LdOpc, StOpc; +#define MEM_SWITCH(X) \ +LdOpc = NewMemEncoding ? SBF::LD##X##_V2 : SBF::LD##X##_V1; \ +StOpc = NewMemEncoding ? SBF::ST##X##_V2 : SBF::ST##X##_V1; + unsigned BytesPerOp = std::min(static_cast(Alignment), 8u); switch (Alignment) { case 1: - LdOpc = SBF::LDB; - StOpc = SBF::STB; + MEM_SWITCH(B) break; case 2: - LdOpc = SBF::LDH; - StOpc = SBF::STH; + MEM_SWITCH(H) break; case 4: - LdOpc = SBF::LDW; - StOpc = SBF::STW; + MEM_SWITCH(W) break; case 8: case 16: - LdOpc = SBF::LDD; - StOpc = SBF::STD; + MEM_SWITCH(D) break; default: llvm_unreachable("unsupported memcpy alignment"); @@ -104,20 +105,16 @@ void SBFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const { if (BytesLeft < 2) { Offset = CopyLen - 1; - LdOpc = SBF::LDB; - StOpc = SBF::STB; + MEM_SWITCH(B) } else if (BytesLeft <= 2) { Offset = CopyLen - 2; - LdOpc = SBF::LDH; - StOpc = SBF::STH; + MEM_SWITCH(H) } else if (BytesLeft <= 4) { Offset = CopyLen - 4; - LdOpc = SBF::LDW; - StOpc = SBF::STW; + MEM_SWITCH(W) } else if (BytesLeft <= 8) { Offset = CopyLen - 8; - LdOpc = SBF::LDD; - StOpc = SBF::STD; + MEM_SWITCH(D) } else { llvm_unreachable("There cannot be more than 8 bytes left"); } @@ -154,12 +151,14 @@ void SBFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, DL = I->getDebugLoc(); if (RC == &SBF::GPRRegClass) - BuildMI(MBB, I, DL, get(SBF::STD)) + BuildMI(MBB, I, DL, get(NewMemEncoding ? + SBF::STD_V2 : SBF::STD_V1)) .addReg(SrcReg, getKillRegState(IsKill)) .addFrameIndex(FI) .addImm(0); else if (RC == &SBF::GPR32RegClass) - BuildMI(MBB, I, DL, get(SBF::STW32)) + BuildMI(MBB, I, DL, get(NewMemEncoding ? + SBF::STW32_V2 : SBF::STW32_V1)) .addReg(SrcReg, getKillRegState(IsKill)) .addFrameIndex(FI) .addImm(0); @@ -178,9 +177,13 @@ void SBFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, DL = I->getDebugLoc(); if (RC == &SBF::GPRRegClass) - BuildMI(MBB, I, DL, get(SBF::LDD), DestReg).addFrameIndex(FI).addImm(0); + BuildMI(MBB, I, DL, get(NewMemEncoding ? + SBF::LDD_V2 : SBF::LDD_V1), + DestReg).addFrameIndex(FI).addImm(0); else if (RC == &SBF::GPR32RegClass) - BuildMI(MBB, I, DL, get(SBF::LDW32), DestReg).addFrameIndex(FI).addImm(0); + BuildMI(MBB, I, DL, get(NewMemEncoding ? + SBF::LDW32_V2 : SBF::LDW32_V1), + DestReg).addFrameIndex(FI).addImm(0); else llvm_unreachable("Can't load this register from stack slot"); } diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.h b/llvm/lib/Target/SBF/SBFInstrInfo.h index 5c4afdb2a25789..a6ee6ad4767f20 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.h +++ b/llvm/lib/Target/SBF/SBFInstrInfo.h @@ -58,11 +58,12 @@ class SBFInstrInfo : public SBFGenInstrInfo { MachineBasicBlock *FBB, ArrayRef Cond, const DebugLoc &DL, int *BytesAdded = nullptr) const override; - void setHasExplicitSignExt(bool HasExplicitSext); + void initializeTargetFeatures(bool HasExplicitSext, bool NewMemEncoding); private: void expandMEMCPY(MachineBasicBlock::iterator) const; bool HasExplicitSignExt; + bool NewMemEncoding; }; } diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index f50a10a89f01ba..057c92327a9297 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -67,6 +67,8 @@ def SBFNoPqrInstr : Predicate<"!Subtarget->getHasPqrClass()">; def SBFHasStoreImm : Predicate<"Subtarget->getHasStoreImm()">; def SBFExplicitSignExt : Predicate<"Subtarget->getHasExplicitSignExt()">; def SBFNoExplicitSignExt : Predicate<"!Subtarget->getHasExplicitSignExt()">; +def SBFNewMemEncoding : Predicate<"Subtarget->getNewMemEncoding()">, AssemblerPredicate<(all_of FeatureNewMemEncoding)>; +def SBFOldMemEncoding : Predicate<"!Subtarget->getNewMemEncoding()">; def brtarget : Operand { let PrintMethod = "printBrTargetOperand"; @@ -173,6 +175,22 @@ class TYPE_LD_ST mode, bits<2> size, let Inst{60-59} = size; } +//For load and store instructions in SBFv2 the 8-bit 'code' field is divided as: +// +// +--------+---------------+-------------------+ +// | 4 bits | 1 bit | 3 bits | +// | size | source type | instruction class | +// +--------+---------------+-------------------+ +// (MSB) (LSB) +class TYPE_LD_ST_V2 size, bits<1> srctype, + dag outs, dag ins, string asmstr, list pattern> + : InstSBF { + + let Inst{63-60} = size; + let Inst{59} = srctype; +} + + // jump instructions class JMP_RR : TYPE_ALU_JMP Pattern> +class STORE_V1 : TYPE_LD_ST { + []> { bits<4> src; bits<20> addr; @@ -489,23 +507,68 @@ class STORE Pattern> let SBFClass = SBF_STX; } -class STOREi64 - : STORE; +class STORE_V2 + : TYPE_LD_ST_V2 { + bits<4> src; + bits<20> addr; + + let Inst{51-48} = addr{19-16}; // base reg + let Inst{55-52} = src; + let Inst{47-32} = addr{15-0}; // offset + let SBFClass = SBF_ST_V2; +} + +multiclass STOREi64 { + def _V1 : STORE_V1, Requires<[SBFOldMemEncoding]>; -let Predicates = [SBFNoALU32] in { - def STW : STOREi64; - def STH : STOREi64; - def STB : STOREi64; + let DecoderNamespace = "SBFv2" in { + def _V2 : STORE_V2, Requires<[SBFNewMemEncoding]>; + } } -def STD : STOREi64; -class STORE_imm + +defm STW : STOREi64; +defm STH : STOREi64; +defm STB : STOREi64; +defm STD : STOREi64; + +def : Pat<(store GPR:$src, ADDRri:$addr), + (STD_V1 GPR:$src, ADDRri:$addr)>, Requires<[SBFOldMemEncoding]>; + +def : Pat<(store GPR:$src, ADDRri:$addr), + (STD_V2 GPR:$src, ADDRri:$addr)>, Requires<[SBFNewMemEncoding]>; + +let Predicates = [SBFNoALU32, SBFOldMemEncoding] in { + def : Pat<(truncstorei32 GPR:$src, ADDRri:$addr), + (STW_V1 GPR:$src, ADDRri:$addr)>; + def : Pat<(truncstorei16 GPR:$src, ADDRri:$addr), + (STH_V1 GPR:$src, ADDRri:$addr)>; + def : Pat<(truncstorei8 GPR:$src, ADDRri:$addr), + (STB_V1 GPR:$src, ADDRri:$addr)>; +} + +let Predicates = [SBFNoALU32, SBFNewMemEncoding] in { + def : Pat<(truncstorei32 GPR:$src, ADDRri:$addr), + (STW_V2 GPR:$src, ADDRri:$addr)>; + def : Pat<(truncstorei16 GPR:$src, ADDRri:$addr), + (STH_V2 GPR:$src, ADDRri:$addr)>; + def : Pat<(truncstorei8 GPR:$src, ADDRri:$addr), + (STB_V2 GPR:$src, ADDRri:$addr)>; +} + + +class STORE_imm_V1 : TYPE_LD_ST { + []> { bits<20> addr; bits<32> imm; let Inst{51-48} = addr{19-16}; // base reg @@ -514,6 +577,30 @@ class STORE_imm + : TYPE_LD_ST_V2 { + bits<20> addr; + bits<32> imm; + let Inst{51-48} = addr{19-16}; // base reg + let Inst{47-32} = addr{15-0}; // offset + let Inst{31-0} = imm; + let SBFClass = SBF_ST_V2; +} + +multiclass STORE_imm { + def _V1 : STORE_imm_V1, Requires<[SBFOldMemEncoding]>; + + let DecoderNamespace = "SBFv2" in { + def _V2 : STORE_imm_V2, Requires<[SBFNewMemEncoding]>; + } +} + // Opcode (SBF_ST | SBF_MEM | SBF_DW) implies sign extension for // value stored to memory: // - it is fine to generate such write when immediate is -1 @@ -526,29 +613,68 @@ class STORE_imm; - def STW_imm : STORE_imm; - def STH_imm : STORE_imm; - def STB_imm : STORE_imm; +defm STD_imm : STORE_imm; +defm STW_imm : STORE_imm; +defm STH_imm : STORE_imm; +defm STB_imm : STORE_imm; + +let Predicates = [SBFHasStoreImm, SBFOldMemEncoding] in { + def : Pat<(store (i64 i64immSExt32:$imm), ADDRri:$addr), + (STD_imm_V1 (i64 imm:$imm), ADDRri:$addr)>; + def : Pat<(truncstorei32 (i64 i64immZExt32:$imm), ADDRri:$addr), + (STW_imm_V1 (i64 imm:$imm), ADDRri:$addr)>; + def : Pat<(truncstorei16 (i64 i64immZExt32:$imm), ADDRri:$addr), + (STH_imm_V1 (i64 imm:$imm), ADDRri:$addr)>; + def : Pat<(truncstorei8 (i64 i64immZExt32:$imm), ADDRri:$addr), + (STB_imm_V1 (i64 imm:$imm), ADDRri:$addr)>; +} + +let Predicates = [SBFHasStoreImm, SBFNewMemEncoding] in { + def : Pat<(store (i64 i64immSExt32:$imm), ADDRri:$addr), + (STD_imm_V2 (i64 imm:$imm), ADDRri:$addr)>; + def : Pat<(truncstorei32 (i64 i64immZExt32:$imm), ADDRri:$addr), + (STW_imm_V2 (i64 imm:$imm), ADDRri:$addr)>; + def : Pat<(truncstorei16 (i64 i64immZExt32:$imm), ADDRri:$addr), + (STH_imm_V2 (i64 imm:$imm), ADDRri:$addr)>; + def : Pat<(truncstorei8 (i64 i64immZExt32:$imm), ADDRri:$addr), + (STB_imm_V2 (i64 imm:$imm), ADDRri:$addr)>; +} + +let Predicates = [SBFHasStoreImm, SBFNewMemEncoding] in { + def : Pat<(store (i32 imm:$src), ADDRri:$dst), + (STW_imm_V2 (imm_to_i64 $src), ADDRri:$dst)>; + def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst), + (STH_imm_V2 (imm_to_i64 imm:$src), ADDRri:$dst)>; + def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst), + (STB_imm_V2 (imm_to_i64 imm:$src), ADDRri:$dst)>; } -let Predicates = [SBFHasALU32, SBFHasStoreImm] in { + +let Predicates = [SBFHasALU32, SBFHasStoreImm, SBFOldMemEncoding] in { def : Pat<(store (i32 imm:$src), ADDRri:$dst), - (STW_imm (imm_to_i64 $src), ADDRri:$dst)>; + (STW_imm_V1 (imm_to_i64 $src), ADDRri:$dst)>; def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst), - (STH_imm (imm_to_i64 imm:$src), ADDRri:$dst)>; + (STH_imm_V1 (imm_to_i64 imm:$src), ADDRri:$dst)>; def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst), - (STB_imm (imm_to_i64 imm:$src), ADDRri:$dst)>; + (STB_imm_V1 (imm_to_i64 imm:$src), ADDRri:$dst)>; +} + +let Predicates = [SBFHasALU32, SBFHasStoreImm, SBFNewMemEncoding] in { + def : Pat<(store (i32 imm:$src), ADDRri:$dst), + (STW_imm_V2 (imm_to_i64 $src), ADDRri:$dst)>; + def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst), + (STH_imm_V2 (imm_to_i64 imm:$src), ADDRri:$dst)>; + def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst), + (STB_imm_V2 (imm_to_i64 imm:$src), ADDRri:$dst)>; } // LOAD instructions -class LOAD Pattern> +class LOAD_V1 : TYPE_LD_ST { + []> { bits<4> dst; bits<20> addr; @@ -558,25 +684,59 @@ class LOAD Pattern> let SBFClass = SBF_LDX; } -class LOADi64 - : LOAD; +class LOAD_V2 + : TYPE_LD_ST_V2 { + bits<4> dst; + bits<20> addr; + + let Inst{51-48} = dst; + let Inst{55-52} = addr{19-16}; + let Inst{47-32} = addr{15-0}; + let SBFClass = SBF_LD_V2; +} + +multiclass LOADi64 { + def _V1 : LOAD_V1, Requires<[SBFOldMemEncoding]>; + + let DecoderNamespace = "SBFv2" in { + def _V2 : LOAD_V2, Requires<[SBFNewMemEncoding]>; + } +} let isCodeGenOnly = 1 in { - class CORE_LD - : TYPE_LD_ST; + multiclass CORE_LD { + def _V1 : TYPE_LD_ST; + + def _V2 : TYPE_LD_ST_V2; + } - def CORE_LD64 : CORE_LD; - def CORE_LD32 : CORE_LD; + defm CORE_LD64 : CORE_LD; + defm CORE_LD32 : CORE_LD; - def CORE_ST : TYPE_LD_ST; + + def CORE_ST_V2 : TYPE_LD_ST_V2; + let Constraints = "$dst = $src" in { def CORE_SHIFT : MATH_RR; - def LDH : LOADi64; - def LDB : LOADi64; +defm LDW : LOADi64; +defm LDH : LOADi64; +defm LDB : LOADi64; +defm LDD : LOADi64; + +def : Pat<(load ADDRri:$addr), + (LDD_V1 ADDRri:$addr)>, Requires<[SBFOldMemEncoding]>; + +def : Pat<(load ADDRri:$addr), + (LDD_V2 ADDRri:$addr)>, Requires<[SBFNewMemEncoding]>; + +let Predicates = [SBFNoALU32, SBFOldMemEncoding] in { + def : Pat<(zextloadi32 ADDRri:$addr), + (LDW_V1 ADDRri:$addr)>; + def : Pat<(zextloadi16 ADDRri:$addr), + (LDH_V1 ADDRri:$addr)>; + def : Pat<(zextloadi8 ADDRri:$addr), + (LDB_V1 ADDRri:$addr)>; } -def LDD : LOADi64; +let Predicates = [SBFNoALU32, SBFNewMemEncoding] in { + def : Pat<(zextloadi32 ADDRri:$addr), + (LDW_V2 ADDRri:$addr)>; + def : Pat<(zextloadi16 ADDRri:$addr), + (LDH_V2 ADDRri:$addr)>; + def : Pat<(zextloadi8 ADDRri:$addr), + (LDB_V2 ADDRri:$addr)>; +} class BRANCH Pattern> : TYPE_ALU_JMP, Requires<[SBFNoCallxSrc]>; def : Pat<(SBFcall GPR:$dst), (JALX_v2 GPR:$dst)>, Requires<[SBFCallxSrc]>; // Loads -let Predicates = [SBFNoALU32] in { - def : Pat<(i64 (extloadi8 ADDRri:$src)), (i64 (LDB ADDRri:$src))>; - def : Pat<(i64 (extloadi16 ADDRri:$src)), (i64 (LDH ADDRri:$src))>; - def : Pat<(i64 (extloadi32 ADDRri:$src)), (i64 (LDW ADDRri:$src))>; +let Predicates = [SBFNoALU32, SBFOldMemEncoding] in { + def : Pat<(i64 (extloadi8 ADDRri:$src)), (i64 (LDB_V1 ADDRri:$src))>; + def : Pat<(i64 (extloadi16 ADDRri:$src)), (i64 (LDH_V1 ADDRri:$src))>; + def : Pat<(i64 (extloadi32 ADDRri:$src)), (i64 (LDW_V1 ADDRri:$src))>; +} + +let Predicates = [SBFNoALU32, SBFNewMemEncoding] in { + def : Pat<(i64 (extloadi8 ADDRri:$src)), (i64 (LDB_V2 ADDRri:$src))>; + def : Pat<(i64 (extloadi16 ADDRri:$src)), (i64 (LDH_V2 ADDRri:$src))>; + def : Pat<(i64 (extloadi32 ADDRri:$src)), (i64 (LDW_V2 ADDRri:$src))>; } // Atomic XADD for SBFNoALU32 @@ -1078,12 +1265,12 @@ def : Pat<(i64 (anyext GPR32:$src)), def : Pat<(i64 (anyext GPR32:$src)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>, Requires<[SBFNoExplicitSignExt]>; -class STORE32 Pattern> +class STORE32_V1 : TYPE_LD_ST { + []> { bits<4> src; bits<20> addr; @@ -1093,21 +1280,61 @@ class STORE32 Pattern> let SBFClass = SBF_STX; } -class STOREi32 - : STORE32; +class STORE32_V2 + : TYPE_LD_ST_V2 { + bits<4> src; + bits<20> addr; -let Predicates = [SBFHasALU32], DecoderNamespace = "SBFALU32" in { - def STW32 : STOREi32; - def STH32 : STOREi32; - def STB32 : STOREi32; + let Inst{51-48} = addr{19-16}; // base reg + let Inst{55-52} = src; + let Inst{47-32} = addr{15-0}; // offset + let SBFClass = SBF_ST_V2; +} + +multiclass STOREi32 { + let DecoderNamespace = "SBFALU32" in { + def _V1 : STORE32_V1, Requires<[SBFOldMemEncoding]>; + } + + let DecoderNamespace = "SBFALU32MEMv2" in { + def _V2 : STORE32_V2, Requires<[SBFNewMemEncoding]>; + } } -class LOAD32 Pattern> +defm STW32 : STOREi32; +defm STH32 : STOREi32; +defm STB32 : STOREi32; + +let Predicates = [SBFHasALU32, SBFOldMemEncoding] in { + def : Pat<(store GPR32:$src, ADDRri:$addr), + (STW32_V1 GPR32:$src, ADDRri:$addr)>; + def : Pat<(truncstorei16 GPR32:$src, ADDRri:$addr), + (STH32_V1 GPR32:$src, ADDRri:$addr)>; + def : Pat<(truncstorei8 GPR32:$src, ADDRri:$addr), + (STB32_V1 GPR32:$src, ADDRri:$addr)>; +} + +let Predicates = [SBFHasALU32, SBFNewMemEncoding] in { + def : Pat<(store GPR32:$src, ADDRri:$addr), + (STW32_V2 GPR32:$src, ADDRri:$addr)>; + def : Pat<(truncstorei16 GPR32:$src, ADDRri:$addr), + (STH32_V2 GPR32:$src, ADDRri:$addr)>; + def : Pat<(truncstorei8 GPR32:$src, ADDRri:$addr), + (STB32_V2 GPR32:$src, ADDRri:$addr)>; +} + +class LOAD32_V1 : TYPE_LD_ST { + []> { bits<4> dst; bits<20> addr; @@ -1117,36 +1344,99 @@ class LOAD32 Pattern> let SBFClass = SBF_LDX; } -class LOADi32 - : LOAD32; +class LOAD32_V2 + : TYPE_LD_ST_V2 { + bits<4> dst; + bits<20> addr; + + let Inst{51-48} = dst; + let Inst{55-52} = addr{19-16}; + let Inst{47-32} = addr{15-0}; + let SBFClass = SBF_LD_V2; +} -let Predicates = [SBFHasALU32], DecoderNamespace = "SBFALU32" in { - def LDW32 : LOADi32; - def LDH32 : LOADi32; - def LDB32 : LOADi32; + +multiclass LOADi32 { + let DecoderNamespace = "SBFALU32" in { + def _V1 : LOAD32_V1, Requires<[SBFOldMemEncoding]>; + } + let DecoderNamespace = "SBFALU32MEMv2" in { + def _V2 : LOAD32_V2, Requires<[SBFNewMemEncoding]>; + } +} + + +defm LDW32 : LOADi32; +defm LDH32 : LOADi32; +defm LDB32 : LOADi32; + +let Predicates = [SBFHasALU32, SBFOldMemEncoding] in { + def : Pat<(load ADDRri:$addr), + (LDW32_V1 ADDRri:$addr)>; + def : Pat<(zextloadi16 ADDRri:$addr), + (LDH32_V1 ADDRri:$addr)>; + def : Pat<(zextloadi8 ADDRri:$addr), + (LDB32_V1 ADDRri:$addr)>; +} + +let Predicates = [SBFHasALU32, SBFNewMemEncoding] in { + def : Pat<(load ADDRri:$addr), + (LDW32_V2 ADDRri:$addr)>; + def : Pat<(zextloadi16 ADDRri:$addr), + (LDH32_V2 ADDRri:$addr)>; + def : Pat<(zextloadi8 ADDRri:$addr), + (LDB32_V2 ADDRri:$addr)>; +} + +let Predicates = [SBFHasALU32, SBFOldMemEncoding] in { + def : Pat<(truncstorei8 GPR:$src, ADDRri:$dst), + (STB32_V1 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; + def : Pat<(truncstorei16 GPR:$src, ADDRri:$dst), + (STH32_V1 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; + def : Pat<(truncstorei32 GPR:$src, ADDRri:$dst), + (STW32_V1 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; + def : Pat<(i32 (extloadi8 ADDRri:$src)), (i32 (LDB32_V1 ADDRri:$src))>; + def : Pat<(i32 (extloadi16 ADDRri:$src)), (i32 (LDH32_V1 ADDRri:$src))>; + def : Pat<(i64 (zextloadi8 ADDRri:$src)), + (SUBREG_TO_REG (i64 0), (LDB32_V1 ADDRri:$src), sub_32)>; + def : Pat<(i64 (zextloadi16 ADDRri:$src)), + (SUBREG_TO_REG (i64 0), (LDH32_V1 ADDRri:$src), sub_32)>; + def : Pat<(i64 (zextloadi32 ADDRri:$src)), + (SUBREG_TO_REG (i64 0), (LDW32_V1 ADDRri:$src), sub_32)>; + def : Pat<(i64 (extloadi8 ADDRri:$src)), + (SUBREG_TO_REG (i64 0), (LDB32_V1 ADDRri:$src), sub_32)>; + def : Pat<(i64 (extloadi16 ADDRri:$src)), + (SUBREG_TO_REG (i64 0), (LDH32_V1 ADDRri:$src), sub_32)>; + def : Pat<(i64 (extloadi32 ADDRri:$src)), + (SUBREG_TO_REG (i64 0), (LDW32_V1 ADDRri:$src), sub_32)>; } -let Predicates = [SBFHasALU32] in { +let Predicates = [SBFHasALU32, SBFNewMemEncoding] in { def : Pat<(truncstorei8 GPR:$src, ADDRri:$dst), - (STB32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; + (STB32_V2 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; def : Pat<(truncstorei16 GPR:$src, ADDRri:$dst), - (STH32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; + (STH32_V2 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; def : Pat<(truncstorei32 GPR:$src, ADDRri:$dst), - (STW32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; - def : Pat<(i32 (extloadi8 ADDRri:$src)), (i32 (LDB32 ADDRri:$src))>; - def : Pat<(i32 (extloadi16 ADDRri:$src)), (i32 (LDH32 ADDRri:$src))>; + (STW32_V2 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; + def : Pat<(i32 (extloadi8 ADDRri:$src)), (i32 (LDB32_V2 ADDRri:$src))>; + def : Pat<(i32 (extloadi16 ADDRri:$src)), (i32 (LDH32_V2 ADDRri:$src))>; def : Pat<(i64 (zextloadi8 ADDRri:$src)), - (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>; + (SUBREG_TO_REG (i64 0), (LDB32_V2 ADDRri:$src), sub_32)>; def : Pat<(i64 (zextloadi16 ADDRri:$src)), - (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>; + (SUBREG_TO_REG (i64 0), (LDH32_V2 ADDRri:$src), sub_32)>; def : Pat<(i64 (zextloadi32 ADDRri:$src)), - (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>; + (SUBREG_TO_REG (i64 0), (LDW32_V2 ADDRri:$src), sub_32)>; def : Pat<(i64 (extloadi8 ADDRri:$src)), - (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>; + (SUBREG_TO_REG (i64 0), (LDB32_V2 ADDRri:$src), sub_32)>; def : Pat<(i64 (extloadi16 ADDRri:$src)), - (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>; + (SUBREG_TO_REG (i64 0), (LDH32_V2 ADDRri:$src), sub_32)>; def : Pat<(i64 (extloadi32 ADDRri:$src)), - (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>; + (SUBREG_TO_REG (i64 0), (LDW32_V2 ADDRri:$src), sub_32)>; } let usesCustomInserter = 1, isCodeGenOnly = 1 in { diff --git a/llvm/lib/Target/SBF/SBFMIPeephole.cpp b/llvm/lib/Target/SBF/SBFMIPeephole.cpp index 0a84933ebababd..13caaf29f8b522 100644 --- a/llvm/lib/Target/SBF/SBFMIPeephole.cpp +++ b/llvm/lib/Target/SBF/SBFMIPeephole.cpp @@ -245,16 +245,28 @@ struct SBFMIPeepholeTruncElim : public MachineFunctionPass { } }; -static bool TruncSizeCompatible(int TruncSize, unsigned opcode) +static bool TruncSizeCompatible(int TruncSize, unsigned opcode, bool NewEncoding) { - if (TruncSize == 1) - return opcode == SBF::LDB || opcode == SBF::LDB32; + if (TruncSize == 1) { + if (NewEncoding) + return opcode == SBF::LDB_V2 || opcode == SBF::LDB32_V2; - if (TruncSize == 2) - return opcode == SBF::LDH || opcode == SBF::LDH32; + return opcode == SBF::LDB_V1 || opcode == SBF::LDB32_V1; + } + + if (TruncSize == 2) { + if (NewEncoding) + return opcode == SBF::LDH_V2 || opcode == SBF::LDH32_V2; + + return opcode == SBF::LDH_V1 || opcode == SBF::LDH32_V1; + } + + if (TruncSize == 4) { + if (NewEncoding) + return opcode == SBF::LDW_V2 || opcode == SBF::LDW32_V2; - if (TruncSize == 4) - return opcode == SBF::LDW || opcode == SBF::LDW32; + return opcode == SBF::LDW_V1 || opcode == SBF::LDW32_V1; + } return false; } @@ -281,6 +293,7 @@ bool SBFMIPeepholeTruncElim::eliminateTruncSeq() { MachineInstr* ToErase = nullptr; bool Eliminated = false; + bool NewEncoding = MF->getSubtarget().getNewMemEncoding(); for (MachineBasicBlock &MBB : *MF) { for (MachineInstr &MI : MBB) { // The second insn to remove if the eliminate candidate is a pair. @@ -348,7 +361,8 @@ bool SBFMIPeepholeTruncElim::eliminateTruncSeq() { MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg()); if (!PhiDef || PhiDef->isPHI() || - !TruncSizeCompatible(TruncSize, PhiDef->getOpcode())) { + !TruncSizeCompatible(TruncSize, + PhiDef->getOpcode(), NewEncoding)) { CheckFail = true; break; } @@ -356,7 +370,8 @@ bool SBFMIPeepholeTruncElim::eliminateTruncSeq() { if (CheckFail) continue; - } else if (!TruncSizeCompatible(TruncSize, DefMI->getOpcode())) { + } else if (!TruncSizeCompatible(TruncSize, + DefMI->getOpcode(), NewEncoding)) { continue; } diff --git a/llvm/lib/Target/SBF/SBFMISimplifyPatchable.cpp b/llvm/lib/Target/SBF/SBFMISimplifyPatchable.cpp index 358b7c2e4e013c..449be751eba970 100644 --- a/llvm/lib/Target/SBF/SBFMISimplifyPatchable.cpp +++ b/llvm/lib/Target/SBF/SBFMISimplifyPatchable.cpp @@ -92,31 +92,57 @@ void SBFMISimplifyPatchable::initialize(MachineFunction &MFParm) { LLVM_DEBUG(dbgs() << "*** SBF simplify patchable insts pass ***\n\n"); } -static bool isST(unsigned Opcode) { - return Opcode == SBF::STB_imm || Opcode == SBF::STH_imm || - Opcode == SBF::STW_imm || Opcode == SBF::STD_imm; +static bool isST(unsigned Opcode, bool NewEncoding) { + if (NewEncoding) { + return Opcode == SBF::STB_imm_V2 || Opcode == SBF::STH_imm_V2 || + Opcode == SBF::STW_imm_V2 || Opcode == SBF::STD_imm_V2; + } + + return Opcode == SBF::STB_imm_V1 || Opcode == SBF::STH_imm_V1 || + Opcode == SBF::STW_imm_V1 || Opcode == SBF::STD_imm_V1; } -static bool isSTX32(unsigned Opcode) { - return Opcode == SBF::STB32 || Opcode == SBF::STH32 || Opcode == SBF::STW32; +static bool isSTX32(unsigned Opcode, bool NewEncoding) { + if (NewEncoding) { + return Opcode == SBF::STB32_V2 || Opcode == SBF::STH32_V2 + || Opcode == SBF::STW32_V2; + } + return Opcode == SBF::STB32_V1 || Opcode == SBF::STH32_V1 + || Opcode == SBF::STW32_V1; } -static bool isSTX64(unsigned Opcode) { - return Opcode == SBF::STB || Opcode == SBF::STH || Opcode == SBF::STW || - Opcode == SBF::STD; +static bool isSTX64(unsigned Opcode, bool NewEncoding) { + if (NewEncoding) { + return Opcode == SBF::STB_V2 || Opcode == SBF::STH_V2 || + Opcode == SBF::STW_V2 ||Opcode == SBF::STD_V2; + } + + return Opcode == SBF::STB_V1 || Opcode == SBF::STH_V1 || + Opcode == SBF::STW_V1 ||Opcode == SBF::STD_V1; } -static bool isLDX32(unsigned Opcode) { - return Opcode == SBF::LDB32 || Opcode == SBF::LDH32 || Opcode == SBF::LDW32; +static bool isLDX32(unsigned Opcode, bool NewEncoding) { + if (NewEncoding) + return Opcode == SBF::LDB32_V2 || Opcode == SBF::LDH32_V2 || + Opcode == SBF::LDW32_V2; + + return Opcode == SBF::LDB32_V1 || Opcode == SBF::LDH32_V1 || + Opcode == SBF::LDW32_V1; } -static bool isLDX64(unsigned Opcode) { - return Opcode == SBF::LDB || Opcode == SBF::LDH || Opcode == SBF::LDW || - Opcode == SBF::LDD; +static bool isLDX64(unsigned Opcode, bool NewEncoding) { + if (NewEncoding) + return Opcode == SBF::LDB_V2 || Opcode == SBF::LDH_V2 || + Opcode == SBF::LDW_V2 || Opcode == SBF::LDD_V2; + + return Opcode == SBF::LDB_V1 || Opcode == SBF::LDH_V1 || + Opcode == SBF::LDW_V1 || Opcode == SBF::LDD_V1; } bool SBFMISimplifyPatchable::isLoadInst(unsigned Opcode) { - return isLDX32(Opcode) || isLDX64(Opcode); + bool NewMemEncoding = MF->getSubtarget().getNewMemEncoding(); + return isLDX32(Opcode, NewMemEncoding) || + isLDX64(Opcode, NewMemEncoding); } void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI, @@ -127,6 +153,8 @@ void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI, const MachineOperand *BaseOp = (RelocOp == Op1) ? Op2 : Op1; // Go through all uses of %1 as in %1 = ADD_rr %2, %3 + const SBFSubtarget& SubTarget = MF->getSubtarget(); + bool NewMemEncoding = SubTarget.getNewMemEncoding(); const MachineOperand Op0 = Inst->getOperand(0); for (MachineOperand &MO : llvm::make_early_inc_range(MRI->use_operands(Op0.getReg()))) { @@ -137,12 +165,14 @@ void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI, MachineInstr *DefInst = MO.getParent(); unsigned Opcode = DefInst->getOpcode(); unsigned COREOp; - if (isLDX64(Opcode)) - COREOp = SBF::CORE_LD64; - else if (isLDX32(Opcode)) - COREOp = SBF::CORE_LD32; - else if (isSTX64(Opcode) || isSTX32(Opcode) || isST(Opcode)) - COREOp = SBF::CORE_ST; + if (isLDX64(Opcode, NewMemEncoding)) + COREOp = NewMemEncoding ? SBF::CORE_LD64_V2 : SBF::CORE_LD64_V1; + else if (isLDX32(Opcode, NewMemEncoding)) + COREOp = NewMemEncoding ? SBF::CORE_LD32_V2 : SBF::CORE_LD32_V1; + else if (isSTX64(Opcode, NewMemEncoding) || + isSTX32(Opcode, NewMemEncoding) || + isST(Opcode, NewMemEncoding)) + COREOp = NewMemEncoding ? SBF::CORE_ST_V2 : SBF::CORE_ST_V1; else continue; @@ -154,7 +184,8 @@ void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI, // Reject the form: // %1 = ADD_rr %2, %3 // *(type *)(%2 + 0) = %1 - if (isSTX64(Opcode) || isSTX32(Opcode)) { + if (isSTX64(Opcode, NewMemEncoding) || + isSTX32(Opcode, NewMemEncoding)) { const MachineOperand &Opnd = DefInst->getOperand(0); if (Opnd.isReg() && Opnd.getReg() == MO.getReg()) continue; diff --git a/llvm/lib/Target/SBF/SBFSubtarget.cpp b/llvm/lib/Target/SBF/SBFSubtarget.cpp index ff2c27df0d7819..5d3e24fef099c4 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.cpp +++ b/llvm/lib/Target/SBF/SBFSubtarget.cpp @@ -30,7 +30,7 @@ SBFSubtarget &SBFSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef FS) { initializeEnvironment(TT); initSubtargetFeatures(CPU, FS); - InstrInfo.setHasExplicitSignExt(HasExplicitSignExt); + InstrInfo.initializeTargetFeatures(HasExplicitSignExt, NewMemEncoding); return *this; } @@ -49,6 +49,7 @@ void SBFSubtarget::initializeEnvironment(const Triple &TT) { HasStoreImm = false; HasAlu32 = false; HasExplicitSignExt = false; + NewMemEncoding = false; } void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { diff --git a/llvm/lib/Target/SBF/SBFSubtarget.h b/llvm/lib/Target/SBF/SBFSubtarget.h index be578f8e993ce6..f30fcf51607097 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.h +++ b/llvm/lib/Target/SBF/SBFSubtarget.h @@ -80,6 +80,9 @@ class SBFSubtarget : public SBFGenSubtargetInfo { // Whether we have the explicit sign extension instruction (mov32) bool HasExplicitSignExt; + // Whether we enable the new encoding for memory instructions + bool NewMemEncoding; + public: // This constructor initializes the data members to match that // of the specified triple. @@ -103,6 +106,7 @@ class SBFSubtarget : public SBFGenSubtargetInfo { bool getHasPqrClass() const { return HasPqrClass; } bool getHasStoreImm() const { return HasStoreImm; } bool getHasExplicitSignExt() const { return HasExplicitSignExt; } + bool getNewMemEncoding() const { return NewMemEncoding; } const SBFInstrInfo *getInstrInfo() const override { return &InstrInfo; } const SBFFrameLowering *getFrameLowering() const override { return &FrameLowering; diff --git a/llvm/lib/Target/SBF/SBFTargetFeatures.td b/llvm/lib/Target/SBF/SBFTargetFeatures.td index dc2cf380600b87..a11b0aacbbd17c 100644 --- a/llvm/lib/Target/SBF/SBFTargetFeatures.td +++ b/llvm/lib/Target/SBF/SBFTargetFeatures.td @@ -46,6 +46,9 @@ def FeatureStoreImm : SubtargetFeature<"store-imm", "HasStoreImm", "true", def FeatureExplicitSext : SubtargetFeature<"explicit-sext", "HasExplicitSignExt", "true", "Enable the explicit sign extension instruction mov32">; +def FeatureNewMemEncoding : SubtargetFeature<"mem-encoding", "NewMemEncoding", + "true", "Enable the new encoding for memory instructions">; + class Proc Features> : Processor; diff --git a/llvm/test/CodeGen/SBF/32-bit-subreg-load-store.ll b/llvm/test/CodeGen/SBF/32-bit-subreg-load-store.ll index e4fcde383c02f8..c79daf1fd995d1 100644 --- a/llvm/test/CodeGen/SBF/32-bit-subreg-load-store.ll +++ b/llvm/test/CodeGen/SBF/32-bit-subreg-load-store.ll @@ -1,4 +1,6 @@ ; RUN: llc -O2 -march=sbf -mattr=+alu32 < %s | FileCheck %s +; RUN: llc -O2 -march=sbf -mattr=+alu32,+mem-encoding < %s | FileCheck %s + ; ; unsigned char loadu8(unsigned char *p) ; { diff --git a/llvm/test/CodeGen/SBF/CORE/field-reloc-st-imm.ll b/llvm/test/CodeGen/SBF/CORE/field-reloc-st-imm.ll index ab5a6a68f2b229..7f76a4b92957b4 100644 --- a/llvm/test/CodeGen/SBF/CORE/field-reloc-st-imm.ll +++ b/llvm/test/CodeGen/SBF/CORE/field-reloc-st-imm.ll @@ -1,4 +1,5 @@ ; RUN: llc -march=sbf -mattr=+store-imm -sbf-enable-btf-emission < %s | FileCheck %s +; RUN: llc -march=sbf -mattr=+store-imm,+mem-encoding -sbf-enable-btf-emission < %s | FileCheck %s ; Make sure that CO-RE relocations had been generated correctly for ; BPF_ST (store immediate) instructions and that diff --git a/llvm/test/CodeGen/SBF/load.ll b/llvm/test/CodeGen/SBF/load.ll index 9710b7df111ef3..0084b2ab72dfe0 100644 --- a/llvm/test/CodeGen/SBF/load.ll +++ b/llvm/test/CodeGen/SBF/load.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -march=sbf | FileCheck %s +; RUN: llc < %s -march=sbf -mattr=+mem-encoding | FileCheck %s define i16 @am1(i16* %a) nounwind { %1 = load i16, i16* %a diff --git a/llvm/test/CodeGen/SBF/many_args_new_conv.ll b/llvm/test/CodeGen/SBF/many_args_new_conv.ll index b2a7fbe5ff863a..0fe748a6266f06 100644 --- a/llvm/test/CodeGen/SBF/many_args_new_conv.ll +++ b/llvm/test/CodeGen/SBF/many_args_new_conv.ll @@ -1,4 +1,5 @@ ; RUN: llc -O2 -march=sbf -mcpu=sbfv2 < %s | FileCheck %s +; RUN: llc -O2 -march=sbf -mcpu=sbfv2 -mattr=+mem-encoding < %s | FileCheck %s ; Function Attrs: nounwind uwtable define i32 @caller_no_alloca(i32 %a, i32 %b, i32 %c) #0 { diff --git a/llvm/test/CodeGen/SBF/memcpy_16.ll b/llvm/test/CodeGen/SBF/memcpy_16.ll index 4cfa911aab1911..678fb7aa28790c 100644 --- a/llvm/test/CodeGen/SBF/memcpy_16.ll +++ b/llvm/test/CodeGen/SBF/memcpy_16.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -march=sbf -sbf-expand-memcpy-in-order | FileCheck %s +; RUN: llc < %s -march=sbf -sbf-expand-memcpy-in-order -mattr=+mem-encoding | FileCheck %s ; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite) declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #1 diff --git a/llvm/test/CodeGen/SBF/preprocess-loads.ll b/llvm/test/CodeGen/SBF/preprocess-loads.ll index f36e2a976ec74d..7c7dc12b7cd542 100644 --- a/llvm/test/CodeGen/SBF/preprocess-loads.ll +++ b/llvm/test/CodeGen/SBF/preprocess-loads.ll @@ -1,4 +1,5 @@ ; RUN: llc -O2 -march=sbf -filetype=asm < %s | FileCheck --check-prefix=CHECK %s +; RUN: llc -O2 -march=sbf -filetype=asm -mattr=+mem-encoding < %s | FileCheck --check-prefix=CHECK %s %Pool = type <{ [0 x i8], [32 x i8], [0 x i8], i8, [0 x i8], [10 x %Decimal], [0 x i8] }> %Decimal = type { [0 x i32], i32, [0 x i32], i32, [0 x i32], i32, [0 x i32], i32, [0 x i32] } diff --git a/llvm/test/CodeGen/SBF/remove_truncate_3.ll b/llvm/test/CodeGen/SBF/remove_truncate_3.ll index 336015266607b1..ec8888cde7f2fb 100644 --- a/llvm/test/CodeGen/SBF/remove_truncate_3.ll +++ b/llvm/test/CodeGen/SBF/remove_truncate_3.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -march=sbf -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -march=sbf -mattr=+mem-encoding -verify-machineinstrs | FileCheck %s ; Source code: ; struct xdp_md { diff --git a/llvm/test/CodeGen/SBF/store-imm.ll b/llvm/test/CodeGen/SBF/store-imm.ll index 37b0bb1a32edb4..fe31bbbdbbebe8 100644 --- a/llvm/test/CodeGen/SBF/store-imm.ll +++ b/llvm/test/CodeGen/SBF/store-imm.ll @@ -1,11 +1,15 @@ ; RUN: llc < %s -march=sbf -mattr=+store-imm -show-mc-encoding | FileCheck %s ; RUN: llc < %s -march=sbf -mattr=+store-imm,+alu32 -show-mc-encoding | FileCheck %s +; RUN: llc < %s -march=sbf -mattr=+store-imm,+mem-encoding -show-mc-encoding | FileCheck --check-prefix=CHECK-V2 %s define void @byte(ptr %p0) { ; CHECK-LABEL: byte: ; CHECK: # %bb.0: ; CHECK-NEXT: stb [r1 + 0], 1 # encoding: [0x72,0x01,0x00,0x00,0x01,0x00,0x00,0x00] ; CHECK-NEXT: stb [r1 + 1], 255 # encoding: [0x72,0x01,0x01,0x00,0xff,0x00,0x00,0x00] + +; CHECK-V2: stb [r1 + 0], 1 # encoding: [0x27,0x01,0x00,0x00,0x01,0x00,0x00,0x00] +; CHECK-V2: stb [r1 + 1], 255 # encoding: [0x27,0x01,0x01,0x00,0xff,0x00,0x00,0x00] %p1 = getelementptr i8, ptr %p0, i32 1 store volatile i8 1, ptr %p0, align 1 store volatile i8 -1, ptr %p1, align 1 @@ -16,6 +20,9 @@ define void @half(ptr, ptr %p0) { ; CHECK: # %bb.0: ; CHECK-NEXT: sth [r2 + 0], 1 # encoding: [0x6a,0x02,0x00,0x00,0x01,0x00,0x00,0x00] ; CHECK-NEXT: sth [r2 + 2], 65535 # encoding: [0x6a,0x02,0x02,0x00,0xff,0xff,0x00,0x00] + +; CHECK-V2: sth [r2 + 0], 1 # encoding: [0x37,0x02,0x00,0x00,0x01,0x00,0x00,0x00] +; CHECK-V2: sth [r2 + 2], 65535 # encoding: [0x37,0x02,0x02,0x00,0xff,0xff,0x00,0x00] %p1 = getelementptr i8, ptr %p0, i32 2 store volatile i16 1, ptr %p0, align 2 store volatile i16 -1, ptr %p1, align 2 @@ -29,6 +36,12 @@ define void @word(ptr, ptr, ptr %p0) { ; CHECK-NEXT: stw [r3 + 8], -2000000000 # encoding: [0x62,0x03,0x08,0x00,0x00,0x6c,0xca,0x88] ; CHECK-NEXT: stw [r3 + 12], -1 # encoding: [0x62,0x03,0x0c,0x00,0xff,0xff,0xff,0xff] ; CHECK-NEXT: stw [r3 + 12], 0 # encoding: [0x62,0x03,0x0c,0x00,0x00,0x00,0x00,0x00] + +; CHECK-V2: stw [r3 + 0], 1 # encoding: [0x87,0x03,0x00,0x00,0x01,0x00,0x00,0x00] +; CHECK-V2: stw [r3 + 4], -1 # encoding: [0x87,0x03,0x04,0x00,0xff,0xff,0xff,0xff] +; CHECK-V2: stw [r3 + 8], -2000000000 # encoding: [0x87,0x03,0x08,0x00,0x00,0x6c,0xca,0x88] +; CHECK-V2: stw [r3 + 12], -1 # encoding: [0x87,0x03,0x0c,0x00,0xff,0xff,0xff,0xff] +; CHECK-V2: stw [r3 + 12], 0 # encoding: [0x87,0x03,0x0c,0x00,0x00,0x00,0x00,0x00] %p1 = getelementptr i8, ptr %p0, i32 4 %p2 = getelementptr i8, ptr %p0, i32 8 %p3 = getelementptr i8, ptr %p0, i32 12 @@ -48,6 +61,13 @@ define void @dword(ptr, ptr, ptr, ptr %p0) { ; CHECK-NEXT: stdw [r4 + 16], -2000000000 # encoding: [0x7a,0x04,0x10,0x00,0x00,0x6c,0xca,0x88] ; CHECK-NEXT: lddw r1, 4294967295 # encoding: [0x18,0x01,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] ; CHECK-NEXT: stxdw [r4 + 24], r1 # encoding: [0x7b,0x14,0x18,0x00,0x00,0x00,0x00,0x00] + +; CHECK-V2: stdw [r4 + 0], 1 # encoding: [0x97,0x04,0x00,0x00,0x01,0x00,0x00,0x00] +; CHECK-V2: stdw [r4 + 8], -1 # encoding: [0x97,0x04,0x08,0x00,0xff,0xff,0xff,0xff] +; CHECK-V2: stdw [r4 + 16], 2000000000 # encoding: [0x97,0x04,0x10,0x00,0x00,0x94,0x35,0x77] +; CHECK-V2: stdw [r4 + 16], -2000000000 # encoding: [0x97,0x04,0x10,0x00,0x00,0x6c,0xca,0x88] +; CHECK-V2: lddw r1, 4294967295 # encoding: [0x18,0x01,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] +; CHECK-V2: stxdw [r4 + 24], r1 # encoding: [0x9f,0x14,0x18,0x00,0x00,0x00,0x00,0x00] %p1 = getelementptr i8, ptr %p0, i32 8 %p2 = getelementptr i8, ptr %p0, i32 16 %p3 = getelementptr i8, ptr %p0, i32 24 @@ -66,6 +86,10 @@ define void @unaligned(ptr %p0) { ; CHECK-NEXT: sth [r1 + 0], 65534 # encoding: [0x6a,0x01,0x00,0x00,0xfe,0xff,0x00,0x00] ; CHECK-NEXT: stw [r1 + 8], -2 # encoding: [0x62,0x01,0x08,0x00,0xfe,0xff,0xff,0xff] ; CHECK-NEXT: stdw [r1 + 16], -2 # encoding: [0x7a,0x01,0x10,0x00,0xfe,0xff,0xff,0xff] + +; CHECK-V2: sth [r1 + 0], 65534 # encoding: [0x37,0x01,0x00,0x00,0xfe,0xff,0x00,0x00] +; CHECK-V2: stw [r1 + 8], -2 # encoding: [0x87,0x01,0x08,0x00,0xfe,0xff,0xff,0xff] +; CHECK-V2: stdw [r1 + 16], -2 # encoding: [0x97,0x01,0x10,0x00,0xfe,0xff,0xff,0xff] %p1 = getelementptr i8, ptr %p0, i32 8 %p2 = getelementptr i8, ptr %p0, i32 16 store volatile i16 -2, ptr %p0, align 1 diff --git a/llvm/test/CodeGen/SBF/undef.ll b/llvm/test/CodeGen/SBF/undef.ll index e3fcffdd92e759..1bf9360e1419b0 100644 --- a/llvm/test/CodeGen/SBF/undef.ll +++ b/llvm/test/CodeGen/SBF/undef.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -march=sbf | FileCheck -check-prefixes=CHECK %s +; RUN: llc < %s -march=sbf -mattr=+mem-encoding | FileCheck -check-prefixes=CHECK %s %struct.bpf_map_def = type { i32, i32, i32, i32 } %struct.__sk_buff = type opaque diff --git a/llvm/test/MC/Disassembler/SBF/sbf-ldst-new.txt b/llvm/test/MC/Disassembler/SBF/sbf-ldst-new.txt new file mode 100644 index 00000000000000..54f903f72cc11b --- /dev/null +++ b/llvm/test/MC/Disassembler/SBF/sbf-ldst-new.txt @@ -0,0 +1,62 @@ +# RUN: llvm-mc --disassemble %s -triple=sbf-solana-solana -mattr=+mem-encoding,+pqr-instr \ +# RUN: | FileCheck %s --check-prefix=CHECK-NEW +# RUN: llvm-mc --disassemble %s -triple=sbf-solana-solana -mattr=+alu32,+mem-encoding,+pqr-instr \ +# RUN: | FileCheck %s --check-prefix=CHECK32-NEW + + +# CHECK-NEW: ldxb r6, [r1 + 17] +# CHECK-NEW: ldxb r1, [r10 - 3] +# CHECK-NEW: ldxh r8, [r2 + 32] +# CHECK-NEW: ldxw r4, [r3 + 64] +# CHECK-NEW: ldxdw r0, [r4 + 128] +0x2c,0x16,0x11,0x00,0x00,0x00,0x00,0x00 +0x2c,0xa1,0xfd,0xff,0x00,0x00,0x00,0x00 +0x3c,0x28,0x20,0x00,0x00,0x00,0x00,0x00 +0x8c,0x34,0x40,0x00,0x00,0x00,0x00,0x00 +0x9c,0x40,0x80,0x00,0x00,0x00,0x00,0x00 + + + +# CHECK32-NEW: ldxb w6, [r1 + 17] +# CHECK32-NEW: ldxb w1, [r10 - 3] +# CHECK32-NEW: ldxh w8, [r2 + 32] +# CHECK32-NEW: ldxw w4, [r3 + 64] +0x2c,0x16,0x11,0x00,0x00,0x00,0x00,0x00 +0x2c,0xa1,0xfd,0xff,0x00,0x00,0x00,0x00 +0x3c,0x28,0x20,0x00,0x00,0x00,0x00,0x00 +0x8c,0x34,0x40,0x00,0x00,0x00,0x00,0x00 + + + +# CHECK-NEW: stxb [r1 + 17], r6 +# CHECK-NEW: stxb [r10 - 3], r1 +# CHECK-NEW: stxh [r2 + 32], r8 +# CHECK-NEW: stxw [r3 + 64], r4 +# CHECK-NEW: stxdw [r4 + 128], r0 +0x2f,0x61,0x11,0x00,0x00,0x00,0x00,0x00 +0x2f,0x1a,0xfd,0xff,0x00,0x00,0x00,0x00 +0x3f,0x82,0x20,0x00,0x00,0x00,0x00,0x00 +0x8f,0x43,0x40,0x00,0x00,0x00,0x00,0x00 +0x9f,0x04,0x80,0x00,0x00,0x00,0x00,0x00 + + + +# CHECK32-NEW: stxb [r1 + 17], w6 +# CHECK32-NEW: stxb [r10 - 3], w1 +# CHECK32-NEW: stxh [r2 + 32], w8 +# CHECK32-NEW: stxw [r3 + 64], w4 +0x2f,0x61,0x11,0x00,0x00,0x00,0x00,0x00 +0x2f,0x1a,0xfd,0xff,0x00,0x00,0x00,0x00 +0x3f,0x82,0x20,0x00,0x00,0x00,0x00,0x00 +0x8f,0x43,0x40,0x00,0x00,0x00,0x00,0x00 + + + +# CHECK-NEW: stb [r10 - 8], 2 +# CHECK-NEW: sth [r9 + 4], -20 +# CHECK-NEW: stw [r4 - 16], 34 +# CHECK-NEW: stdw [r1 + 24], 65534 +0x27,0x0a,0xf8,0xff,0x02,0x00,0x00,0x00 +0x37,0x09,0x04,0x00,0xec,0xff,0xff,0xff +0x87,0x04,0xf0,0xff,0x22,0x00,0x00,0x00 +0x97,0x01,0x18,0x00,0xfe,0xff,0x00,0x00 \ No newline at end of file diff --git a/llvm/test/MC/SBF/sbf-ldst-new.s b/llvm/test/MC/SBF/sbf-ldst-new.s new file mode 100644 index 00000000000000..5c2ac216f709f0 --- /dev/null +++ b/llvm/test/MC/SBF/sbf-ldst-new.s @@ -0,0 +1,91 @@ +# RUN: llvm-mc %s -triple=sbf-solana-solana -mattr=+mem-encoding,+pqr-instr --show-encoding \ +# RUN: | FileCheck %s --check-prefix=CHECK-ASM-NEW +# RUN: llvm-mc %s -triple=sbf-solana-solana -mcpu=sbfv2 -mattr=+mem-encoding,+pqr-instr -filetype=obj \ +# RUN: | llvm-objdump --mattr=+mem-encoding,+pqr-instr -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-OBJ-NEW %s +# RUN: llvm-mc %s -triple=sbf-solana-solana -mattr=+alu32,+mem-encoding,+pqr-instr --show-encoding \ +# RUN: | FileCheck %s --check-prefix=CHECK32-ASM-NEW +# RUN: llvm-mc %s -triple=sbf-solana-solana -mcpu=sbfv2 -mattr=+alu32,+mem-encoding,+pqr-instr -filetype=obj \ +# RUN: | llvm-objdump --mattr=+mem-encoding,+pqr-instr,+alu32 -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK32-OBJ-NEW %s + + + +# CHECK-OBJ-NEW: ldxb r6, [r1 + 0x11] +# CHECK-OBJ-NEW: ldxb r1, [r10 - 0x3] +# CHECK-OBJ-NEW: ldxh r8, [r2 + 0x20] +# CHECK-OBJ-NEW: ldxw r4, [r3 + 0x40] +# CHECK-OBJ-NEW: ldxdw r0, [r4 + 0x80] +# CHECK-ASM-NEW: encoding: [0x2c,0x16,0x11,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x2c,0xa1,0xfd,0xff,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x3c,0x28,0x20,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x8c,0x34,0x40,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x9c,0x40,0x80,0x00,0x00,0x00,0x00,0x00] +ldxb r6, [r1 + 17] +ldxb r1, [r10 - 3] +ldxh r8, [r2 + 32] +ldxw r4, [r3 + 64] +ldxdw r0, [r4 + 128] + + + +# CHECK32-OBJ-NEW: ldxb w6, [r1 + 0x11] +# CHECK32-OBJ-NEW: ldxb w1, [r10 - 0x3] +# CHECK32-OBJ-NEW: ldxh w8, [r2 + 0x20] +# CHECK32-OBJ-NEW: ldxw w4, [r3 + 0x40] +# CHECK32-ASM-NEW: encoding: [0x2c,0x16,0x11,0x00,0x00,0x00,0x00,0x00] +# CHECK32-ASM-NEW: encoding: [0x2c,0xa1,0xfd,0xff,0x00,0x00,0x00,0x00] +# CHECK32-ASM-NEW: encoding: [0x3c,0x28,0x20,0x00,0x00,0x00,0x00,0x00] +# CHECK32-ASM-NEW: encoding: [0x8c,0x34,0x40,0x00,0x00,0x00,0x00,0x00] +ldxb w6, [r1 + 17] +ldxb w1, [r10 - 3] +ldxh w8, [r2 + 32] +ldxw w4, [r3 + 64] + + + +# CHECK-OBJ-NEW: stxb [r1 + 0x11], r6 +# CHECK-OBJ-NEW: stxb [r10 - 0x3], r1 +# CHECK-OBJ-NEW: stxh [r2 + 0x20], r8 +# CHECK-OBJ-NEW: stxw [r3 + 0x40], r4 +# CHECK-OBJ-NEW: stxdw [r4 + 0x80], r0 +# CHECK-ASM-NEW: encoding: [0x2f,0x61,0x11,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x2f,0x1a,0xfd,0xff,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x3f,0x82,0x20,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x8f,0x43,0x40,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x9f,0x04,0x80,0x00,0x00,0x00,0x00,0x00] +stxb [r1 + 17], r6 +stxb [r10 - 3], r1 +stxh [r2 + 32], r8 +stxw [r3 + 64], r4 +stxdw [r4 + 128], r0 + + + +# CHECK32-OBJ-NEW: stxb [r1 + 0x11], w6 +# CHECK32-OBJ-NEW: stxb [r10 - 0x3], w1 +# CHECK32-OBJ-NEW: stxh [r2 + 0x20], w8 +# CHECK32-OBJ-NEW: stxw [r3 + 0x40], w4 +# CHECK32-ASM-NEW: encoding: [0x2f,0x61,0x11,0x00,0x00,0x00,0x00,0x00] +# CHECK32-ASM-NEW: encoding: [0x2f,0x1a,0xfd,0xff,0x00,0x00,0x00,0x00] +# CHECK32-ASM-NEW: encoding: [0x3f,0x82,0x20,0x00,0x00,0x00,0x00,0x00] +# CHECK32-ASM-NEW: encoding: [0x8f,0x43,0x40,0x00,0x00,0x00,0x00,0x00] +stxb [r1 + 17], w6 +stxb [r10 - 3], w1 +stxh [r2 + 32], w8 +stxw [r3 + 64], w4 + + + +# CHECK-OBJ-NEW: stb [r10 - 0x8], 0x2 +# CHECK-OBJ-NEW: sth [r9 + 0x4], -0x14 +# CHECK-OBJ-NEW: stw [r4 - 0x10], 0x22 +# CHECK-OBJ-NEW: stdw [r1 + 0x18], 0xfffe +# CHECK-ASM-NEW: encoding: [0x27,0x0a,0xf8,0xff,0x02,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x37,0x09,0x04,0x00,0xec,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0x87,0x04,0xf0,0xff,0x22,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x97,0x01,0x18,0x00,0xfe,0xff,0x00,0x00] +stb [r10 - 8], 2 +sth [r9 + 4], -20 +stw [r4 - 16], 34 +stdw [r1 + 24], 65534 \ No newline at end of file