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

This patch adds an even more aggressive short-circuit on `!and` and
`!or` that completely avoids the evaluation of RHS operand until short
circuiting decisions are made.
This commit is contained in:
Min-Yih Hsu 2025-06-13 10:36:09 -07:00 committed by GitHub
parent 5578bcbcfd
commit ecdb549e6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 13 additions and 7 deletions

View File

@ -1557,8 +1557,7 @@ unresolved:
}
const Init *BinOpInit::resolveReferences(Resolver &R) const {
const Init *lhs = LHS->resolveReferences(R);
const Init *rhs = RHS->resolveReferences(R);
const Init *NewLHS = LHS->resolveReferences(R);
unsigned Opc = getOpcode();
if (Opc == AND || Opc == OR) {
@ -1570,15 +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;
}
}
if (LHS != lhs || RHS != rhs)
return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))
const Init *NewRHS = RHS->resolveReferences(R);
if (LHS != NewLHS || RHS != NewRHS)
return (BinOpInit::get(getOpcode(), NewLHS, NewRHS, getType()))
->Fold(R.getCurrentRecord());
return this;
}

View File

@ -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-circuited 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));