Skip to content

Commit

Permalink
[SCEVExpander] Reuse removePointerBase() for canonical addrecs
Browse files Browse the repository at this point in the history
ExposePointerBase() in SCEVExpander implements basically the same
functionality as removePointerBase() in SCEV, so reuse it.

The SCEVExpander code assumes that the pointer operand on adds is
the last one -- I'm not sure that always holds. As such this might
not be strictly NFC.
  • Loading branch information
nikic committed Aug 29, 2021
1 parent 204b290 commit 9f78737
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 44 deletions.
3 changes: 3 additions & 0 deletions llvm/include/llvm/Analysis/ScalarEvolution.h
Expand Up @@ -704,6 +704,9 @@ class ScalarEvolution {
/// cases do exist.
const SCEV *getPointerBase(const SCEV *V);

/// Compute an expression equivalent to S - getPointerBase(S).
const SCEV *removePointerBase(const SCEV *S);

/// Return a SCEV expression for the specified value at the specified scope
/// in the program. The L value specifies a loop nest to evaluate the
/// expression at, where null is the top-level or a specified loop is
Expand Down
17 changes: 8 additions & 9 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Expand Up @@ -4154,17 +4154,16 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) {
return getMinusSCEV(getMinusOne(Ty), V);
}

/// Compute an expression equivalent to S - getPointerBase(S).
static const SCEV *removePointerBase(ScalarEvolution *SE, const SCEV *P) {
const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
assert(P->getType()->isPointerTy());

if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(P)) {
// The base of an AddRec is the first operand.
SmallVector<const SCEV *> Ops{AddRec->operands()};
Ops[0] = removePointerBase(SE, Ops[0]);
Ops[0] = removePointerBase(Ops[0]);
// Don't try to transfer nowrap flags for now. We could in some cases
// (for example, if pointer operand of the AddRec is a SCEVUnknown).
return SE->getAddRecExpr(Ops, AddRec->getLoop(), SCEV::FlagAnyWrap);
return getAddRecExpr(Ops, AddRec->getLoop(), SCEV::FlagAnyWrap);
}
if (auto *Add = dyn_cast<SCEVAddExpr>(P)) {
// The base of an Add is the pointer operand.
Expand All @@ -4176,13 +4175,13 @@ static const SCEV *removePointerBase(ScalarEvolution *SE, const SCEV *P) {
PtrOp = &AddOp;
}
}
*PtrOp = removePointerBase(SE, *PtrOp);
*PtrOp = removePointerBase(*PtrOp);
// Don't try to transfer nowrap flags for now. We could in some cases
// (for example, if the pointer operand of the Add is a SCEVUnknown).
return SE->getAddExpr(Ops);
return getAddExpr(Ops);
}
// Any other expression must be a pointer base.
return SE->getZero(P->getType());
return getZero(P->getType());
}

const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
Expand All @@ -4199,8 +4198,8 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
if (!LHS->getType()->isPointerTy() ||
getPointerBase(LHS) != getPointerBase(RHS))
return getCouldNotCompute();
LHS = removePointerBase(this, LHS);
RHS = removePointerBase(this, RHS);
LHS = removePointerBase(LHS);
RHS = removePointerBase(RHS);
}

// We represent LHS - RHS as LHS + (-1)*RHS. This transformation
Expand Down
41 changes: 6 additions & 35 deletions llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
Expand Up @@ -917,28 +917,6 @@ Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) {
/*IsSafeToHoist*/ SE.isKnownNonZero(S->getRHS()));
}

/// Move parts of Base into Rest to leave Base with the minimal
/// expression that provides a pointer operand suitable for a
/// GEP expansion.
static void ExposePointerBase(const SCEV *&Base, const SCEV *&Rest,
ScalarEvolution &SE) {
while (const SCEVAddRecExpr *A = dyn_cast<SCEVAddRecExpr>(Base)) {
Base = A->getStart();
Rest = SE.getAddExpr(Rest,
SE.getAddRecExpr(SE.getConstant(A->getType(), 0),
A->getStepRecurrence(SE),
A->getLoop(),
A->getNoWrapFlags(SCEV::FlagNW)));
}
if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(Base)) {
Base = A->getOperand(A->getNumOperands()-1);
SmallVector<const SCEV *, 8> NewAddOps(A->operands());
NewAddOps.back() = Rest;
Rest = SE.getAddExpr(NewAddOps);
ExposePointerBase(Base, Rest, SE);
}
}

/// Determine if this is a well-behaved chain of instructions leading back to
/// the PHI. If so, it may be reused by expanded expressions.
bool SCEVExpander::isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV,
Expand Down Expand Up @@ -1568,24 +1546,17 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {

// {X,+,F} --> X + {0,+,F}
if (!S->getStart()->isZero()) {
if (PointerType *PTy = dyn_cast<PointerType>(S->getType())) {
Value *StartV = expand(SE.getPointerBase(S));
assert(StartV->getType() == PTy && "Pointer type mismatch for GEP!");
return expandAddToGEP(SE.removePointerBase(S), PTy, Ty, StartV);
}

SmallVector<const SCEV *, 4> NewOps(S->operands());
NewOps[0] = SE.getConstant(Ty, 0);
const SCEV *Rest = SE.getAddRecExpr(NewOps, L,
S->getNoWrapFlags(SCEV::FlagNW));

// Turn things like ptrtoint+arithmetic+inttoptr into GEP. See the
// comments on expandAddToGEP for details.
const SCEV *Base = S->getStart();
// Dig into the expression to find the pointer base for a GEP.
const SCEV *ExposedRest = Rest;
ExposePointerBase(Base, ExposedRest, SE);
// If we found a pointer, expand the AddRec with a GEP.
if (PointerType *PTy = dyn_cast<PointerType>(Base->getType())) {
Value *StartV = expand(Base);
assert(StartV->getType() == PTy && "Pointer type mismatch for GEP!");
return expandAddToGEP(ExposedRest, PTy, Ty, StartV);
}

// Just do a normal add. Pre-expand the operands to suppress folding.
//
// The LHS and RHS values are factored out of the expand call to make the
Expand Down

0 comments on commit 9f78737

Please sign in to comment.