[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:
parent
5578bcbcfd
commit
ecdb549e6d
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user