Skip to content

Commit

Permalink
[LLVM] Don't peek through bitcast on pointers and gep with zero indic…
Browse files Browse the repository at this point in the history
…es. NFC. (#102889)

Since we are using opaque pointers now, we don't need to peek through
bitcast on pointers and gep with zero indices.
  • Loading branch information
dtcxzyw authored Aug 13, 2024
1 parent f807c5e commit f364b2e
Show file tree
Hide file tree
Showing 12 changed files with 37 additions and 116 deletions.
53 changes: 12 additions & 41 deletions llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,6 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
if (isa<GlobalValue>(LoadOperand))
return MemDepResult::getUnknown();

// Queue to process all pointers that are equivalent to load operand.
SmallVector<const Value *, 8> LoadOperandsQueue;
LoadOperandsQueue.push_back(LoadOperand);

Instruction *ClosestDependency = nullptr;
// Order of instructions in uses list is unpredictible. In order to always
// get the same result, we will look for the closest dominance.
Expand All @@ -305,44 +301,19 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
return Best;
};

// FIXME: This loop is O(N^2) because dominates can be O(n) and in worst case
// we will see all the instructions. This should be fixed in MSSA.
while (!LoadOperandsQueue.empty()) {
const Value *Ptr = LoadOperandsQueue.pop_back_val();
assert(Ptr && !isa<GlobalValue>(Ptr) &&
"Null or GlobalValue should not be inserted");

for (const Use &Us : Ptr->uses()) {
auto *U = dyn_cast<Instruction>(Us.getUser());
if (!U || U == LI || !DT.dominates(U, LI))
continue;

// Bitcast or gep with zeros are using Ptr. Add to queue to check it's
// users. U = bitcast Ptr
if (isa<BitCastInst>(U)) {
LoadOperandsQueue.push_back(U);
continue;
}
// Gep with zeros is equivalent to bitcast.
// FIXME: we are not sure if some bitcast should be canonicalized to gep 0
// or gep 0 to bitcast because of SROA, so there are 2 forms. When
// typeless pointers will be ready then both cases will be gone
// (and this BFS also won't be needed).
if (auto *GEP = dyn_cast<GetElementPtrInst>(U))
if (GEP->hasAllZeroIndices()) {
LoadOperandsQueue.push_back(U);
continue;
}
for (const Use &Us : LoadOperand->uses()) {
auto *U = dyn_cast<Instruction>(Us.getUser());
if (!U || U == LI || !DT.dominates(U, LI))
continue;

// If we hit load/store with the same invariant.group metadata (and the
// same pointer operand) we can assume that value pointed by pointer
// operand didn't change.
if ((isa<LoadInst>(U) ||
(isa<StoreInst>(U) &&
cast<StoreInst>(U)->getPointerOperand() == Ptr)) &&
U->hasMetadata(LLVMContext::MD_invariant_group))
ClosestDependency = GetClosestDependency(ClosestDependency, U);
}
// If we hit load/store with the same invariant.group metadata (and the
// same pointer operand) we can assume that value pointed by pointer
// operand didn't change.
if ((isa<LoadInst>(U) ||
(isa<StoreInst>(U) &&
cast<StoreInst>(U)->getPointerOperand() == LoadOperand)) &&
U->hasMetadata(LLVMContext::MD_invariant_group))
ClosestDependency = GetClosestDependency(ClosestDependency, U);
}

if (!ClosestDependency)
Expand Down
45 changes: 11 additions & 34 deletions llvm/lib/Analysis/MemorySSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2507,45 +2507,22 @@ getInvariantGroupClobberingInstruction(Instruction &I, DominatorTree &DT) {
if (isa<Constant>(PointerOperand))
return nullptr;

// Queue to process all pointers that are equivalent to load operand.
SmallVector<const Value *, 8> PointerUsesQueue;
PointerUsesQueue.push_back(PointerOperand);

const Instruction *MostDominatingInstruction = &I;

// FIXME: This loop is O(n^2) because dominates can be O(n) and in worst case
// we will see all the instructions. It may not matter in practice. If it
// does, we will have to support MemorySSA construction and updates.
while (!PointerUsesQueue.empty()) {
const Value *Ptr = PointerUsesQueue.pop_back_val();
assert(Ptr && !isa<GlobalValue>(Ptr) &&
"Null or GlobalValue should not be inserted");

for (const User *Us : Ptr->users()) {
auto *U = dyn_cast<Instruction>(Us);
if (!U || U == &I || !DT.dominates(U, MostDominatingInstruction))
continue;

// Add bitcasts and zero GEPs to queue.
if (isa<BitCastInst>(U)) {
PointerUsesQueue.push_back(U);
continue;
}
if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) {
if (GEP->hasAllZeroIndices())
PointerUsesQueue.push_back(U);
continue;
}
for (const User *Us : PointerOperand->users()) {
auto *U = dyn_cast<Instruction>(Us);
if (!U || U == &I || !DT.dominates(U, MostDominatingInstruction))
continue;

// If we hit a load/store with an invariant.group metadata and the same
// pointer operand, we can assume that value pointed to by the pointer
// operand didn't change.
if (U->hasMetadata(LLVMContext::MD_invariant_group) &&
getLoadStorePointerOperand(U) == Ptr && !U->isVolatile()) {
MostDominatingInstruction = U;
}
// If we hit a load/store with an invariant.group metadata and the same
// pointer operand, we can assume that value pointed to by the pointer
// operand didn't change.
if (U->hasMetadata(LLVMContext::MD_invariant_group) &&
getLoadStorePointerOperand(U) == PointerOperand && !U->isVolatile()) {
MostDominatingInstruction = U;
}
}

return MostDominatingInstruction == &I ? nullptr : MostDominatingInstruction;
}

Expand Down
6 changes: 1 addition & 5 deletions llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
append_range(Worklist, Arg.users());
while (!Worklist.empty()) {
Value *V = Worklist.pop_back_val();
if (isa<BitCastInst>(V) || isa<GetElementPtrInst>(V)) {
if (isa<GetElementPtrInst>(V)) {
DeadInsts.push_back(cast<Instruction>(V));
append_range(Worklist, V->users());
continue;
Expand Down Expand Up @@ -608,10 +608,6 @@ static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR,
while (!Worklist.empty()) {
const Use *U = Worklist.pop_back_val();
Value *V = U->getUser();
if (isa<BitCastInst>(V)) {
AppendUses(V);
continue;
}

if (auto *GEP = dyn_cast<GetElementPtrInst>(V)) {
if (!GEP->hasAllConstantIndices())
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2327,8 +2327,8 @@ struct AANoFreeFloating : AANoFreeImpl {
DepClassTy::REQUIRED, IsKnown);
}

if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
if (isa<GetElementPtrInst>(UserI) || isa<PHINode>(UserI) ||
isa<SelectInst>(UserI)) {
Follow = true;
return true;
}
Expand Down
5 changes: 0 additions & 5 deletions llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,11 +481,6 @@ Constant *FunctionSpecializer::getPromotableAlloca(AllocaInst *Alloca,
// the usage in the CallInst, which is what we check here.
if (User == Call)
continue;
if (auto *Bitcast = dyn_cast<BitCastInst>(User)) {
if (!Bitcast->hasOneUse() || *Bitcast->user_begin() != Call)
return nullptr;
continue;
}

if (auto *Store = dyn_cast<StoreInst>(User)) {
// This is a duplicate store, bail out.
Expand Down
5 changes: 0 additions & 5 deletions llvm/lib/Transforms/IPO/GlobalOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,11 +1050,6 @@ valueIsOnlyUsedLocallyOrStoredToOneGlobal(const CallInst *CI,
continue; // Otherwise, storing through it, or storing into GV... fine.
}

if (auto *BCI = dyn_cast<BitCastInst>(U)) {
Worklist.push_back(BCI);
continue;
}

if (auto *GEPI = dyn_cast<GetElementPtrInst>(U)) {
Worklist.push_back(GEPI);
continue;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ static Type *getPromotedType(Type *Ty) {
/// requires a deeper change to allow either unread or unwritten objects.
static bool hasUndefSource(AnyMemTransferInst *MI) {
auto *Src = MI->getRawSource();
while (isa<GetElementPtrInst>(Src) || isa<BitCastInst>(Src)) {
while (isa<GetElementPtrInst>(Src)) {
if (!Src->hasOneUse())
return false;
Src = cast<Instruction>(Src)->getOperand(0);
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4707,8 +4707,7 @@ static bool SoleWriteToDeadLocal(Instruction *I, TargetLibraryInfo &TLI) {
pushUsers(*AI);
while (!AllocaUsers.empty()) {
auto *UserI = cast<Instruction>(AllocaUsers.pop_back_val());
if (isa<BitCastInst>(UserI) || isa<GetElementPtrInst>(UserI) ||
isa<AddrSpaceCastInst>(UserI)) {
if (isa<GetElementPtrInst>(UserI) || isa<AddrSpaceCastInst>(UserI)) {
pushUsers(*UserI);
continue;
}
Expand Down
7 changes: 1 addition & 6 deletions llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -980,12 +980,7 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
while (!srcUseList.empty()) {
User *U = srcUseList.pop_back_val();

if (isa<BitCastInst>(U) || isa<AddrSpaceCastInst>(U)) {
append_range(srcUseList, U->users());
continue;
}
if (const auto *G = dyn_cast<GetElementPtrInst>(U);
G && G->hasAllZeroIndices()) {
if (isa<AddrSpaceCastInst>(U)) {
append_range(srcUseList, U->users());
continue;
}
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/Transforms/Utils/GlobalStatus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,8 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
GS.StoredType = GlobalStatus::Stored;
}
}
} else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I) ||
isa<AddrSpaceCastInst>(I)) {
// Skip over bitcasts and GEPs; we don't care about the type or offset
} else if (isa<GetElementPtrInst>(I) || isa<AddrSpaceCastInst>(I)) {
// Skip over GEPs; we don't care about the type or offset
// of the pointer.
if (analyzeGlobalAux(I, GS, VisitedUsers))
return true;
Expand Down
4 changes: 0 additions & 4 deletions llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7652,10 +7652,6 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValu
}
}

// Look through bitcasts.
if (BitCastInst *BC = dyn_cast<BitCastInst>(Use))
return passingValueIsAlwaysUndefined(V, BC, PtrValueMayBeModified);

// Load from null is undefined.
if (LoadInst *LI = dyn_cast<LoadInst>(Use))
if (!LI->isVolatile())
Expand Down
14 changes: 6 additions & 8 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3139,12 +3139,10 @@ void LoopVectorizationCostModel::collectLoopScalars(ElementCount VF) {
return WideningDecision != CM_GatherScatter;
};

// A helper that returns true if the given value is a bitcast or
// getelementptr instruction contained in the loop.
auto isLoopVaryingBitCastOrGEP = [&](Value *V) {
return ((isa<BitCastInst>(V) && V->getType()->isPointerTy()) ||
isa<GetElementPtrInst>(V)) &&
!TheLoop->isLoopInvariant(V);
// A helper that returns true if the given value is a getelementptr
// instruction contained in the loop.
auto isLoopVaryingGEP = [&](Value *V) {
return isa<GetElementPtrInst>(V) && !TheLoop->isLoopInvariant(V);
};

// A helper that evaluates a memory access's use of a pointer. If the use will
Expand All @@ -3154,7 +3152,7 @@ void LoopVectorizationCostModel::collectLoopScalars(ElementCount VF) {
auto evaluatePtrUse = [&](Instruction *MemAccess, Value *Ptr) {
// We only care about bitcast and getelementptr instructions contained in
// the loop.
if (!isLoopVaryingBitCastOrGEP(Ptr))
if (!isLoopVaryingGEP(Ptr))
return;

// If the pointer has already been identified as scalar (e.g., if it was
Expand Down Expand Up @@ -3220,7 +3218,7 @@ void LoopVectorizationCostModel::collectLoopScalars(ElementCount VF) {
unsigned Idx = 0;
while (Idx != Worklist.size()) {
Instruction *Dst = Worklist[Idx++];
if (!isLoopVaryingBitCastOrGEP(Dst->getOperand(0)))
if (!isLoopVaryingGEP(Dst->getOperand(0)))
continue;
auto *Src = cast<Instruction>(Dst->getOperand(0));
if (llvm::all_of(Src->users(), [&](User *U) -> bool {
Expand Down

0 comments on commit f364b2e

Please sign in to comment.