-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[GVN] Restrict equality propagation for pointers #82458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
f4ebdf0
1f141c4
92ef55f
022ddef
cb54b76
02332a9
40d8181
6f25334
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -710,22 +710,63 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, BatchAAResults &AA, | |
return Available; | ||
} | ||
|
||
bool llvm::canReplacePointersIfEqual(Value *A, Value *B, const DataLayout &DL, | ||
Instruction *CtxI) { | ||
Type *Ty = A->getType(); | ||
assert(Ty == B->getType() && Ty->isPointerTy() && | ||
"values must have matching pointer types"); | ||
|
||
// NOTE: The checks in the function are incomplete and currently miss illegal | ||
// cases! The current implementation is a starting point and the | ||
// implementation should be made stricter over time. | ||
if (auto *C = dyn_cast<Constant>(B)) { | ||
// Do not allow replacing a pointer with a constant pointer, unless it is | ||
// either null or at least one byte is dereferenceable. | ||
APInt OneByte(DL.getPointerTypeSizeInBits(Ty), 1); | ||
return C->isNullValue() || | ||
isDereferenceableAndAlignedPointer(B, Align(1), OneByte, DL, CtxI); | ||
// Returns true if a use is either in an ICmp/PtrToInt or a Phi/Select that only | ||
// feeds into them. | ||
static bool isPointerUseReplacable(const Use &U) { | ||
unsigned Limit = 40; | ||
SmallVector<const User *> Worklist({U.getUser()}); | ||
SmallPtrSet<const User *, 8> Visited; | ||
|
||
while (!Worklist.empty() && --Limit) { | ||
auto *User = Worklist.pop_back_val(); | ||
Visited.insert(User); | ||
if (isa<ICmpInst, PtrToIntInst>(User)) | ||
continue; | ||
if (isa<PHINode, SelectInst>(User)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Early return here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't return true here as we still need to check other users in the list. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I meant here is to write:
But now that the if block has become so small it doesn't really matter anymore. |
||
for (const auto &Use : User->uses()) | ||
UsmanNadeem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!Visited.contains(Use.getUser())) | ||
Worklist.push_back(Use.getUser()); | ||
} else | ||
return false; | ||
} | ||
|
||
return true; | ||
return Limit; | ||
UsmanNadeem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// Returns true if `To` is a null pointer, constant dereferenceable pointer or | ||
// both pointers have the same underlying objects. | ||
static bool isPointerAlwaysReplaceable(const Value *From, const Value *To, | ||
const DataLayout &DL) { | ||
// This is not strictly correct, but we do it for now to retain important | ||
// optimizations. | ||
if (isa<ConstantPointerNull>(To)) | ||
UsmanNadeem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return true; | ||
if (isa<Constant>(To) && | ||
isDereferenceablePointer(To, Type::getInt8Ty(To->getContext()), DL)) | ||
return true; | ||
if (getUnderlyingObject(From) == getUnderlyingObject(To)) | ||
return true; | ||
return false; | ||
} | ||
|
||
bool llvm::canReplacePointersInUseIfEqual(const Use &U, const Value *To, | ||
const DataLayout &DL) { | ||
assert(U->getType() == To->getType() && "values must have matching types"); | ||
// Not a pointer, just return true. | ||
if (!To->getType()->isPointerTy()) | ||
return true; | ||
|
||
if (isPointerAlwaysReplaceable(&*U, To, DL)) | ||
return true; | ||
return isPointerUseReplacable(U); | ||
} | ||
|
||
bool llvm::canReplacePointersIfEqual(const Value *From, const Value *To, | ||
const DataLayout &DL) { | ||
assert(From->getType() == To->getType() && "values must have matching types"); | ||
// Not a pointer, just return true. | ||
if (!From->getType()->isPointerTy()) | ||
return true; | ||
|
||
return isPointerAlwaysReplaceable(From, To, DL); | ||
} |
Uh oh!
There was an error while loading. Please reload this page.