[PATCH] D27413: Simplify gep (gep p, a), (b-a)

Andrea Canciani via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 5 06:10:41 PST 2016


ranma42 created this revision.
ranma42 added reviewers: majnemer, wmi.
ranma42 added a subscriber: llvm-commits.

This patch extends the patterns recognised by InstCombine to also optimise gep (gep p, a), (b-a) into gep p, b.
Some minor refactoring was done in order to make the various optimisation/shortcut cases share the same code structure.

The missing optimisation was found investigating why LLVM did not optimise away pointer computations in Rust slices: https://github.com/rust-lang/rust/pull/37921


https://reviews.llvm.org/D27413

Files:
  lib/Transforms/InstCombine/InstructionCombining.cpp
  test/Transforms/InstCombine/getelementptr.ll


Index: test/Transforms/InstCombine/getelementptr.ll
===================================================================
--- test/Transforms/InstCombine/getelementptr.ll
+++ test/Transforms/InstCombine/getelementptr.ll
@@ -883,6 +883,15 @@
 ; CHECK-NEXT:  ret %struct.C* [[GEP]]
 }
 
+define i32* @test47(i32* %I, i64 %C, i64 %D) {
+  %A = getelementptr i32, i32* %I, i64 %C
+  %sub = sub i64 %D, %C
+  %B = getelementptr i32, i32* %A, i64 %sub
+  ret i32* %B
+; CHECK-LABEL: @test47(
+; CHECK: %B = getelementptr i32, i32* %I, i64 %D
+}
+
 define i32 addrspace(1)* @ascast_0_gep(i32* %p) nounwind {
 ; CHECK-LABEL: @ascast_0_gep(
 ; CHECK-NOT: getelementptr
Index: lib/Transforms/InstCombine/InstructionCombining.cpp
===================================================================
--- lib/Transforms/InstCombine/InstructionCombining.cpp
+++ lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1556,23 +1556,27 @@
       Value *Sum;
       Value *SO1 = Src->getOperand(Src->getNumOperands()-1);
       Value *GO1 = GEP.getOperand(1);
+
+      // Only do the combine when we are sure the cost after the
+      // merge is never more than that before the merge.
       if (SO1 == Constant::getNullValue(SO1->getType())) {
         Sum = GO1;
       } else if (GO1 == Constant::getNullValue(GO1->getType())) {
         Sum = SO1;
-      } else {
+      } else if (SO1->getType() != GO1->getType()) {
         // If they aren't the same type, then the input hasn't been processed
         // by the loop above yet (which canonicalizes sequential index types to
         // intptr_t).  Just avoid transforming this until the input has been
         // normalized.
-        if (SO1->getType() != GO1->getType())
-          return nullptr;
-        // Only do the combine when GO1 and SO1 are both constants. Only in
-        // this case, we are sure the cost after the merge is never more than
-        // that before the merge.
-        if (!isa<Constant>(GO1) || !isa<Constant>(SO1))
-          return nullptr;
+        return nullptr;
+      } else if (isa<Constant>(GO1) && isa<Constant>(SO1)) {
+        // GO1 and SO1 are both constants, combine them
         Sum = Builder->CreateAdd(SO1, GO1, PtrOp->getName()+".sum");
+      } else if (match(GO1, m_Sub(m_Value(Sum), m_Specific(SO1)))) {
+        // GO1 = V - SO1, combine them
+        // Sum = GO1 + SO1 = (V - SO1) + SO1 = V (captured by the match)
+      } else {
+        return nullptr;
       }
 
       // Update the GEP in place if possible.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D27413.80256.patch
Type: text/x-patch
Size: 2512 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161205/17b2d08f/attachment.bin>


More information about the llvm-commits mailing list