[llvm] [NFC][SimplifyCFG] Refactor `passingValueIsAlwaysUndefined` to work on `Use` (PR #125519)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 3 07:46:27 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Yingwei Zheng (dtcxzyw)
<details>
<summary>Changes</summary>
Address comment https://github.com/llvm/llvm-project/pull/125383#discussion_r1938436526
---
Full diff: https://github.com/llvm/llvm-project/pull/125519.diff
1 Files Affected:
- (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+25-34)
``````````diff
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 12dd49da279b9c..8743df8e9c8520 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -8175,8 +8175,8 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValu
if (C->isNullValue() || isa<UndefValue>(C)) {
// Only look at the first use we can handle, avoid hurting compile time with
// long uselists
- auto FindUse = llvm::find_if(I->users(), [](auto *U) {
- auto *Use = cast<Instruction>(U);
+ auto FindUse = llvm::find_if(I->uses(), [](auto &U) {
+ auto *Use = cast<Instruction>(U.getUser());
// Change this list when we want to add new instructions.
switch (Use->getOpcode()) {
default:
@@ -8199,26 +8199,28 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValu
return true;
}
});
- if (FindUse == I->user_end())
+ if (FindUse == I->use_end())
return false;
- auto *Use = cast<Instruction>(*FindUse);
- // Bail out if Use is not in the same BB as I or Use == I or Use comes
- // before I in the block. The latter two can be the case if Use is a
+ auto &Use = *FindUse;
+ auto *User = cast<Instruction>(Use.getUser());
+ // Bail out if User is not in the same BB as I or User == I or User comes
+ // before I in the block. The latter two can be the case if User is a
// PHI node.
- if (Use->getParent() != I->getParent() || Use == I || Use->comesBefore(I))
+ if (User->getParent() != I->getParent() || User == I ||
+ User->comesBefore(I))
return false;
// Now make sure that there are no instructions in between that can alter
// control flow (eg. calls)
auto InstrRange =
- make_range(std::next(I->getIterator()), Use->getIterator());
+ make_range(std::next(I->getIterator()), User->getIterator());
if (any_of(InstrRange, [](Instruction &I) {
return !isGuaranteedToTransferExecutionToSuccessor(&I);
}))
return false;
// Look through GEPs. A load from a GEP derived from NULL is still undefined
- if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Use))
+ if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User))
if (GEP->getPointerOperand() == I) {
// The current base address is null, there are four cases to consider:
// getelementptr (TY, null, 0) -> null
@@ -8235,7 +8237,7 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValu
}
// Look through return.
- if (ReturnInst *Ret = dyn_cast<ReturnInst>(Use)) {
+ if (ReturnInst *Ret = dyn_cast<ReturnInst>(User)) {
bool HasNoUndefAttr =
Ret->getFunction()->hasRetAttribute(Attribute::NoUndef);
// Return undefined to a noundef return value is undefined.
@@ -8249,56 +8251,45 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValu
}
// Load from null is undefined.
- if (LoadInst *LI = dyn_cast<LoadInst>(Use))
+ if (LoadInst *LI = dyn_cast<LoadInst>(User))
if (!LI->isVolatile())
return !NullPointerIsDefined(LI->getFunction(),
LI->getPointerAddressSpace());
// Store to null is undefined.
- if (StoreInst *SI = dyn_cast<StoreInst>(Use))
+ if (StoreInst *SI = dyn_cast<StoreInst>(User))
if (!SI->isVolatile())
return (!NullPointerIsDefined(SI->getFunction(),
SI->getPointerAddressSpace())) &&
SI->getPointerOperand() == I;
// llvm.assume(false/undef) always triggers immediate UB.
- if (auto *Assume = dyn_cast<AssumeInst>(Use)) {
+ if (auto *Assume = dyn_cast<AssumeInst>(User)) {
// Ignore assume operand bundles.
if (I == Assume->getArgOperand(0))
return true;
}
- if (auto *CB = dyn_cast<CallBase>(Use)) {
+ if (auto *CB = dyn_cast<CallBase>(User)) {
if (C->isNullValue() && NullPointerIsDefined(CB->getFunction()))
return false;
// A call to null is undefined.
if (CB->getCalledOperand() == I)
return true;
- if (C->isNullValue()) {
- for (const llvm::Use &Arg : CB->args())
- if (Arg == I) {
- unsigned ArgIdx = CB->getArgOperandNo(&Arg);
- if (CB->isPassingUndefUB(ArgIdx) &&
- CB->paramHasAttr(ArgIdx, Attribute::NonNull)) {
- // Passing null to a nonnnull+noundef argument is undefined.
- return !PtrValueMayBeModified;
- }
- }
- } else if (isa<UndefValue>(C)) {
+ if (CB->isArgOperand(&Use)) {
+ unsigned ArgIdx = CB->getArgOperandNo(&Use);
+ // Passing null to a nonnnull+noundef argument is undefined.
+ if (C->isNullValue() && CB->isPassingUndefUB(ArgIdx) &&
+ CB->paramHasAttr(ArgIdx, Attribute::NonNull))
+ return !PtrValueMayBeModified;
// Passing undef to a noundef argument is undefined.
- for (const llvm::Use &Arg : CB->args())
- if (Arg == I) {
- unsigned ArgIdx = CB->getArgOperandNo(&Arg);
- if (CB->isPassingUndefUB(ArgIdx)) {
- // Passing undef to a noundef argument is undefined.
- return true;
- }
- }
+ if (isa<UndefValue>(C) && CB->isPassingUndefUB(ArgIdx))
+ return true;
}
}
// Div/Rem by zero is immediate UB
- if (match(Use, m_BinOp(m_Value(), m_Specific(I))) && Use->isIntDivRem())
+ if (match(User, m_BinOp(m_Value(), m_Specific(I))) && User->isIntDivRem())
return true;
}
return false;
``````````
</details>
https://github.com/llvm/llvm-project/pull/125519
More information about the llvm-commits
mailing list