Skip to content

Commit 82e440d

Browse files
committed
Handle Nested gep with one variable index in the outer gep
1 parent 4c12140 commit 82e440d

File tree

1 file changed

+46
-11
lines changed

1 file changed

+46
-11
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,29 +2997,64 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
29972997
return nullptr;
29982998
}
29992999

3000-
/// Return true if we should lower multi-dimensional geps
3001-
static bool ismultiDimGep(GetElementPtrInst &GEP) {
3002-
// Limit handling to only 3D and 4D arrays with integer types.
3003-
// getelementptr [9 x [9 x [9 x i32]]], ptr @arr, i64 0, i64 %i, i64 2, i64 3
3004-
unsigned NumOps = GEP.getNumOperands();
3000+
/// Accumulate constant indices from GEPs with all-constant indices, then
3001+
/// check if the outermost GEP (with one variable index) is flattenable.
3002+
/// Matches and returns true for multi-dimensional array geps with only one
3003+
/// variable index. The pointer could also be another gep with all constant
3004+
/// indices. For ex:
3005+
/// -getelementptr [9 x [9 x [9 x i32]]], ptr @arr, i64 0, i64 %i, i64 2, i64 3
3006+
/// -getelementptr [9 x [9 x [9 x i32]]],
3007+
/// <another gep>, i64 0, i64 %i, i64 2, i64 3
3008+
static bool ismultiDimGepFlattenable(const GetElementPtrInst &GEP) {
3009+
// Collect all indices, outermost last
3010+
SmallVector<const GEPOperator *, 4> GEPChain;
3011+
const Value *Base = &GEP;
3012+
3013+
// Go over GEPs with all constant indices
3014+
while (auto *CurGep = dyn_cast<GEPOperator>(Base)) {
3015+
bool AllConst = true;
3016+
for (unsigned I = 1; I < CurGep->getNumOperands(); ++I)
3017+
if (!isa<ConstantInt>(CurGep->getOperand(I)))
3018+
AllConst = false;
3019+
if (!AllConst)
3020+
break;
3021+
GEPChain.push_back(CurGep);
3022+
Base = CurGep->getOperand(0)->stripPointerCasts();
3023+
}
3024+
3025+
// Accumulate all indices from innermost to outermost
3026+
SmallVector<Value *, 8> Indices;
3027+
for (int I = GEPChain.size() - 1; I >= 0; --I) {
3028+
const GEPOperator *GO = GEPChain[I];
3029+
for (unsigned J = 1; J < GO->getNumOperands(); ++J)
3030+
Indices.push_back(GO->getOperand(J));
3031+
}
3032+
3033+
// Add indices from the main GEP (skip pointer operand)
3034+
for (unsigned J = 1; J < GEP.getNumOperands(); ++J)
3035+
Indices.push_back(GEP.getOperand(J));
3036+
3037+
if (Indices.empty())
3038+
return false;
30053039

30063040
// First index must be constant zero (array base)
3007-
if (!isa<ConstantInt>(GEP.getOperand(1)) ||
3008-
!cast<ConstantInt>(GEP.getOperand(1))->isZero())
3041+
if (!isa<ConstantInt>(Indices[0]) || !cast<ConstantInt>(Indices[0])->isZero())
30093042
return false;
30103043

3044+
unsigned NumDims = Indices.size() - 1;
3045+
30113046
// Limit lowering for arrays with 3 or more dimensions
3012-
if (NumOps < 5)
3047+
if (NumDims < 3)
30133048
return false;
30143049

30153050
// Check that it's arrays all the way
30163051
Type *CurTy = GEP.getSourceElementType();
30173052
unsigned NumVar = 0;
3018-
for (unsigned I = 2; I < NumOps; ++I) {
3053+
for (unsigned I = 1; I < Indices.size(); ++I) {
30193054
auto *ArrTy = dyn_cast<ArrayType>(CurTy);
30203055
if (!ArrTy)
30213056
return false;
3022-
if (!isa<ConstantInt>(GEP.getOperand(I)))
3057+
if (!isa<ConstantInt>(Indices[I]))
30233058
++NumVar;
30243059
CurTy = ArrTy->getElementType();
30253060
}
@@ -3054,7 +3089,7 @@ static bool shouldCanonicalizeGEPToPtrAdd(GetElementPtrInst &GEP) {
30543089
m_Shl(m_Value(), m_ConstantInt())))))
30553090
return true;
30563091

3057-
if (ismultiDimGep(GEP))
3092+
if (ismultiDimGepFlattenable(GEP))
30583093
return true;
30593094

30603095
// gep (gep %p, C1), %x, C2 is expanded so the two constants can

0 commit comments

Comments
 (0)