diff options
| author | Yonghong Song <yhs@fb.com> | 2017-09-28 02:46:11 +0000 |
|---|---|---|
| committer | Yonghong Song <yhs@fb.com> | 2017-09-28 02:46:11 +0000 |
| commit | e9165f87203a0480fcc0308004467a9b4237170a (patch) | |
| tree | 6b6f94bc6fec13bc9b6a882f63fc020c41308cb0 /llvm/lib/Target | |
| parent | def1729dc40d4d24ee979be9b2be8d4d70fae1c9 (diff) | |
| download | bcm5719-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.cpp | 41 | ||||
| -rw-r--r-- | llvm/lib/Target/BPF/BPFInstrFormats.td | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/BPF/BPFInstrInfo.td | 42 |
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, |

