aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp58
1 files changed, 35 insertions, 23 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 7f5a7b666903..351fc3b0174f 100644
--- a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2469,31 +2469,43 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
DL.getIndexSizeInBits(AS)) {
uint64_t TyAllocSize = DL.getTypeAllocSize(GEPEltType).getFixedValue();
- bool Matched = false;
- uint64_t C;
- Value *V = nullptr;
if (TyAllocSize == 1) {
- V = GEP.getOperand(1);
- Matched = true;
- } else if (match(GEP.getOperand(1),
- m_AShr(m_Value(V), m_ConstantInt(C)))) {
- if (TyAllocSize == 1ULL << C)
- Matched = true;
- } else if (match(GEP.getOperand(1),
- m_SDiv(m_Value(V), m_ConstantInt(C)))) {
- if (TyAllocSize == C)
- Matched = true;
+ // Canonicalize (gep i8* X, (ptrtoint Y)-(ptrtoint X)) to (bitcast Y),
+ // but only if the result pointer is only used as if it were an integer,
+ // or both point to the same underlying object (otherwise provenance is
+ // not necessarily retained).
+ Value *X = GEP.getPointerOperand();
+ Value *Y;
+ if (match(GEP.getOperand(1),
+ m_Sub(m_PtrToInt(m_Value(Y)), m_PtrToInt(m_Specific(X)))) &&
+ GEPType == Y->getType()) {
+ bool HasSameUnderlyingObject =
+ getUnderlyingObject(X) == getUnderlyingObject(Y);
+ bool Changed = false;
+ GEP.replaceUsesWithIf(Y, [&](Use &U) {
+ bool ShouldReplace = HasSameUnderlyingObject ||
+ isa<ICmpInst>(U.getUser()) ||
+ isa<PtrToIntInst>(U.getUser());
+ Changed |= ShouldReplace;
+ return ShouldReplace;
+ });
+ return Changed ? &GEP : nullptr;
+ }
+ } else {
+ // Canonicalize (gep T* X, V / sizeof(T)) to (gep i8* X, V)
+ Value *V;
+ if ((has_single_bit(TyAllocSize) &&
+ match(GEP.getOperand(1),
+ m_Exact(m_AShr(m_Value(V),
+ m_SpecificInt(countr_zero(TyAllocSize)))))) ||
+ match(GEP.getOperand(1),
+ m_Exact(m_SDiv(m_Value(V), m_SpecificInt(TyAllocSize))))) {
+ GetElementPtrInst *NewGEP = GetElementPtrInst::Create(
+ Builder.getInt8Ty(), GEP.getPointerOperand(), V);
+ NewGEP->setIsInBounds(GEP.isInBounds());
+ return NewGEP;
+ }
}
-
- // Canonicalize (gep i8* X, (ptrtoint Y)-(ptrtoint X)) to (bitcast Y), but
- // only if both point to the same underlying object (otherwise provenance
- // is not necessarily retained).
- Value *Y;
- Value *X = GEP.getOperand(0);
- if (Matched &&
- match(V, m_Sub(m_PtrToInt(m_Value(Y)), m_PtrToInt(m_Specific(X)))) &&
- getUnderlyingObject(X) == getUnderlyingObject(Y))
- return CastInst::CreatePointerBitCastOrAddrSpaceCast(Y, GEPType);
}
}
// We do not handle pointer-vector geps here.