Skip to content

Conversation

@Camsyn
Copy link
Contributor

@Camsyn Camsyn commented Oct 28, 2025

Some analysis/transformation, e.g., predicate info/ mem ssa, insert instruction annotations as comments, referring to #165249 (comment).

This PR makes UTC support checking these instruction annotations with an extra UTC option -check-inst-comments.

E.g.,
Before:

; CHECK:         [[Z_0:%.*]] = bitcast i1 [[Z]] to i1

After:

; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = and i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label %nope], RenamedOp: [[Z]] }
; CHECK-NEXT:    [[Z_0:%.*]] = bitcast i1 [[Z]] to i1

This PR also regenerates all UTC-generated tests for PredicateInfo; No MemSSA test is updated, as there are no UTC-generated tests designated for print<memoryssa>.

@llvmbot
Copy link
Member

llvmbot commented Oct 28, 2025

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-testing-tools

Author: Kunqiu Chen (Camsyn)

Changes

Some analysis/transformation, e.g., predicate info/ mem ssa, insert annotations as comments, referring to #165249 (comment).

This PR makes UTC support checking these annotations with an extra UTC option -check-comments.

E.g.,
Before:

; CHECK:         [[Z_0:%.*]] = bitcast i1 [[Z]] to i1

After:

; CHECK-NEXT:  ; Has predicate info
; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = and i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label %nope], RenamedOp: [[Z]] }
; CHECK-NEXT:    [[Z_0:%.*]] = bitcast i1 [[Z]] to i1

This PR also regenerates all UTC-generated tests for PredicateInfo; No MemSSA test is updated, as there are no UTC-generated tests designated for print&lt;memoryssa&gt;.


Patch is 76.69 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/165419.diff

9 Files Affected:

  • (modified) llvm/test/Transforms/Util/PredicateInfo/branch-on-same-cond.ll (+22-15)
  • (modified) llvm/test/Transforms/Util/PredicateInfo/condprop.ll (+82-28)
  • (modified) llvm/test/Transforms/Util/PredicateInfo/diamond.ll (+14-6)
  • (modified) llvm/test/Transforms/Util/PredicateInfo/edge.ll (+39-21)
  • (modified) llvm/test/Transforms/Util/PredicateInfo/pr33456.ll (+12-7)
  • (modified) llvm/test/Transforms/Util/PredicateInfo/pr33457.ll (+17-10)
  • (modified) llvm/test/Transforms/Util/PredicateInfo/testandor.ll (+320-108)
  • (modified) llvm/utils/UpdateTestChecks/common.py (+19-5)
  • (modified) llvm/utils/update_test_checks.py (+8)
diff --git a/llvm/test/Transforms/Util/PredicateInfo/branch-on-same-cond.ll b/llvm/test/Transforms/Util/PredicateInfo/branch-on-same-cond.ll
index 0be13ee76bece..3d4cf57d734a3 100644
--- a/llvm/test/Transforms/Util/PredicateInfo/branch-on-same-cond.ll
+++ b/llvm/test/Transforms/Util/PredicateInfo/branch-on-same-cond.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-comments
 ; RUN: opt -S -passes=print-predicateinfo < %s 2>&1 >/dev/null | FileCheck %s
 
 ; FIXME:  RenamedOp should be %cmp or %x in all cases here,
@@ -9,24 +9,31 @@ define i32 @test(i32 %x) {
 ; CHECK-NEXT:    br label [[BB1:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK: RenamedOp: [[CMP]]
-; CHECK:         [[CMP_0:%.*]] = bitcast i1 [[CMP]] to i1
-; CHECK: RenamedOp: [[X]]
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB1]],label %bb2], RenamedOp: [[CMP]] }
+; CHECK-NEXT:    [[CMP_0:%.*]] = bitcast i1 [[CMP]] to i1
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB1]],label %bb2], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB2:%.*]], label [[EXIT1:%.*]]
 ; CHECK:       bb2:
