llvm.org GIT mirror llvm / 71b1a84
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> ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_37@251175 91177308-0d34-0410-b5e6-96231b3b80d8 Alexei Starovoitov 3 years ago
4 changed file(s) with 83 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
4949
5050 // Complex Pattern for address selection.
5151 bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
52 bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
5253 };
5354 }
5455
6667 Addr.getOpcode() == ISD::TargetGlobalAddress)
6768 return false;
6869
69 // Addresses of the form FI+const or FI|const
70 // Addresses of the form Addr+const or Addr|const
7071 if (CurDAG->isBaseWithConstantOffset(Addr)) {
7172 ConstantSDNode *CN = dyn_cast(Addr.getOperand(1));
7273 if (isInt<32>(CN->getSExtValue())) {
8687 Base = Addr;
8788 Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
8889 return true;
90 }
91
92 // ComplexPattern used on BPF FI instruction
93 bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
94 SDLoc DL(Addr);
95
96 if (!CurDAG->isBaseWithConstantOffset(Addr))
97 return false;
98
99 // Addresses of the form Addr+const or Addr|const
100 ConstantSDNode *CN = dyn_cast(Addr.getOperand(1));
101 if (isInt<32>(CN->getSExtValue())) {
102
103 // If the first operand is a FI, get the TargetFI Node
104 if (FrameIndexSDNode *FIN =
105 dyn_cast(Addr.getOperand(0)))
106 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
107 else
108 return false;
109
110 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
111 return true;
112 }
113
114 return false;
89115 }
90116
91117 SDNode *BPFDAGToDAGISel::Select(SDNode *Node) {
5353 [{return isInt<32>(N->getSExtValue()); }]>;
5454
5555 // Addressing modes.
56 def ADDRri : ComplexPatternframeindex], []>;
56 def ADDRri : ComplexPattern], []>;
57 def FIri : ComplexPattern;
5758
5859 // Address operands
5960 def MEMri : Operand {
259260 def MOV_ri : MOV_RI<"mov">;
260261 }
261262
263 def FI_ri
264 : InstBPF<(outs GPR:$dst), (ins MEMri:$addr),
265 "lea\t$dst, $addr",
266 [(set i64:$dst, FIri:$addr)]> {
267 // This is a tentative instruction, and will be replaced
268 // with MOV_rr and ADD_ri in PEI phase
269 }
270
271
262272 def LD_pseudo
263273 : InstBPF<(outs GPR:$dst), (ins i64imm:$pseudo, u64imm:$imm),
264274 "ld_pseudo\t$dst, $pseudo, $imm",
5757
5858 unsigned FrameReg = getFrameRegister(MF);
5959 int FrameIndex = MI.getOperand(i).getIndex();
60 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
61 MachineBasicBlock &MBB = *MI.getParent();
6062
6163 if (MI.getOpcode() == BPF::MOV_rr) {
62 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
6364 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
6465
6566 MI.getOperand(i).ChangeToRegister(FrameReg, false);
66
67 MachineBasicBlock &MBB = *MI.getParent();
6867 unsigned reg = MI.getOperand(i - 1).getReg();
6968 BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg)
7069 .addReg(reg)
7877 if (!isInt<32>(Offset))
7978 llvm_unreachable("bug in frame offset");
8079
81 MI.getOperand(i).ChangeToRegister(FrameReg, false);
82 MI.getOperand(i + 1).ChangeToImmediate(Offset);
80 if (MI.getOpcode() == BPF::FI_ri) {
81 // architecture does not really support FI_ri, replace it with
82 // MOV_rr , frame_reg
83 // ADD_ri , imm
84 unsigned reg = MI.getOperand(i - 1).getReg();
85
86 BuildMI(MBB, ++II, DL, TII.get(BPF::MOV_rr), reg)
87 .addReg(FrameReg);
88 BuildMI(MBB, II, DL, TII.get(BPF::ADD_ri), reg)
89 .addReg(reg)
90 .addImm(Offset);
91
92 // Remove FI_ri instruction
93 MI.eraseFromParent();
94 } else {
95 MI.getOperand(i).ChangeToRegister(FrameReg, false);
96 MI.getOperand(i + 1).ChangeToImmediate(Offset);
97 }
8398 }
8499
85100 unsigned BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
0 ; RUN: llc < %s -march=bpf | FileCheck %s
1
2 %struct.key_t = type { i32, [16 x i8] }
3
4 ; Function Attrs: nounwind uwtable
5 define i32 @test() #0 {
6 %key = alloca %struct.key_t, align 4
7 %1 = bitcast %struct.key_t* %key to i8*
8 ; CHECK: mov r1, 0
9 ; CHECK: stw -8(r10), r1
10 ; CHECK: std -16(r10), r1
11 ; CHECK: std -24(r10), r1
12 call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 20, i32 4, i1 false)
13 ; CHECK: mov r1, r10
14 ; CHECK: addi r1, -20
15 %2 = getelementptr inbounds %struct.key_t, %struct.key_t* %key, i64 0, i32 1, i64 0
16 ; CHECK: call test1
17 call void @test1(i8* %2) #3
18 ret i32 0
19 }
20
21 ; Function Attrs: nounwind argmemonly
22 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) #1
23
24 declare void @test1(i8*) #2