[llvm] [TableGen] Avoid evaluating RHS of a BinOp until short-circuit is complete (PR #144021)

Min-Yih Hsu via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 13 10:26:52 PDT 2025


https://github.com/mshockwave updated https://github.com/llvm/llvm-project/pull/144021

>From a5fda5be493bfba5c7a45a32aeb6df0e16ec4ef1 Mon Sep 17 00:00:00 2001
From: Min Hsu <min at myhsu.dev>
Date: Thu, 12 Jun 2025 22:45:11 -0700
Subject: [PATCH 1/2] [TableGen] Avoid evaluating RHS of a BinOp until
 short-circuit is complete

---
 llvm/lib/TableGen/Record.cpp     | 3 ++-
 llvm/test/TableGen/true-false.td | 9 +++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 4c8b41237c604..d0bf8323511c2 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -1558,7 +1558,6 @@ const Init *BinOpInit::Fold(const Record *CurRec) const {
 
 const Init *BinOpInit::resolveReferences(Resolver &R) const {
   const Init *lhs = LHS->resolveReferences(R);
-  const Init *rhs = RHS->resolveReferences(R);
 
   unsigned Opc = getOpcode();
   if (Opc == AND || Opc == OR) {
@@ -1577,6 +1576,8 @@ const Init *BinOpInit::resolveReferences(Resolver &R) const {
     }
   }
 
+  const Init *rhs = RHS->resolveReferences(R);
+
   if (LHS != lhs || RHS != rhs)
     return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))
         ->Fold(R.getCurrentRecord());
diff --git a/llvm/test/TableGen/true-false.td b/llvm/test/TableGen/true-false.td
index 5a59f20b21d25..8a1949327e610 100644
--- a/llvm/test/TableGen/true-false.td
+++ b/llvm/test/TableGen/true-false.td
@@ -67,13 +67,18 @@ def rec7 {
   bits<3> flags = { true, false, true };
 }
 
-// `!and` and `!or` should be short-circuit such that `!tail` on empty list will never
-// be evaluated.
+// `!and` and `!or` should be short-circuit such that any of the `!head` or
+// `!tail` on empty list below will never be evaluated.
 // CHECK: def rec8
+// CHECK:   bit v = 0;
+// CHECK:   int v2 = -1;
 // CHECK:   list<int> newSeq = [];
 // CHECK:   list<int> newSeq2 = [];
 
 class Foo <list<int> seq = []> {
+  bit v = !and(false, !head(seq));
+  int v2 = !or(-1, !head(seq));
+
   bit unresolved = !ne(!find(NAME, "BAR"), -1);
   list<int> newSeq  = !if(!and(false, unresolved), !tail(seq), seq);
   list<int> newSeq2 = !if(!or(-1, unresolved), seq, !tail(seq));

>From 959814d6d570a209607fcc1632e8f7e3514f0623 Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Fri, 13 Jun 2025 10:26:28 -0700
Subject: [PATCH 2/2] fixup! Address review comments

---
 llvm/lib/TableGen/Record.cpp     | 10 +++++-----
 llvm/test/TableGen/true-false.td |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index d0bf8323511c2..7f2ed77a74099 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -1557,7 +1557,7 @@ const Init *BinOpInit::Fold(const Record *CurRec) const {
 }
 
 const Init *BinOpInit::resolveReferences(Resolver &R) const {
-  const Init *lhs = LHS->resolveReferences(R);
+  const Init *NewLHS = LHS->resolveReferences(R);
 
   unsigned Opc = getOpcode();
   if (Opc == AND || Opc == OR) {
@@ -1569,17 +1569,17 @@ const Init *BinOpInit::resolveReferences(Resolver &R) const {
     // limited version of short-circuit against all ones (`true` is casted
     // to 1 rather than all ones before we evaluate `!or`).
     if (const auto *LHSi = dyn_cast_or_null<IntInit>(
-            lhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
+            NewLHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
       if ((Opc == AND && !LHSi->getValue()) ||
           (Opc == OR && LHSi->getValue() == -1))
         return LHSi;
     }
   }
 
-  const Init *rhs = RHS->resolveReferences(R);
+  const Init *NewRHS = RHS->resolveReferences(R);
 
-  if (LHS != lhs || RHS != rhs)
-    return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))
+  if (LHS != NewLHS || RHS != NewRHS)
+    return (BinOpInit::get(getOpcode(), NewLHS, NewRHS, getType()))
         ->Fold(R.getCurrentRecord());
   return this;
 }
diff --git a/llvm/test/TableGen/true-false.td b/llvm/test/TableGen/true-false.td
index 8a1949327e610..5fa5702314489 100644
--- a/llvm/test/TableGen/true-false.td
+++ b/llvm/test/TableGen/true-false.td
@@ -67,7 +67,7 @@ def rec7 {
   bits<3> flags = { true, false, true };
 }
 
-// `!and` and `!or` should be short-circuit such that any of the `!head` or
+// `!and` and `!or` should be short-circuited such that any of the `!head` or
 // `!tail` on empty list below will never be evaluated.
 // CHECK: def rec8
 // CHECK:   bit v = 0;



More information about the llvm-commits mailing list