Skip to content

Commit c802dc2

Browse files
committed
LAA: clarify loop-variant GEP idx computation
The stripGetElementPtr function is mysteriously named, and calls into another mysterious getGEPInductionOperand which does something complicated with GEP indices. The real purpose of the badly-named stripGetElementPtr function is to get a loop-variant GEP index, if there is one. The getGEPInductionOperand is totally redundant, as stripping off zeros from the end of GEP indices has no effect on computing the loop-variant GEP index, as constant zeros are always loop-invariant. Moreover, the GEP induction operand is simply the first non-zero index from the end, which stripGetElementPtr returns when it finds that any of the GEP indices are loop-variant: this is a completely unrelated value to the GEP index that is loop-variant. The implicit assumption here is that there is only ever one loop-variant index, and it is the first non-zero one from the end. The logic is unnecessarily complicated for what stripGetElementPtr wants to achieve, and the header comments are confusing as well. Strip getGEPInductionOperand, rework and rename stripGetElementPtr.
1 parent c6b13a2 commit c802dc2

File tree

1 file changed

+15
-43
lines changed

1 file changed

+15
-43
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,12 @@
4242
#include "llvm/IR/DiagnosticInfo.h"
4343
#include "llvm/IR/Dominators.h"
4444
#include "llvm/IR/Function.h"
45-
#include "llvm/IR/GetElementPtrTypeIterator.h"
4645
#include "llvm/IR/InstrTypes.h"
4746
#include "llvm/IR/Instruction.h"
4847
#include "llvm/IR/Instructions.h"
48+
#include "llvm/IR/IntrinsicInst.h"
4949
#include "llvm/IR/Operator.h"
5050
#include "llvm/IR/PassManager.h"
51-
#include "llvm/IR/PatternMatch.h"
5251
#include "llvm/IR/Type.h"
5352
#include "llvm/IR/Value.h"
5453
#include "llvm/IR/ValueHandle.h"
@@ -66,7 +65,6 @@
6665
#include <vector>
6766

6867
using namespace llvm;
69-
using namespace llvm::PatternMatch;
7068

7169
#define DEBUG_TYPE "loop-accesses"
7270

@@ -2809,50 +2807,24 @@ bool LoopAccessInfo::isInvariant(Value *V) const {
28092807
return SE->isLoopInvariant(S, TheLoop);
28102808
}
28112809

2812-
/// Find the operand of the GEP that should be checked for consecutive
2813-
/// stores. This ignores trailing indices that have no effect on the final
2814-
/// pointer.
2815-
static unsigned getGEPInductionOperand(const GetElementPtrInst *Gep) {
2816-
const DataLayout &DL = Gep->getDataLayout();
2817-
unsigned LastOperand = Gep->getNumOperands() - 1;
2818-
TypeSize GEPAllocSize = DL.getTypeAllocSize(Gep->getResultElementType());
2819-
2820-
// Walk backwards and try to peel off zeros.
2821-
while (LastOperand > 1 && match(Gep->getOperand(LastOperand), m_Zero())) {
2822-
// Find the type we're currently indexing into.
2823-
gep_type_iterator GEPTI = gep_type_begin(Gep);
2824-
std::advance(GEPTI, LastOperand - 2);
2825-
2826-
// If it's a type with the same allocation size as the result of the GEP we
2827-
// can peel off the zero index.
2828-
TypeSize ElemSize = GEPTI.isStruct()
2829-
? DL.getTypeAllocSize(GEPTI.getIndexedType())
2830-
: GEPTI.getSequentialElementStride(DL);
2831-
if (ElemSize != GEPAllocSize)
2832-
break;
2833-
--LastOperand;
2834-
}
2835-
2836-
return LastOperand;
2837-
}
2838-
2839-
/// If the argument is a GEP, then returns the operand identified by
2840-
/// getGEPInductionOperand. However, if there is some other non-loop-invariant
2841-
/// operand, it returns that instead.
2842-
static Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp) {
2810+
/// If \p Ptr is a GEP, which has a loop-variant operand, return that operand.
2811+
/// Otherwise, return \p Ptr.
2812+
static Value *getLoopVariantGEPOperand(Value *Ptr, ScalarEvolution *SE,
2813+
Loop *Lp) {
28432814
auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
28442815
if (!GEP)
28452816
return Ptr;
28462817

2847-
unsigned InductionOperand = getGEPInductionOperand(GEP);
2818+
// There must be exactly one loop-variant operand.
2819+
if (count_if(GEP->operands(), [&](const Use &U) {
2820+
return !SE->isLoopInvariant(SE->getSCEV(U), Lp);
2821+
}) != 1)
2822+
return Ptr;
28482823

2849-
// Check that all of the gep indices are uniform except for our induction
2850-
// operand.
2851-
for (unsigned I = 0, E = GEP->getNumOperands(); I != E; ++I)
2852-
if (I != InductionOperand &&
2853-
!SE->isLoopInvariant(SE->getSCEV(GEP->getOperand(I)), Lp))
2854-
return Ptr;
2855-
return GEP->getOperand(InductionOperand);
2824+
auto *It = find_if(GEP->operands(), [&](const Use &U) {
2825+
return !SE->isLoopInvariant(SE->getSCEV(U), Lp);
2826+
});
2827+
return It->get();
28562828
}
28572829

28582830
/// Get the stride of a pointer access in a loop. Looks for symbolic
@@ -2867,7 +2839,7 @@ static const SCEV *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *L
28672839
// pointer, otherwise, we are analyzing the index.
28682840
Value *OrigPtr = Ptr;
28692841

2870-
Ptr = stripGetElementPtr(Ptr, SE, Lp);
2842+
Ptr = getLoopVariantGEPOperand(Ptr, SE, Lp);
28712843
const SCEV *V = SE->getSCEV(Ptr);
28722844

28732845
if (Ptr != OrigPtr)

0 commit comments

Comments
 (0)