InstSimplify: Simplify trivial pointer expressions like b + (e - b)
consider:
long long *f(long long *b, long long *e) {
return b + (e - b);
}
we would lower this to something like:
define i64* @f(i64* %b, i64* %e) {
%1 = ptrtoint i64* %e to i64
%2 = ptrtoint i64* %b to i64
%3 = sub i64 %1, %2
%4 = ashr exact i64 %3, 3
%5 = getelementptr inbounds i64* %b, i64 %4
ret i64* %5
}
This should fold away to just 'e'.
N.B. This adds m_SpecificInt as a convenient way to match against a
particular 64-bit integer when using LLVM's match interface.
llvm-svn: 216439
This commit is contained in:
@@ -2783,6 +2783,7 @@ Value *llvm::SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||
static Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const Query &Q, unsigned) {
|
||||
// The type of the GEP pointer operand.
|
||||
PointerType *PtrTy = cast<PointerType>(Ops[0]->getType()->getScalarType());
|
||||
unsigned AS = PtrTy->getAddressSpace();
|
||||
|
||||
// getelementptr P -> P.
|
||||
if (Ops.size() == 1)
|
||||
@@ -2791,7 +2792,7 @@ static Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const Query &Q, unsigned) {
|
||||
if (isa<UndefValue>(Ops[0])) {
|
||||
// Compute the (pointer) type returned by the GEP instruction.
|
||||
Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, Ops.slice(1));
|
||||
Type *GEPTy = PointerType::get(LastType, PtrTy->getAddressSpace());
|
||||
Type *GEPTy = PointerType::get(LastType, AS);
|
||||
if (VectorType *VT = dyn_cast<VectorType>(Ops[0]->getType()))
|
||||
GEPTy = VectorType::get(GEPTy, VT->getNumElements());
|
||||
return UndefValue::get(GEPTy);
|
||||
@@ -2801,11 +2802,41 @@ static Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const Query &Q, unsigned) {
|
||||
// getelementptr P, 0 -> P.
|
||||
if (match(Ops[1], m_Zero()))
|
||||
return Ops[0];
|
||||
// getelementptr P, N -> P if P points to a type of zero size.
|
||||
if (Q.DL) {
|
||||
Type *Ty = PtrTy->getElementType();
|
||||
if (Ty->isSized() && Q.DL->getTypeAllocSize(Ty) == 0)
|
||||
|
||||
Type *Ty = PtrTy->getElementType();
|
||||
if (Q.DL && Ty->isSized()) {
|
||||
Value *P;
|
||||
uint64_t C;
|
||||
uint64_t TyAllocSize = Q.DL->getTypeAllocSize(Ty);
|
||||
// getelementptr P, N -> P if P points to a type of zero size.
|
||||
if (TyAllocSize == 0)
|
||||
return Ops[0];
|
||||
|
||||
// The following transforms are only safe if the ptrtoint cast
|
||||
// doesn't truncate the pointers.
|
||||
if (Ops[1]->getType()->getScalarSizeInBits() ==
|
||||
Q.DL->getPointerSizeInBits(AS)) {
|
||||
// getelementptr P, (sub Q, P) -> Q if P points to a type of size 1.
|
||||
if (TyAllocSize == 1 &&
|
||||
match(Ops[1], m_Sub(m_PtrToInt(m_Value(P)),
|
||||
m_PtrToInt(m_Specific(Ops[0])))))
|
||||
return P;
|
||||
|
||||
// getelementptr P, (ashr (sub Q, P), C) -> Q
|
||||
// if P points to a type of size 1 << C.
|
||||
if (match(Ops[1], m_AShr(m_Sub(m_PtrToInt(m_Value(P)),
|
||||
m_PtrToInt(m_Specific(Ops[0]))),
|
||||
m_ConstantInt(C))) &&
|
||||
TyAllocSize == 1ULL << C)
|
||||
return P;
|
||||
|
||||
// getelementptr P, (sdiv (sub Q, P), C) -> Q
|
||||
// if P points to a type of size C.
|
||||
if (match(Ops[1], m_SDiv(m_Sub(m_PtrToInt(m_Value(P)),
|
||||
m_PtrToInt(m_Specific(Ops[0]))),
|
||||
m_SpecificInt(TyAllocSize))))
|
||||
return P;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user