mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
[Attributor][NFCI] Add UsedAssumedInformation to more interfaces
As with other Attributor interfaces we often want to know if assumed information was used to answer a query. This is important if only known information is allowed or if known information can lead to an early fixpoint. The users have been adjusted but none of them utilizes the new information yet.
This commit is contained in:
parent
df82045809
commit
90355478cc
@ -1120,7 +1120,7 @@ struct Attributor {
|
||||
: Allocator(InfoCache.Allocator), Functions(Functions),
|
||||
InfoCache(InfoCache), CGUpdater(CGUpdater), Allowed(Allowed),
|
||||
DeleteFns(DeleteFns), RewriteSignatures(RewriteSignatures),
|
||||
MaxFixpointIterations(None), OREGetter(None), PassName("") {}
|
||||
MaxFixpointIterations(None), OREGetter(None), PassName("") {}
|
||||
|
||||
/// Constructor
|
||||
///
|
||||
@ -1529,6 +1529,7 @@ public:
|
||||
///
|
||||
/// If \p LivenessAA is not provided it is queried.
|
||||
bool isAssumedDead(const AbstractAttribute &AA, const AAIsDead *LivenessAA,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL);
|
||||
|
||||
@ -1536,7 +1537,7 @@ public:
|
||||
///
|
||||
/// If \p LivenessAA is not provided it is queried.
|
||||
bool isAssumedDead(const Instruction &I, const AbstractAttribute *QueryingAA,
|
||||
const AAIsDead *LivenessAA,
|
||||
const AAIsDead *LivenessAA, bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL);
|
||||
|
||||
@ -1544,7 +1545,7 @@ public:
|
||||
///
|
||||
/// If \p FnLivenessAA is not provided it is queried.
|
||||
bool isAssumedDead(const Use &U, const AbstractAttribute *QueryingAA,
|
||||
const AAIsDead *FnLivenessAA,
|
||||
const AAIsDead *FnLivenessAA, bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL);
|
||||
|
||||
@ -1552,7 +1553,7 @@ public:
|
||||
///
|
||||
/// If \p FnLivenessAA is not provided it is queried.
|
||||
bool isAssumedDead(const IRPosition &IRP, const AbstractAttribute *QueryingAA,
|
||||
const AAIsDead *FnLivenessAA,
|
||||
const AAIsDead *FnLivenessAA, bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL);
|
||||
|
||||
@ -1735,6 +1736,7 @@ public:
|
||||
bool checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
|
||||
const AbstractAttribute &QueryingAA,
|
||||
const ArrayRef<unsigned> &Opcodes,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly = false,
|
||||
bool CheckPotentiallyDead = false);
|
||||
|
||||
@ -1743,13 +1745,14 @@ public:
|
||||
/// See checkForAllCallLikeInstructions(...) for more information.
|
||||
bool checkForAllCallLikeInstructions(function_ref<bool(Instruction &)> Pred,
|
||||
const AbstractAttribute &QueryingAA,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly = false,
|
||||
bool CheckPotentiallyDead = false) {
|
||||
return checkForAllInstructions(Pred, QueryingAA,
|
||||
{(unsigned)Instruction::Invoke,
|
||||
(unsigned)Instruction::CallBr,
|
||||
(unsigned)Instruction::Call},
|
||||
CheckBBLivenessOnly, CheckPotentiallyDead);
|
||||
return checkForAllInstructions(
|
||||
Pred, QueryingAA,
|
||||
{(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
|
||||
(unsigned)Instruction::Call},
|
||||
UsedAssumedInformation, CheckBBLivenessOnly, CheckPotentiallyDead);
|
||||
}
|
||||
|
||||
/// Check \p Pred on all Read/Write instructions.
|
||||
@ -1758,7 +1761,8 @@ public:
|
||||
/// to memory present in the information cache and return true if \p Pred
|
||||
/// holds on all of them.
|
||||
bool checkForAllReadWriteInstructions(function_ref<bool(Instruction &)> Pred,
|
||||
AbstractAttribute &QueryingAA);
|
||||
AbstractAttribute &QueryingAA,
|
||||
bool &UsedAssumedInformation);
|
||||
|
||||
/// Create a shallow wrapper for \p F such that \p F has internal linkage
|
||||
/// afterwards. It also sets the original \p F 's name to anonymous
|
||||
|
@ -725,21 +725,24 @@ Attributor::~Attributor() {
|
||||
|
||||
bool Attributor::isAssumedDead(const AbstractAttribute &AA,
|
||||
const AAIsDead *FnLivenessAA,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly, DepClassTy DepClass) {
|
||||
const IRPosition &IRP = AA.getIRPosition();
|
||||
if (!Functions.count(IRP.getAnchorScope()))
|
||||
return false;
|
||||
return isAssumedDead(IRP, &AA, FnLivenessAA, CheckBBLivenessOnly, DepClass);
|
||||
return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
|
||||
CheckBBLivenessOnly, DepClass);
|
||||
}
|
||||
|
||||
bool Attributor::isAssumedDead(const Use &U,
|
||||
const AbstractAttribute *QueryingAA,
|
||||
const AAIsDead *FnLivenessAA,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly, DepClassTy DepClass) {
|
||||
Instruction *UserI = dyn_cast<Instruction>(U.getUser());
|
||||
if (!UserI)
|
||||
return isAssumedDead(IRPosition::value(*U.get()), QueryingAA, FnLivenessAA,
|
||||
CheckBBLivenessOnly, DepClass);
|
||||
UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
|
||||
|
||||
if (auto *CB = dyn_cast<CallBase>(UserI)) {
|
||||
// For call site argument uses we can check if the argument is
|
||||
@ -748,25 +751,27 @@ bool Attributor::isAssumedDead(const Use &U,
|
||||
const IRPosition &CSArgPos =
|
||||
IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
|
||||
return isAssumedDead(CSArgPos, QueryingAA, FnLivenessAA,
|
||||
CheckBBLivenessOnly, DepClass);
|
||||
UsedAssumedInformation, CheckBBLivenessOnly,
|
||||
DepClass);
|
||||
}
|
||||
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
|
||||
const IRPosition &RetPos = IRPosition::returned(*RI->getFunction());
|
||||
return isAssumedDead(RetPos, QueryingAA, FnLivenessAA, CheckBBLivenessOnly,
|
||||
DepClass);
|
||||
return isAssumedDead(RetPos, QueryingAA, FnLivenessAA,
|
||||
UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
|
||||
} else if (PHINode *PHI = dyn_cast<PHINode>(UserI)) {
|
||||
BasicBlock *IncomingBB = PHI->getIncomingBlock(U);
|
||||
return isAssumedDead(*IncomingBB->getTerminator(), QueryingAA, FnLivenessAA,
|
||||
CheckBBLivenessOnly, DepClass);
|
||||
UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
|
||||
}
|
||||
|
||||
return isAssumedDead(IRPosition::value(*UserI), QueryingAA, FnLivenessAA,
|
||||
CheckBBLivenessOnly, DepClass);
|
||||
UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
|
||||
}
|
||||
|
||||
bool Attributor::isAssumedDead(const Instruction &I,
|
||||
const AbstractAttribute *QueryingAA,
|
||||
const AAIsDead *FnLivenessAA,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly, DepClassTy DepClass) {
|
||||
const IRPosition::CallBaseContext *CBCtx =
|
||||
QueryingAA ? QueryingAA->getCallBaseContext() : nullptr;
|
||||
@ -782,6 +787,8 @@ bool Attributor::isAssumedDead(const Instruction &I,
|
||||
FnLivenessAA->isAssumedDead(&I)) {
|
||||
if (QueryingAA)
|
||||
recordDependence(*FnLivenessAA, *QueryingAA, DepClass);
|
||||
if (!FnLivenessAA->isKnownDead(&I))
|
||||
UsedAssumedInformation = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -797,6 +804,8 @@ bool Attributor::isAssumedDead(const Instruction &I,
|
||||
if (IsDeadAA.isAssumedDead()) {
|
||||
if (QueryingAA)
|
||||
recordDependence(IsDeadAA, *QueryingAA, DepClass);
|
||||
if (!IsDeadAA.isKnownDead())
|
||||
UsedAssumedInformation = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -806,10 +815,11 @@ bool Attributor::isAssumedDead(const Instruction &I,
|
||||
bool Attributor::isAssumedDead(const IRPosition &IRP,
|
||||
const AbstractAttribute *QueryingAA,
|
||||
const AAIsDead *FnLivenessAA,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly, DepClassTy DepClass) {
|
||||
Instruction *CtxI = IRP.getCtxI();
|
||||
if (CtxI &&
|
||||
isAssumedDead(*CtxI, QueryingAA, FnLivenessAA,
|
||||
isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true,
|
||||
CheckBBLivenessOnly ? DepClass : DepClassTy::OPTIONAL))
|
||||
return true;
|
||||
@ -832,6 +842,8 @@ bool Attributor::isAssumedDead(const IRPosition &IRP,
|
||||
if (IsDeadAA->isAssumedDead()) {
|
||||
if (QueryingAA)
|
||||
recordDependence(*IsDeadAA, *QueryingAA, DepClass);
|
||||
if (!IsDeadAA->isKnownDead())
|
||||
UsedAssumedInformation = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -868,7 +880,8 @@ bool Attributor::checkForAllUses(function_ref<bool(const Use &, bool &)> Pred,
|
||||
continue;
|
||||
LLVM_DEBUG(dbgs() << "[Attributor] Check use: " << **U << " in "
|
||||
<< *U->getUser() << "\n");
|
||||
if (isAssumedDead(*U, &QueryingAA, LivenessAA,
|
||||
bool UsedAssumedInformation = false;
|
||||
if (isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ false, LivenessDepClass)) {
|
||||
LLVM_DEBUG(dbgs() << "[Attributor] Dead use, skip!\n");
|
||||
continue;
|
||||
@ -932,7 +945,9 @@ bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred,
|
||||
const Use &U = *Uses[u];
|
||||
LLVM_DEBUG(dbgs() << "[Attributor] Check use: " << *U << " in "
|
||||
<< *U.getUser() << "\n");
|
||||
if (isAssumedDead(U, QueryingAA, nullptr, /* CheckBBLivenessOnly */ true)) {
|
||||
bool UsedAssumedInformation = false;
|
||||
if (isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true)) {
|
||||
LLVM_DEBUG(dbgs() << "[Attributor] Dead use, skip!\n");
|
||||
continue;
|
||||
}
|
||||
@ -1051,7 +1066,8 @@ static bool checkForAllInstructionsImpl(
|
||||
Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap,
|
||||
function_ref<bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA,
|
||||
const AAIsDead *LivenessAA, const ArrayRef<unsigned> &Opcodes,
|
||||
bool CheckBBLivenessOnly = false, bool CheckPotentiallyDead = false) {
|
||||
bool &UsedAssumedInformation, bool CheckBBLivenessOnly = false,
|
||||
bool CheckPotentiallyDead = false) {
|
||||
for (unsigned Opcode : Opcodes) {
|
||||
// Check if we have instructions with this opcode at all first.
|
||||
auto *Insts = OpcodeInstMap.lookup(Opcode);
|
||||
@ -1062,7 +1078,7 @@ static bool checkForAllInstructionsImpl(
|
||||
// Skip dead instructions.
|
||||
if (A && !CheckPotentiallyDead &&
|
||||
A->isAssumedDead(IRPosition::value(*I), QueryingAA, LivenessAA,
|
||||
CheckBBLivenessOnly))
|
||||
UsedAssumedInformation, CheckBBLivenessOnly))
|
||||
continue;
|
||||
|
||||
if (!Pred(*I))
|
||||
@ -1075,6 +1091,7 @@ static bool checkForAllInstructionsImpl(
|
||||
bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
|
||||
const AbstractAttribute &QueryingAA,
|
||||
const ArrayRef<unsigned> &Opcodes,
|
||||
bool &UsedAssumedInformation,
|
||||
bool CheckBBLivenessOnly,
|
||||
bool CheckPotentiallyDead) {
|
||||
|
||||
@ -1094,15 +1111,16 @@ bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
|
||||
auto &OpcodeInstMap =
|
||||
InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
|
||||
if (!checkForAllInstructionsImpl(this, OpcodeInstMap, Pred, &QueryingAA,
|
||||
LivenessAA, Opcodes, CheckBBLivenessOnly,
|
||||
CheckPotentiallyDead))
|
||||
LivenessAA, Opcodes, UsedAssumedInformation,
|
||||
CheckBBLivenessOnly, CheckPotentiallyDead))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Attributor::checkForAllReadWriteInstructions(
|
||||
function_ref<bool(Instruction &)> Pred, AbstractAttribute &QueryingAA) {
|
||||
function_ref<bool(Instruction &)> Pred, AbstractAttribute &QueryingAA,
|
||||
bool &UsedAssumedInformation) {
|
||||
|
||||
const Function *AssociatedFunction =
|
||||
QueryingAA.getIRPosition().getAssociatedFunction();
|
||||
@ -1117,7 +1135,8 @@ bool Attributor::checkForAllReadWriteInstructions(
|
||||
for (Instruction *I :
|
||||
InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
|
||||
// Skip dead instructions.
|
||||
if (isAssumedDead(IRPosition::value(*I), &QueryingAA, &LivenessAA))
|
||||
if (isAssumedDead(IRPosition::value(*I), &QueryingAA, &LivenessAA,
|
||||
UsedAssumedInformation))
|
||||
continue;
|
||||
|
||||
if (!Pred(*I))
|
||||
@ -1143,7 +1162,6 @@ void Attributor::runTillFixpoint() {
|
||||
else
|
||||
MaxFixedPointIterations = SetFixpointIterations;
|
||||
|
||||
|
||||
SmallVector<AbstractAttribute *, 32> ChangedAAs;
|
||||
SetVector<AbstractAttribute *> Worklist, InvalidAAs;
|
||||
Worklist.insert(DG.SyntheticRoot.begin(), DG.SyntheticRoot.end());
|
||||
@ -1296,7 +1314,9 @@ ChangeStatus Attributor::manifestAttributes() {
|
||||
continue;
|
||||
|
||||
// Skip dead code.
|
||||
if (isAssumedDead(*AA, nullptr, /* CheckBBLivenessOnly */ true))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (isAssumedDead(*AA, nullptr, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true))
|
||||
continue;
|
||||
// Check if the manifest debug counter that allows skipping manifestation of
|
||||
// AAs
|
||||
@ -1660,7 +1680,9 @@ ChangeStatus Attributor::updateAA(AbstractAttribute &AA) {
|
||||
|
||||
auto &AAState = AA.getState();
|
||||
ChangeStatus CS = ChangeStatus::UNCHANGED;
|
||||
if (!isAssumedDead(AA, nullptr, /* CheckBBLivenessOnly */ true))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!isAssumedDead(AA, nullptr, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true))
|
||||
CS = AA.update(*this);
|
||||
|
||||
if (DV.empty()) {
|
||||
@ -1825,9 +1847,11 @@ bool Attributor::isValidFunctionSignatureRewrite(
|
||||
|
||||
// Forbid must-tail calls for now.
|
||||
// TODO:
|
||||
bool UsedAssumedInformation = false;
|
||||
auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
|
||||
if (!checkForAllInstructionsImpl(nullptr, OpcodeInstMap, InstPred, nullptr,
|
||||
nullptr, {Instruction::Call})) {
|
||||
nullptr, {Instruction::Call},
|
||||
UsedAssumedInformation)) {
|
||||
LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite due to instructions\n");
|
||||
return false;
|
||||
}
|
||||
@ -2394,10 +2418,12 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
|
||||
|
||||
auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
|
||||
bool Success;
|
||||
bool UsedAssumedInformation = false;
|
||||
Success = checkForAllInstructionsImpl(
|
||||
nullptr, OpcodeInstMap, CallSitePred, nullptr, nullptr,
|
||||
{(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
|
||||
(unsigned)Instruction::Call});
|
||||
(unsigned)Instruction::Call},
|
||||
UsedAssumedInformation);
|
||||
(void)Success;
|
||||
assert(Success && "Expected the check call to be successful!");
|
||||
|
||||
@ -2412,7 +2438,8 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
|
||||
};
|
||||
Success = checkForAllInstructionsImpl(
|
||||
nullptr, OpcodeInstMap, LoadStorePred, nullptr, nullptr,
|
||||
{(unsigned)Instruction::Load, (unsigned)Instruction::Store});
|
||||
{(unsigned)Instruction::Load, (unsigned)Instruction::Store},
|
||||
UsedAssumedInformation);
|
||||
(void)Success;
|
||||
assert(Success && "Expected the check call to be successful!");
|
||||
}
|
||||
|
@ -335,8 +335,9 @@ static bool genericValueTraversal(
|
||||
"Expected liveness in the presence of instructions!");
|
||||
for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
|
||||
BasicBlock *IncomingBB = PHI->getIncomingBlock(u);
|
||||
bool UsedAssumedInformation = false;
|
||||
if (A.isAssumedDead(*IncomingBB->getTerminator(), &QueryingAA,
|
||||
LivenessAA,
|
||||
LivenessAA, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true)) {
|
||||
AnyDead = true;
|
||||
continue;
|
||||
@ -794,7 +795,9 @@ struct AANoUnwindImpl : AANoUnwind {
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
|
||||
return ChangeStatus::UNCHANGED;
|
||||
@ -1052,7 +1055,9 @@ ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
|
||||
|
||||
// Discover returned values from all live returned instructions in the
|
||||
// associated function.
|
||||
if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret}))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
return Changed;
|
||||
}
|
||||
@ -1185,8 +1190,11 @@ ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
|
||||
return !cast<CallBase>(I).isConvergent();
|
||||
};
|
||||
|
||||
if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) ||
|
||||
!A.checkForAllCallLikeInstructions(CheckForNoSync, *this))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
|
||||
UsedAssumedInformation) ||
|
||||
!A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
|
||||
return ChangeStatus::UNCHANGED;
|
||||
@ -1246,7 +1254,9 @@ struct AANoFreeImpl : public AANoFree {
|
||||
return NoFreeAA.isAssumedNoFree();
|
||||
};
|
||||
|
||||
if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
return ChangeStatus::UNCHANGED;
|
||||
}
|
||||
@ -1708,7 +1718,9 @@ struct AANoRecurseFunction final : AANoRecurseImpl {
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!A.checkForAllCallLikeInstructions(CheckForNoRecurse, *this))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllCallLikeInstructions(CheckForNoRecurse, *this,
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
return ChangeStatus::UNCHANGED;
|
||||
}
|
||||
@ -1915,20 +1927,24 @@ struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
|
||||
return true;
|
||||
};
|
||||
|
||||
bool UsedAssumedInformation = false;
|
||||
A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
|
||||
{Instruction::Load, Instruction::Store,
|
||||
Instruction::AtomicCmpXchg,
|
||||
Instruction::AtomicRMW},
|
||||
UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true);
|
||||
A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},
|
||||
UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true);
|
||||
A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this);
|
||||
A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
|
||||
UsedAssumedInformation);
|
||||
|
||||
// If the returned position of the anchor scope has noundef attriubte, check
|
||||
// all returned instructions.
|
||||
if (!getAnchorScope()->getReturnType()->isVoidTy()) {
|
||||
const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
|
||||
if (!A.isAssumedDead(ReturnIRP, this, nullptr)) {
|
||||
if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
|
||||
auto &RetPosNoUndefAA =
|
||||
A.getAAFor<AANoUndef>(*this, ReturnIRP, DepClassTy::NONE);
|
||||
if (RetPosNoUndefAA.isKnownNoUndef())
|
||||
@ -2146,7 +2162,9 @@ struct AAWillReturnImpl : public AAWillReturn {
|
||||
return NoRecurseAA.isAssumedNoRecurse();
|
||||
};
|
||||
|
||||
if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
|
||||
return ChangeStatus::UNCHANGED;
|
||||
@ -2882,8 +2900,9 @@ struct AAIsDeadReturned : public AAIsDeadValueImpl {
|
||||
/// See AbstractAttribute::updateImpl(...).
|
||||
ChangeStatus updateImpl(Attributor &A) override {
|
||||
|
||||
bool UsedAssumedInformation = false;
|
||||
A.checkForAllInstructions([](Instruction &) { return true; }, *this,
|
||||
{Instruction::Ret});
|
||||
{Instruction::Ret}, UsedAssumedInformation);
|
||||
|
||||
auto PredForCallSite = [&](AbstractCallSite ACS) {
|
||||
if (ACS.isCallbackCall() || !ACS.getInstruction())
|
||||
@ -2910,7 +2929,9 @@ struct AAIsDeadReturned : public AAIsDeadValueImpl {
|
||||
AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
|
||||
return true;
|
||||
};
|
||||
A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret});
|
||||
bool UsedAssumedInformation = false;
|
||||
A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
|
||||
UsedAssumedInformation);
|
||||
return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
|
||||
}
|
||||
|
||||
@ -3871,8 +3892,10 @@ struct AANoReturnImpl : public AANoReturn {
|
||||
/// See AbstractAttribute::updateImpl(Attributor &A).
|
||||
virtual ChangeStatus updateImpl(Attributor &A) override {
|
||||
auto CheckForNoReturn = [](Instruction &) { return false; };
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllInstructions(CheckForNoReturn, *this,
|
||||
{(unsigned)Instruction::Ret}))
|
||||
{(unsigned)Instruction::Ret},
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
return ChangeStatus::UNCHANGED;
|
||||
}
|
||||
@ -4134,8 +4157,10 @@ struct AACaptureUseTracker final : public CaptureTracker {
|
||||
/// See CaptureTracker::shouldExplore(...).
|
||||
bool shouldExplore(const Use *U) override {
|
||||
// Check liveness and ignore droppable users.
|
||||
bool UsedAssumedInformation = false;
|
||||
return !U->getUser()->isDroppable() &&
|
||||
!A.isAssumedDead(*U, &NoCaptureAA, &IsDeadAA);
|
||||
!A.isAssumedDead(*U, &NoCaptureAA, &IsDeadAA,
|
||||
UsedAssumedInformation);
|
||||
}
|
||||
|
||||
/// Update the state according to \p CapturedInMem, \p CapturedInInt, and
|
||||
@ -4542,7 +4567,7 @@ struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
|
||||
// in other functions, e.g., we don't want to say a an argument in a
|
||||
// static function is actually an argument in a different function.
|
||||
Value &ArgOp = ACSArgPos.getAssociatedValue();
|
||||
bool UsedAssumedInformation;
|
||||
bool UsedAssumedInformation = false;
|
||||
Optional<Value *> SimpleArgOp =
|
||||
A.getAssumedSimplified(ACSArgPos, *this, UsedAssumedInformation);
|
||||
if (!SimpleArgOp.hasValue())
|
||||
@ -4817,7 +4842,7 @@ struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
|
||||
DepClassTy::REQUIRED);
|
||||
auto PredForReturned =
|
||||
[&](Value &RetVal, const SmallSetVector<ReturnInst *, 4> &RetInsts) {
|
||||
bool UsedAssumedInformation;
|
||||
bool UsedAssumedInformation = false;
|
||||
Optional<Value *> CSRetVal = A.translateArgumentToCallSiteContent(
|
||||
&RetVal, *cast<CallBase>(getCtxI()), *this,
|
||||
UsedAssumedInformation);
|
||||
@ -4938,8 +4963,10 @@ struct AAHeapToStackFunction final : public AAHeapToStack {
|
||||
return true;
|
||||
};
|
||||
|
||||
bool UsedAssumedInformation = false;
|
||||
bool Success = A.checkForAllCallLikeInstructions(
|
||||
AllocationIdentifierCB, *this, /* CheckBBLivenessOnly */ false,
|
||||
AllocationIdentifierCB, *this, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ false,
|
||||
/* CheckPotentiallyDead */ true);
|
||||
(void)Success;
|
||||
assert(Success && "Did not expect the call base visit callback to fail!");
|
||||
@ -5142,7 +5169,8 @@ ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
|
||||
continue;
|
||||
|
||||
// No need to analyze dead calls, ignore them instead.
|
||||
if (A.isAssumedDead(*DI.CB, this, &LivenessAA,
|
||||
bool UsedAssumedInformation = false;
|
||||
if (A.isAssumedDead(*DI.CB, this, &LivenessAA, UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true))
|
||||
continue;
|
||||
|
||||
@ -5768,6 +5796,7 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
|
||||
// escape into tail recursion.
|
||||
// TODO: Be smarter about new allocas escaping into tail calls.
|
||||
SmallVector<CallInst *, 16> TailCalls;
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllInstructions(
|
||||
[&](Instruction &I) {
|
||||
CallInst &CI = cast<CallInst>(I);
|
||||
@ -5775,7 +5804,7 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
|
||||
TailCalls.push_back(&CI);
|
||||
return true;
|
||||
},
|
||||
*this, {Instruction::Call}))
|
||||
*this, {Instruction::Call}, UsedAssumedInformation))
|
||||
return ChangeStatus::UNCHANGED;
|
||||
|
||||
Argument *Arg = getAssociatedArgument();
|
||||
@ -6323,7 +6352,9 @@ ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
|
||||
return !isAtFixpoint();
|
||||
};
|
||||
|
||||
if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
|
||||
return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
|
||||
@ -6375,10 +6406,13 @@ ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
|
||||
for (unsigned i = 0; i < Uses.size() && !isAtFixpoint(); i++) {
|
||||
const Use *U = Uses[i];
|
||||
Instruction *UserI = cast<Instruction>(U->getUser());
|
||||
bool UsedAssumedInformation = false;
|
||||
LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << **U << " in " << *UserI
|
||||
<< " [Dead: " << (A.isAssumedDead(*U, this, &LivenessAA))
|
||||
<< " [Dead: "
|
||||
<< (A.isAssumedDead(*U, this, &LivenessAA,
|
||||
UsedAssumedInformation))
|
||||
<< "]\n");
|
||||
if (A.isAssumedDead(*U, this, &LivenessAA))
|
||||
if (A.isAssumedDead(*U, this, &LivenessAA, UsedAssumedInformation))
|
||||
continue;
|
||||
|
||||
// Droppable users, e.g., llvm::assume does not actually perform any action.
|
||||
@ -6995,7 +7029,9 @@ struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
|
||||
return getAssumedNotAccessedLocation() != VALID_STATE;
|
||||
};
|
||||
|
||||
if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
|
||||
UsedAssumedInformation))
|
||||
return indicatePessimisticFixpoint();
|
||||
|
||||
Changed |= AssumedState != getAssumed();
|
||||
@ -7159,7 +7195,7 @@ struct AAValueConstantRangeImpl : AAValueConstantRange {
|
||||
const DominatorTree *DT =
|
||||
InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
|
||||
*I->getFunction());
|
||||
return DT && DT->dominates(I, CtxI);
|
||||
return DT && DT->dominates(I, CtxI);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -8302,12 +8338,13 @@ struct AANoUndefImpl : AANoUndef {
|
||||
// We don't manifest noundef attribute for dead positions because the
|
||||
// associated values with dead positions would be replaced with undef
|
||||
// values.
|
||||
if (A.isAssumedDead(getIRPosition(), nullptr, nullptr))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
|
||||
UsedAssumedInformation))
|
||||
return ChangeStatus::UNCHANGED;
|
||||
// A position whose simplified value does not have any value is
|
||||
// considered to be dead. We don't manifest noundef in such positions for
|
||||
// the same reason above.
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation)
|
||||
.hasValue())
|
||||
return ChangeStatus::UNCHANGED;
|
||||
@ -8458,7 +8495,9 @@ struct AACallEdgesFunction : public AACallEdges {
|
||||
};
|
||||
|
||||
// Visit all callable instructions.
|
||||
if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this))
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
|
||||
UsedAssumedInformation))
|
||||
// If we haven't looked at all call like instructions, assume that there
|
||||
// are unknown callees.
|
||||
HasUnknownCallee = true;
|
||||
|
@ -2078,7 +2078,9 @@ struct AAICVTrackerFunction : public AAICVTracker {
|
||||
// Track all changes of an ICV.
|
||||
SetterRFI.foreachUse(TrackValues, F);
|
||||
|
||||
bool UsedAssumedInformation = false;
|
||||
A.checkForAllInstructions(CallCheck, *this, {Instruction::Call},
|
||||
UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true);
|
||||
|
||||
/// TODO: Figure out a way to avoid adding entry in
|
||||
@ -2261,7 +2263,9 @@ struct AAICVTrackerFunctionReturned : AAICVTracker {
|
||||
return true;
|
||||
};
|
||||
|
||||
bool UsedAssumedInformation = false;
|
||||
if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret},
|
||||
UsedAssumedInformation,
|
||||
/* CheckBBLivenessOnly */ true))
|
||||
UniqueICVValue = nullptr;
|
||||
|
||||
@ -3203,7 +3207,10 @@ struct AAKernelInfoFunction : AAKernelInfo {
|
||||
SPMDCompatibilityTracker.insert(&I);
|
||||
return true;
|
||||
};
|
||||
if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this))
|
||||
|
||||
bool UsedAssumedInformationInCheckRWInst = false;
|
||||
if (!A.checkForAllReadWriteInstructions(
|
||||
CheckRWInst, *this, UsedAssumedInformationInCheckRWInst))
|
||||
SPMDCompatibilityTracker.indicatePessimisticFixpoint();
|
||||
|
||||
// Callback to check a call instruction.
|
||||
@ -3216,7 +3223,9 @@ struct AAKernelInfoFunction : AAKernelInfo {
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!A.checkForAllCallLikeInstructions(CheckCallInst, *this))
|
||||
bool UsedAssumedInformationInCheckCallInst = false;
|
||||
if (!A.checkForAllCallLikeInstructions(
|
||||
CheckCallInst, *this, UsedAssumedInformationInCheckCallInst))
|
||||
return indicatePessimisticFixpoint();
|
||||
|
||||
return StateBefore == getState() ? ChangeStatus::UNCHANGED
|
||||
|
Loading…
Reference in New Issue
Block a user