[llvm] [LoopPeel] LCSSA form is destroyed by LoopPeel, preserve it (PR #78696)

Vedant Paranjape via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 19 03:21:01 PST 2024


https://github.com/vedantparanjape-amd created https://github.com/llvm/llvm-project/pull/78696

LoopPeel util takes in the PreserveLCSSA argument, but the transformation doesn't seem to preserve the LCSSA form. But, it passes on the same argument to simplifyLoop which checks if the loop is in a valid LCSSA form, when (PreserveLCSSA = true).

This causes an assert in simplifyLoop when (PreserveLCSSA = true), as LoopPeel doesn't preserve LCSSA, and thus crashes at the following assert.

assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
           "Requested to preserve LCSSA, but it's already broken.");

This patch fixes llvm#77118, it tries to form LCSSA at the end of the optimization if (PreserveLCSSA = true) and the loop is not in LCSSA form. It also adds a test case of LoopUnrolling which crashed earlier.

>From 9b1b4486f59ba7784c7d79400695361a83081fda Mon Sep 17 00:00:00 2001
From: Vedant Paranjape <vedant.paranjape at amd.com>
Date: Fri, 19 Jan 2024 10:53:36 +0000
Subject: [PATCH] [LoopPeel] LCSSA form is destroyed by LoopPeel, preserve it

LoopPeel util takes in the PreserveLCSSA argument, but the
transformation doesn't seem to preserve the LCSSA form. But, it passes
on the same argument to simplifyLoop which checks if the loop is in a
valid LCSSA form, when (PreserveLCSSA = true).

This causes an assert in simplifyLoop when (PreserveLCSSA = true), as
LoopPeel doesn't preserve LCSSA, and thus crashes at the following
assert.

assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
           "Requested to preserve LCSSA, but it's already broken.");

This patch fixes llvm#77118, it tries to form LCSSA at the end of the
optimization if (PreserveLCSSA = true) and the loop is not in LCSSA
form. It also adds a test case of LoopUnrolling which crashed earlier.
---
 llvm/lib/Transforms/Utils/LoopPeel.cpp        |   2 +
 .../gh-issue77118-broken-lcssa-form.ll        | 117 ++++++++++++++++++
 2 files changed, 119 insertions(+)
 create mode 100644 llvm/test/Transforms/LoopUnroll/gh-issue77118-broken-lcssa-form.ll

diff --git a/llvm/lib/Transforms/Utils/LoopPeel.cpp b/llvm/lib/Transforms/Utils/LoopPeel.cpp
index f76fa3bb6c6114..3e0545656d493c 100644
--- a/llvm/lib/Transforms/Utils/LoopPeel.cpp
+++ b/llvm/lib/Transforms/Utils/LoopPeel.cpp
@@ -1054,6 +1054,8 @@ bool llvm::peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI,
   assert(DT.verify(DominatorTree::VerificationLevel::Fast));
 #endif
 
+  if (PreserveLCSSA && !L->isRecursivelyLCSSAForm(DT, *LI))
+    formLCSSARecursively(*L, DT, LI, SE);
   // FIXME: Incrementally update loop-simplify
   simplifyLoop(L, &DT, LI, SE, AC, nullptr, PreserveLCSSA);
 