-; CHECK: RenamedOp: [[CMP_0]]
-; CHECK:         [[CMP_0_1:%.*]] = bitcast i1 [[CMP_0]] to i1
-; CHECK: RenamedOp: [[X]]
-; CHECK:         [[X_0_1:%.*]] = bitcast i32 [[X_0]] to i32
-; CHECK: RenamedOp: [[X_0]]
-; CHECK:         [[X_0_4:%.*]] = bitcast i32 [[X_0]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB2]],label %bb3], RenamedOp: [[CMP_0]] }
+; CHECK-NEXT:    [[CMP_0_1:%.*]] = bitcast i1 [[CMP_0]] to i1
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB2]],label %bb3], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0_1:%.*]] = bitcast i32 [[X_0]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB2]],label %exit2], RenamedOp: [[X_0]] }
+; CHECK-NEXT:    [[X_0_4:%.*]] = bitcast i32 [[X_0]] to i32
 ; CHECK-NEXT:    br i1 [[CMP_0]], label [[BB3:%.*]], label [[EXIT2:%.*]]
 ; CHECK:       bb3:
-; CHECK: RenamedOp: [[X]]
-; CHECK:         [[X_0_1_2:%.*]] = bitcast i32 [[X_0_1]] to i32
-; CHECK: RenamedOp: [[X_0_1]]
-; CHECK:         [[X_0_1_3:%.*]] = bitcast i32 [[X_0_1]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB3]],label %exit3], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0_1_2:%.*]] = bitcast i32 [[X_0_1]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB3]],label %exit4], RenamedOp: [[X_0_1]] }
+; CHECK-NEXT:    [[X_0_1_3:%.*]] = bitcast i32 [[X_0_1]] to i32
 ; CHECK-NEXT:    br i1 [[CMP_0_1]], label [[EXIT3:%.*]], label [[EXIT4:%.*]]
 ; CHECK:       exit1:
 ; CHECK-NEXT:    ret i32 0
diff --git a/llvm/test/Transforms/Util/PredicateInfo/condprop.ll b/llvm/test/Transforms/Util/PredicateInfo/condprop.ll
index 256d0d908ec1e..2720e8b2c06e2 100644
--- a/llvm/test/Transforms/Util/PredicateInfo/condprop.ll
+++ b/llvm/test/Transforms/Util/PredicateInfo/condprop.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-comments
 ; RUN: opt -passes=print-predicateinfo -disable-output < %s 2>&1 | FileCheck %s
 
 @a = external global i32		; <ptr> [#uses=7]
@@ -98,11 +98,21 @@ define void @test3(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
 ; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
 ; CHECK-NEXT:    [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
-; CHECK:         [[Z_0:%.*]] = bitcast i1 [[Z]] to i1
-; CHECK:         [[XZ_0:%.*]] = bitcast i1 [[XZ]] to i1
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
-; CHECK:         [[YZ_0:%.*]] = bitcast i1 [[YZ]] to i1
-; CHECK:         [[Y_0:%.*]] = bitcast i32 [[Y]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = and i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label %nope], RenamedOp: [[Z]] }
+; CHECK-NEXT:    [[Z_0:%.*]] = bitcast i1 [[Z]] to i1
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label %both_zero], RenamedOp: [[XZ]] }
+; CHECK-NEXT:    [[XZ_0:%.*]] = bitcast i1 [[XZ]] to i1
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label %both_zero], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label %both_zero], RenamedOp: [[YZ]] }
+; CHECK-NEXT:    [[YZ_0:%.*]] = bitcast i1 [[YZ]] to i1
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label %both_zero], RenamedOp: [[Y]] }
+; CHECK-NEXT:    [[Y_0:%.*]] = bitcast i32 [[Y]] to i32
 ; CHECK-NEXT:    br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
 ; CHECK:       both_zero:
 ; CHECK-NEXT:    call void @foo(i1 [[XZ_0]])
