Skip to content

Commit a802634

Browse files
authored
[SOL] Implement store imm instructions (#115)
1 parent 9fd4663 commit a802634

File tree

10 files changed

+364
-28
lines changed

10 files changed

+364
-28
lines changed

llvm/lib/Target/SBF/BTFDebug.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,8 +1345,9 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) {
13451345
// If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>",
13461346
// The LD_imm64 result will be replaced with a btf type id.
13471347
processGlobalValue(MI->getOperand(1));
1348-
} else if (MI->getOpcode() == SBF::CORE_MEM ||
1349-
MI->getOpcode() == SBF::CORE_ALU32_MEM ||
1348+
} else if (MI->getOpcode() == SBF::CORE_LD64 ||
1349+
MI->getOpcode() == SBF::CORE_LD32 ||
1350+
MI->getOpcode() == SBF::CORE_ST ||
13501351
MI->getOpcode() == SBF::CORE_SHIFT) {
13511352
// relocation insn is a load, store or shift insn.
13521353
processGlobalValue(MI->getOperand(3));
@@ -1524,8 +1525,9 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) {
15241525
return true;
15251526
}
15261527
}
1527-
} else if (MI->getOpcode() == SBF::CORE_MEM ||
1528-
MI->getOpcode() == SBF::CORE_ALU32_MEM ||
1528+
} else if (MI->getOpcode() == SBF::CORE_LD64 ||
1529+
MI->getOpcode() == SBF::CORE_LD32 ||
1530+
MI->getOpcode() == SBF::CORE_ST ||
15291531
MI->getOpcode() == SBF::CORE_SHIFT) {
15301532
const MachineOperand &MO = MI->getOperand(3);
15311533
if (MO.isGlobal()) {

llvm/lib/Target/SBF/SBFInstrInfo.td

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def SBFCallxSrc : Predicate<"Subtarget->getCallXRegSrc()">, AssemblerPredicate<(
6464
def SBFNoCallxSrc : Predicate<"!Subtarget->getCallXRegSrc()">;
6565
def SBFPqrInstr : Predicate<"Subtarget->getHasPqrClass()">;
6666
def SBFNoPqrInstr : Predicate<"!Subtarget->getHasPqrClass()">;
67+
def SBFHasStoreImm : Predicate<"Subtarget->getHasStoreImm()">;
6768

6869
def brtarget : Operand<OtherVT> {
6970
let PrintMethod = "printBrTargetOperand";
@@ -74,10 +75,18 @@ def u64imm : Operand<i64> {
7475
let PrintMethod = "printImm64Operand";
7576
}
7677

78+
def gpr_or_imm : Operand<i64>;
79+
7780
def i64immSExt32 : PatLeaf<(i64 imm),
7881
[{return isInt<32>(N->getSExtValue()); }]>;
7982
def i32immSExt32 : PatLeaf<(i32 imm),
8083
[{return isInt<32>(N->getSExtValue()); }]>;
84+
def i64immZExt32 : PatLeaf<(i64 imm),
85+
[{return isUInt<32>(N->getZExtValue()); }]>;
86+
87+
def imm_to_i64 : SDNodeXForm<timm, [{
88+
return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
89+
}]>;
8190

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

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

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

490+
class STORE_imm<SBFWidthModifer SizeOp,
491+
string Mnemonic, dag Pattern>
492+
: TYPE_LD_ST<SBF_MEM.Value, SizeOp.Value,
493+
(outs),
494+
(ins i64imm:$imm, MEMri:$addr),
495+
Mnemonic # " [$addr], $imm",
496+
[Pattern]> {
497+
bits<20> addr;
498+
bits<32> imm;
499+
let Inst{51-48} = addr{19-16}; // base reg
500+
let Inst{47-32} = addr{15-0}; // offset
501+
let Inst{31-0} = imm;
502+
let SBFClass = SBF_ST;
503+
}
504+
505+
// Opcode (SBF_ST | SBF_MEM | SBF_DW) implies sign extension for
506+
// value stored to memory:
507+
// - it is fine to generate such write when immediate is -1
508+
// - it is incorrect to generate such write when immediate is
509+
// +0xffff_ffff.
510+
//
511+
// In the latter case two instructions would be generated instead of
512+
// one BPF_ST:
513+
// lddw rA, 0xffffffff
514+
// stx [rb], rA
515+
//
516+
// For SBF_{B,H,W} the size of value stored matches size of the immediate.
517+
let Predicates = [SBFHasStoreImm] in {
518+
def STD_imm : STORE_imm<SBF_DW, "stdw", (store (i64 i64immSExt32:$imm), ADDRri:$addr)>;
519+
def STW_imm : STORE_imm<SBF_W, "stw", (truncstorei32 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
520+
def STH_imm : STORE_imm<SBF_H, "sth", (truncstorei16 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
521+
def STB_imm : STORE_imm<SBF_B, "stb", (truncstorei8 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
522+
}
523+
524+
let Predicates = [SBFHasALU32, SBFHasStoreImm] in {
525+
def : Pat<(store (i32 imm:$src), ADDRri:$dst),
526+
(STW_imm (imm_to_i64 $src), ADDRri:$dst)>;
527+
def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst),
528+
(STH_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
529+
def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst),
530+
(STB_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
531+
}
532+
481533
// LOAD instructions
482534
class LOAD<SBFWidthModifer SizeOp, string Mnemonic, list<dag> Pattern>
483535
: TYPE_LD_ST<SBF_MEM.Value, SizeOp.Value,
@@ -498,16 +550,21 @@ class LOADi64<SBFWidthModifer SizeOp, string Mnemonic, PatFrag OpNode>
498550
: LOAD<SizeOp, Mnemonic, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
499551

500552
let isCodeGenOnly = 1 in {
501-
def CORE_MEM : TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
502-
(outs GPR:$dst),
553+
class CORE_LD<RegisterClass RegClass, string Sz>
554+
: TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
555+
(outs RegClass:$dst),
503556
(ins u64imm:$opcode, GPR:$src, u64imm:$offset),
504-
"$dst = core_mem($opcode, $src, $offset)",
557+
"$dst = core_ld"#Sz#"($opcode, $src, $offset)",
505558
[]>;
506-
def CORE_ALU32_MEM : TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
507-
(outs GPR32:$dst),
508-
(ins u64imm:$opcode, GPR:$src, u64imm:$offset),
509-
"$dst = core_alu32_mem($opcode, $src, $offset)",
510-
[]>;
559+
560+
def CORE_LD64 : CORE_LD<GPR, "64">;
561+
def CORE_LD32 : CORE_LD<GPR32, "32">;
562+
563+
def CORE_ST : TYPE_LD_ST<SBF_MEM.Value, SBF_W.Value,
564+
(outs),
565+
(ins gpr_or_imm:$src, u64imm:$opcode, GPR:$ptr, u64imm:$offset),
566+
"core_st($src, $opcode, $ptr, $offset)",
567+
[]>;
511568
let Constraints = "$dst = $src" in {
512569
def CORE_SHIFT : MATH_RR<SBF_ALU64, SBF_LSH,
513570
(outs GPR:$dst),
@@ -996,7 +1053,7 @@ class STORE32<SBFWidthModifer SizeOp, string Mnemonic, list<dag> Pattern>
9961053
}
9971054

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

10011058
let Predicates = [SBFHasALU32], DecoderNamespace = "SBFALU32" in {
10021059
def STW32 : STOREi32<SBF_W, "stxw", store>;

llvm/lib/Target/SBF/SBFMISimplifyPatchable.cpp

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,31 @@ void SBFMISimplifyPatchable::initialize(MachineFunction &MFParm) {
9292
LLVM_DEBUG(dbgs() << "*** SBF simplify patchable insts pass ***\n\n");
9393
}
9494

95+
static bool isST(unsigned Opcode) {
96+
return Opcode == SBF::STB_imm || Opcode == SBF::STH_imm ||
97+
Opcode == SBF::STW_imm || Opcode == SBF::STD_imm;
98+
}
99+
100+
static bool isSTX32(unsigned Opcode) {
101+
return Opcode == SBF::STB32 || Opcode == SBF::STH32 || Opcode == SBF::STW32;
102+
}
103+
104+
static bool isSTX64(unsigned Opcode) {
105+
return Opcode == SBF::STB || Opcode == SBF::STH || Opcode == SBF::STW ||
106+
Opcode == SBF::STD;
107+
}
108+
109+
static bool isLDX32(unsigned Opcode) {
110+
return Opcode == SBF::LDB32 || Opcode == SBF::LDH32 || Opcode == SBF::LDW32;
111+
}
112+
113+
static bool isLDX64(unsigned Opcode) {
114+
return Opcode == SBF::LDB || Opcode == SBF::LDH || Opcode == SBF::LDW ||
115+
Opcode == SBF::LDD;
116+
}
117+
95118
bool SBFMISimplifyPatchable::isLoadInst(unsigned Opcode) {
96-
return Opcode == SBF::LDD || Opcode == SBF::LDW || Opcode == SBF::LDH ||
97-
Opcode == SBF::LDB || Opcode == SBF::LDW32 || Opcode == SBF::LDH32 ||
98-
Opcode == SBF::LDB32;
119+
return isLDX32(Opcode) || isLDX64(Opcode);
99120
}
100121

101122
void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
@@ -116,14 +137,12 @@ void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
116137
MachineInstr *DefInst = MO.getParent();
117138
unsigned Opcode = DefInst->getOpcode();
118139
unsigned COREOp;
119-
if (Opcode == SBF::LDB || Opcode == SBF::LDH || Opcode == SBF::LDW ||
120-
Opcode == SBF::LDD || Opcode == SBF::STB || Opcode == SBF::STH ||
121-
Opcode == SBF::STW || Opcode == SBF::STD)
122-
COREOp = SBF::CORE_MEM;
123-
else if (Opcode == SBF::LDB32 || Opcode == SBF::LDH32 ||
124-
Opcode == SBF::LDW32 || Opcode == SBF::STB32 ||
125-
Opcode == SBF::STH32 || Opcode == SBF::STW32)
126-
COREOp = SBF::CORE_ALU32_MEM;
140+
if (isLDX64(Opcode))
141+
COREOp = SBF::CORE_LD64;
142+
else if (isLDX32(Opcode))
143+
COREOp = SBF::CORE_LD32;
144+
else if (isSTX64(Opcode) || isSTX32(Opcode) || isST(Opcode))
145+
COREOp = SBF::CORE_ST;
127146
else
128147
continue;
129148

@@ -135,9 +154,7 @@ void SBFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
135154
// Reject the form:
136155
// %1 = ADD_rr %2, %3
137156
// *(type *)(%2 + 0) = %1
138-
if (Opcode == SBF::STB || Opcode == SBF::STH || Opcode == SBF::STW ||
139-
Opcode == SBF::STD || Opcode == SBF::STB32 || Opcode == SBF::STH32 ||
140-
Opcode == SBF::STW32) {
157+
if (isSTX64(Opcode) || isSTX32(Opcode)) {
141158
const MachineOperand &Opnd = DefInst->getOperand(0);
142159
if (Opnd.isReg() && Opnd.getReg() == MO.getReg())
143160
continue;

llvm/lib/Target/SBF/SBFSubtarget.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ void SBFSubtarget::initializeEnvironment(const Triple &TT) {
4747
CallxRegSrc = false;
4848
HasPqrClass = false;
4949
NewCallConvention = false;
50+
HasStoreImm = false;
5051
}
5152

5253
void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {

llvm/lib/Target/SBF/SBFSubtarget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ class SBFSubtarget : public SBFGenSubtargetInfo {
7777
// Whether to use the new call convention in SBFv2
7878
bool NewCallConvention;
7979

80+
// Whether we have store imm instructions
81+
bool HasStoreImm;
82+
8083
public:
8184
// This constructor initializes the data members to match that
8285
// of the specified triple.
@@ -101,6 +104,7 @@ class SBFSubtarget : public SBFGenSubtargetInfo {
101104
bool getEnableNewCallConvention() const {
102105
return HasDynamicFrames && NewCallConvention;
103106
}
107+
bool getHasStoreImm() const { return HasStoreImm; }
104108
const SBFInstrInfo *getInstrInfo() const override { return &InstrInfo; }
105109
const SBFFrameLowering *getFrameLowering() const override {
106110
return &FrameLowering;

llvm/lib/Target/SBF/SBFTargetFeatures.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ def FeaturePqrInstr : SubtargetFeature<"pqr-instr", "HasPqrClass", "true",
4343
def FeatureCallConv : SubtargetFeature<"new-call-conv", "NewCallConvention", "true",
4444
"Enable new call convetion for SBFv2">;
4545

46+
def FeatureStoreImm : SubtargetFeature<"store-imm", "HasStoreImm", "true",
47+
"Enable store imm instructions">;
48+
4649
class Proc<string Name, list<SubtargetFeature> Features>
4750
: Processor<Name, NoItineraries, Features>;
4851

0 commit comments

Comments
 (0)