Skip to content

Commit 1ff84a0

Browse files
yonghong-songtstellar
authored andcommitted
BPF: fix incorrect DAG2DAG load optimization
Currently, bpf backend Instruction section DAG2DAG phase has an optimization to replace loading constant struct memeber or array element with direct values. The reason is that these locally defined struct or array variables may have their initial values stored in a readonly section and early bpf ecosystem is not able to handle such cases. Bpf ecosystem now can not only handle readonly sections, but also global variables. global variable can also have initialized data and global variable may or may not be constant, i.e., global variable data can be put in .data section or .rodata section. This exposed a bug in DAG2DAG Load optimization as it did not check whether the global variable is constant or not. This patch fixed the bug by checking whether global variable, representing the initial data, is constant or not and will not do optimization if it is not a constant. Another bug is also fixed in this patch to check whether the load is simple (not volatile/atomic) or not. If it is not simple, we will not do optimization. To summary for globals: - struct t var = { ... } ; // no load optimization - const struct t var = { ... }; // load optimization is possible - volatile const struct t var = { ... }; // no load optimization Differential Revision: https://reviews.llvm.org/D89021 (cherry picked from commit 3161172)
1 parent 38399ce commit 1ff84a0

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node,
254254
const LoadSDNode *LD = cast<LoadSDNode>(Node);
255255
uint64_t size = LD->getMemOperand()->getSize();
256256

257-
if (!size || size > 8 || (size & (size - 1)))
257+
if (!size || size > 8 || (size & (size - 1)) || !LD->isSimple())
258258
return;
259259

260260
SDNode *LDAddrNode = LD->getOperand(1).getNode();
@@ -342,7 +342,7 @@ bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node,
342342
unsigned char *ByteSeq) {
343343
const GlobalVariable *V = dyn_cast<GlobalVariable>(Node->getGlobal());
344344

345-
if (!V || !V->hasInitializer())
345+
if (!V || !V->hasInitializer() || !V->isConstant())
346346
return false;
347347

348348
const Constant *Init = V->getInitializer();

llvm/test/CodeGen/BPF/rodata_6.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: llc -march=bpf < %s | FileCheck %s
2+
;
3+
; Source code:
4+
; struct t1 { int a; };
5+
; struct t1 data = { .a = 3 };
6+
; int foo(void) {
7+
; return data.a + 20;
8+
; }
9+
; Compilation flag:
10+
; clang -target bpf -O2 -S -emit-llvm test.c
11+
12+
%struct.t1 = type { i32 }
13+
14+
@data = dso_local local_unnamed_addr global %struct.t1 { i32 3 }, align 4
15+
16+
; Function Attrs: norecurse nounwind readonly
17+
define dso_local i32 @foo() local_unnamed_addr {
18+
entry:
19+
%0 = load i32, i32* getelementptr inbounds (%struct.t1, %struct.t1* @data, i64 0, i32 0), align 4
20+
%add = add nsw i32 %0, 20
21+
; CHECK: [[REG1:r[0-9]+]] = data ll
22+
; CHECK: r0 = *(u32 *)([[REG1]] + 0)
23+
; CHECK: r0 += 20
24+
ret i32 %add
25+
}

llvm/test/CodeGen/BPF/rodata_7.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: llc -march=bpf < %s | FileCheck %s
2+
;
3+
; Source code:
4+
; struct t1 { int a; };
5+
; volatile const struct t1 data = { .a = 3 };
6+
; int foo(void) {
7+
; return data.a + 20;
8+
; }
9+
; Compilation flag:
10+
; clang -target bpf -O2 -S -emit-llvm test.c
11+
12+
%struct.t1 = type { i32 }
13+
14+
@data = dso_local constant %struct.t1 { i32 3 }, align 4
15+
16+
; Function Attrs: nofree norecurse nounwind
17+
define dso_local i32 @foo() local_unnamed_addr {
18+
entry:
19+
%0 = load volatile i32, i32* getelementptr inbounds (%struct.t1, %struct.t1* @data, i64 0, i32 0), align 4
20+
%add = add nsw i32 %0, 20
21+
; CHECK: [[REG1:r[0-9]+]] = data ll
22+
; CHECK: r0 = *(u32 *)([[REG1]] + 0)
23+
; CHECK: r0 += 20
24+
ret i32 %add
25+
}

0 commit comments

Comments
 (0)