[llvm] 5004320 - [LoopFusion] sink second loop PHIs

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 13 10:13:55 PST 2022


Author: Joshua Cao
Date: 2022-12-13T10:13:39-08:00
New Revision: 5004320590aed2e27140fb458ebd67b68af05a91

URL: https://github.com/llvm/llvm-project/commit/5004320590aed2e27140fb458ebd67b68af05a91
DIFF: https://github.com/llvm/llvm-project/commit/5004320590aed2e27140fb458ebd67b68af05a91.diff

LOG: [LoopFusion] sink second loop PHIs

Fixes https://github.com/llvm/llvm-project/issues/59023

PHI nodes that are in the second loop only have the first loop as its
predecessor. These PHI nodes should be sunk to the end of the fused
loop. If the second loop uses the PHI, then the loops cannot be fused.

I don't think this should happen in typical compilation workflows.
The PHI will be in a dedicated exit block of the first loop following
LCSSA transformations.

Reviewed By: aeubanks

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

Added: 
    llvm/test/Transforms/LoopFusion/lcssa.ll

Modified: 
    llvm/lib/Transforms/Scalar/LoopFuse.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/LoopFuse.cpp b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
index 6a4a6ee9aa3c5..abbc59203b094 100644
--- a/llvm/lib/Transforms/Scalar/LoopFuse.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
@@ -1064,6 +1064,11 @@ struct LoopFuser {
       }
     }
 
+    // PHIs in FC1's header only have FC0 blocks as predecessors. PHIs
+    // cannot be hoisted and should be sunk to the exit of the fused loop.
+    if (isa<PHINode>(I))
+      return false;
+
     // If this isn't a memory inst, hoisting is safe
     if (!I.mayReadOrWriteMemory())
       return true;

diff  --git a/llvm/test/Transforms/LoopFusion/lcssa.ll b/llvm/test/Transforms/LoopFusion/lcssa.ll
new file mode 100644
index 0000000000000..679f637cb3b68
--- /dev/null
+++ b/llvm/test/Transforms/LoopFusion/lcssa.ll
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=loop-fusion < %s 2>&1 | FileCheck %s
+
+; Tests when the second loop preheader has a phi coming from the first loop
+; exit. If the phi is not used in the second loop, the loops can be fused and
+; the phi is sunk to the fused loop exit. If the phi is used in the second loop,
+; the loops cannot be fused.
+
+define void @test1() {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[VECTOR_PH:%.*]]
+; CHECK:       vector.ph:
+; CHECK-NEXT:    br label [[MIDDLE_BLOCK:%.*]]
+; CHECK:       middle.block:
+; CHECK-NEXT:    br i1 true, label [[FOR_END41:%.*]], label [[VECTOR_PH]]
+; CHECK:       for.end41:
+; CHECK-NEXT:    [[DOTLCSSA92:%.*]] = phi i16 [ 1, [[MIDDLE_BLOCK]] ]
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %vector.ph
+
+vector.ph:                                        ; preds = %middle.block, %entry
+  br label %middle.block
+
+middle.block:                                     ; preds = %vector.ph
+  br i1 true, label %for.cond17.preheader, label %vector.ph
+
+for.cond17.preheader:                             ; preds = %middle.block
+  %.lcssa92 = phi i16 [ 1, %middle.block ]
+  br label %vector.ph61
+
+vector.ph61:                                      ; preds = %middle.block59, %for.cond17.preheader
+  br i1 true, label %for.end41, label %vector.ph61
+
+for.end41:                                        ; preds = %middle.block59
+  ret void
+}
+
+define void @test2() {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[VECTOR_PH:%.*]]
+; CHECK:       vector.ph:
+; CHECK-NEXT:    br label [[MIDDLE_BLOCK:%.*]]
+; CHECK:       middle.block:
+; CHECK-NEXT:    br i1 true, label [[FOR_COND17_PREHEADER:%.*]], label [[VECTOR_PH]]
+; CHECK:       for.cond17.preheader:
+; CHECK-NEXT:    [[DOTLCSSA92:%.*]] = phi i16 [ 1, [[MIDDLE_BLOCK]] ]
+; CHECK-NEXT:    br label [[VECTOR_PH61:%.*]]
+; CHECK:       vector.ph61:
+; CHECK-NEXT:    call void @a(i16 [[DOTLCSSA92]])
+; CHECK-NEXT:    br i1 true, label [[FOR_END41:%.*]], label [[VECTOR_PH61]]
+; CHECK:       for.end41:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %vector.ph
+
+vector.ph:                                        ; preds = %middle.block, %entry
+  br label %middle.block
+
+middle.block:                                     ; preds = %vector.ph
+  br i1 true, label %for.cond17.preheader, label %vector.ph
+
+for.cond17.preheader:                             ; preds = %middle.block
+  %.lcssa92 = phi i16 [ 1, %middle.block ]
+  br label %vector.ph61
+
+vector.ph61:                                      ; preds = %middle.block59, %for.cond17.preheader
+  call void @a(i16 %.lcssa92)
+  br i1 true, label %for.end41, label %vector.ph61
+
+for.end41:                                        ; preds = %middle.block59
+  ret void
+}
+
+declare void @a(i16);


        


More information about the llvm-commits mailing list