Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SOL] Implement store imm instructions #115

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading