summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp14
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.td99
2 files changed, 103 insertions, 10 deletions
diff --git a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
index 014dc86eaec..1c3a246bc09 100644
--- a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
+++ b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
@@ -39,8 +39,14 @@ using namespace llvm;
namespace {
class BPFDAGToDAGISel : public SelectionDAGISel {
+
+ /// Subtarget - Keep a pointer to the BPFSubtarget around so that we can
+ /// make the right decision when generating code for different subtargets.
+ const BPFSubtarget *Subtarget;
+
public:
- explicit BPFDAGToDAGISel(BPFTargetMachine &TM) : SelectionDAGISel(TM) {
+ explicit BPFDAGToDAGISel(BPFTargetMachine &TM)
+ : SelectionDAGISel(TM), Subtarget(nullptr) {
curr_func_ = nullptr;
}
@@ -48,6 +54,12 @@ public:
return "BPF DAG->DAG Pattern Instruction Selection";
}
+ bool runOnMachineFunction(MachineFunction &MF) override {
+ // Reset the subtarget each time through.
+ Subtarget = &MF.getSubtarget<BPFSubtarget>();
+ return SelectionDAGISel::runOnMachineFunction(MF);
+ }
+
void PreprocessISelDAG() override;
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index 942a5b013ff..dc4fdc571ab 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -45,6 +45,8 @@ def BPFselectcc : SDNode<"BPFISD::SELECT_CC", SDT_BPFSelectCC, [SDNPInGlue]>
def BPFWrapper : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>;
def BPFIsLittleEndian : Predicate<"CurDAG->getDataLayout().isLittleEndian()">;
def BPFIsBigEndian : Predicate<"!CurDAG->getDataLayout().isLittleEndian()">;
+def BPFHasALU32 : Predicate<"Subtarget->getHasAlu32()">;
+def BPFNoALU32 : Predicate<"!Subtarget->getHasAlu32()">;
def brtarget : Operand<OtherVT> {
let PrintMethod = "printBrTargetOperand";
@@ -349,9 +351,11 @@ class STORE<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
class STOREi64<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
: STORE<Opc, OpcodeStr, [(OpNode i64:$src, ADDRri:$addr)]>;
-def STW : STOREi64<BPF_W, "u32", truncstorei32>;
-def STH : STOREi64<BPF_H, "u16", truncstorei16>;
-def STB : STOREi64<BPF_B, "u8", truncstorei8>;
+let Predicates = [BPFNoALU32] in {
+ def STW : STOREi64<BPF_W, "u32", truncstorei32>;
+ def STH : STOREi64<BPF_H, "u16", truncstorei16>;
+ def STB : STOREi64<BPF_B, "u8", truncstorei8>;
+}
def STD : STOREi64<BPF_DW, "u64", store>;
// LOAD instructions
@@ -373,9 +377,13 @@ class LOAD<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
class LOADi64<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
: LOAD<SizeOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
-def LDW : LOADi64<BPF_W, "u32", zextloadi32>;
-def LDH : LOADi64<BPF_H, "u16", zextloadi16>;
-def LDB : LOADi64<BPF_B, "u8", zextloadi8>;
+
+let Predicates = [BPFNoALU32] in {
+ def LDW : LOADi64<BPF_W, "u32", zextloadi32>;
+ def LDH : LOADi64<BPF_H, "u16", zextloadi16>;
+ def LDB : LOADi64<BPF_B, "u8", zextloadi8>;
+}
+
def LDD : LOADi64<BPF_DW, "u64", load>;
class BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
@@ -524,9 +532,11 @@ def : Pat<(BPFcall imm:$dst), (JAL imm:$dst)>;
def : Pat<(BPFcall GPR:$dst), (JALX GPR:$dst)>;
// Loads
-def : Pat<(extloadi8 ADDRri:$src), (i64 (LDB ADDRri:$src))>;
-def : Pat<(extloadi16 ADDRri:$src), (i64 (LDH ADDRri:$src))>;
-def : Pat<(extloadi32 ADDRri:$src), (i64 (LDW ADDRri:$src))>;
+let Predicates = [BPFNoALU32] 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))>;
+}
// Atomics
class XADD<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
@@ -633,3 +643,74 @@ def : Pat<(i32 (trunc GPR:$src)),
// For i32 -> i64 anyext, we don't care about the high bits.
def : Pat<(i64 (anyext GPR32:$src)),
(INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>;
+
+class STORE32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
+ : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
+ (outs),
+ (ins GPR32:$src, MEMri:$addr),
+ "*("#OpcodeStr#" *)($addr) = $src",
+ Pattern> {
+ 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 BPFClass = BPF_STX;
+}
+
+class STOREi32<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
+ : STORE32<Opc, OpcodeStr, [(OpNode i32:$src, ADDRri:$addr)]>;
+
+let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
+ def STW32 : STOREi32<BPF_W, "u32", store>;
+ def STH32 : STOREi32<BPF_H, "u16", truncstorei16>;
+ def STB32 : STOREi32<BPF_B, "u8", truncstorei8>;
+}
+
+class LOAD32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
+ : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
+ (outs GPR32:$dst),
+ (ins MEMri:$addr),
+ "$dst = *("#OpcodeStr#" *)($addr)",
+ Pattern> {
+ 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 BPFClass = BPF_LDX;
+}
+
+class LOADi32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
+ : LOAD32<SizeOp, OpcodeStr, [(set i32:$dst, (OpNode ADDRri:$addr))]>;
+
+let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
+ def LDW32 : LOADi32<BPF_W, "u32", load>;
+ def LDH32 : LOADi32<BPF_H, "u16", zextloadi16>;
+ def LDB32 : LOADi32<BPF_B, "u8", zextloadi8>;
+}
+
+let Predicates = [BPFHasALU32] in {
+ def : Pat<(truncstorei8 GPR:$src, ADDRri:$dst),
+ (STB32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>;
+ def : Pat<(truncstorei16 GPR:$src, ADDRri:$dst),
+ (STH32 (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))>;
+ def : Pat<(i64 (zextloadi8 ADDRri:$src)),
+ (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>;
+ def : Pat<(i64 (zextloadi16 ADDRri:$src)),
+ (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>;
+ def : Pat<(i64 (zextloadi32 ADDRri:$src)),
+ (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>;
+ def : Pat<(i64 (extloadi8 ADDRri:$src)),
+ (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>;
+ def : Pat<(i64 (extloadi16 ADDRri:$src)),
+ (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>;
+ def : Pat<(i64 (extloadi32 ADDRri:$src)),
+ (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>;
+}
OpenPOWER on IntegriCloud