Skip to content

Commit

Permalink
[GlobalStatus] Skip non-pointer dead constant users
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Feb 1, 2022
1 parent d9b4577 commit 236fbf5
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 13 deletions.
25 changes: 12 additions & 13 deletions llvm/lib/Transforms/Utils/GlobalStatus.cpp
Expand Up @@ -65,15 +65,18 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,

for (const Use &U : V->uses()) {
const User *UR = U.getUser();
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(UR)) {
// If the result of the constantexpr isn't pointer type, then we won't
// know to expect it in various places. Just reject early.
if (!isa<PointerType>(CE->getType()))
return true;

// FIXME: Do we need to add constexpr selects to VisitedUsers?
if (analyzeGlobalAux(CE, GS, VisitedUsers))
return true;
if (const Constant *C = dyn_cast<Constant>(UR)) {
const ConstantExpr *CE = dyn_cast<ConstantExpr>(C);
if (CE && isa<PointerType>(CE->getType())) {
// Recursively analyze pointer-typed constant expressions.
// FIXME: Do we need to add constexpr selects to VisitedUsers?
if (analyzeGlobalAux(CE, GS, VisitedUsers))
return true;
} else {
// Ignore dead constant users.
if (!isSafeToDestroyConstant(C))
return true;
}
} else if (const Instruction *I = dyn_cast<Instruction>(UR)) {
if (!GS.HasMultipleAccessingFunctions) {
const Function *F = I->getParent()->getParent();
Expand Down Expand Up @@ -169,10 +172,6 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
} else {
return true; // Any other non-load instruction might take address!
}
} else if (const Constant *C = dyn_cast<Constant>(UR)) {
// We might have a dead and dangling constant hanging off of here.
if (!isSafeToDestroyConstant(C))
return true;
} else {
// Otherwise must be some other user.
return true;
Expand Down
23 changes: 23 additions & 0 deletions llvm/test/Transforms/GlobalOpt/dead-constant-user.ll
@@ -0,0 +1,23 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes='function(early-cse),globalopt' < %s | FileCheck %s
; RUN: opt -S -passes='function(early-cse)' < %s | opt -S -passes=globalopt | FileCheck %s

@g = internal global [6 x i16*] undef

define void @test1() {
; CHECK-LABEL: @test1(
; CHECK-NEXT: ret void
;
%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
%t0 = load i16*, i16** bitcast (i8* getelementptr (i8, i8* bitcast ([6 x i16*]* @g to i8*), i64 3) to i16**), align 1
%t1 = load i16, i16* %t0, align 1
ret void
}

define void @test2() {
; CHECK-LABEL: @test2(
; CHECK-NEXT: ret void
;
store i16* null, i16** getelementptr inbounds ([6 x i16*], [6 x i16*]* @g, i32 0, i32 5)
ret void
}

0 comments on commit 236fbf5

Please sign in to comment.