[llvm] [NewGVN] Prevent cyclic reference when building phiofops (PR #69418)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 17 21:23:44 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: XChy (XChy)
<details>
<summary>Changes</summary>
Fixes #<!-- -->69211.
This patch adds self-reference check in `findPHIOfOpsLeader`.
---
Full diff: https://github.com/llvm/llvm-project/pull/69418.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/NewGVN.cpp (+10)
- (modified) llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll (+68-6)
``````````diff
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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/69418
More information about the llvm-commits
mailing list