[PATCH] D137212: [InstCombine] Simplify chain of GEP with constant indices

William Junda Huang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 8 16:43:08 PST 2022


huangjd updated this revision to Diff 474109.
huangjd added a comment.

Merged after adding baseline


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D137212/new/

https://reviews.llvm.org/D137212

Files:
  llvm/lib/Transforms/InstCombine/InstCombineInternal.h
  llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
  llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll


Index: llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll
===================================================================
--- llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll
+++ llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll
@@ -230,9 +230,9 @@
 ; CHECK-LABEL: @gepChain1(
 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 2
 ; CHECK-NEXT:    call void @use(ptr nonnull [[TMP1]])
-; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[A:%.*]]
-; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 [[B:%.*]]
-; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i16, ptr [[TMP3]], i64 3
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i32, ptr [[P]], i64 [[A:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr i32, ptr [[TMP2]], i64 [[B:%.*]]
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP3]], i64 22
 ; CHECK-NEXT:    ret ptr [[TMP4]]
 ;
   %1 = getelementptr inbounds i64, ptr %p, i64 2
@@ -249,10 +249,9 @@
 ; CHECK-LABEL: @gepChain2(
 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 2
 ; CHECK-NEXT:    call void @use(ptr nonnull [[TMP1]])
-; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[A:%.*]]
-; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 [[B:%.*]]
-; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i16, ptr [[TMP3]], i64 -8
-; CHECK-NEXT:    ret ptr [[TMP4]]
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i32, ptr [[P]], i64 [[A:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr i32, ptr [[TMP2]], i64 [[B:%.*]]
+; CHECK-NEXT:    ret ptr [[TMP3]]
 ;
   %1 = getelementptr inbounds i64, ptr %p, i64 2
   call void @use(ptr %1)
Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1935,6 +1935,28 @@
   return SelectInst::Create(Cond, NewTrueC, NewFalseC, "", nullptr, Sel);
 }
 
+// For a chain of GEP in the form GEP (GEP ... (GEP (GEP p C1) X1) ... Xn) C2
+// where C1 and C2 are constants, and GEP X1 ... Xn each has no other uses,
+// we can split GEP p C1 from the use-def chain so that it can be reassociated
+// and merged with the outermost GEP by visitGEPofGEP.
+Value *InstCombinerImpl::splitConstantGEP(Value *Src) {
+  if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Src)) {
+    APInt Offset(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
+    if (GEP->hasAllConstantIndices() &&
+        GEP->accumulateConstantOffset(DL, Offset))
+      return Builder.CreateGEP(GEP->getSourceElementType(),
+                               GEP->getPointerOperand(),
+                               SmallVector<Value *>(GEP->indices()),
+                               GEP->getName(), GEP->isInBounds());
+    if (Src->hasOneUse())
+      if (Value *NewV = splitConstantGEP(GEP->getPointerOperand()))
+        return Builder.CreateGEP(GEP->getSourceElementType(), NewV,
+                                 SmallVector<Value *>(GEP->indices()),
+                                 GEP->getName(), GEP->isInBounds());
+  }
+  return nullptr;
+}
+
 Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
                                              GEPOperator *Src) {
   // Combine Indices - If the source pointer to this getelementptr instruction
@@ -2444,6 +2466,19 @@
     if (Instruction *I = visitGEPOfGEP(GEP, Src))
       return I;
 
+  // This check must be after visitGEPOfGEP, since GEP (GEP p C1) C2 can be
+  // merged by it. If GEP has zero offset, do not transform because it is a zero
+  // cost bitcast.
+  APInt Offset(DL.getIndexTypeSizeInBits(GEP.getType()), 0);
+  if (GEP.hasAllConstantIndices() && !GEP.hasAllZeroIndices() &&
+      GEP.accumulateConstantOffset(DL, Offset) && !Offset.isZero())
+    if (Value *V = splitConstantGEP(GEP.getPointerOperand())) {
+      GetElementPtrInst *NewGEP = GetElementPtrInst::Create(
+          GEP.getSourceElementType(), V, SmallVector<Value *>(GEP.indices()));
+      NewGEP->setIsInBounds(GEP.isInBounds());
+      return NewGEP;
+    }
+
   // Skip if GEP source element type is scalable. The type alloc size is unknown
   // at compile-time.
   if (GEP.getNumIndices() == 1 && !IsGEPSrcEleScalable) {
Index: llvm/lib/Transforms/InstCombine/InstCombineInternal.h
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -148,6 +148,7 @@
   Instruction *SliceUpIllegalIntegerPHI(PHINode &PN);
   Instruction *visitPHINode(PHINode &PN);
   Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
+  Value *splitConstantGEP(Value *Src);
   Instruction *visitGEPOfGEP(GetElementPtrInst &GEP, GEPOperator *Src);
   Instruction *visitGEPOfBitcast(BitCastInst *BCI, GetElementPtrInst &GEP);
   Instruction *visitAllocaInst(AllocaInst &AI);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D137212.474109.patch
Type: text/x-patch
Size: 5111 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20221109/664a7544/attachment.bin>


More information about the llvm-commits mailing list