summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexei Starovoitov <alexei.starovoitov@gmail.com>2015-10-24 01:58:14 +0000
committerAlexei Starovoitov <alexei.starovoitov@gmail.com>2015-10-24 01:58:14 +0000
commit3b02531fa74cf622e7e190e677a0b9c742b5d432 (patch)
treeb59bbb3dc1a5bd0c0aff47eb8a0d7eadc7e7a4ba
parentbc860efaa4aa3b6a6766397b079f3243bc52f32f (diff)
downloadllvm-3b02531fa74cf622e7e190e677a0b9c742b5d432.tar.gz
Merging r249371:
------------------------------------------------------------------------ r249371 | ast | 2015-10-05 21:00:53 -0700 (Mon, 05 Oct 2015) | 25 lines [bpf] Avoid extra pointer arithmetic for stack access For the program like below struct key_t { int pid; char name[16]; }; extern void test1(char *); int test() { struct key_t key = {}; test1(key.name); return 0; } For key.name, the llc/bpf may generate the below code: R1 = R10 // R10 is the frame pointer R1 += -24 // framepointer adjustment R1 |= 4 // R1 is then used as the first parameter of test1 OR operation is not recognized by in-kernel verifier. This patch introduces an intermediate FI_ri instruction and generates the following code that can be properly verified: R1 = R10 R1 += -20 Patch by Yonghong Song <yhs@plumgrid.com> ------------------------------------------------------------------------ llvm-svn: 251175
-rw-r--r--llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp28
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.td12
-rw-r--r--llvm/lib/Target/BPF/BPFRegisterInfo.cpp25
-rw-r--r--llvm/test/CodeGen/BPF/fi_ri.ll25
4 files changed, 83 insertions, 7 deletions
diff --git a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
index d9e654c76428..44ecb181a1c5 100644
--- a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
+++ b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
@@ -50,6 +50,7 @@ private:
// Complex Pattern for address selection.
bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
+ bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
};
}
@@ -67,7 +68,7 @@ bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
Addr.getOpcode() == ISD::TargetGlobalAddress)
return false;
- // Addresses of the form FI+const or FI|const
+ // Addresses of the form Addr+const or Addr|const
if (CurDAG->isBaseWithConstantOffset(Addr)) {
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
if (isInt<32>(CN->getSExtValue())) {
@@ -89,6 +90,31 @@ bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
return true;
}
+// ComplexPattern used on BPF FI instruction
+bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
+ SDLoc DL(Addr);
+
+ if (!CurDAG->isBaseWithConstantOffset(Addr))
+ return false;
+
+ // Addresses of the form Addr+const or Addr|const
+ ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
+ if (isInt<32>(CN->getSExtValue())) {
+
+ // If the first operand is a FI, get the TargetFI Node
+ if (FrameIndexSDNode *FIN =
+ dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
+ else
+ return false;
+
+ Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
+ return true;
+ }
+
+ return false;
+}
+
SDNode *BPFDAGToDAGISel::Select(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index 26b2cfebdc83..6b73db87fa26 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -54,7 +54,8 @@ def i64immSExt32 : PatLeaf<(imm),
[{return isInt<32>(N->getSExtValue()); }]>;
// Addressing modes.
-def ADDRri : ComplexPattern<i64, 2, "SelectAddr", [frameindex], []>;
+def ADDRri : ComplexPattern<i64, 2, "SelectAddr", [], []>;
+def FIri : ComplexPattern<i64, 2, "SelectFIAddr", [add, or], []>;
// Address operands
def MEMri : Operand<i64> {
@@ -260,6 +261,15 @@ def MOV_rr : MOV_RR<"mov">;
def MOV_ri : MOV_RI<"mov">;
}
+def FI_ri
+ : InstBPF<(outs GPR:$dst), (ins MEMri:$addr),
+ "lea\t$dst, $addr",
+ [(set i64:$dst, FIri:$addr)]> {
+ // This is a tentative instruction, and will be replaced
+ // with MOV_rr and ADD_ri in PEI phase
+}
+
+
def LD_pseudo
: InstBPF<(outs GPR:$dst), (ins i64imm:$pseudo, u64imm:$imm),
"ld_pseudo\t$dst, $pseudo, $imm",
diff --git a/llvm/lib/Target/BPF/BPFRegisterInfo.cpp b/llvm/lib/Target/BPF/BPFRegisterInfo.cpp
index 8f885c3ea61b..952615bd1c2b 100644
--- a/llvm/lib/Target/BPF/BPFRegisterInfo.cpp
+++ b/llvm/lib/Target/BPF/BPFRegisterInfo.cpp
@@ -58,14 +58,13 @@ void BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
unsigned FrameReg = getFrameRegister(MF);
int FrameIndex = MI.getOperand(i).getIndex();
+ const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
+ MachineBasicBlock &MBB = *MI.getParent();
if (MI.getOpcode() == BPF::MOV_rr) {
- const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
MI.getOperand(i).ChangeToRegister(FrameReg, false);
-
- MachineBasicBlock &MBB = *MI.getParent();
unsigned reg = MI.getOperand(i - 1).getReg();
BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg)
.addReg(reg)
@@ -79,8 +78,24 @@ void BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
if (!isInt<32>(Offset))
llvm_unreachable("bug in frame offset");
- MI.getOperand(i).ChangeToRegister(FrameReg, false);
- MI.getOperand(i + 1).ChangeToImmediate(Offset);
+ if (MI.getOpcode() == BPF::FI_ri) {
+ // architecture does not really support FI_ri, replace it with
+ // MOV_rr <target_reg>, frame_reg
+ // ADD_ri <target_reg>, imm
+ unsigned reg = MI.getOperand(i - 1).getReg();
+
+ BuildMI(MBB, ++II, DL, TII.get(BPF::MOV_rr), reg)
+ .addReg(FrameReg);
+ BuildMI(MBB, II, DL, TII.get(BPF::ADD_ri), reg)
+ .addReg(reg)
+ .addImm(Offset);
+
+ // Remove FI_ri instruction
+ MI.eraseFromParent();
+ } else {
+ MI.getOperand(i).ChangeToRegister(FrameReg, false);
+ MI.getOperand(i + 1).ChangeToImmediate(Offset);
+ }
}
unsigned BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
diff --git a/llvm/test/CodeGen/BPF/fi_ri.ll b/llvm/test/CodeGen/BPF/fi_ri.ll
new file mode 100644
index 000000000000..64773b429fba
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/fi_ri.ll
@@ -0,0 +1,25 @@
+; RUN: llc < %s -march=bpf | FileCheck %s
+
+%struct.key_t = type { i32, [16 x i8] }
+
+; Function Attrs: nounwind uwtable
+define i32 @test() #0 {
+ %key = alloca %struct.key_t, align 4
+ %1 = bitcast %struct.key_t* %key to i8*
+; CHECK: mov r1, 0
+; CHECK: stw -8(r10), r1
+; CHECK: std -16(r10), r1
+; CHECK: std -24(r10), r1
+ call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 20, i32 4, i1 false)
+; CHECK: mov r1, r10
+; CHECK: addi r1, -20
+ %2 = getelementptr inbounds %struct.key_t, %struct.key_t* %key, i64 0, i32 1, i64 0
+; CHECK: call test1
+ call void @test1(i8* %2) #3
+ ret i32 0
+}
+
+; Function Attrs: nounwind argmemonly
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) #1
+
+declare void @test1(i8*) #2