[llvm] [NewGVN] Prevent cyclic reference when building phiofops (PR #69418)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 17 21:22:33 PDT 2023


https://github.com/XChy created https://github.com/llvm/llvm-project/pull/69418

Fixes #69211.
This patch adds self-reference check in `findPHIOfOpsLeader`.

>From 02dfc47d2e44d31d180d5e4d2995982dfb2f9220 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Wed, 18 Oct 2023 01:20:43 +0800
Subject: [PATCH] [NewGVN] Prevent cyclic reference when building phiofops

---
 llvm/lib/Transforms/Scalar/NewGVN.cpp         | 10 +++
 .../Transforms/NewGVN/cyclic-phi-handling.ll  | 74 +++++++++++++++++--
 2 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp
index 19ac9526b5f88b6..2bd5e2127aa340a 100644
--- a/llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -3812,6 +3812,16 @@ Value *NewGVN::findPHIOfOpsLeader(const Expression *E,
     auto *MemberInst = dyn_cast<Instruction>(Member);
     if (MemberInst == OrigInst)
       continue;
+
+    // Prevent cyclic reference, such as:
+    // %a = add i64 %phi, 1
+    // %foundinst = add i64 %a, 1
+    // =>
+    // %phiofops = phi i64 [1, %BB1], [%foundinst, %BB2]
+    // %foundinst = add i64 %phiofops, 1
+    if (llvm::find(MemberInst->operands(), OrigInst) != MemberInst->op_end())
+      continue;
+
     // Anything that isn't an instruction is always available.
     if (!MemberInst)
       return Member;
diff --git a/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll b/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll
index 4a2f0b972c9fe1a..5f8d90aa4a6aa21 100644
--- a/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll
+++ b/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll
@@ -5,15 +5,15 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
 define void @foo(i32 %arg, i32 %arg1, ptr %arg2) {
 ; CHECK-LABEL: @foo(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    br label %bb3
+; CHECK-NEXT:    br label [[BB3:%.*]]
 ; CHECK:       bb3:
-; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ %arg1, %bb ], [ [[TMP:%.*]]4, %bb7 ]
-; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ %arg, %bb ], [ [[TMP]], %bb7 ]
-; CHECK-NEXT:    [[TMP5:%.*]] = call i32 %arg2(i32 [[TMP4]], i32 [[TMP]])
+; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ [[ARG1:%.*]], [[BB:%.*]] ], [ [[TMP4:%.*]], [[BB7:%.*]] ]
+; CHECK-NEXT:    [[TMP4]] = phi i32 [ [[ARG:%.*]], [[BB]] ], [ [[TMP]], [[BB7]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = call i32 [[ARG2:%.*]](i32 [[TMP4]], i32 [[TMP]])
 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
-; CHECK-NEXT:    br i1 [[TMP6]], label %bb7, label %bb8
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB7]], label [[BB8:%.*]]
 ; CHECK:       bb7:
-; CHECK-NEXT:    br label %bb3
+; CHECK-NEXT:    br label [[BB3]]
 ; CHECK:       bb8:
 ; CHECK-NEXT:    ret void
 ;
@@ -35,3 +35,65 @@ bb7:                                              ; preds = %bb3
 bb8:                                              ; preds = %bb3
   ret void
 }
+
+; Don't let %b be the candidate when making %a phi of ops
+define i64 @phis_of_ops_cyclic() {
+; CHECK-LABEL: @phis_of_ops_cyclic(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[A:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT:    [[A]] = add i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[B:%.*]] = add i64 [[A]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp slt i64 [[A]], 100
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[FOR_BODY]], label [[END:%.*]]
+; CHECK:       end:
+; CHECK-NEXT:    ret i64 [[B]]
+;
+entry:
+  br label %for.body
+
+for.body:                                        ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %a = add i64 %indvars.iv, 1
+  %b = add i64 %a, 1
+
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %tobool = icmp slt i64 %indvars.iv.next, 100
+  br i1 %tobool, label %for.body, label %end
+
+end:
+  ret i64 %b
+}
+
+define i64 @phis_of_ops_cyclic_multiple() {
+; CHECK-LABEL: @phis_of_ops_cyclic_multiple(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[A:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT:    [[A]] = add i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[B:%.*]] = add i64 [[A]], 1
+; CHECK-NEXT:    [[D:%.*]] = add i64 [[B]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp slt i64 [[A]], 100
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[FOR_BODY]], label [[END:%.*]]
+; CHECK:       end:
+; CHECK-NEXT:    ret i64 [[D]]
+;
+entry:
+  br label %for.body
+
+for.body:                                        ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %a = add i64 %indvars.iv, 1
+  %b = add i64 %a, 1
+  %c = add i64 %a, 1
+  %d = add i64 %b, 1
+
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %tobool = icmp slt i64 %indvars.iv.next, 100
+  br i1 %tobool, label %for.body, label %end
+
+end:
+  ret i64 %d
+}



More information about the llvm-commits mailing list