[llvm] 54cb552 - [LoopInterchange] Form LCSSA phis for values in orig outer loop header.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 10 03:34:00 PDT 2020


Author: Florian Hahn
Date: 2020-08-10T11:33:19+01:00
New Revision: 54cb552b962097d0e3ef7306b69a3c82cc7fff37

URL: https://github.com/llvm/llvm-project/commit/54cb552b962097d0e3ef7306b69a3c82cc7fff37
DIFF: https://github.com/llvm/llvm-project/commit/54cb552b962097d0e3ef7306b69a3c82cc7fff37.diff

LOG: [LoopInterchange] Form LCSSA phis for values in orig outer loop header.

Values defined in the outer loop header could be used in the inner loop
latch. In that case, we need to create LCSSA phis for them, because after
interchanging they will be defined in the new inner loop and used in the
new outer loop.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/LoopInterchange.cpp
    llvm/test/Transforms/LoopInterchange/lcssa-preheader.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 3cfe1b595571..cf783e947a1c 100644
--- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -27,6 +27,7 @@
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
@@ -1594,6 +1595,17 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
   InnerLoopHeader->replacePhiUsesWith(OuterLoopPreHeader, InnerLoopPreHeader);
   InnerLoopHeader->replacePhiUsesWith(OuterLoopLatch, InnerLoopLatch);
 
+  // Values defined in the outer loop header could be used in the inner loop
+  // latch. In that case, we need to create LCSSA phis for them, because after
+  // interchanging they will be defined in the new inner loop and used in the
+  // new outer loop.
+  IRBuilder<> Builder(OuterLoopHeader->getContext());
+  SmallVector<Instruction *, 4> MayNeedLCSSAPhis;
+  for (Instruction &I :
+       make_range(OuterLoopHeader->begin(), std::prev(OuterLoopHeader->end())))
+    MayNeedLCSSAPhis.push_back(&I);
+  formLCSSAForInstructions(MayNeedLCSSAPhis, *DT, *LI, SE, Builder);
+
   return true;
 }
 

diff  --git a/llvm/test/Transforms/LoopInterchange/lcssa-preheader.ll b/llvm/test/Transforms/LoopInterchange/lcssa-preheader.ll
index 3d2b532d65aa..57cabfc9bed6 100644
--- a/llvm/test/Transforms/LoopInterchange/lcssa-preheader.ll
+++ b/llvm/test/Transforms/LoopInterchange/lcssa-preheader.ll
@@ -101,3 +101,65 @@ outer.crit_edge:              ; preds = %outer.latch
 for.cond.cleanup:                                 ; preds = %outer.crit_edge, %entry
   ret void
 }
+
+ at global = external local_unnamed_addr global [4 x [4 x [2 x i16]]] align 16
+
+; %N.ext is defined in the outer loop header and used in the inner loop. After
+; interchanging, it will be defined in the new inner loop and used in the new;
+; outer latch, so we need to create a new LCSSA phi node for it.
+
+define void @test2(i32 %N) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[INNER_PREHEADER:%.*]]
+; CHECK:       outer.header.preheader:
+; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
+; CHECK:       outer.header:
+; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i64 [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ], [ 0, [[OUTER_HEADER_PREHEADER:%.*]] ]
+; CHECK-NEXT:    [[N_EXT:%.*]] = sext i32 [[N:%.*]] to i64
+; CHECK-NEXT:    br label [[INNER_SPLIT1:%.*]]
+; CHECK:       inner.preheader:
+; CHECK-NEXT:    br label [[INNER:%.*]]
+; CHECK:       inner:
+; CHECK-NEXT:    [[INNER_IV:%.*]] = phi i64 [ [[TMP0:%.*]], [[INNER_SPLIT:%.*]] ], [ 0, [[INNER_PREHEADER]] ]
+; CHECK-NEXT:    br label [[OUTER_HEADER_PREHEADER]]
+; CHECK:       inner.split1:
+; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [4 x [4 x [2 x i16]]], [4 x [4 x [2 x i16]]]* @global, i64 0, i64 [[INNER_IV]], i64 [[OUTER_IV]], i64 0
+; CHECK-NEXT:    [[INNER_IV_NEXT:%.*]] = add nsw i64 [[INNER_IV]], 1
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ne i64 [[INNER_IV_NEXT]], [[N_EXT]]
+; CHECK-NEXT:    br label [[OUTER_LATCH]]
+; CHECK:       inner.split:
+; CHECK-NEXT:    [[N_EXT_LCSSA:%.*]] = phi i64 [ [[N_EXT]], [[OUTER_LATCH]] ]
+; CHECK-NEXT:    [[TMP0]] = add nsw i64 [[INNER_IV]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[TMP0]], [[N_EXT_LCSSA]]
+; CHECK-NEXT:    br i1 [[TMP1]], label [[INNER]], label [[EXIT:%.*]]
+; CHECK:       outer.latch:
+; CHECK-NEXT:    [[OUTER_IV_NEXT]] = add nsw i64 [[OUTER_IV]], 1
+; CHECK-NEXT:    [[C_2:%.*]] = icmp ne i64 [[OUTER_IV]], [[N_EXT]]
+; CHECK-NEXT:    br i1 [[C_2]], label [[OUTER_HEADER]], label [[INNER_SPLIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+bb:
+  br label %outer.header
+
+outer.header:                                              ; preds = %bb11, %bb2
+  %outer.iv = phi i64 [ 0, %bb ], [ %outer.iv.next, %outer.latch ]
+  %N.ext = sext i32 %N to i64
+  br label %inner
+
+inner:                                              ; preds = %bb6, %bb4
+  %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner ]
+  %tmp8 = getelementptr inbounds [4 x [4 x [2 x i16]]], [4 x [4 x [2 x i16]]]* @global, i64 0, i64 %inner.iv, i64 %outer.iv, i64 0
+  %inner.iv.next = add nsw i64 %inner.iv, 1
+  %c.1 = icmp ne i64 %inner.iv.next, %N.ext
+  br i1 %c.1, label %inner, label %outer.latch
+
+outer.latch:                                             ; preds = %bb6
+  %outer.iv.next = add nsw i64 %outer.iv, 1
+  %c.2 = icmp ne i64 %outer.iv, %N.ext
+  br i1 %c.2 , label %outer.header, label %exit
+
+exit:                                             ; preds = %bb11
+  ret void
+}


        


More information about the llvm-commits mailing list