Skip to content

Commit 0e73e55

Browse files
mshockwavetomtor
authored andcommitted
[TableGen] Avoid evaluating RHS of a BinOp until short-circuit is complete (llvm#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.
1 parent 6c8055d commit 0e73e55

File tree

2 files changed

+13
-7
lines changed

2 files changed

+13
-7
lines changed

llvm/lib/TableGen/Record.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,8 +1557,7 @@ const Init *BinOpInit::Fold(const Record *CurRec) const {
15571557
}
15581558

15591559
const Init *BinOpInit::resolveReferences(Resolver &R) const {
1560-
const Init *lhs = LHS->resolveReferences(R);
1561-
const Init *rhs = RHS->resolveReferences(R);
1560+
const Init *NewLHS = LHS->resolveReferences(R);
15621561

15631562
unsigned Opc = getOpcode();
15641563
if (Opc == AND || Opc == OR) {
@@ -1570,15 +1569,17 @@ const Init *BinOpInit::resolveReferences(Resolver &R) const {
15701569
// limited version of short-circuit against all ones (`true` is casted
15711570
// to 1 rather than all ones before we evaluate `!or`).
15721571
if (const auto *LHSi = dyn_cast_or_null<IntInit>(
1573-
lhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
1572+
NewLHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
15741573
if ((Opc == AND && !LHSi->getValue()) ||
15751574
(Opc == OR && LHSi->getValue() == -1))
15761575
return LHSi;
15771576
}
15781577
}
15791578

1580-
if (LHS != lhs || RHS != rhs)
1581-
return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))
1579+
const Init *NewRHS = RHS->resolveReferences(R);
1580+
1581+
if (LHS != NewLHS || RHS != NewRHS)
1582+
return (BinOpInit::get(getOpcode(), NewLHS, NewRHS, getType()))
15821583
->Fold(R.getCurrentRecord());
15831584
return this;
15841585
}

llvm/test/TableGen/true-false.td

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,18 @@ def rec7 {
6767
bits<3> flags = { true, false, true };
6868
}
6969

70-
// `!and` and `!or` should be short-circuit such that `!tail` on empty list will never
71-
// be evaluated.
70+
// `!and` and `!or` should be short-circuited such that any of the `!head` or
71+
// `!tail` on empty list below will never be evaluated.
7272
// CHECK: def rec8
73+
// CHECK: bit v = 0;
74+
// CHECK: int v2 = -1;
7375
// CHECK: list<int> newSeq = [];
7476
// CHECK: list<int> newSeq2 = [];
7577

7678
class Foo <list<int> seq = []> {
79+
bit v = !and(false, !head(seq));
80+
int v2 = !or(-1, !head(seq));
81+
7782
bit unresolved = !ne(!find(NAME, "BAR"), -1);
7883
list<int> newSeq = !if(!and(false, unresolved), !tail(seq), seq);
7984
list<int> newSeq2 = !if(!or(-1, unresolved), seq, !tail(seq));

0 commit comments

Comments
 (0)