[PATCH] D26569: [InstCombine] Support load(gep(A, select(idx1, idx2)))) to select(load(gep(A, idx1)), load(gep(A, idx2))) transformation

Wei Mi via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 11 16:12:16 PST 2016


wmi created this revision.
wmi added reviewers: jmolloy, majnemer, mkuper.
wmi added subscribers: llvm-commits, davidxl.
wmi set the repository for this revision to rL LLVM.

It is to fix PR30950. After SimplifyCfg sinking, it will create IR as  load(gep(A, select(idx1, idx2)))).  Only equipped with the transformation, InstCombine can make the redundent loads hidden by select exposed to GVN.


Repository:
  rL LLVM

https://reviews.llvm.org/D26569

Files:
  lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
  test/Transforms/InstCombine/load-gep-select.ll


Index: test/Transforms/InstCombine/load-gep-select.ll
===================================================================
--- test/Transforms/InstCombine/load-gep-select.ll
+++ test/Transforms/InstCombine/load-gep-select.ll
@@ -0,0 +1,26 @@
+; RUN: opt -instcombine -gvn -S < %s | FileCheck %s
+; PR30950. Check instcombine supports the transformation of load(gep(A, select(I1, I2))) ==> select(load(gep(A, I1)), load(gep(A, I2))), so that global value numbering can remove the redundent loads.
+
+; CHECK-LABEL: @foo
+; CHECK: [[AIDX0:%[^ ]+]] = getelementptr inbounds i64, i64* %maxarray, i64 %k
+; CHECK: [[TMP0:%[^ ]+]] = load i64, i64* [[AIDX0]], align 8
+; CHECK: [[AIDX1:%[^ ]+]] = getelementptr inbounds i64, i64* %maxarray, i64 {{.*}}
+; CHECK: [[TMP1:%[^ ]+]] = load i64, i64* [[AIDX1]], align 8
+; CHECK: [[CMP:%[^ ]+]] = icmp sgt i64 [[TMP0]], [[TMP1]]
+; CHECK: [[SEL:%[^ ]+]] = select i1 [[CMP]], i64 [[TMP0]], i64 [[TMP1]]
+; CHECK: ret i64 [[SEL]]
+
+define i64 @foo(i64* nocapture readonly %maxarray, i64 %k, i64 %size) {
+entry:
+  %arrayidx = getelementptr inbounds i64, i64* %maxarray, i64 %k
+  %t0 = load i64, i64* %arrayidx, align 8
+  %add = add nsw i64 %k, %size
+  %add1 = add nsw i64 %add, 1
+  %arrayidx2 = getelementptr inbounds i64, i64* %maxarray, i64 %add1
+  %t1 = load i64, i64* %arrayidx2, align 8
+  %cmp = icmp sgt i64 %t0, %t1
+  %k.add1 = select i1 %cmp, i64 %k, i64 %add1
+  %arrayidx6 = getelementptr inbounds i64, i64* %maxarray, i64 %k.add1
+  %t2 = load i64, i64* %arrayidx6, align 8
+  ret i64 %t2
+}
Index: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -876,6 +876,38 @@
                     Constant::getNullValue(Op->getType()), &LI);
       return replaceInstUsesWith(LI, UndefValue::get(LI.getType()));
     }
+
+    // load(gep(A, select(Cond, I1, I2)))  -->
+    // select(Cond, load(gep(A, I1)), load(gep(A, I2)).
+    // It helps alias analysis and load elimination. But we need to make sure
+    // load(gep(A, I1)) and load(gep(A, I2)) will never trap.
+    unsigned LastIdx = GEPI->getNumIndices();
+    Value *LastOp = GEPI->getOperand(LastIdx);
+    if (SelectInst *SI = dyn_cast<SelectInst>(LastOp)) {
+      GetElementPtrInst *NewGEP1 = cast<GetElementPtrInst>(GEPI->clone());
+      GetElementPtrInst *NewGEP2 = cast<GetElementPtrInst>(GEPI->clone());
+      NewGEP1->setOperand(LastIdx, SI->getOperand(1));
+      NewGEP2->setOperand(LastIdx, SI->getOperand(2));
+      unsigned Align = LI.getAlignment();
+      if (isSafeToLoadUnconditionally(NewGEP1, Align, DL, GEPI) &&
+          isSafeToLoadUnconditionally(NewGEP2, Align, DL, GEPI)) {
+        Builder->Insert(NewGEP1, "newgep1");
+        Builder->Insert(NewGEP2, "newgep2");
+        LoadInst *V1 =
+            Builder->CreateLoad(NewGEP1, NewGEP1->getName() + ".val");
+        LoadInst *V2 =
+            Builder->CreateLoad(NewGEP2, NewGEP2->getName() + ".val");
+        assert(LI.isUnordered() && "implied by above");
+        V1->setAlignment(Align);
+        V1->setAtomic(LI.getOrdering(), LI.getSynchScope());
+        V2->setAlignment(Align);
+        V2->setAtomic(LI.getOrdering(), LI.getSynchScope());
+        return SelectInst::Create(SI->getCondition(), V1, V2);
+      } else {
+        delete NewGEP1;
+        delete NewGEP2;
+      }
+    }
   }
 
   // load null/undef -> unreachable


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D26569.77694.patch
Type: text/x-patch
Size: 3535 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161112/b4a9b427/attachment.bin>


More information about the llvm-commits mailing list