[llvm] r313593 - bpf: add inline-asm support

Yonghong Song via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 18 16:29:36 PDT 2017


Author: yhs
Date: Mon Sep 18 16:29:36 2017
New Revision: 313593

URL: http://llvm.org/viewvc/llvm-project?rev=313593&view=rev
Log:
bpf: add inline-asm support

Signed-off-by: Yonghong Song <yhs at fb.com>
Acked-by: Alexei Starovoitov <ast at kernel.org>

Added:
    llvm/trunk/test/CodeGen/BPF/inline_asm.ll
Modified:
    llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp
    llvm/trunk/lib/Target/BPF/BPFISelDAGToDAG.cpp
    llvm/trunk/lib/Target/BPF/BPFISelLowering.cpp
    llvm/trunk/lib/Target/BPF/BPFISelLowering.h

Modified: llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp?rev=313593&r1=313592&r2=313593&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/BPF/BPFAsmPrinter.cpp Mon Sep 18 16:29:36 2017
@@ -40,11 +40,88 @@ public:
       : AsmPrinter(TM, std::move(Streamer)) {}
 
   StringRef getPassName() const override { return "BPF Assembly Printer"; }
+  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
+  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                       unsigned AsmVariant, const char *ExtraCode,
+                       raw_ostream &O) override;
+  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
+                             unsigned AsmVariant, const char *ExtraCode,
+                             raw_ostream &O) override;
 
   void EmitInstruction(const MachineInstr *MI) override;
 };
 } // namespace
 
+void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
+                                 raw_ostream &O) {
+  const MachineOperand &MO = MI->getOperand(OpNum);
+
+  switch (MO.getType()) {
+  case MachineOperand::MO_Register:
+    O << BPFInstPrinter::getRegisterName(MO.getReg());
+    break;
+
+  case MachineOperand::MO_Immediate:
+    O << MO.getImm();
+    break;
+
+  case MachineOperand::MO_MachineBasicBlock:
+    O << *MO.getMBB()->getSymbol();
+    break;
+
+  case MachineOperand::MO_GlobalAddress:
+    O << *getSymbol(MO.getGlobal());
+    break;
+
+  case MachineOperand::MO_BlockAddress: {
+    MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
+    O << BA->getName();
+    break;
+  }
+
+  case MachineOperand::MO_ExternalSymbol:
+    O << *GetExternalSymbolSymbol(MO.getSymbolName());
+    break;
+
+  case MachineOperand::MO_JumpTableIndex:
+  case MachineOperand::MO_ConstantPoolIndex:
+  default:
+    llvm_unreachable("<unknown operand type>");
+  }
+}
+
+bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                    unsigned /*AsmVariant*/,
+                                    const char *ExtraCode, raw_ostream &O) {
+  if (ExtraCode && ExtraCode[0])
+    return true; // BPF does not have special modifiers
+
+  printOperand(MI, OpNo, O);
+  return false;
+}
+
+bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
+                                          unsigned OpNum, unsigned AsmVariant,
+                                          const char *ExtraCode,
+                                          raw_ostream &O) {
+  assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
+  const MachineOperand &BaseMO = MI->getOperand(OpNum);
+  const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
+  assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
+  assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
+  int Offset = OffsetMO.getImm();
+
+  if (ExtraCode)
+    return true; // Unknown modifier.
+
+  if (Offset < 0)
+    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
+  else
+    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
+
+  return false;
+}
+
 void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
 
   BPFMCInstLower MCInstLowering(OutContext, *this);

Modified: llvm/trunk/lib/Target/BPF/BPFISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFISelDAGToDAG.cpp?rev=313593&r1=313592&r2=313593&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/BPF/BPFISelDAGToDAG.cpp Mon Sep 18 16:29:36 2017
@@ -48,6 +48,10 @@ public:
 
   void PreprocessISelDAG() override;
 
+  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
+                                    std::vector<SDValue> &OutOps) override;
+
+
 private:
 // Include the pieces autogenerated from the target description.
 #include "BPFGenDAGISel.inc"
@@ -145,6 +149,26 @@ bool BPFDAGToDAGISel::SelectFIAddr(SDVal
   return false;
 }
 
+bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
+    const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
+  SDValue Op0, Op1;
+  switch (ConstraintCode) {
+  default:
+    return true;
+  case InlineAsm::Constraint_m: // memory
+    if (!SelectAddr(Op, Op0, Op1))
+      return true;
+    break;
+  }
+
+  SDLoc DL(Op);
+  SDValue AluOp = CurDAG->getTargetConstant(ISD::ADD, DL, MVT::i32);;
+  OutOps.push_back(Op0);
+  OutOps.push_back(Op1);
+  OutOps.push_back(AluOp);
+  return false;
+}
+
 void BPFDAGToDAGISel::Select(SDNode *Node) {
   unsigned Opcode = Node->getOpcode();
 

Modified: llvm/trunk/lib/Target/BPF/BPFISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFISelLowering.cpp?rev=313593&r1=313592&r2=313593&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/BPF/BPFISelLowering.cpp Mon Sep 18 16:29:36 2017
@@ -139,6 +139,22 @@ bool BPFTargetLowering::isOffsetFoldingL
   return false;
 }
 
+std::pair<unsigned, const TargetRegisterClass *>
+BPFTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+                                                StringRef Constraint,
+                                                MVT VT) const {
+  if (Constraint.size() == 1)
+    // GCC Constraint Letters
+    switch (Constraint[0]) {
+    case 'r': // GENERAL_REGS
+      return std::make_pair(0U, &BPF::GPRRegClass);
+    default:
+      break;
+    }
+
+  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
+}
+
 SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   switch (Op.getOpcode()) {
   case ISD::BR_CC:

Modified: llvm/trunk/lib/Target/BPF/BPFISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/BPF/BPFISelLowering.h?rev=313593&r1=313592&r2=313593&view=diff
==============================================================================
--- llvm/trunk/lib/Target/BPF/BPFISelLowering.h (original)
+++ llvm/trunk/lib/Target/BPF/BPFISelLowering.h Mon Sep 18 16:29:36 2017
@@ -46,6 +46,10 @@ public:
   // with the given GlobalAddress is legal.
   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
 
+  std::pair<unsigned, const TargetRegisterClass *>
+  getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+                               StringRef Constraint, MVT VT) const override;
+
   MachineBasicBlock *
   EmitInstrWithCustomInserter(MachineInstr &MI,
                               MachineBasicBlock *BB) const override;

Added: llvm/trunk/test/CodeGen/BPF/inline_asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/BPF/inline_asm.ll?rev=313593&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/BPF/inline_asm.ll (added)
+++ llvm/trunk/test/CodeGen/BPF/inline_asm.ll Mon Sep 18 16:29:36 2017
@@ -0,0 +1,54 @@
+; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck %s
+
+; Source code:
+; int g[2];
+;
+; int test(void *ctx) {
+;   int a = 4, b;
+;   unsigned long long c = 333333333333ULL;
+;   asm volatile("r0 = *(u16 *)skb[%0]" : : "i"(2));
+;   asm volatile("r0 = *(u16 *)skb[%0]" : : "r"(a));
+;   asm volatile("%0 = %1" : "=r"(b) : "i"(4));
+;   asm volatile("%0 = %1 ll" : "=r"(b) : "i"(c));
+;   asm volatile("%0 = *(u16 *) %1" : "=r"(b) : "m"(a));
+;   asm volatile("%0 = *(u32 *) %1" : "=r"(b) : "m"(g[1]));
+;   return b;
+; }
+;
+
+ at g = common global [2 x i32] zeroinitializer, align 4
+
+; Function Attrs: nounwind
+define i32 @test(i8* nocapture readnone %ctx) local_unnamed_addr #0 {
+entry:
+  %a = alloca i32, align 4
+  %0 = bitcast i32* %a to i8*
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #2
+  store i32 4, i32* %a, align 4
+  tail call void asm sideeffect "r0 = *(u16 *)skb[$0]", "i"(i32 2) #2
+; CHECK: r0 = *(u16 *)skb[2]
+  tail call void asm sideeffect "r0 = *(u16 *)skb[$0]", "r"(i32 4) #2
+; CHECK: r0 = *(u16 *)skb[r1]
+  %1 = tail call i32 asm sideeffect "$0 = $1", "=r,i"(i32 4) #2
+; CHECK: r1 = 4
+  %2 = tail call i32 asm sideeffect "$0 = $1 ll", "=r,i"(i64 333333333333) #2
+; CHECK: r1 = 333333333333 ll
+  %3 = call i32 asm sideeffect "$0 = *(u16 *) $1", "=r,*m"(i32* nonnull %a) #2
+; CHECK: r1 = *(u16 *) (r10 - 4)
+  %4 = call i32 asm sideeffect "$0 = *(u32 *) $1", "=r,*m"(i32* getelementptr inbounds ([2 x i32], [2 x i32]* @g, i64 0, i64 1)) #2
+; CHECK: r1 = g ll
+; CHECK: r0 = *(u32 *) (r1 + 4)
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #2
+  ret i32 %4
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind }




More information about the llvm-commits mailing list