[llvm] [AggressiveInstCombine] Make cttz fold more resiliant to non-array geps (PR #150896)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 29 01:21:56 PDT 2025
================
@@ -547,53 +536,53 @@ static bool tryToRecognizeTableBasedCttz(Instruction &I) {
return false;
GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(LI->getPointerOperand());
- if (!GEP || !GEP->hasNoUnsignedSignedWrap() || GEP->getNumIndices() != 2)
- return false;
-
- if (!GEP->getSourceElementType()->isArrayTy())
+ if (!GEP || !GEP->hasNoUnsignedSignedWrap())
return false;
- uint64_t ArraySize = GEP->getSourceElementType()->getArrayNumElements();
- if (ArraySize != 32 && ArraySize != 64)
+ Type *GEPSrcEltTy = GEP->getSourceElementType();
+ Value *GepIdx;
+ if (GEP->getNumIndices() == 2) {
+ if (!GEPSrcEltTy->isArrayTy() ||
+ !match(GEP->idx_begin()->get(), m_ZeroInt()))
+ return false;
+ GEPSrcEltTy = GEPSrcEltTy->getArrayElementType();
+ GepIdx = std::next(GEP->idx_begin())->get();
+ } else if (GEP->getNumIndices() == 1)
+ GepIdx = GEP->idx_begin()->get();
+ else
return false;
GlobalVariable *GVTable = dyn_cast<GlobalVariable>(GEP->getPointerOperand());
if (!GVTable || !GVTable->hasInitializer() || !GVTable->isConstant())
return false;
- ConstantDataArray *ConstData =
- dyn_cast<ConstantDataArray>(GVTable->getInitializer());
- if (!ConstData)
- return false;
-
- if (!match(GEP->idx_begin()->get(), m_ZeroInt()))
- return false;
-
- Value *Idx2 = std::next(GEP->idx_begin())->get();
Value *X1;
- uint64_t MulConst, ShiftConst;
+ uint64_t MulConst, ShiftConst, AndCst = ~0ull;
// FIXME: 64-bit targets have `i64` type for the GEP index, so this match will
// probably fail for other (e.g. 32-bit) targets.
- if (!match(Idx2, m_ZExtOrSelf(
- m_LShr(m_Mul(m_c_And(m_Neg(m_Value(X1)), m_Deferred(X1)),
- m_ConstantInt(MulConst)),
- m_ConstantInt(ShiftConst)))))
+ if (!match(GepIdx, m_ZExtOrSelf(m_LShr(
+ m_Mul(m_c_And(m_Neg(m_Value(X1)), m_Deferred(X1)),
+ m_ConstantInt(MulConst)),
+ m_ConstantInt(ShiftConst)))) &&
+ !match(GepIdx, m_ZExtOrSelf(m_And(m_LShr(m_Mul(m_c_And(m_Neg(m_Value(X1)),
+ m_Deferred(X1)),
+ m_ConstantInt(MulConst)),
+ m_ConstantInt(ShiftConst)),
+ m_ConstantInt(AndCst)))))
----------------
nikic wrote:
To check my understanding, the reason for this new case is that for an i8 gep the shift + multiply ends up canonicalizing to an and?
Might make sense to store the inner shift pattern in a variable to avoid repeating it.
https://github.com/llvm/llvm-project/pull/150896
More information about the llvm-commits
mailing list