[SCEV] Add initial support for ptrtoaddr. (#158032)
Add initial support for PtrToAddr to SCEV, including a new SCEVPtrToAddrExpr and SCEV expansion support for it. PR: https://github.com/llvm/llvm-project/pull/158032
This commit is contained in:
parent
e83021ab16
commit
3fb914d851
@ -574,6 +574,7 @@ public:
|
||||
LLVM_ABI const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
|
||||
LLVM_ABI const SCEV *getLosslessPtrToIntExpr(const SCEV *Op);
|
||||
|
||||
LLVM_ABI const SCEV *getPtrToAddrExpr(const SCEV *Op);
|
||||
LLVM_ABI const SCEV *getPtrToIntExpr(const SCEV *Op, Type *Ty);
|
||||
LLVM_ABI const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty,
|
||||
unsigned Depth = 0);
|
||||
|
||||
@ -46,6 +46,7 @@ public:
|
||||
|
||||
// Except in the trivial case described above, we do not know how to divide
|
||||
// Expr by Denominator for the following functions with empty implementation.
|
||||
void visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Numerator) {}
|
||||
void visitPtrToIntExpr(const SCEVPtrToIntExpr *Numerator) {}
|
||||
void visitTruncateExpr(const SCEVTruncateExpr *Numerator) {}
|
||||
void visitZeroExtendExpr(const SCEVZeroExtendExpr *Numerator) {}
|
||||
|
||||
@ -52,6 +52,7 @@ enum SCEVTypes : unsigned short {
|
||||
scUMinExpr,
|
||||
scSMinExpr,
|
||||
scSequentialUMinExpr,
|
||||
scPtrToAddr,
|
||||
scPtrToInt,
|
||||
scUnknown,
|
||||
scCouldNotCompute
|
||||
@ -121,8 +122,9 @@ public:
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scPtrToInt || S->getSCEVType() == scTruncate ||
|
||||
S->getSCEVType() == scZeroExtend || S->getSCEVType() == scSignExtend;
|
||||
return S->getSCEVType() == scPtrToAddr || S->getSCEVType() == scPtrToInt ||
|
||||
S->getSCEVType() == scTruncate || S->getSCEVType() == scZeroExtend ||
|
||||
S->getSCEVType() == scSignExtend;
|
||||
}
|
||||
};
|
||||
|
||||
@ -138,6 +140,18 @@ public:
|
||||
static bool classof(const SCEV *S) { return S->getSCEVType() == scPtrToInt; }
|
||||
};
|
||||
|
||||
/// This class represents a cast from a pointer to a pointer-sized integer
|
||||
/// value, without capturing the provenance of the pointer.
|
||||
class SCEVPtrToAddrExpr : public SCEVCastExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVPtrToAddrExpr(const FoldingSetNodeIDRef ID, const SCEV *Op, Type *ITy);
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static bool classof(const SCEV *S) { return S->getSCEVType() == scPtrToAddr; }
|
||||
};
|
||||
|
||||
/// This is the base class for unary integral cast operator classes.
|
||||
class SCEVIntegralCastExpr : public SCEVCastExpr {
|
||||
protected:
|
||||
@ -615,6 +629,8 @@ template <typename SC, typename RetVal = void> struct SCEVVisitor {
|
||||
return ((SC *)this)->visitConstant((const SCEVConstant *)S);
|
||||
case scVScale:
|
||||
return ((SC *)this)->visitVScale((const SCEVVScale *)S);
|
||||
case scPtrToAddr:
|
||||
return ((SC *)this)->visitPtrToAddrExpr((const SCEVPtrToAddrExpr *)S);
|
||||
case scPtrToInt:
|
||||
return ((SC *)this)->visitPtrToIntExpr((const SCEVPtrToIntExpr *)S);
|
||||
case scTruncate:
|
||||
@ -685,6 +701,7 @@ public:
|
||||
case scVScale:
|
||||
case scUnknown:
|
||||
continue;
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
@ -774,6 +791,11 @@ public:
|
||||
|
||||
const SCEV *visitVScale(const SCEVVScale *VScale) { return VScale; }
|
||||
|
||||
const SCEV *visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) {
|
||||
const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
|
||||
return Operand == Expr->getOperand() ? Expr : SE.getPtrToAddrExpr(Operand);
|
||||
}
|
||||
|
||||
const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
|
||||
const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
|
||||
return Operand == Expr->getOperand()
|
||||
|
||||
@ -498,6 +498,8 @@ private:
|
||||
|
||||
Value *visitVScale(const SCEVVScale *S);
|
||||
|
||||
Value *visitPtrToAddrExpr(const SCEVPtrToAddrExpr *S);
|
||||
|
||||
Value *visitPtrToIntExpr(const SCEVPtrToIntExpr *S);
|
||||
|
||||
Value *visitTruncateExpr(const SCEVTruncateExpr *S);
|
||||
|
||||
@ -343,6 +343,9 @@ private:
|
||||
SCEVMonotonicity visitMulExpr(const SCEVMulExpr *Expr) {
|
||||
return invariantOrUnknown(Expr);
|
||||
}
|
||||
SCEVMonotonicity visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) {
|
||||
return invariantOrUnknown(Expr);
|
||||
}
|
||||
SCEVMonotonicity visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
|
||||
return invariantOrUnknown(Expr);
|
||||
}
|
||||
|
||||
@ -277,11 +277,13 @@ void SCEV::print(raw_ostream &OS) const {
|
||||
case scVScale:
|
||||
OS << "vscale";
|
||||
return;
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt: {
|
||||
const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(this);
|
||||
const SCEV *Op = PtrToInt->getOperand();
|
||||
OS << "(ptrtoint " << *Op->getType() << " " << *Op << " to "
|
||||
<< *PtrToInt->getType() << ")";
|
||||
const SCEVCastExpr *PtrCast = cast<SCEVCastExpr>(this);
|
||||
const SCEV *Op = PtrCast->getOperand();
|
||||
StringRef OpS = getSCEVType() == scPtrToAddr ? "addr" : "int";
|
||||
OS << "(ptrto" << OpS << " " << *Op->getType() << " " << *Op << " to "
|
||||
<< *PtrCast->getType() << ")";
|
||||
return;
|
||||
}
|
||||
case scTruncate: {
|
||||
@ -386,6 +388,7 @@ Type *SCEV::getType() const {
|
||||
return cast<SCEVConstant>(this)->getType();
|
||||
case scVScale:
|
||||
return cast<SCEVVScale>(this)->getType();
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
@ -420,6 +423,7 @@ ArrayRef<const SCEV *> SCEV::operands() const {
|
||||
case scVScale:
|
||||
case scUnknown:
|
||||
return {};
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
@ -515,6 +519,13 @@ SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
|
||||
const SCEV *op, Type *ty)
|
||||
: SCEV(ID, SCEVTy, computeExpressionSize(op)), Op(op), Ty(ty) {}
|
||||
|
||||
SCEVPtrToAddrExpr::SCEVPtrToAddrExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *Op, Type *ITy)
|
||||
: SCEVCastExpr(ID, scPtrToAddr, Op, ITy) {
|
||||
assert(getOperand()->getType()->isPointerTy() && Ty->isIntegerTy() &&
|
||||
"Must be a non-bit-width-changing pointer-to-integer cast!");
|
||||
}
|
||||
|
||||
SCEVPtrToIntExpr::SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op,
|
||||
Type *ITy)
|
||||
: SCEVCastExpr(ID, scPtrToInt, Op, ITy) {
|
||||
@ -727,6 +738,7 @@ CompareSCEVComplexity(const LoopInfo *const LI, const SCEV *LHS,
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
@ -1113,6 +1125,40 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op) {
|
||||
return IntOp;
|
||||
}
|
||||
|
||||
const SCEV *ScalarEvolution::getPtrToAddrExpr(const SCEV *Op) {
|
||||
assert(Op->getType()->isPointerTy() && "Op must be a pointer");
|
||||
Type *Ty = DL.getAddressType(Op->getType());
|
||||
|
||||
FoldingSetNodeID ID;
|
||||
ID.AddInteger(scPtrToAddr);
|
||||
ID.AddPointer(Op);
|
||||
|
||||
void *IP = nullptr;
|
||||
|
||||
// Is there already an expression for such a cast?
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
|
||||
return S;
|
||||
|
||||
// If not, is this expression something we can't reduce any further?
|
||||
if (auto *U = dyn_cast<SCEVUnknown>(Op)) {
|
||||
// Perform some basic constant folding. If the operand of the ptr2addr cast
|
||||
// is a null pointer, don't create a ptr2addr SCEV expression (that will be
|
||||
// left as-is), but produce a zero constant.
|
||||
// NOTE: We could handle a more general case, but lack motivational cases.
|
||||
if (isa<ConstantPointerNull>(U->getValue()))
|
||||
return getZero(Ty);
|
||||
}
|
||||
|
||||
// Create an explicit cast node.
|
||||
// We can reuse the existing insert position since if we get here,
|
||||
// we won't have made any changes which would invalidate it.
|
||||
SCEV *S =
|
||||
new (SCEVAllocator) SCEVPtrToAddrExpr(ID.Intern(SCEVAllocator), Op, Ty);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
registerUser(S, Op);
|
||||
return S;
|
||||
}
|
||||
|
||||
const SCEV *ScalarEvolution::getPtrToIntExpr(const SCEV *Op, Type *Ty) {
|
||||
assert(Ty->isIntegerTy() && "Target type must be an integer type!");
|
||||
|
||||
@ -4068,6 +4114,8 @@ public:
|
||||
|
||||
RetVal visitVScale(const SCEVVScale *VScale) { return VScale; }
|
||||
|
||||
RetVal visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) { return Expr; }
|
||||
|
||||
RetVal visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) { return Expr; }
|
||||
|
||||
RetVal visitTruncateExpr(const SCEVTruncateExpr *Expr) { return Expr; }
|
||||
@ -4118,6 +4166,7 @@ static bool scevUnconditionallyPropagatesPoisonFromOperands(SCEVTypes Kind) {
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
@ -6347,8 +6396,9 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S,
|
||||
switch (S->getSCEVType()) {
|
||||
case scConstant:
|
||||
return cast<SCEVConstant>(S)->getAPInt();
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
return getConstantMultiple(cast<SCEVPtrToIntExpr>(S)->getOperand(), CtxI);
|
||||
return getConstantMultiple(cast<SCEVCastExpr>(S)->getOperand());
|
||||
case scUDivExpr:
|
||||
case scVScale:
|
||||
return APInt(BitWidth, 1);
|
||||
@ -6625,6 +6675,7 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
@ -6752,10 +6803,11 @@ const ConstantRange &ScalarEvolution::getRangeRef(
|
||||
SExt, SignHint,
|
||||
ConservativeResult.intersectWith(X.signExtend(BitWidth), RangeType));
|
||||
}
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt: {
|
||||
const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(S);
|
||||
ConstantRange X = getRangeRef(PtrToInt->getOperand(), SignHint, Depth + 1);
|
||||
return setRange(PtrToInt, SignHint, X);
|
||||
const SCEVCastExpr *Cast = cast<SCEVCastExpr>(S);
|
||||
ConstantRange X = getRangeRef(Cast->getOperand(), SignHint, Depth + 1);
|
||||
return setRange(Cast, SignHint, X);
|
||||
}
|
||||
case scAddExpr: {
|
||||
const SCEVAddExpr *Add = cast<SCEVAddExpr>(S);
|
||||
@ -7657,6 +7709,7 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
|
||||
case Instruction::Trunc:
|
||||
case Instruction::ZExt:
|
||||
case Instruction::SExt:
|
||||
case Instruction::PtrToAddr:
|
||||
case Instruction::PtrToInt:
|
||||
Ops.push_back(U->getOperand(0));
|
||||
return nullptr;
|
||||
@ -8129,6 +8182,9 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
|
||||
return getSCEV(U->getOperand(0));
|
||||
break;
|
||||
|
||||
case Instruction::PtrToAddr:
|
||||
return getPtrToAddrExpr(getSCEV(U->getOperand(0)));
|
||||
|
||||
case Instruction::PtrToInt: {
|
||||
// Pointer to integer cast is straight-forward, so do model it.
|
||||
const SCEV *Op = getSCEV(U->getOperand(0));
|
||||
@ -9937,6 +9993,13 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
|
||||
return cast<SCEVConstant>(V)->getValue();
|
||||
case scUnknown:
|
||||
return dyn_cast<Constant>(cast<SCEVUnknown>(V)->getValue());
|
||||
case scPtrToAddr: {
|
||||
const SCEVPtrToAddrExpr *P2I = cast<SCEVPtrToAddrExpr>(V);
|
||||
if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
|
||||
return ConstantExpr::getPtrToAddr(CastOp, P2I->getType());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
case scPtrToInt: {
|
||||
const SCEVPtrToIntExpr *P2I = cast<SCEVPtrToIntExpr>(V);
|
||||
if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
|
||||
@ -9995,6 +10058,7 @@ ScalarEvolution::getWithOperands(const SCEV *S,
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
return getCastExpr(S->getSCEVType(), NewOps[0], S->getType());
|
||||
case scAddRecExpr: {
|
||||
@ -10079,6 +10143,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
@ -14172,6 +14237,7 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
@ -14253,6 +14319,7 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
|
||||
@ -457,6 +457,7 @@ const Loop *SCEVExpander::getRelevantLoop(const SCEV *S) {
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
@ -1433,6 +1434,12 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
|
||||
return expand(T);
|
||||
}
|
||||
|
||||
Value *SCEVExpander::visitPtrToAddrExpr(const SCEVPtrToAddrExpr *S) {
|
||||
Value *V = expand(S->getOperand());
|
||||
return ReuseOrCreateCast(V, S->getType(), CastInst::PtrToAddr,
|
||||
GetOptimalInsertionPointForCastOf(V));
|
||||
}
|
||||
|
||||
Value *SCEVExpander::visitPtrToIntExpr(const SCEVPtrToIntExpr *S) {
|
||||
Value *V = expand(S->getOperand());
|
||||
return ReuseOrCreateCast(V, S->getType(), CastInst::PtrToInt,
|
||||
@ -1957,6 +1964,9 @@ template<typename T> static InstructionCost costAndCollectOperands(
|
||||
case scConstant:
|
||||
case scVScale:
|
||||
return 0;
|
||||
case scPtrToAddr:
|
||||
Cost = CastCost(Instruction::PtrToAddr);
|
||||
break;
|
||||
case scPtrToInt:
|
||||
Cost = CastCost(Instruction::PtrToInt);
|
||||
break;
|
||||
@ -2080,6 +2090,7 @@ bool SCEVExpander::isHighCostExpansionHelper(
|
||||
return Cost > Budget;
|
||||
}
|
||||
case scTruncate:
|
||||
case scPtrToAddr:
|
||||
case scPtrToInt:
|
||||
case scZeroExtend:
|
||||
case scSignExtend: {
|
||||
|
||||
@ -7,7 +7,7 @@ define void @ptrtoaddr(ptr %in, ptr %out0) {
|
||||
; CHECK-LABEL: 'ptrtoaddr'
|
||||
; CHECK-NEXT: Classifying expressions for: @ptrtoaddr
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr %in to i32
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr %in to i32) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr
|
||||
;
|
||||
%p0 = ptrtoaddr ptr %in to i32
|
||||
@ -19,7 +19,7 @@ define void @ptrtoaddr_as1(ptr addrspace(1) %in, ptr %out0) {
|
||||
; CHECK-LABEL: 'ptrtoaddr_as1'
|
||||
; CHECK-NEXT: Classifying expressions for: @ptrtoaddr_as1
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr addrspace(1) %in to i32
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr addrspace(1) %in to i32) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_as1
|
||||
;
|
||||
%p0 = ptrtoaddr ptr addrspace(1) %in to i32
|
||||
@ -33,7 +33,7 @@ define void @ptrtoaddr_of_bitcast(ptr %in, ptr %out0) {
|
||||
; CHECK-NEXT: %in_casted = bitcast ptr %in to ptr
|
||||
; CHECK-NEXT: --> %in U: full-set S: full-set
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr %in_casted to i32
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr %in to i32) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_of_bitcast
|
||||
;
|
||||
%in_casted = bitcast ptr %in to ptr
|
||||
@ -46,7 +46,7 @@ define void @ptrtoaddr_of_nullptr(ptr %out0) {
|
||||
; CHECK-LABEL: 'ptrtoaddr_of_nullptr'
|
||||
; CHECK-NEXT: Classifying expressions for: @ptrtoaddr_of_nullptr
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr null to i32
|
||||
; CHECK-NEXT: --> %p0 U: [0,1) S: [0,1)
|
||||
; CHECK-NEXT: --> 0 U: [0,1) S: [0,1)
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_of_nullptr
|
||||
;
|
||||
%p0 = ptrtoaddr ptr null to i32
|
||||
@ -60,7 +60,7 @@ define void @ptrtoaddr_of_gep(ptr %in, ptr %out0) {
|
||||
; CHECK-NEXT: %in_adj = getelementptr inbounds i8, ptr %in, i64 42
|
||||
; CHECK-NEXT: --> (42 + %in) U: full-set S: full-set
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr %in_adj to i32
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr (42 + %in) to i32) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_of_gep
|
||||
;
|
||||
%in_adj = getelementptr inbounds i8, ptr %in, i64 42
|
||||
|
||||
@ -7,7 +7,7 @@ define void @ptrtoaddr(ptr %in, ptr %out0, ptr %out1, ptr %out2, ptr %out3) {
|
||||
; CHECK-LABEL: 'ptrtoaddr'
|
||||
; CHECK-NEXT: Classifying expressions for: @ptrtoaddr
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr %in to i64
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr %in to i64) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr
|
||||
;
|
||||
%p0 = ptrtoaddr ptr %in to i64
|
||||
@ -19,7 +19,7 @@ define void @ptrtoaddr_as1(ptr addrspace(1) %in, ptr %out0, ptr %out1, ptr %out2
|
||||
; CHECK-LABEL: 'ptrtoaddr_as1'
|
||||
; CHECK-NEXT: Classifying expressions for: @ptrtoaddr_as1
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr addrspace(1) %in to i64
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr addrspace(1) %in to i64) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_as1
|
||||
;
|
||||
%p0 = ptrtoaddr ptr addrspace(1) %in to i64
|
||||
@ -33,7 +33,7 @@ define void @ptrtoaddr_of_bitcast(ptr %in, ptr %out0) {
|
||||
; CHECK-NEXT: %in_casted = bitcast ptr %in to ptr
|
||||
; CHECK-NEXT: --> %in U: full-set S: full-set
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr %in_casted to i64
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr %in to i64) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_of_bitcast
|
||||
;
|
||||
%in_casted = bitcast ptr %in to ptr
|
||||
@ -46,7 +46,7 @@ define void @ptrtoaddr_of_nullptr(ptr %out0) {
|
||||
; CHECK-LABEL: 'ptrtoaddr_of_nullptr'
|
||||
; CHECK-NEXT: Classifying expressions for: @ptrtoaddr_of_nullptr
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr null to i64
|
||||
; CHECK-NEXT: --> %p0 U: [0,1) S: [0,1)
|
||||
; CHECK-NEXT: --> 0 U: [0,1) S: [0,1)
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_of_nullptr
|
||||
;
|
||||
%p0 = ptrtoaddr ptr null to i64
|
||||
@ -60,7 +60,7 @@ define void @ptrtoaddr_of_gep(ptr %in, ptr %out0) {
|
||||
; CHECK-NEXT: %in_adj = getelementptr inbounds i8, ptr %in, i64 42
|
||||
; CHECK-NEXT: --> (42 + %in) U: full-set S: full-set
|
||||
; CHECK-NEXT: %p0 = ptrtoaddr ptr %in_adj to i64
|
||||
; CHECK-NEXT: --> %p0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (ptrtoaddr ptr (42 + %in) to i64) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @ptrtoaddr_of_gep
|
||||
;
|
||||
%in_adj = getelementptr inbounds i8, ptr %in, i64 42
|
||||
|
||||
47
llvm/test/Transforms/LoopVectorize/expand-ptrtoaddr.ll
Normal file
47
llvm/test/Transforms/LoopVectorize/expand-ptrtoaddr.ll
Normal file
@ -0,0 +1,47 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --filter-out-after "scalar.ph:" --version 6
|
||||
; RUN: opt -p loop-vectorize -force-vector-width=4 -S %s | FileCheck %s
|
||||
|
||||
define void @test_ptrtoaddr_tripcount(ptr %start, ptr %end) {
|
||||
; CHECK-LABEL: define void @test_ptrtoaddr_tripcount(
|
||||
; CHECK-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: [[START_ADDR:%.*]] = ptrtoaddr ptr [[START]] to i64
|
||||
; CHECK-NEXT: [[END_ADDR:%.*]] = ptrtoaddr ptr [[END]] to i64
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[END_ADDR]], 1
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[START_ADDR]]
|
||||
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 4
|
||||
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
|
||||
; CHECK: [[VECTOR_PH]]:
|
||||
; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4
|
||||
; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[N_MOD_VF]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[START_ADDR]], [[N_VEC]]
|
||||
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
|
||||
; CHECK: [[VECTOR_BODY]]:
|
||||
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
|
||||
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i64 [[START_ADDR]], [[INDEX]]
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 [[OFFSET_IDX]]
|
||||
; CHECK-NEXT: store <4 x i8> zeroinitializer, ptr [[TMP3]], align 1
|
||||
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; CHECK-NEXT: br i1 [[TMP4]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
|
||||
; CHECK: [[MIDDLE_BLOCK]]:
|
||||
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP1]], [[N_VEC]]
|
||||
; CHECK-NEXT: br i1 [[CMP_N]], [[EXIT:label %.*]], label %[[SCALAR_PH]]
|
||||
; CHECK: [[SCALAR_PH]]:
|
||||
;
|
||||
entry:
|
||||
%start.addr = ptrtoaddr ptr %start to i64
|
||||
%end.addr = ptrtoaddr ptr %end to i64
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%iv = phi i64 [ %start.addr, %entry ], [ %iv.next, %loop ]
|
||||
%gep = getelementptr inbounds i8, ptr %start, i64 %iv
|
||||
store i8 0, ptr %gep
|
||||
%iv.next = add i64 %iv, 1
|
||||
%cmp = icmp ne i64 %iv, %end.addr
|
||||
br i1 %cmp, label %loop, label %exit
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
@ -100,6 +100,7 @@ private:
|
||||
PWACtx visit(const llvm::SCEV *E);
|
||||
PWACtx visitConstant(const llvm::SCEVConstant *E);
|
||||
PWACtx visitVScale(const llvm::SCEVVScale *E);
|
||||
PWACtx visitPtrToAddrExpr(const llvm::SCEVPtrToAddrExpr *E);
|
||||
PWACtx visitPtrToIntExpr(const llvm::SCEVPtrToIntExpr *E);
|
||||
PWACtx visitTruncateExpr(const llvm::SCEVTruncateExpr *E);
|
||||
PWACtx visitZeroExtendExpr(const llvm::SCEVZeroExtendExpr *E);
|
||||
|
||||
@ -271,6 +271,10 @@ PWACtx SCEVAffinator::visitVScale(const SCEVVScale *VScale) {
|
||||
llvm_unreachable("SCEVVScale not yet supported");
|
||||
}
|
||||
|
||||
PWACtx SCEVAffinator::visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) {
|
||||
return visit(Expr->getOperand(0));
|
||||
}
|
||||
|
||||
PWACtx SCEVAffinator::visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
|
||||
return visit(Expr->getOperand(0));
|
||||
}
|
||||
|
||||
@ -156,6 +156,10 @@ public:
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
}
|
||||
|
||||
ValidatorResult visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) {
|
||||
return visit(Expr->getOperand());
|
||||
}
|
||||
|
||||
ValidatorResult visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
|
||||
return visit(Expr->getOperand());
|
||||
}
|
||||
|
||||
@ -367,6 +367,9 @@ private:
|
||||
///{
|
||||
const SCEV *visitConstant(const SCEVConstant *E) { return E; }
|
||||
const SCEV *visitVScale(const SCEVVScale *E) { return E; }
|
||||
const SCEV *visitPtrToAddrExpr(const SCEVPtrToAddrExpr *E) {
|
||||
return GenSE.getPtrToAddrExpr(visit(E->getOperand()));
|
||||
}
|
||||
const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *E) {
|
||||
return GenSE.getPtrToIntExpr(visit(E->getOperand()), E->getType());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user