فهرست منبع

Merge fix for undef in first_iteration case from upstream. (#2672)

Xiang Li 5 سال پیش
والد
کامیت
c0d82459f4
2فایلهای تغییر یافته به همراه48 افزوده شده و 15 حذف شده
  1. 25 15
      lib/Transforms/Utils/PromoteMemoryToRegister.cpp
  2. 23 0
      tools/clang/test/HLSLFileCheck/passes/llvm/mem2reg/undef_phi.hlsl

+ 25 - 15
lib/Transforms/Utils/PromoteMemoryToRegister.cpp

@@ -425,14 +425,17 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
 /// using the Alloca.
 /// using the Alloca.
 ///
 ///
 /// If we cannot promote this alloca (because it is read before it is written),
 /// If we cannot promote this alloca (because it is read before it is written),
-/// return true.  This is necessary in cases where, due to control flow, the
-/// alloca is potentially undefined on some control flow paths.  e.g. code like
-/// this is potentially correct:
-///
-///   for (...) { if (c) { A = undef; undef = B; } }
-///
-/// ... so long as A is not used before undef is set.
-static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
+/// return false.  This is necessary in cases where, due to control flow, the
+/// alloca is undefined only on some control flow paths.  e.g. code like
+/// this is correct in LLVM IR:
+///  // A is an alloca with no stores so far
+///  for (...) {
+///    int t = *A;
+///    if (!first_iteration)
+///      use(t);
+///    *A = 42;
+///  }
+static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
                                      LargeBlockInfo &LBI,
                                      LargeBlockInfo &LBI,
                                      AliasSetTracker *AST) {
                                      AliasSetTracker *AST) {
   // The trickiest case to handle is when we have large blocks. Because of this,
   // The trickiest case to handle is when we have large blocks. Because of this,
@@ -468,12 +471,19 @@ static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
                                         static_cast<StoreInst *>(nullptr)),
                                         static_cast<StoreInst *>(nullptr)),
                          less_first());
                          less_first());
 
 
-    if (I == StoresByIndex.begin())
-      // If there is no store before this load, the load takes the undef value.
-      LI->replaceAllUsesWith(UndefValue::get(LI->getType()));
-    else
+    if (I == StoresByIndex.begin()) {
+      if (StoresByIndex.empty())
+        // If there are no stores, the load takes the undef value.
+        LI->replaceAllUsesWith(UndefValue::get(LI->getType()));
+      else
+        // There is no store before this load, bail out (load may be affected
+        // by the following stores - see main comment).
+        return false;
+    }
+    else {
       // Otherwise, there was a store before this load, the load takes its value.
       // Otherwise, there was a store before this load, the load takes its value.
       LI->replaceAllUsesWith(std::prev(I)->second->getOperand(0));
       LI->replaceAllUsesWith(std::prev(I)->second->getOperand(0));
+    }
 
 
     if (AST && LI->getType()->isPointerTy())
     if (AST && LI->getType()->isPointerTy())
       AST->deleteValue(LI);
       AST->deleteValue(LI);
@@ -506,6 +516,7 @@ static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
   }
   }
 
 
   ++NumLocalPromoted;
   ++NumLocalPromoted;
+  return true;
 }
 }
 
 
 void PromoteMem2Reg::run() {
 void PromoteMem2Reg::run() {
@@ -557,9 +568,8 @@ void PromoteMem2Reg::run() {
 
 
     // If the alloca is only read and written in one basic block, just perform a
     // If the alloca is only read and written in one basic block, just perform a
     // linear sweep over the block to eliminate it.
     // linear sweep over the block to eliminate it.
-    if (Info.OnlyUsedInOneBlock) {
-      promoteSingleBlockAlloca(AI, Info, LBI, AST);
-
+    if (Info.OnlyUsedInOneBlock &&
+        promoteSingleBlockAlloca(AI, Info, LBI, AST)) {
       // The alloca has been processed, move on.
       // The alloca has been processed, move on.
       RemoveFromAllocasList(AllocaNum);
       RemoveFromAllocasList(AllocaNum);
       continue;
       continue;

+ 23 - 0
tools/clang/test/HLSLFileCheck/passes/llvm/mem2reg/undef_phi.hlsl

@@ -0,0 +1,23 @@
+// RUN: %dxc -E main -T lib_6_3 %s  | FileCheck %s
+
+// Make sure phi with undef created.
+// CHECK:phi float {{.*}}undef
+
+float foo(float a, float b);
+
+int c;
+float a;
+
+RWBuffer<float> buf;
+[numthreads(8,8,1)]
+void main() {
+
+  float b;
+  int x = c;
+  while (x>0) {
+    b = foo(b, a);
+    buf[x] = b;
+    x--;
+  }
+
+}