@@ -133,7 +143,9 @@ define void @test4(i1 %b, i32 %x) {
 ; CHECK-LABEL: @test4(
 ; CHECK-NEXT:    br i1 [[B:%.*]], label [[SW:%.*]], label [[CASE3:%.*]]
 ; CHECK:       sw:
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X:%.*]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; switch predicate info { CaseValue: i32 1 Edge: [label [[SW]],label %case1], RenamedOp: [[X:%.*]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
 ; CHECK-NEXT:    switch i32 [[X]], label [[DEFAULT:%.*]] [
 ; CHECK-NEXT:      i32 0, label [[CASE0:%.*]]
 ; CHECK-NEXT:      i32 1, label [[CASE1:%.*]]
@@ -180,10 +192,18 @@ case3:
 define i1 @test5(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test5(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
-; CHECK:         [[X_1:%.*]] = bitcast i32 [[X]] to i32
-; CHECK:         [[Y_0:%.*]] = bitcast i32 [[Y]] to i32
-; CHECK:         [[Y_1:%.*]] = bitcast i32 [[Y]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], [[Y]] Edge: [label [[TMP0:%.*]],label %same], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp eq i32 [[X]], [[Y]] Edge: [label [[TMP0]],label %different], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_1:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], [[Y]] Edge: [label [[TMP0]],label %same], RenamedOp: [[Y]] }
+; CHECK-NEXT:    [[Y_0:%.*]] = bitcast i32 [[Y]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp eq i32 [[X]], [[Y]] Edge: [label [[TMP0]],label %different], RenamedOp: [[Y]] }
+; CHECK-NEXT:    [[Y_1:%.*]] = bitcast i32 [[Y]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
 ; CHECK:       same:
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[X_0]], [[Y_0]]
@@ -253,10 +273,18 @@ different:
 define i1 @test7(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test7(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
-; CHECK:         [[X_1:%.*]] = bitcast i32 [[X]] to i32
-; CHECK:         [[Y_0:%.*]] = bitcast i32 [[Y]] to i32
-; CHECK:         [[Y_1:%.*]] = bitcast i32 [[Y]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp sgt i32 [[X]], [[Y]] Edge: [label [[TMP0:%.*]],label %same], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp sgt i32 [[X]], [[Y]] Edge: [label [[TMP0]],label %different], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_1:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp sgt i32 [[X]], [[Y]] Edge: [label [[TMP0]],label %same], RenamedOp: [[Y]] }
+; CHECK-NEXT:    [[Y_0:%.*]] = bitcast i32 [[Y]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp sgt i32 [[X]], [[Y]] Edge: [label [[TMP0]],label %different], RenamedOp: [[Y]] }
+; CHECK-NEXT:    [[Y_1:%.*]] = bitcast i32 [[Y]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
 ; CHECK:       same:
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[X_0]], [[Y_0]]
@@ -280,10 +308,18 @@ different:
 define i1 @test7_fp(float %x, float %y) {
 ; CHECK-LABEL: @test7_fp(
 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
-; CHECK:         [[X_0:%.*]] = bitcast float [[X]] to float
-; CHECK:         [[X_1:%.*]] = bitcast float [[X]] to float
-; CHECK:         [[Y_0:%.*]] = bitcast float [[Y]] to float
-; CHECK:         [[Y_1:%.*]] = bitcast float [[Y]] to float
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = fcmp ogt float [[X]], [[Y]] Edge: [label [[TMP0:%.*]],label %same], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast float [[X]] to float
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = fcmp ogt float [[X]], [[Y]] Edge: [label [[TMP0]],label %different], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_1:%.*]] = bitcast float [[X]] to float
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = fcmp ogt float [[X]], [[Y]] Edge: [label [[TMP0]],label %same], RenamedOp: [[Y]] }
+; CHECK-NEXT:    [[Y_0:%.*]] = bitcast float [[Y]] to float
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = fcmp ogt float [[X]], [[Y]] Edge: [label [[TMP0]],label %different], RenamedOp: [[Y]] }
+; CHECK-NEXT:    [[Y_1:%.*]] = bitcast float [[Y]] to float
 ; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
 ; CHECK:       same:
 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ule float [[X_0]], [[Y_0]]
@@ -353,8 +389,12 @@ different:
 define i32 @test9(i32 %i, i32 %j) {
 ; CHECK-LABEL: @test9(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
-; CHECK:         [[I_0:%.*]] = bitcast i32 [[I]] to i32
-; CHECK:         [[J_0:%.*]] = bitcast i32 [[J]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[I]], [[J]] Edge: [label [[TMP0:%.*]],label %cond_true], RenamedOp: [[I]] }
+; CHECK-NEXT:    [[I_0:%.*]] = bitcast i32 [[I]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[I]], [[J]] Edge: [label [[TMP0]],label %cond_true], RenamedOp: [[J]] }
+; CHECK-NEXT:    [[J_0:%.*]] = bitcast i32 [[J]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
 ; CHECK:       cond_true:
 ; CHECK-NEXT:    [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
@@ -376,8 +416,12 @@ ret:
 define i32 @test10(i32 %j, i32 %i) {
 ; CHECK-LABEL: @test10(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
-; CHECK:         [[I_0:%.*]] = bitcast i32 [[I]] to i32
-; CHECK:         [[J_0:%.*]] = bitcast i32 [[J]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[I]], [[J]] Edge: [label [[TMP0:%.*]],label %cond_true], RenamedOp: [[I]] }
+; CHECK-NEXT:    [[I_0:%.*]] = bitcast i32 [[I]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[I]], [[J]] Edge: [label [[TMP0]],label %cond_true], RenamedOp: [[J]] }
+; CHECK-NEXT:    [[J_0:%.*]] = bitcast i32 [[J]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
 ; CHECK:       cond_true:
 ; CHECK-NEXT:    [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
@@ -403,14 +447,20 @@ define i32 @test11(i32 %x) {
 ; CHECK-NEXT:    [[V0:%.*]] = call i32 @yogibar()
 ; CHECK-NEXT:    [[V1:%.*]] = call i32 @yogibar()
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[V0]], [[V1]]
-; CHECK:         [[V0_0:%.*]] = bitcast i32 [[V0]] to i32
-; CHECK:         [[V1_0:%.*]] = bitcast i32 [[V1]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp eq i32 [[V0]], [[V1]] Edge: [label [[TMP0:%.*]],label %next], RenamedOp: [[V0]] }
+; CHECK-NEXT:    [[V0_0:%.*]] = bitcast i32 [[V0]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[V0]], [[V1]] Edge: [label [[TMP0]],label %cond_true], RenamedOp: [[V1]] }
+; CHECK-NEXT:    [[V1_0:%.*]] = bitcast i32 [[V1]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[NEXT:%.*]]
 ; CHECK:       cond_true:
 ; CHECK-NEXT:    ret i32 [[V1_0]]
 ; CHECK:       next:
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], [[V0_0]]
-; CHECK:         [[V0_0_1:%.*]] = bitcast i32 [[V0_0]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP2]] = icmp eq i32 [[X]], [[V0_0]] Edge: [label [[NEXT]],label %cond_true2], RenamedOp: [[V0_0]] }
+; CHECK-NEXT:    [[V0_0_1:%.*]] = bitcast i32 [[V0_0]] to i32
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE2:%.*]], label [[NEXT2:%.*]]
 ; CHECK:       cond_true2:
 ; CHECK-NEXT:    ret i32 [[V0_0_1]]
@@ -439,8 +489,12 @@ next2:
 define i32 @test12(i32 %x) {
 ; CHECK-LABEL: @test12(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
-; CHECK:         [[X_1:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0:%.*]],label %cond_true], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label %cond_false], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_1:%.*]] = bitcast i32 [[X]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
 ; CHECK:       cond_true:
 ; CHECK-NEXT:    br label [[RET:%.*]]
diff --git a/llvm/test/Transforms/Util/PredicateInfo/diamond.ll b/llvm/test/Transforms/Util/PredicateInfo/diamond.ll
index ac2c9a1026e76..6900a2a710c72 100644
--- a/llvm/test/Transforms/Util/PredicateInfo/diamond.ll
+++ b/llvm/test/Transforms/Util/PredicateInfo/diamond.ll
@@ -1,16 +1,20 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=print-predicateinfo < %s 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-comments
+; RUN: opt -passes=print-predicateinfo -disable-output < %s 2>&1 | FileCheck %s
 define i1 @f(i32 %x, i1 %y) {
 ; CHECK-LABEL: @f(
 ; CHECK-NEXT:    br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb0:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp sge i32 [[X]], 0 Edge: [label [[BB0]],label %bb2], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[X2:%.*]] = add nuw nsw i32 [[X]], 1
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
-; CHECK:         [[X2_0:%.*]] = bitcast i32 [[X2]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP2]] = icmp sge i32 [[X2]], 2 Edge: [label [[BB1]],label %bb2], RenamedOp: [[X2]] }
+; CHECK-NEXT:    [[X2_0:%.*]] = bitcast i32 [[X2]] to i32
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[BB2]], label [[BB3]]
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
@@ -38,12 +42,16 @@ define i1 @g(i32 %x, i1 %y) {
 ; CHECK-NEXT:    br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb0:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp sge i32 [[X]], 0 Edge: [label [[BB0]],label %bb2], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB3:%.*]], label [[BB2:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[X2:%.*]] = add nuw nsw i32 [[X]], 1
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
-; CHECK:         [[X2_0:%.*]] = bitcast i32 [[X2]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP2]] = icmp sge i32 [[X2]], 2 Edge: [label [[BB1]],label %bb2], RenamedOp: [[X2]] }
+; CHECK-NEXT:    [[X2_0:%.*]] = bitcast i32 [[X2]] to i32
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[BB3]], label [[BB2]]
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
diff --git a/llvm/test/Transforms/Util/PredicateInfo/edge.ll b/llvm/test/Transforms/Util/PredicateInfo/edge.ll
index ef757f323921a..86acca2245e3e 100644
--- a/llvm/test/Transforms/Util/PredicateInfo/edge.ll
+++ b/llvm/test/Transforms/Util/PredicateInfo/edge.ll
@@ -1,16 +1,18 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=print-predicateinfo < %s 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-comments
+; RUN: opt -passes=print-predicateinfo -disable-output < %s 2>&1 | FileCheck %s
 
 define i32 @f1(i32 %x) {
 ; CHECK-LABEL: @f1(
 ; CHECK-NEXT:  bb0:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 1 Comparison: [[CMP]] = icmp eq i32 [[X]], 0 Edge: [label [[BB0:%.*]],label %bb2], RenamedOp: [[X]] }
+; CHECK-NEXT:    [[X_0:%.*]] = bitcast i32 [[X]] to i32
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB2:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    br label [[BB2]]
 ; CHECK:       bb2:
-; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ 0, [[BB1]] ]
 ; CHECK-NEXT:    [[FOO:%.*]] = add i32 [[COND]], [[X]]
 ; CHECK-NEXT:    ret i32 [[FOO]]
 ;
