[llvm] [InstCombine] Fold chained GEP with constant base into single GEP (PR #170439)
Jianjian Guan via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 11 22:23:07 PST 2025
================
@@ -2803,6 +2803,51 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
if (Src->getResultElementType() != GEP.getSourceElementType())
return nullptr;
+ // Fold chained GEP with constant base into single GEP:
+ // gep i8, (gep i8, %base, C1), (select Cond, C2, C3)
+ // -> gep i8, %base, (select Cond, C1+C2, C1+C3)
+ if (GEP.getNumIndices() == 1 && Src->getNumIndices() == 1) {
+ Value *SrcIdx = *Src->idx_begin();
+ Value *GEPIdx = *GEP.idx_begin();
+ const APInt *ConstOffset, *TrueVal, *FalseVal;
+ Value *Cond;
+
+ if ((match(SrcIdx, m_APInt(ConstOffset)) &&
+ match(GEPIdx,
+ m_Select(m_Value(Cond), m_APInt(TrueVal), m_APInt(FalseVal)))) ||
+ (match(GEPIdx, m_APInt(ConstOffset)) &&
+ match(SrcIdx,
+ m_Select(m_Value(Cond), m_APInt(TrueVal), m_APInt(FalseVal))))) {
+ auto *Select = isa<SelectInst>(GEPIdx) ? cast<SelectInst>(GEPIdx)
+ : cast<SelectInst>(SrcIdx);
+
+ // Make sure the select has only one use.
+ if (!Select->hasOneUse())
+ return nullptr;
+
+ if (TrueVal->getBitWidth() != ConstOffset->getBitWidth() ||
+ FalseVal->getBitWidth() != ConstOffset->getBitWidth())
+ return nullptr;
+
+ APInt NewTrueVal = *ConstOffset + *TrueVal;
+ APInt NewFalseVal = *ConstOffset + *FalseVal;
+ Constant *NewTrue = Builder.getInt(NewTrueVal);
+ Constant *NewFalse = Builder.getInt(NewFalseVal);
+ // Consider vector splat.
+ if (auto *VT = dyn_cast<VectorType>(Select->getType())) {
+ NewTrue = ConstantVector::getSplat(VT->getElementCount(), NewTrue);
+ NewFalse = ConstantVector::getSplat(VT->getElementCount(), NewFalse);
+ }
----------------
jacquesguan wrote:
Changed.
https://github.com/llvm/llvm-project/pull/170439
More information about the llvm-commits
mailing list