From a5fda5be493bfba5c7a45a32aeb6df0e16ec4ef1 Mon Sep 17 00:00:00 2001 From: Min Hsu 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 newSeq = []; // CHECK: list newSeq2 = []; class Foo seq = []> { + bit v = !and(false, !head(seq)); + int v2 = !or(-1, !head(seq)); + bit unresolved = !ne(!find(NAME, "BAR"), -1); list newSeq = !if(!and(false, unresolved), !tail(seq), seq); list newSeq2 = !if(!or(-1, unresolved), seq, !tail(seq)); From 959814d6d570a209607fcc1632e8f7e3514f0623 Mon Sep 17 00:00:00 2001 From: Min-Yih Hsu 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( - 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;