@@ -29,12 +31,14 @@ define i32 @f2(i32 %x) {
 ; CHECK-LABEL: @f2(
 ; CHECK-NEXT:  bb0:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0
-; CHECK:         [[X_0:%.*]] = bitcast i32 [[X]] to i32
+; CHECK-NEXT:  ; Has predicate info
+; CHECK-NEXT:  ; branch predicate info { TrueEdge: 0 Comparison: [[CMP]] = icmp ne i32 [[X]], 0 Edge: [label...
[truncated]

; CHECK-NEXT: store i32 6, ptr @e, align 4
; CHECK-NEXT: br label [[TMP1:%.*]]
; CHECK: [[TMP2:%.*]] = load i32, ptr @d, align 4
; CHECK: 1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should probably be variable captures. Any idea why it's not working?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the script regex for labels expected a leading alphabetical character?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocks are only variables in newer UTC versions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it works. The change here is adding a check for block labels.
From

; CHECK:         [[TMP2:%.*]] = load i32, ptr @d, align  4

To

; CHECK:       1:
; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr @d, align 4

Copy link
Contributor Author

@Camsyn Camsyn Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the script regex for labels expected a leading alphabetical character?

In fact, this change was not introduced by this PR, and I don't know why the label check here is CHECK: 1:.

Copy link
Member

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be the default behaviour (with a --version bump)?

Being able to use CHECK-NEXT more instead of the more fragile CHECK is IMO a good thing.

; CHECK-NEXT: store i32 6, ptr @e, align 4
; CHECK-NEXT: br label [[TMP1:%.*]]
; CHECK: [[TMP2:%.*]] = load i32, ptr @d, align 4
; CHECK: 1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the script regex for labels expected a leading alphabetical character?

; CHECK: [[CMP_0:%.*]] = bitcast i1 [[CMP]] to i1
; CHECK: RenamedOp: [[X]]
; CHECK: [[X_0:%.*]] = bitcast i32 [[X]] to i32
; CHECK-NEXT: ; Has predicate info
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest dropping this from the PredicateInfo printing, it's rather redundant...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done by #165434

@Camsyn
Copy link
Contributor Author

Camsyn commented Oct 28, 2025

Hi, @arichardson

Should this be the default behaviour (with a --version bump)?

This change is the default behaviour, but only enabled when an extra UTC option --check-comments specified.
And I don't think it's necessary to control it with versions.

Being able to use CHECK-NEXT more instead of the more fragile CHECK is IMO a good thing.

This change is not introduced by this PR. And I think using CHECK instead of CHECK-NEXT is somehow reasonable, since there is an empty line between the two lines required checking:

; CHECK-NEXT:    br label [[TMP1:%.*]]
; CHECK:         [[TMP2:%.*]] = load i32, ptr @d, align 4
....
  br label %1

; <label>:1:                                      ; preds = %17, %0
  %2 = load i32, ptr @d, align 4

Copy link
Member

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have a --check-attributes option to check another subset of comments. Could you add a test showing whether the new --check-comments flag also checks the function attributes comment?

Comment on lines 1910 to 1916
scrubbed_line = (
# Ignore any comments, since the check lines will too.
SCRUB_IR_COMMENT_RE.sub(r"", line)
if ignore_all_comments
# Ignore comments of predecessors only.
else SCRUB_PRED_COMMENT_RE.sub(r"", line)
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
scrubbed_line = (
# Ignore any comments, since the check lines will too.
SCRUB_IR_COMMENT_RE.sub(r"", line)
if ignore_all_comments
# Ignore comments of predecessors only.
else SCRUB_PRED_COMMENT_RE.sub(r"", line)
)
if ignore_all_comments:
# Ignore any comments, since the check lines will too.
scrubbed_line = SCRUB_IR_COMMENT_RE.sub(r"", line)
else:
# Ignore comments of predecessors only.
scrubbed_line = SCRUB_PRED_COMMENT_RE.sub(r"", line)

Same number of lines and IMO slightly easier to read than the ternary.

@arichardson
Copy link
Member

Hi, @arichardson

Should this be the default behaviour (with a --version bump)?

This change is the default behaviour, but only enabled when an extra UTC option --check-comments specified. And I don't think it's necessary to control it with versions.

Being able to use CHECK-NEXT more instead of the more fragile CHECK is IMO a good thing.

This change is not introduced by this PR. And I think using CHECK instead of CHECK-NEXT is somehow reasonable, since there is an empty line between the two lines required checking:

; CHECK-NEXT:    br label [[TMP1:%.*]]
; CHECK:         [[TMP2:%.*]] = load i32, ptr @d, align 4
....
  br label %1

; <label>:1:                                      ; preds = %17, %0
  %2 = load i32, ptr @d, align 4

We could add a CHECK-EMPTY: and a CHECK-NEXT for the label comment, but that should probably be a separate change.

@Camsyn
Copy link
Contributor Author

Camsyn commented Oct 28, 2025

We also have a --check-attributes option to check another subset of comments. Could you add a test showing whether the new --check-comments flag also checks the function attributes comment?

It does not.
--check-comments only checks IR comments, orthogonal to --check-attributes, which checks the function comments.

Maybe we should rename this option to --check-ir-comments?

@Camsyn
Copy link
Contributor Author

Camsyn commented Oct 28, 2025

We could add a CHECK-EMPTY: and a CHECK-NEXT for the label comment, but that should probably be a separate change.

I will take a look.

@github-actions
Copy link

github-actions bot commented Oct 28, 2025

✅ With the latest revision this PR passed the Python code formatter.

@arichardson
Copy link
Member

We also have a --check-attributes option to check another subset of comments. Could you add a test showing whether the new --check-comments flag also checks the function attributes comment?

It does not. --check-comments only checks IR comments, orthogonal to --check-attributes, which checks the function comments.

Maybe we should rename this option to --check-ir-comments?

Technically I guess the whole file is IR but I can't think of a better name that isn't super long (--check-comments-in-function). So this sounds good to me.

@Camsyn
Copy link
Contributor Author

Camsyn commented Oct 28, 2025

Technically I guess the whole file is IR but I can't think of a better name that isn't super long (--check-comments-in-function). So this sounds good to me.

My mistake. It should be comments attached to IR instructions.

I'm wondering if we need to check all comments through this option, i.e., global/function/BB/instruction comments (print-predicate-info/print<memssa> insert instruction comments; but I don't know if there is any other pass inserting other comments required checking...).
If not, maybe --check-inst-comments is a good name, and I will validate that it only works on IR instructions.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after a rebase.

@@ -1,4 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-comments
Copy link
Member

@arichardson arichardson Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-comments
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-inst-comments

And the same below

help="Check global entries (global variables, metadata, attribute sets, ...) for functions",
)
parser.add_argument(
"--check-inst_comments",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"--check-inst_comments",
"--check-inst-comments",

Copy link
Member

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with updated tests

Camsyn added a commit that referenced this pull request Oct 29, 2025
See
#165419 (comment)
for details.

The extra annotation `"; Has predicate info"` does not provide any extra
information and might poison the UTC-generated checks introduced by
#165419.
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Oct 29, 2025
…165434)

See
llvm/llvm-project#165419 (comment)
for details.

The extra annotation `"; Has predicate info"` does not provide any extra
information and might poison the UTC-generated checks introduced by
#165419.
; CHECK: [[X_0:%.*]] = bitcast i32 [[X]] to i32
; CHECK: [[YZ_0:%.*]] = bitcast i1 [[YZ]] to i1
; CHECK: [[Y_0:%.*]] = bitcast i32 [[Y]] to i32
; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = and i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label %nope], RenamedOp: [[Z]] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here one of the labels gets a wildcard and the other doesn't. I wonder whether printing a space after the comma would give use consistent behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether printing a space after the comma would give use consistent behavior?

@nikic, Unfortunately, it does not work :(.

It is another reason to cause such inconsistency.
image

Copy link
Contributor Author

@Camsyn Camsyn Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the wildcard is used to define [[TMP0]] when it first appears, and the following [[TMP0]]]s just reference the first definition, just like mermaid/dot grammar

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these tests default to an old --version which doesn't use wildcards for labels. Could you try adding --version 6 to the start of the test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants