[llvm] r320510 - [InstCombine] Fix PR35618: Instcombine hangs on single minmax load bitcast.

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 12 10:47:00 PST 2017


Author: abataev
Date: Tue Dec 12 10:47:00 2017
New Revision: 320510

URL: http://llvm.org/viewvc/llvm-project?rev=320510&view=rev
Log:
[InstCombine] Fix PR35618: Instcombine hangs on single minmax load bitcast.

Summary:
If we have pattern `store (load(bitcast(select (cmp(V1, V2), &V1,
&V2)))), bitcast)`, but the load is used in other instructions, it leads
to looping in InstCombiner. Patch adds additional check that all users
of the load instructions are stores and then replaces all uses of load
instruction by the new one with new type.

Reviewers: RKSimon, spatel, majnemer

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D41072

Added:
    llvm/trunk/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll
Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp?rev=320510&r1=320509&r2=320510&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp Tue Dec 12 10:47:00 2017
@@ -1339,25 +1339,39 @@ static bool equivalentAddressValues(Valu
 /// Converts store (bitcast (load (bitcast (select ...)))) to
 /// store (load (select ...)), where select is minmax:
 /// select ((cmp load V1, load V2), V1, V2).
-bool removeBitcastsFromLoadStoreOnMinMax(InstCombiner &IC, StoreInst &SI) {
+static Instruction *removeBitcastsFromLoadStoreOnMinMax(InstCombiner &IC,
+                                                        StoreInst &SI) {
   // bitcast?
-  Value *StoreAddr;
-  if (!match(SI.getPointerOperand(), m_BitCast(m_Value(StoreAddr))))
-    return false;
+  if (!match(SI.getPointerOperand(), m_BitCast(m_Value())))
+    return nullptr;
   // load? integer?
   Value *LoadAddr;
   if (!match(SI.getValueOperand(), m_Load(m_BitCast(m_Value(LoadAddr)))))
-    return false;
+    return nullptr;
   auto *LI = cast<LoadInst>(SI.getValueOperand());
   if (!LI->getType()->isIntegerTy())
-    return false;
+    return nullptr;
   if (!isMinMaxWithLoads(LoadAddr))
-    return false;
+    return nullptr;
 
+  if (!all_of(LI->users(), [LI, LoadAddr](User *U) {
+        auto *SI = dyn_cast<StoreInst>(U);
+        return SI && SI->getPointerOperand() != LI &&
+               peekThroughBitcast(SI->getPointerOperand()) != LoadAddr &&
+               !SI->getPointerOperand()->isSwiftError();
+      }))
+    return nullptr;
+
+  IC.Builder.SetInsertPoint(LI);
   LoadInst *NewLI = combineLoadToNewType(
       IC, *LI, LoadAddr->getType()->getPointerElementType());
-  combineStoreToNewValue(IC, SI, NewLI);
-  return true;
+  // Replace all the stores with stores of the newly loaded value.
+  for (auto *UI : LI->users()) {
+    auto *USI = cast<StoreInst>(UI);
+    IC.Builder.SetInsertPoint(USI);
+    combineStoreToNewValue(IC, *USI, NewLI);
+  }
+  return LI;
 }
 
 Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
@@ -1384,8 +1398,12 @@ Instruction *InstCombiner::visitStoreIns
   if (unpackStoreToAggregate(*this, SI))
     return eraseInstFromFunction(SI);
 
-  if (removeBitcastsFromLoadStoreOnMinMax(*this, SI))
-    return eraseInstFromFunction(SI);
+  if (Instruction *I = removeBitcastsFromLoadStoreOnMinMax(*this, SI)) {
+    for (auto *UI : I->users())
+      eraseInstFromFunction(*cast<Instruction>(UI));
+    eraseInstFromFunction(*I);
+    return nullptr;
+  }
 
   // Replace GEP indices if possible.
   if (Instruction *NewGEPI = replaceGEPIdxWithZero(*this, Ptr, SI)) {

Added: llvm/trunk/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll?rev=320510&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll Tue Dec 12 10:47:00 2017
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instcombine -S -data-layout="E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64" | FileCheck %s
+
+define void @PR35618(i64* %st1, double* %st2) {
+; CHECK-LABEL: @PR35618(
+; CHECK-NEXT:    [[Y1:%.*]] = alloca double, align 8
+; CHECK-NEXT:    [[Z1:%.*]] = alloca double, align 8
+; CHECK-NEXT:    [[LD1:%.*]] = load double, double* [[Y1]], align 8
+; CHECK-NEXT:    [[LD2:%.*]] = load double, double* [[Z1]], align 8
+; CHECK-NEXT:    [[TMP10:%.*]] = fcmp olt double [[LD1]], [[LD2]]
+; CHECK-NEXT:    [[TMP121:%.*]] = select i1 [[TMP10]], double [[LD1]], double [[LD2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i64* [[ST1:%.*]] to double*
+; CHECK-NEXT:    store double [[TMP121]], double* [[TMP1]], align 8
+; CHECK-NEXT:    store double [[TMP121]], double* [[ST2:%.*]], align 8
+; CHECK-NEXT:    ret void
+;
+  %y1 = alloca double
+  %z1 = alloca double
+  %ld1 = load double, double* %y1
+  %ld2 = load double, double* %z1
+  %tmp10 = fcmp olt double %ld1, %ld2
+  %sel = select i1 %tmp10, double* %y1, double* %z1
+  %tmp11 = bitcast double* %sel to i64*
+  %tmp12 = load i64, i64* %tmp11
+  store i64 %tmp12, i64* %st1
+  %bc = bitcast double* %st2 to i64*
+  store i64 %tmp12, i64* %bc
+  ret void
+}
+




More information about the llvm-commits mailing list