Skip to content

Commit 236fbf5

Browse files
committed
[GlobalStatus] Skip non-pointer dead constant users
Constant expressions with a non-pointer result type used an early exit that bypassed the later dead constant user check, and resulted in different optimization outcomes depending on whether dead users were present or not. This fixes the issue reported in https://reviews.llvm.org/D117223#3287039.
1 parent d9b4577 commit 236fbf5

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

llvm/lib/Transforms/Utils/GlobalStatus.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,18 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
6565

6666
for (const Use &U : V->uses()) {
6767
const User *UR = U.getUser();
68-
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(UR)) {
69-
// If the result of the constantexpr isn't pointer type, then we won't
70-
// know to expect it in various places. Just reject early.
71-
if (!isa<PointerType>(CE->getType()))
72-
return true;
73-
74-
// FIXME: Do we need to add constexpr selects to VisitedUsers?
75-
if (analyzeGlobalAux(CE, GS, VisitedUsers))
76-
return true;
68+
if (const Constant *C = dyn_cast<Constant>(UR)) {
69+
const ConstantExpr *CE = dyn_cast<ConstantExpr>(C);
70+
if (CE && isa<PointerType>(CE->getType())) {
71+
// Recursively analyze pointer-typed constant expressions.
72+
// FIXME: Do we need to add constexpr selects to VisitedUsers?
73+
if (analyzeGlobalAux(CE, GS, VisitedUsers))
74+
return true;
75+
} else {
76+
// Ignore dead constant users.
77+
if (!isSafeToDestroyConstant(C))
78+
return true;
79+
}
7780
} else if (const Instruction *I = dyn_cast<Instruction>(UR)) {
7881
if (!GS.HasMultipleAccessingFunctions) {
7982
const Function *F = I->getParent()->getParent();
@@ -169,10 +172,6 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
169172
} else {
170173
return true; // Any other non-load instruction might take address!
171174
}
172-
} else if (const Constant *C = dyn_cast<Constant>(UR)) {
173-
// We might have a dead and dangling constant hanging off of here.
174-
if (!isSafeToDestroyConstant(C))
175-
return true;
176175
} else {
177176
// Otherwise must be some other user.
178177
return true;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes='function(early-cse),globalopt' < %s | FileCheck %s
3+
; RUN: opt -S -passes='function(early-cse)' < %s | opt -S -passes=globalopt | FileCheck %s
4+
5+
@g = internal global [6 x i16*] undef
6+
7+
define void @test1() {
8+
; CHECK-LABEL: @test1(
9+
; CHECK-NEXT: ret void
10+
;
11+
%xor4 = xor i32 zext (i1 icmp ne (i8* getelementptr (i8, i8* bitcast ([6 x i16*]* @g to i8*), i64 3), i8* null) to i32), 0
12+
%t0 = load i16*, i16** bitcast (i8* getelementptr (i8, i8* bitcast ([6 x i16*]* @g to i8*), i64 3) to i16**), align 1
13+
%t1 = load i16, i16* %t0, align 1
14+
ret void
15+
}
16+
17+
define void @test2() {
18+
; CHECK-LABEL: @test2(
19+
; CHECK-NEXT: ret void
20+
;
21+
store i16* null, i16** getelementptr inbounds ([6 x i16*], [6 x i16*]* @g, i32 0, i32 5)
22+
ret void
23+
}

0 commit comments

Comments
 (0)