Skip to content

Commit fe37d44

Browse files
committed
[GlobalOpt] Check if global gets compared to pointer of different obj.
Add an extra check to the compare handling to make sure the other compared pointer cannot be based on a different object. For example, consider the IR below, which may write @b via a pointer constructed from @A using PtrToInt and a compare against @b. ``` %cmp = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr) , @b br i1 %cmp, label %then, label %else then: store i64 10, ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr) br label %exit else: br label %exit exit: %l = load i64, ptr @b ret i64 %l } ```
1 parent 536cbe6 commit fe37d44

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

llvm/lib/Transforms/Utils/GlobalStatus.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,45 @@ bool llvm::isSafeToDestroyConstant(const Constant *C) {
6161
return true;
6262
}
6363

64+
static bool
65+
maybePointerToDifferentObjectRecursive(Value *V,
66+
SmallPtrSetImpl<Value *> &Visited) {
67+
if (!Visited.insert(V).second)
68+
return false;
69+
70+
if (Visited.size() > 32)
71+
return true;
72+
73+
// PtrToInt may be used to construct a pointer to a different object. Loads
74+
// and calls may return a pointer for a different object.
75+
if (isa<PtrToIntInst, LoadInst, CallInst>(V))
76+
return true;
77+
78+
if (auto *CE = dyn_cast<ConstantExpr>(V)) {
79+
if (CE->getOpcode() == Instruction::PtrToInt)
80+
return true;
81+
82+
for (auto &Op : CE->operands()) {
83+
if (maybePointerToDifferentObjectRecursive(Op.get(), Visited))
84+
return true;
85+
}
86+
return false;
87+
}
88+
89+
if (auto *U = dyn_cast<User>(V)) {
90+
for (auto &Op : U->operands()) {
91+
if (maybePointerToDifferentObjectRecursive(Op.get(), Visited))
92+
return true;
93+
}
94+
}
95+
return false;
96+
}
97+
98+
bool maybePointerToDifferentObject(Value *V) {
99+
SmallPtrSet<Value *, 32> Visited;
100+
return maybePointerToDifferentObjectRecursive(V, Visited);
101+
}
102+
64103
static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
65104
SmallPtrSetImpl<const Value *> &VisitedUsers) {
66105
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
@@ -158,6 +197,12 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
158197
return true;
159198
} else if (isa<CmpInst>(I)) {
160199
GS.IsCompared = true;
200+
201+
if (VisitedUsers.insert(I).second) {
202+
for (Value *Op : I->operands())
203+
if (Op != V && maybePointerToDifferentObject(Op))
204+
return true;
205+
}
161206
} else if (const MemTransferInst *MTI = dyn_cast<MemTransferInst>(I)) {
162207
if (MTI->isVolatile())
163208
return true;

llvm/test/Transforms/GlobalOpt/globals-compares-with-ptrtoint.ll

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@
1717

1818
;.
1919
; CHECK: @A = internal global i64 0
20-
; CHECK: @B = internal constant i64 0
20+
; CHECK: @B = internal global i64 0
2121
; CHECK: @C = internal global i64 0
22-
; CHECK: @D = internal constant i64 0
22+
; CHECK: @D = internal global i64 0
2323
; CHECK: @G = internal global i64 0
24-
; CHECK: @H = internal constant i64 0
25-
; CHECK: @J = internal constant [2 x ptr] zeroinitializer
2624
;.
2725
define i64 @A_and_B_cmp_ptrtoint_constant_expr() {
2826
; CHECK-LABEL: define i64 @A_and_B_cmp_ptrtoint_constant_expr() local_unnamed_addr {
@@ -34,7 +32,8 @@ define i64 @A_and_B_cmp_ptrtoint_constant_expr() {
3432
; CHECK: [[ELSE]]:
3533
; CHECK-NEXT: br label %[[EXIT]]
3634
; CHECK: [[EXIT]]:
37-
; CHECK-NEXT: ret i64 0
35+
; CHECK-NEXT: [[L:%.*]] = load i64, ptr @B, align 4
36+
; CHECK-NEXT: ret i64 [[L]]
3837
;
3938
%cmp = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @A to i64), i64 8) to ptr) , @B
4039
br i1 %cmp, label %then, label %else
@@ -61,7 +60,8 @@ define i64 @G_and_H_cmp_ptrtoint_constant_expr_cmp_ops_swapped() {
6160
; CHECK: [[ELSE]]:
6261
; CHECK-NEXT: br label %[[EXIT]]
6362
; CHECK: [[EXIT]]:
64-
; CHECK-NEXT: ret i64 0
63+
; CHECK-NEXT: [[L:%.*]] = load i64, ptr @H, align 4
64+
; CHECK-NEXT: ret i64 [[L]]
6565
;
6666
%cmp = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @G to i64), i64 8) to ptr) , @H
6767
br i1 %cmp, label %then, label %else
@@ -91,7 +91,8 @@ define i64 @C_and_D_cmp_ptr_load() {
9191
; CHECK: [[ELSE]]:
9292
; CHECK-NEXT: br label %[[EXIT]]
9393
; CHECK: [[EXIT]]:
94-
; CHECK-NEXT: ret i64 0
94+
; CHECK-NEXT: [[L:%.*]] = load i64, ptr @D, align 4
95+
; CHECK-NEXT: ret i64 [[L]]
9596
;
9697
%p = alloca ptr
9798
store ptr inttoptr (i64 add (i64 ptrtoint (ptr @C to i64), i64 8) to ptr), ptr %p
@@ -124,7 +125,8 @@ define i64 @D_and_E_cmp_ptrtoint_constant_expr() {
124125
; CHECK: [[ELSE]]:
125126
; CHECK-NEXT: br label %[[EXIT]]
126127
; CHECK: [[EXIT]]:
127-
; CHECK-NEXT: ret i64 0
128+
; CHECK-NEXT: [[L:%.*]] = load i64, ptr @B, align 4
129+
; CHECK-NEXT: ret i64 [[L]]
128130
;
129131
%ptr2int = ptrtoint ptr @A to i64
130132
%add = add i64 %ptr2int, 8

0 commit comments

Comments
 (0)