diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 12dd49da279b9..8743df8e9c852 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(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(U); + auto FindUse = llvm::find_if(I->uses(), [](auto &U) { + auto *Use = cast(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(*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(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(Use)) + if (GetElementPtrInst *GEP = dyn_cast(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(Use)) { + if (ReturnInst *Ret = dyn_cast(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(Use)) + if (LoadInst *LI = dyn_cast(User)) if (!LI->isVolatile()) return !NullPointerIsDefined(LI->getFunction(), LI->getPointerAddressSpace()); // Store to null is undefined. - if (StoreInst *SI = dyn_cast(Use)) + if (StoreInst *SI = dyn_cast(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(Use)) { + if (auto *Assume = dyn_cast(User)) { // Ignore assume operand bundles. if (I == Assume->getArgOperand(0)) return true; } - if (auto *CB = dyn_cast(Use)) { + if (auto *CB = dyn_cast(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(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(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;