Skip to content

Commit 4c12140

Browse files
committed
Add more constraints for handing multi-dimensional geps for global arrays
1 parent 269f0dd commit 4c12140

File tree

2 files changed

+99
-7
lines changed

2 files changed

+99
-7
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,6 +2997,43 @@ 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();
3005+
3006+
// First index must be constant zero (array base)
3007+
if (!isa<ConstantInt>(GEP.getOperand(1)) ||
3008+
!cast<ConstantInt>(GEP.getOperand(1))->isZero())
3009+
return false;
3010+
3011+
// Limit lowering for arrays with 3 or more dimensions
3012+
if (NumOps < 5)
3013+
return false;
3014+
3015+
// Check that it's arrays all the way
3016+
Type *CurTy = GEP.getSourceElementType();
3017+
unsigned NumVar = 0;
3018+
for (unsigned I = 2; I < NumOps; ++I) {
3019+
auto *ArrTy = dyn_cast<ArrayType>(CurTy);
3020+
if (!ArrTy)
3021+
return false;
3022+
if (!isa<ConstantInt>(GEP.getOperand(I)))
3023+
++NumVar;
3024+
CurTy = ArrTy->getElementType();
3025+
}
3026+
3027+
// Limit lowering only for one variable index
3028+
if (NumVar != 1)
3029+
return false;
3030+
3031+
if (!CurTy->isIntegerTy() || CurTy->getIntegerBitWidth() > 128)
3032+
return false;
3033+
3034+
return true;
3035+
}
3036+
30003037
/// Return true if we should canonicalize the gep to an i8 ptradd.
30013038
static bool shouldCanonicalizeGEPToPtrAdd(GetElementPtrInst &GEP) {
30023039
Value *PtrOp = GEP.getOperand(0);
@@ -3017,13 +3054,7 @@ static bool shouldCanonicalizeGEPToPtrAdd(GetElementPtrInst &GEP) {
30173054
m_Shl(m_Value(), m_ConstantInt())))))
30183055
return true;
30193056

3020-
// Flatten multidimensional GEPs with one variable index.
3021-
unsigned NumVarIndices = 0;
3022-
for (unsigned i = 1; i < GEP.getNumOperands(); ++i) {
3023-
if (!isa<ConstantInt>(GEP.getOperand(i)))
3024-
++NumVarIndices;
3025-
}
3026-
if (NumVarIndices == 1)
3057+
if (ismultiDimGep(GEP))
30273058
return true;
30283059

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

llvm/test/Transforms/InstCombine/canonicalize-gep-constglob.ll

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
33

44
@glob = internal global [10 x [10 x [10 x i32]]] zeroinitializer
5+
@glob_i8 = internal global [10 x [10 x [10 x i8]]] zeroinitializer
6+
@glob_i16 = internal global [10 x [10 x [10 x i16]]] zeroinitializer
7+
@glob_i64 = internal global [10 x [10 x [10 x i64]]] zeroinitializer
58

69
define ptr @x12(i64 %x) {
710
; CHECK-LABEL: define ptr @x12(
@@ -78,3 +81,61 @@ entry:
7881
%c = add i32 %a, %b
7982
ret i32 %c
8083
}
84+
85+
define i8* @flat_gep8(i64 %x) {
86+
; CHECK-LABEL: define ptr @flat_gep8(
87+
; CHECK-SAME: i64 [[X:%.*]]) {
88+
; CHECK-NEXT: entry:
89+
; CHECK-NEXT: [[GEP_IDX:%.*]] = mul i64 [[X]], 100
90+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr @glob_i8, i64 [[GEP_IDX]]
91+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 35
92+
; CHECK-NEXT: ret ptr [[GEP]]
93+
;
94+
entry:
95+
%gep = getelementptr [10 x [10 x [10 x i8]]], ptr @glob_i8, i64 0, i64 %x, i64 3, i64 5
96+
ret ptr %gep
97+
}
98+
99+
define i16* @flat_gep16(i64 %x) {
100+
; CHECK-LABEL: define ptr @flat_gep16(
101+
; CHECK-SAME: i64 [[X:%.*]]) {
102+
; CHECK-NEXT: entry:
103+
; CHECK-NEXT: [[GEP_IDX:%.*]] = mul i64 [[X]], 200
104+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr @glob_i16, i64 [[GEP_IDX]]
105+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 46
106+
; CHECK-NEXT: ret ptr [[GEP]]
107+
;
108+
entry:
109+
%gep = getelementptr [10 x [10 x [10 x i16]]], ptr @glob_i16, i64 0, i64 %x, i64 2, i64 3
110+
ret ptr %gep
111+
}
112+
113+
define i32* @flat_gep(i64 %x) {
114+
; CHECK-LABEL: define ptr @flat_gep(
115+
; CHECK-SAME: i64 [[X:%.*]]) {
116+
; CHECK-NEXT: entry:
117+
; CHECK-NEXT: [[GEP_IDX:%.*]] = mul i64 [[X]], 400
118+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr @glob, i64 [[GEP_IDX]]
119+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 100
120+
; CHECK-NEXT: ret ptr [[GEP]]
121+
;
122+
entry:
123+
%gep = getelementptr [10 x [10 x [10 x i32]]], ptr @glob, i64 0, i64 %x, i64 2, i64 5
124+
ret ptr %gep
125+
}
126+
127+
define i64* @flat_gep64(i64 %x) {
128+
; CHECK-LABEL: define ptr @flat_gep64(
129+
; CHECK-SAME: i64 [[X:%.*]]) {
130+
; CHECK-NEXT: entry:
131+
; CHECK-NEXT: [[GEP_IDX:%.*]] = mul i64 [[X]], 800
132+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr @glob_i64, i64 [[GEP_IDX]]
133+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 288
134+
; CHECK-NEXT: ret ptr [[GEP]]
135+
;
136+
entry:
137+
%gep = getelementptr [10 x [10 x [10 x i64]]], ptr @glob_i64, i64 0, i64 %x, i64 3, i64 6
138+
ret ptr %gep
139+
}
140+
141+

0 commit comments

Comments
 (0)