summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorYonghong Song <yhs@fb.com>2017-09-28 02:46:11 +0000
committerYonghong Song <yhs@fb.com>2017-09-28 02:46:11 +0000
commite9165f87203a0480fcc0308004467a9b4237170a (patch)
tree6b6f94bc6fec13bc9b6a882f63fc020c41308cb0 /llvm/lib/Target
parentdef1729dc40d4d24ee979be9b2be8d4d70fae1c9 (diff)
downloadbcm5719-llvm-e9165f87203a0480fcc0308004467a9b4237170a.tar.gz
bcm5719-llvm-e9165f87203a0480fcc0308004467a9b4237170a.zip
bpf: add new insns for bswap_to_le and negation
This patch adds new insn, "reg = be16/be32/be64 reg", for bswap to little endian for big-endian target (bpfeb). It also adds new insn for negation "reg = -reg". Currently, for source code, e.g., b = -a LLVM still prefers to generate: b = 0 - a But "reg = -reg" format can be used in assembly code. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Alexei Starovoitov <ast@kernel.org> llvm-svn: 314376
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp41
-rw-r--r--llvm/lib/Target/BPF/BPFInstrFormats.td1
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.td42
3 files changed, 70 insertions, 14 deletions
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index d00200c1850..9e251d211d2 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -30,6 +30,8 @@ struct BPFOperand;
class BPFAsmParser : public MCTargetAsmParser {
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
+ bool PreMatchCheck(OperandVector &Operands);
+
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
uint64_t &ErrorInfo,
@@ -225,9 +227,6 @@ public:
.Case("*", true)
.Case("exit", true)
.Case("lock", true)
- .Case("bswap64", true)
- .Case("bswap32", true)
- .Case("bswap16", true)
.Case("ld_pseudo", true)
.Default(false);
}
@@ -239,6 +238,12 @@ public:
.Case("u32", true)
.Case("u16", true)
.Case("u8", true)
+ .Case("be64", true)
+ .Case("be32", true)
+ .Case("be16", true)
+ .Case("le64", true)
+ .Case("le32", true)
+ .Case("le16", true)
.Case("goto", true)
.Case("ll", true)
.Case("skb", true)
@@ -252,6 +257,28 @@ public:
#define GET_MATCHER_IMPLEMENTATION
#include "BPFGenAsmMatcher.inc"
+bool BPFAsmParser::PreMatchCheck(OperandVector &Operands) {
+
+ if (Operands.size() == 4) {
+ // check "reg1 = -reg2" and "reg1 = be16/be32/be64/le16/le32/le64 reg2",
+ // reg1 must be the same as reg2
+ BPFOperand &Op0 = (BPFOperand &)*Operands[0];
+ BPFOperand &Op1 = (BPFOperand &)*Operands[1];
+ BPFOperand &Op2 = (BPFOperand &)*Operands[2];
+ BPFOperand &Op3 = (BPFOperand &)*Operands[3];
+ if (Op0.isReg() && Op1.isToken() && Op2.isToken() && Op3.isReg()
+ && Op1.getToken() == "="
+ && (Op2.getToken() == "-" || Op2.getToken() == "be16"
+ || Op2.getToken() == "be32" || Op2.getToken() == "be64"
+ || Op2.getToken() == "le16" || Op2.getToken() == "le32"
+ || Op2.getToken() == "le64")
+ && Op0.getReg() != Op3.getReg())
+ return true;
+ }
+
+ return false;
+}
+
bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out, uint64_t &ErrorInfo,
@@ -259,6 +286,9 @@ bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
MCInst Inst;
SMLoc ErrorLoc;
+ if (PreMatchCheck(Operands))
+ return Error(IDLoc, "additional inst constraint not met");
+
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
default:
break;
@@ -324,13 +354,8 @@ BPFAsmParser::parseOperandAsOperator(OperandVector &Operands) {
switch (getLexer().getKind()) {
case AsmToken::Minus:
case AsmToken::Plus: {
- StringRef Name = getLexer().getTok().getString();
-
if (getLexer().peekTok().is(AsmToken::Integer))
return MatchOperand_NoMatch;
-
- getLexer().Lex();
- Operands.push_back(BPFOperand::createToken(Name, S));
}
// Fall through.
diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td
index 1e3bc3b7a6d..92d4a62fd87 100644
--- a/llvm/lib/Target/BPF/BPFInstrFormats.td
+++ b/llvm/lib/Target/BPF/BPFInstrFormats.td
@@ -38,6 +38,7 @@ def BPF_OR : BPFArithOp<0x4>;
def BPF_AND : BPFArithOp<0x5>;
def BPF_LSH : BPFArithOp<0x6>;
def BPF_RSH : BPFArithOp<0x7>;
+def BPF_NEG : BPFArithOp<0x8>;
def BPF_XOR : BPFArithOp<0xa>;
def BPF_MOV : BPFArithOp<0xb>;
def BPF_ARSH : BPFArithOp<0xc>;
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index e1f233e4d45..7d4b03deebe 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -43,6 +43,8 @@ def BPFbrcc : SDNode<"BPFISD::BR_CC", SDT_BPFBrCC,
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 brtarget : Operand<OtherVT>;
def calltarget : Operand<i64>;
@@ -232,6 +234,26 @@ let isAsCheapAsAMove = 1 in {
defm DIV : ALU<BPF_DIV, "/=", udiv>;
}
+class NEG_RR<BPFOpClass Class, BPFArithOp Opc,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : TYPE_ALU_JMP<Opc.Value, 0, outs, ins, asmstr, pattern> {
+ bits<4> dst;
+ bits<4> src;
+
+ let Inst{55-52} = src;
+ let Inst{51-48} = dst;
+ let BPFClass = Class;
+}
+
+let Constraints = "$dst = $src", isAsCheapAsAMove = 1 in {
+ def NEG_64: NEG_RR<BPF_ALU64, BPF_NEG, (outs GPR:$dst), (ins GPR:$src),
+ "$dst = -$src",
+ [(set GPR:$dst, (ineg i64:$src))]>;
+ def NEG_32: NEG_RR<BPF_ALU, BPF_NEG, (outs GPR32:$dst), (ins GPR32:$src),
+ "$dst = -$src",
+ [(set GPR32:$dst, (ineg i32:$src))]>;
+}
+
class LD_IMM64<bits<4> Pseudo, string OpcodeStr>
: TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
(outs GPR:$dst),
@@ -484,11 +506,11 @@ def XADD64 : XADD<BPF_DW, "u64", atomic_load_add_64>;
}
// bswap16, bswap32, bswap64
-class BSWAP<bits<32> SizeOp, string OpcodeStr, list<dag> Pattern>
- : TYPE_ALU_JMP<BPF_END.Value, BPF_TO_BE.Value,
+class BSWAP<bits<32> SizeOp, string OpcodeStr, BPFSrcType SrcType, list<dag> Pattern>
+ : TYPE_ALU_JMP<BPF_END.Value, SrcType.Value,
(outs GPR:$dst),
(ins GPR:$src),
- !strconcat(OpcodeStr, "\t$dst"),
+ "$dst = "#OpcodeStr#" $src",
Pattern> {
bits<4> dst;
@@ -497,10 +519,18 @@ class BSWAP<bits<32> SizeOp, string OpcodeStr, list<dag> Pattern>
let BPFClass = BPF_ALU;
}
+
let Constraints = "$dst = $src" in {
-def BSWAP16 : BSWAP<16, "bswap16", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
-def BSWAP32 : BSWAP<32, "bswap32", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
-def BSWAP64 : BSWAP<64, "bswap64", [(set GPR:$dst, (bswap GPR:$src))]>;
+ let Predicates = [BPFIsLittleEndian] in {
+ def BE16 : BSWAP<16, "be16", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
+ def BE32 : BSWAP<32, "be32", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
+ def BE64 : BSWAP<64, "be64", BPF_TO_BE, [(set GPR:$dst, (bswap GPR:$src))]>;
+ }
+ let Predicates = [BPFIsBigEndian] in {
+ def LE16 : BSWAP<16, "le16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
+ def LE32 : BSWAP<32, "le32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
+ def LE64 : BSWAP<64, "le64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>;
+ }
}
let Defs = [R0, R1, R2, R3, R4, R5], Uses = [R6], hasSideEffects = 1,
OpenPOWER on IntegriCloud