[llvm] r272649 - [LoopVer] Update all existing PHIs in the exit block

Adam Nemet via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 14 02:38:55 PDT 2016


Author: anemet
Date: Tue Jun 14 04:38:54 2016
New Revision: 272649

URL: http://llvm.org/viewvc/llvm-project?rev=272649&view=rev
Log:
[LoopVer] Update all existing PHIs in the exit block

We only used to add the edge from the cloned loop to PHIs that
corresponded to values defined by the loop.  We need to do this for all
PHIs obviously since we need a PHI operand for each incoming edge.

This includes things like PHIs with a constant value or with values
defined before the original loop (see the testcases).

After the patch the PHIs are added to the exit block in two passes.

In the first pass we ensure there is a single-operand (LCSSA) PHI for
each value defined by the loop.

In the second pass we loop through each (single-operand) PHI and add the
value for the edge from the cloned loop.  If the value is defined in the
loop we'll use the cloned instruction from the cloned loop.

Fixes PR28037

Added:
    llvm/trunk/test/Transforms/LoopVersioning/incorrect-phi.ll
Modified:
    llvm/trunk/lib/Transforms/Utils/LoopVersioning.cpp

Modified: llvm/trunk/lib/Transforms/Utils/LoopVersioning.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopVersioning.cpp?rev=272649&r1=272648&r2=272649&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopVersioning.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopVersioning.cpp Tue Jun 14 04:38:54 2016
@@ -125,12 +125,12 @@ void LoopVersioning::addPHINodes(
     const SmallVectorImpl<Instruction *> &DefsUsedOutside) {
   BasicBlock *PHIBlock = VersionedLoop->getExitBlock();
   assert(PHIBlock && "No single successor to loop exit block");
+  PHINode *PN;
 
+  // First add a single-operand PHI for each DefsUsedOutside if one does not
+  // exists yet.
   for (auto *Inst : DefsUsedOutside) {
-    auto *NonVersionedLoopInst = cast<Instruction>(VMap[Inst]);
-    PHINode *PN;
-
-    // First see if we have a single-operand PHI with the value defined by the
+    // See if we have a single-operand PHI with the value defined by the
     // original loop.
     for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) {
       if (PN->getIncomingValue(0) == Inst) {
@@ -148,8 +148,20 @@ void LoopVersioning::addPHINodes(
           User->replaceUsesOfWith(Inst, PN);
       PN->addIncoming(Inst, VersionedLoop->getExitingBlock());
     }
-    // Add the new incoming value from the non-versioned loop.
-    PN->addIncoming(NonVersionedLoopInst, NonVersionedLoop->getExitingBlock());
+  }
+
+  // Then for each PHI add the operand for the edge from the cloned loop.
+  for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) {
+    assert(PN->getNumOperands() == 1 &&
+           "Exit block should only have on predecessor");
+
+    // If the definition was cloned used that otherwise use the same value.
+    Value *ClonedValue = PN->getIncomingValue(0);
+    auto Mapped = VMap.find(ClonedValue);
+    if (Mapped != VMap.end())
+      ClonedValue = Mapped->second;
+
+    PN->addIncoming(ClonedValue, NonVersionedLoop->getExitingBlock());
   }
 }
 

Added: llvm/trunk/test/Transforms/LoopVersioning/incorrect-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVersioning/incorrect-phi.ll?rev=272649&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoopVersioning/incorrect-phi.ll (added)
+++ llvm/trunk/test/Transforms/LoopVersioning/incorrect-phi.ll Tue Jun 14 04:38:54 2016
@@ -0,0 +1,62 @@
+; RUN: opt -loop-versioning -S < %s | FileCheck %s
+
+; Make sure all PHIs are properly updated in the exit block.  Based on
+; PR28037.
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at x = external global [2 x [3 x [5 x i16]]]
+
+; CHECK-LABEL: @phi_with_undef
+define void @phi_with_undef() {
+bb6.lr.ph:                                        ; preds = %bb5.preheader
+  br label %bb6
+
+bb6:                                              ; preds = %bb6.lr.ph, %bb6
+  %_tmp1423 = phi i16 [ undef, %bb6.lr.ph ], [ %_tmp142, %bb6 ]
+  %_tmp123 = getelementptr [2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i16 0, i64 undef
+  %_tmp125 = sext i16 %_tmp1423 to i64
+  %_tmp126 = getelementptr [3 x [5 x i16]], [3 x [5 x i16]]* %_tmp123, i16 0, i64 %_tmp125
+  %_tmp129 = getelementptr [5 x i16], [5 x i16]* %_tmp126, i16 0, i64 undef
+  %_tmp130 = load i16, i16* %_tmp129
+  store i16 undef, i16* getelementptr ([2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i64 0, i64 undef, i64 undef, i64 undef)
+  %_tmp142 = add i16 %_tmp1423, 1
+  br i1 false, label %bb6, label %loop.exit
+
+loop.exit:                                ; preds = %bb6
+  %_tmp142.lcssa = phi i16 [ %_tmp142, %bb6 ]
+  %split = phi i16 [ undef, %bb6 ]
+; CHECK: %split = phi i16 [ undef, %bb6 ], [ undef, %bb6.lver.orig ]
+  br label %bb9
+
+bb9:                                              ; preds = %bb9.loopexit, %bb1
+  ret void
+}
+
+; CHECK-LABEL: @phi_with_non_loop_defined_value
+define void @phi_with_non_loop_defined_value() {
+bb6.lr.ph:                                        ; preds = %bb5.preheader
+  %t = add i16 1, 1
+  br label %bb6
+
+bb6:                                              ; preds = %bb6.lr.ph, %bb6
+  %_tmp1423 = phi i16 [ undef, %bb6.lr.ph ], [ %_tmp142, %bb6 ]
+  %_tmp123 = getelementptr [2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i16 0, i64 undef
+  %_tmp125 = sext i16 %_tmp1423 to i64
+  %_tmp126 = getelementptr [3 x [5 x i16]], [3 x [5 x i16]]* %_tmp123, i16 0, i64 %_tmp125
+  %_tmp129 = getelementptr [5 x i16], [5 x i16]* %_tmp126, i16 0, i64 undef
+  %_tmp130 = load i16, i16* %_tmp129
+  store i16 undef, i16* getelementptr ([2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i64 0, i64 undef, i64 undef, i64 undef)
+  %_tmp142 = add i16 %_tmp1423, 1
+  br i1 false, label %bb6, label %loop.exit
+
+loop.exit:                                ; preds = %bb6
+  %_tmp142.lcssa = phi i16 [ %_tmp142, %bb6 ]
+  %split = phi i16 [ %t, %bb6 ]
+; CHECK: %split = phi i16 [ %t, %bb6 ], [ %t, %bb6.lver.orig ]
+  br label %bb9
+
+bb9:                                              ; preds = %bb9.loopexit, %bb1
+  ret void
+}




More information about the llvm-commits mailing list