Skip to content

Commit

Permalink
[SOL] Implement store imm instructions (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasSte authored Dec 2, 2024
1 parent 9fd4663 commit a802634
Show file tree
Hide file tree
Showing 10 changed files with 364 additions and 28 deletions.
10 changes: 6 additions & 4 deletions llvm/lib/Target/SBF/BTFDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,8 +1345,9 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) {
// If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>",
// The LD_imm64 result will be replaced with a btf type id.
processGlobalValue(MI->getOperand(1));
} else if (MI->getOpcode() == SBF::CORE_MEM ||
MI->getOpcode() == SBF::CORE_ALU32_MEM ||
} else if (MI->getOpcode() == SBF::CORE_LD64 ||
MI->getOpcode() == SBF::CORE_LD32 ||
MI->getOpcode() == SBF::CORE_ST ||
MI->getOpcode() == SBF::CORE_SHIFT) {
// relocation insn is a load, store or shift insn.
processGlobalValue(MI->getOperand(3));
Expand Down Expand Up @@ -1524,8 +1525,9 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) {
return true;
}
}
} else if (MI->getOpcode() == SBF::CORE_MEM ||
MI->getOpcode() == SBF::CORE_ALU32_MEM ||
} else if (MI->getOpcode() == SBF::CORE_LD64 ||
MI->getOpcode() == SBF::CORE_LD32 ||
MI->getOpcode() == SBF::CORE_ST ||
MI->getOpcode() == SBF::CORE_SHIFT) {
const MachineOperand &MO = MI->getOperand(3);
if (MO.isGlobal()) {
Expand Down
77 changes: 67 additions & 10 deletions llvm/lib/Target/SBF/SBFInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def SBFCallxSrc : Predicate<"Subtarget->getCallXRegSrc()">, AssemblerPredicate<(
def SBFNoCallxSrc : Predicate<"!Subtarget->getCallXRegSrc()">;
def SBFPqrInstr : Predicate<"Subtarget->getHasPqrClass()">;
def SBFNoPqrInstr : Predicate<"!Subtarget->getHasPqrClass()">;
def SBFHasStoreImm : Predicate<"Subtarget->getHasStoreImm()">;

def brtarget : Operand<OtherVT> {
let PrintMethod = "printBrTargetOperand";
Expand All @@ -74,10 +75,18 @@ def u64imm : Operand<i64> {
let PrintMethod = "printImm64Operand";
}

def gpr_or_imm : Operand<i64>;

def i64immSExt32 : PatLeaf<(i64 imm),
[{return isInt<32>(N->getSExtValue()); }]>;
def i32immSExt32 : PatLeaf<(i32 imm),
[{return isInt<32>(N->getSExtValue()); }]>;
def i64immZExt32 : PatLeaf<(i64 imm),
[{return isUInt<32>(N->getZExtValue()); }]>;

def imm_to_i64 : SDNodeXForm<timm, [{
return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
}]>;

// Fetch the upper 32-bits of a 64-bit integer.
def Upper32 : SDNodeXForm<imm, [{
Expand Down Expand Up @@ -469,7 +478,7 @@ class STORE<SBFWidthModifer SizeOp, string Mnemonic, list<dag> Pattern>
}

class STOREi64<SBFWidthModifer Opc, string Mnemonic, PatFrag OpNode>
: STORE<Opc, Mnemonic, [(OpNode i64:$src, ADDRri:$addr)]>;
: STORE<Opc, Mnemonic, [(OpNode GPR:$src, ADDRri:$addr)]>;

let Predicates = [SBFNoALU32] in {
def STW : STOREi64<SBF_W, "stxw", truncstorei32>;
Expand All @@ -478,6 +487,49 @@ let Predicates = [SBFNoALU32] in {
}
def STD : STOREi64<SBF_DW, "stxdw", store>;

class STORE_imm<SBFWidthModifer SizeOp,
string Mnemonic, dag Pattern>
: TYPE_LD_ST<SBF_MEM.Value, SizeOp.Value,
(outs),
(ins i64imm:$imm, MEMri:$addr),
Mnemonic # " [$addr], $imm",
[Pattern]> {
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;
}

// 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
// - it is incorrect to generate such write when immediate is
// +0xffff_ffff.
//
// In the latter case two instructions would be generated instead of
// one BPF_ST:
// lddw rA, 0xffffffff
// stx [rb], rA
//
// For SBF_{B,H,W} the size of value stored matches size of the immediate.
let Predicates = [SBFHasStoreImm] in {
def STD_imm : STORE_imm<SBF_DW, "stdw", (store (i64 i64immSExt32:$imm), ADDRri:$addr)>;
def STW_imm : STORE_imm<SBF_W, "stw", (truncstorei32 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
def STH_imm : STORE_imm<SBF_H, "sth", (truncstorei16 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
def STB_imm : STORE_imm<SBF_B, "stb", (truncstorei8 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
}

let Predicates = [SBFHasALU32, SBFHasStoreImm] in {
def : Pat<(store (i32 imm:$src), ADDRri:$dst),
(STW_imm (imm_to_i64 $src), ADDRri:$dst)>;
def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst),
(STH_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst),
(STB_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
}

// LOAD instructions
class LOAD<SBFWidthModifer SizeOp, string Mnemonic, list<dag> Pattern>
: TYPE_LD_ST<SBF_MEM.Value, SizeOp.Value,
Expand All @@ -498,16 +550,21 @@ class LOADi64<SBFWidthModifer SizeOp, string Mnemonic, PatFrag OpNode>
: LOAD<SizeOp, Mnemonic, [(set i64:$dst, (OpNode ADDRri:$addr))]>;

let isCodeGenOnly = 1 in {
def CORE_MEM : TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
(outs GPR:$dst),
class CORE_LD<RegisterClass RegClass, string Sz>
: TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
(outs RegClass:$dst),
(ins u64imm:$opcode, GPR:$src, u64imm:$offset),
"$dst = core_mem($opcode, $src, $offset)",
"$dst = core_ld"#Sz#"($opcode, $src, $offset)",
[]>;
def CORE_ALU32_MEM : TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
(outs GPR32:$dst),
(ins u64imm:$opcode, GPR:$src, u64imm:$offset),
"$dst = core_alu32_mem($opcode, $src, $offset)",
[]>;

def CORE_LD64 : CORE_LD<GPR, "64">;
def CORE_LD32 : CORE_LD<GPR32, "32">;

def CORE_ST : TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
(outs),
(ins gpr_or_imm:$src, u64imm:$opcode, GPR:$ptr, u64imm:$offset),
"core_st($src, $opcode, $ptr, $offset)",
[]>;
let Constraints = "$dst = $src" in {
def CORE_SHIFT : MATH_RR<SBF_ALU64, SBF_LSH,
(outs GPR:$dst),
Expand Down Expand Up @@ -996,7 +1053,7 @@ class STORE32<SBFWidthModifer SizeOp, string Mnemonic, list<dag> Pattern>
}

class STOREi32<SBFWidthModifer Opc, string Mnemonic, PatFrag OpNode>
: STORE32<Opc, Mnemonic, [(OpNode i32:$src, ADDRri:$addr)]>;
: STORE32<Opc, Mnemonic, [(OpNode GPR32:$src, ADDRri:$addr)]>;

let Predicates = [SBFHasALU32], DecoderNamespace = "SBFALU32" in {
def STW32 : STOREi32<SBF_W, "stxw", store>;
Expand Down
45 changes: 31 additions & 14 deletions llvm/lib/Target/SBF/SBFMISimplifyPatchable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,31 @@ 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 isSTX32(unsigned Opcode) {
return Opcode == SBF::STB32 || Opcode == SBF::STH32 || Opcode == SBF::STW32;
}

static bool isSTX64(unsigned Opcode) {
return Opcode == SBF::STB || Opcode == SBF::STH || Opcode == SBF::STW ||
Opcode == SBF::STD;
}

static bool isLDX32(unsigned Opcode) {
return Opcode == SBF::LDB32 || Opcode == SBF::LDH32 || Opcode == SBF::LDW32;
}

static bool isLDX64(unsigned Opcode) {
return Opcode == SBF::LDB || Opcode == SBF::LDH || Opcode == SBF::LDW ||
Opcode == SBF::LDD;
}

bool SBFMISimplifyPatchable::isLoadInst(unsigned Opcode) {
return Opcode == SBF::LDD || Opcode == SBF::LDW || Opcode == SBF::LDH ||
Opcode == SBF::LDB || Opcode == SBF::LDW32 || Opcode == SBF::LDH32 ||
Opcode == SBF::LDB32;
return isLDX32(Opcode) || isLDX64(Opcode);
}

void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
Expand All @@ -116,14 +137,12 @@ void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
MachineInstr *DefInst = MO.getParent();
unsigned Opcode = DefInst->getOpcode();
unsigned COREOp;
if (Opcode == SBF::LDB || Opcode == SBF::LDH || Opcode == SBF::LDW ||
Opcode == SBF::LDD || Opcode == SBF::STB || Opcode == SBF::STH ||
Opcode == SBF::STW || Opcode == SBF::STD)
COREOp = SBF::CORE_MEM;
else if (Opcode == SBF::LDB32 || Opcode == SBF::LDH32 ||
Opcode == SBF::LDW32 || Opcode == SBF::STB32 ||
Opcode == SBF::STH32 || Opcode == SBF::STW32)
COREOp = SBF::CORE_ALU32_MEM;
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;
else
continue;

Expand All @@ -135,9 +154,7 @@ void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
// Reject the form:
// %1 = ADD_rr %2, %3
// *(type *)(%2 + 0) = %1
if (Opcode == SBF::STB || Opcode == SBF::STH || Opcode == SBF::STW ||
Opcode == SBF::STD || Opcode == SBF::STB32 || Opcode == SBF::STH32 ||
Opcode == SBF::STW32) {
if (isSTX64(Opcode) || isSTX32(Opcode)) {
const MachineOperand &Opnd = DefInst->getOperand(0);
if (Opnd.isReg() && Opnd.getReg() == MO.getReg())
continue;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SBF/SBFSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void SBFSubtarget::initializeEnvironment(const Triple &TT) {
CallxRegSrc = false;
HasPqrClass = false;
NewCallConvention = false;
HasStoreImm = false;
}

void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/SBF/SBFSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class SBFSubtarget : public SBFGenSubtargetInfo {
// Whether to use the new call convention in SBFv2
bool NewCallConvention;

// Whether we have store imm instructions
bool HasStoreImm;

public:
// This constructor initializes the data members to match that
// of the specified triple.
Expand All @@ -101,6 +104,7 @@ class SBFSubtarget : public SBFGenSubtargetInfo {
bool getEnableNewCallConvention() const {
return HasDynamicFrames && NewCallConvention;
}
bool getHasStoreImm() const { return HasStoreImm; }
const SBFInstrInfo *getInstrInfo() const override { return &InstrInfo; }
const SBFFrameLowering *getFrameLowering() const override {
return &FrameLowering;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/SBF/SBFTargetFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def FeaturePqrInstr : SubtargetFeature<"pqr-instr", "HasPqrClass", "true",
def FeatureCallConv : SubtargetFeature<"new-call-conv", "NewCallConvention", "true",
"Enable new call convetion for SBFv2">;

def FeatureStoreImm : SubtargetFeature<"store-imm", "HasStoreImm", "true",
"Enable store imm instructions">;

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

Expand Down
Loading

0 comments on commit a802634

Please sign in to comment.