diff --git a/llvm/test/Transforms/LoopUnroll/gh-issue77118-broken-lcssa-form.ll b/llvm/test/Transforms/LoopUnroll/gh-issue77118-broken-lcssa-form.ll
new file mode 100644
index 00000000000000..fe0607e59421c0
--- /dev/null
+++ b/llvm/test/Transforms/LoopUnroll/gh-issue77118-broken-lcssa-form.ll
@@ -0,0 +1,117 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -S -passes=loop-unroll < %s | FileCheck %s
+source_filename = "./reduced.ll"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @wombat() gc "statepoint-example" !prof !0 {
+; CHECK-LABEL: define void @wombat(
+; CHECK-SAME: ) gc "statepoint-example" !prof [[PROF0:![0-9]+]] {
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1.loopexit.loopexit:
+; CHECK-NEXT:    br label [[BB1_LOOPEXIT:%.*]]
+; CHECK:       bb1.loopexit:
+; CHECK-NEXT:    br label [[BB1]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[BB1_LOOPEXIT]] ]
+; CHECK-NEXT:    br label [[BB2_PEEL_BEGIN:%.*]]
+; CHECK:       bb2.peel.begin:
+; CHECK-NEXT:    br label [[BB2_PEEL:%.*]]
+; CHECK:       bb2.peel:
+; CHECK-NEXT:    br label [[BB4_PEEL:%.*]]
+; CHECK:       bb4.peel:
+; CHECK-NEXT:    [[TRUNC_PEEL:%.*]] = trunc i64 0 to i32
+; CHECK-NEXT:    br i1 true, label [[BB9_PEEL:%.*]], label [[BB7_LOOPEXIT2:%.*]]
+; CHECK:       bb9.peel:
+; CHECK-NEXT:    [[ADD_PEEL:%.*]] = add i32 1, [[PHI]]
+; CHECK-NEXT:    br i1 true, label [[BB9_1_PEEL:%.*]], label [[BB7_LOOPEXIT2]]
+; CHECK:       bb9.1.peel:
+; CHECK-NEXT:    br i1 false, label [[BB12_PREHEADER:%.*]], label [[BB2_PEEL_NEXT:%.*]]
+; CHECK:       bb2.peel.next:
+; CHECK-NEXT:    br label [[BB2_PEEL_NEXT1:%.*]]
+; CHECK:       bb2.peel.next1:
+; CHECK-NEXT:    br label [[BB1_PEEL_NEWPH:%.*]]
+; CHECK:       bb1.peel.newph:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nuw nsw i32 [[PHI]], 1
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    br i1 true, label [[BB9:%.*]], label [[BB7_LOOPEXIT:%.*]]
+; CHECK:       bb7.loopexit:
+; CHECK-NEXT:    [[DOTLCSSA:%.*]] = phi i32 [ [[TMP0]], [[BB4]] ], [ [[TMP0]], [[BB9]] ]
+; CHECK-NEXT:    br label [[BB7:%.*]]
+; CHECK:       bb7.loopexit2:
+; CHECK-NEXT:    [[PHI8_PH3:%.*]] = phi i32 [ [[ADD_PEEL]], [[BB9_PEEL]] ], [ [[TRUNC_PEEL]], [[BB4_PEEL]] ]
+; CHECK-NEXT:    br label [[BB7]]
+; CHECK:       bb7:
+; CHECK-NEXT:    [[PHI8:%.*]] = phi i32 [ [[DOTLCSSA]], [[BB7_LOOPEXIT]] ], [ [[PHI8_PH3]], [[BB7_LOOPEXIT2]] ]
+; CHECK-NEXT:    ret void
+; CHECK:       bb9:
+; CHECK-NEXT:    br i1 true, label [[BB9_1:%.*]], label [[BB7_LOOPEXIT]]
+; CHECK:       bb9.1:
+; CHECK-NEXT:    br i1 false, label [[BB12_PREHEADER_LOOPEXIT:%.*]], label [[BB2]], !llvm.loop [[LOOP1:![0-9]+]]
+; CHECK:       bb12.preheader.loopexit:
+; CHECK-NEXT:    br label [[BB12_PREHEADER]]
+; CHECK:       bb12.preheader:
+; CHECK-NEXT:    br label [[BB12_PEEL_BEGIN:%.*]]
+; CHECK:       bb12.peel.begin:
+; CHECK-NEXT:    br label [[BB12_PEEL:%.*]]
+; CHECK:       bb12.peel:
+; CHECK-NEXT:    br i1 false, label [[BB1_LOOPEXIT]], label [[BB12_PEEL_NEXT:%.*]], !prof [[PROF3:![0-9]+]]
+; CHECK:       bb12.peel.next:
+; CHECK-NEXT:    br label [[BB12_PEEL_NEXT4:%.*]]
+; CHECK:       bb12.peel.next4:
+; CHECK-NEXT:    br label [[BB12_PREHEADER_PEEL_NEWPH:%.*]]
+; CHECK:       bb12.preheader.peel.newph:
+; CHECK-NEXT:    br label [[BB12:%.*]]
+; CHECK:       bb12:
+; CHECK-NEXT:    br i1 false, label [[BB1_LOOPEXIT_LOOPEXIT:%.*]], label [[BB12]], !prof [[PROF4:![0-9]+]], !llvm.loop [[LOOP5:![0-9]+]]
+;
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb12, %bb
+  %phi = phi i32 [ 1, %bb ], [ 0, %bb12 ]
+  br label %bb2
+
+bb2:                                              ; preds = %bb11, %bb1
+  %phi3 = phi i64 [ 0, %bb1 ], [ %sext, %bb11 ]
+  br label %bb4
+
+bb4:                                              ; preds = %bb9, %bb2
+  %phi5 = phi i64 [ %phi3, %bb2 ], [ %sext, %bb9 ]
+  %phi6 = phi i32 [ 1, %bb2 ], [ %add10, %bb9 ]
+  %trunc = trunc i64 %phi5 to i32
+  br i1 true, label %bb9, label %bb7
+
+bb7:                                              ; preds = %bb4
+  %phi8 = phi i32 [ %trunc, %bb4 ]
+  ret void
+
+bb9:                                              ; preds = %bb4
+  %add = add i32 1, %phi
+  %sext = sext i32 %add to i64
+  %add10 = add i32 %phi6, 1
+  %icmp = icmp ugt i32 %add10, 2
+  br i1 %icmp, label %bb11, label %bb4
+
+bb11:                                             ; preds = %bb9
+  br i1 false, label %bb12, label %bb2
+
+bb12:                                             ; preds = %bb12, %bb11
+  br i1 false, label %bb1, label %bb12, !prof !1
+}
+
+!0 = !{!"function_entry_count", i64 32768}
+!1 = !{!"branch_weights", i32 11, i32 1}
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i64 32768}
+; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]]}
+; CHECK: [[META2]] = !{!"llvm.loop.peeled.count", i32 1}
+; CHECK: [[PROF3]] = !{!"branch_weights", i32 11, i32 1}
+; CHECK: [[PROF4]] = !{!"branch_weights", i32 11, i32 11}
+; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META6:![0-9]+]]}
+; CHECK: [[META6]] = !{!"llvm.loop.unroll.disable"}
+;.



More information about the llvm-commits mailing list