[PATCH] D106352: [InstCombine] Fold (select C, (gep (gep Ptr, Idx0), Idx1), (gep Ptr, Idx0)) -> (gep Ptr, (select C, Idx0+Idx1, Idx0)) (PR51069)

Simon Pilgrim via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 20 03:42:44 PDT 2021


RKSimon created this revision.
RKSimon added reviewers: spatel, reames, lebedev.ri.
Herald added a subscriber: hiraditya.
RKSimon requested review of this revision.
Herald added a project: LLVM.

This extends the PR50183/D105901 <https://reviews.llvm.org/D105901> "(select C, (gep Ptr, Idx), Ptr) -> (gep Ptr, (select C, Idx, 0))" fold to account if the inner Ptr was a base gep, allowing us to merge the geps and select between the base index and the offset'd index.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106352

Files:
  llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
  llvm/test/Transforms/InstCombine/select-gep.ll


Index: llvm/test/Transforms/InstCombine/select-gep.ll
===================================================================
--- llvm/test/Transforms/InstCombine/select-gep.ll
+++ llvm/test/Transforms/InstCombine/select-gep.ll
@@ -102,10 +102,10 @@
 ; PR51069
 define i32* @test2c(i32* %p, i64 %x, i64 %y) {
 ; CHECK-LABEL: @test2c(
-; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[X:%.*]]
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]]
-; CHECK-NEXT:    [[SEL_IDX:%.*]] = select i1 [[ICMP]], i64 0, i64 6
-; CHECK-NEXT:    [[SEL:%.*]] = getelementptr i32, i32* [[GEP1]], i64 [[SEL_IDX]]
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[SEL_ADD:%.*]] = add i64 [[X]], 6
+; CHECK-NEXT:    [[SEL_IDX:%.*]] = select i1 [[ICMP]], i64 [[X]], i64 [[SEL_ADD]]
+; CHECK-NEXT:    [[SEL:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[SEL_IDX]]
 ; CHECK-NEXT:    ret i32* [[SEL]]
 ;
   %gep1 = getelementptr inbounds i32, i32* %p, i64 %x
@@ -118,10 +118,10 @@
 ; PR51069
 define i32* @test2d(i32* %p, i64 %x, i64 %y) {
 ; CHECK-LABEL: @test2d(
-; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[X:%.*]]
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]]
-; CHECK-NEXT:    [[SEL_IDX:%.*]] = select i1 [[ICMP]], i64 6, i64 0
-; CHECK-NEXT:    [[SEL:%.*]] = getelementptr i32, i32* [[GEP1]], i64 [[SEL_IDX]]
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[SEL_ADD:%.*]] = add i64 [[X]], 6
+; CHECK-NEXT:    [[SEL_IDX:%.*]] = select i1 [[ICMP]], i64 [[SEL_ADD]], i64 [[X]]
+; CHECK-NEXT:    [[SEL:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[SEL_IDX]]
 ; CHECK-NEXT:    ret i32* [[SEL]]
 ;
   %gep1 = getelementptr inbounds i32, i32* %p, i64 %x
Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2937,14 +2937,33 @@
   // Fold (select C, Ptr, (gep Ptr, Idx)) -> (gep Ptr, (select C, 0, Idx))
   auto SelectGepWithBase = [&](GetElementPtrInst *Gep, Value *Base,
                                bool Swap) -> GetElementPtrInst * {
-    Value *Ptr = Gep->getPointerOperand();
     if (Gep->getNumOperands() != 2 || Gep->getPointerOperand() != Base ||
         !Gep->hasOneUse())
       return nullptr;
+
+    auto *BaseGep = dyn_cast<GetElementPtrInst>(Base);
     Type *ElementType = Gep->getResultElementType();
     Value *Idx = Gep->getOperand(1);
-    Value *NewT = Idx;
-    Value *NewF = Constant::getNullValue(Idx->getType());
+    Value *Ptr, *NewT, *NewF;
+
+    // Handle nested geps special case.
+    // Fold (select C, (gep (gep Ptr, Idx0), Idx1), (gep Ptr, Idx0))
+    //  --> (gep Ptr,(select C, Idx0+Idx1, Idx0))
+    // Fold (select C, (gep Ptr, Idx0), (gep (gep Ptr, Idx0), Idx1))
+    //  --> (gep Ptr,(select C, Idx0, Idx0+Idx1))
+    if (BaseGep && BaseGep->getNumOperands() == 2 && 
+        ElementType == BaseGep->getResultElementType() &&
+        Idx->getType() == BaseGep->getOperand(1)->getType()) {
+      NewT =
+          Builder.CreateAdd(Idx, BaseGep->getOperand(1), SI.getName() + ".add");
+      NewF = BaseGep->getOperand(1);
+      Ptr = BaseGep->getPointerOperand();
+    } else {
+      NewT = Idx;
+      NewF = Constant::getNullValue(Idx->getType());
+      Ptr = Gep->getPointerOperand();
+    }
+
     if (Swap)
       std::swap(NewT, NewF);
     Value *NewSI =


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D106352.360072.patch
Type: text/x-patch
Size: 3560 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210720/86a518da/attachment.bin>


More information about the llvm-commits mailing list