Skip to content

Commit 4ada34b

Browse files
committed
Add more constraints for handing multi-dimensional geps for global arrays
1 parent fbd143d commit 4ada34b

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
@@ -2975,6 +2975,43 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
29752975
return nullptr;
29762976
}
29772977

2978+
/// Return true if we should lower multi-dimensional geps
2979+
static bool ismultiDimGep(GetElementPtrInst &GEP) {
2980+
// Limit handling to only 3D and 4D arrays with integer types.
2981+
// getelementptr [9 x [9 x [9 x i32]]], ptr @arr, i64 0, i64 %i, i64 2, i64 3
2982+
unsigned NumOps = GEP.getNumOperands();
2983+
2984+
// First index must be constant zero (array base)
2985+
if (!isa<ConstantInt>(GEP.getOperand(1)) ||
2986+
!cast<ConstantInt>(GEP.getOperand(1))->isZero())
2987+
return false;
2988+
2989+
// Limit lowering for arrays with 3 or more dimensions
2990+
if (NumOps < 5)
2991+
return false;
2992+
2993+
// Check that it's arrays all the way
2994+
Type *CurTy = GEP.getSourceElementType();
2995+
unsigned NumVar = 0;
2996+
for (unsigned I = 2; I < NumOps; ++I) {
2997+
auto *ArrTy = dyn_cast<ArrayType>(CurTy);
2998+
if (!ArrTy)
2999+
return false;
3000+
if (!isa<ConstantInt>(GEP.getOperand(I)))
3001+
++NumVar;
3002+
CurTy = ArrTy->getElementType();
3003+
}
3004+
3005+
// Limit lowering only for one variable index
3006+
if (NumVar != 1)
3007+
return false;
3008+
3009+
if (!CurTy->isIntegerTy() || CurTy->getIntegerBitWidth() > 128)
3010+
return false;
3011+
3012+
return true;
3013+
}
3014+
29783015
/// Return true if we should canonicalize the gep to an i8 ptradd.
29793016
static bool shouldCanonicalizeGEPToPtrAdd(GetElementPtrInst &GEP) {
29803017
Value *PtrOp = GEP.getOperand(0);
@@ -2995,13 +3032,7 @@ static bool shouldCanonicalizeGEPToPtrAdd(GetElementPtrInst &GEP) {
29953032
m_Shl(m_Value(), m_ConstantInt())))))
29963033
return true;
29973034

2998-
// Flatten multidimensional GEPs with one variable index.
2999-
unsigned NumVarIndices = 0;
3000-
for (unsigned i = 1; i < GEP.getNumOperands(); ++i) {
3001-
if (!isa<ConstantInt>(GEP.getOperand(i)))
3002-
++NumVarIndices;
3003-
}
3004-
if (NumVarIndices == 1)
3035+
if (ismultiDimGep(GEP))
30053036
return true;
30063037

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

0 commit comments

Comments
 (0)