Skip to content

Commit 8cce6ce

Browse files
committed
Add short-circuit for !or and add documentations
1 parent 425ddc6 commit 8cce6ce

File tree

3 files changed

+29
-17
lines changed

3 files changed

+29
-17
lines changed

llvm/docs/TableGen/ProgRef.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,7 +1646,8 @@ and non-0 as true.
16461646
``!and(``\ *a*\ ``,`` *b*\ ``, ...)``
16471647
This operator does a bitwise AND on *a*, *b*, etc., and produces the
16481648
result. A logical AND can be performed if all the arguments are either
1649-
0 or 1.
1649+
0 or 1. This operator is short-circuit to 0 when one of the operands
1650+
is 0.
16501651

16511652
``!cast<``\ *type*\ ``>(``\ *a*\ ``)``
16521653
This operator performs a cast on *a* and produces the result.
@@ -1872,7 +1873,8 @@ and non-0 as true.
18721873
``!or(``\ *a*\ ``,`` *b*\ ``, ...)``
18731874
This operator does a bitwise OR on *a*, *b*, etc., and produces the
18741875
result. A logical OR can be performed if all the arguments are either
1875-
0 or 1.
1876+
0 or 1. This operator is short-circuit to -1 (all ones) if one of the
1877+
operands is -1.
18761878

18771879
``!range([``\ *start*\ ``,]`` *end*\ ``[,``\ *step*\ ``])``
18781880
This operator produces half-open range sequence ``[start : end : step)`` as

llvm/lib/TableGen/Record.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,21 +1543,27 @@ const Init *BinOpInit::resolveReferences(Resolver &R) const {
15431543
const Init *lhs = LHS->resolveReferences(R);
15441544
const Init *rhs = RHS->resolveReferences(R);
15451545

1546-
if (getOpcode() == AND) {
1546+
unsigned Opc = getOpcode();
1547+
if (Opc == AND || Opc == OR) {
15471548
// Short-circuit. Regardless whether this is a logical or bitwise
1548-
// AND.
1549-
if (lhs != LHS)
1550-
if (const auto *LHSi = dyn_cast_or_null<IntInit>(
1551-
lhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
1552-
if (!LHSi->getValue())
1553-
return LHSi;
1554-
}
1555-
if (rhs != RHS)
1556-
if (const auto *RHSi = dyn_cast_or_null<IntInit>(
1557-
rhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
1558-
if (!RHSi->getValue())
1559-
return RHSi;
1560-
}
1549+
// AND/OR.
1550+
// Ideally we could also short-circuit `!or(true, ...)`, but it's
1551+
// difficult to do it right without knowing if rest of the operands
1552+
// are all `bit` or not. Therefore, we're only implementing a relatively
1553+
// limited version of short-circuit against all ones (`true` is casted
1554+
// to 1 rather than all ones before we evaluate `!or`).
1555+
if (const auto *LHSi = dyn_cast_or_null<IntInit>(
1556+
lhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
1557+
if ((Opc == AND && !LHSi->getValue()) ||
1558+
(Opc == OR && LHSi->getValue() == -1))
1559+
return LHSi;
1560+
}
1561+
if (const auto *RHSi = dyn_cast_or_null<IntInit>(
1562+
rhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
1563+
if ((Opc == AND && !RHSi->getValue()) ||
1564+
(Opc == OR && RHSi->getValue() == -1))
1565+
return RHSi;
1566+
}
15611567
}
15621568

15631569
if (LHS != lhs || RHS != rhs)

llvm/test/TableGen/true-false.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,20 @@ def rec7 {
6767
bits<3> flags = { true, false, true };
6868
}
6969

70-
// The `!and` should be short-circuit such that `!tail` on empty list will never
70+
// `!and` and `!or` should be short-circuit such that `!tail` on empty list will never
7171
// be evaluated.
7272
// CHECK: def rec8
7373
// CHECK: list<int> newSeq = [];
7474
// CHECK: list<int> newSeq2 = [];
75+
// CHECK: list<int> newSeq3 = [];
76+
// CHECK: list<int> newSeq4 = [];
7577

7678
class Foo <list<int> seq = []> {
7779
bit containsStr = !ne(!find(NAME, "BAR"), -1);
7880
list<int> newSeq = !if(!and(!not(!empty(seq)), containsStr), !tail(seq), seq);
7981
list<int> newSeq2 = !if(!and(containsStr, !not(!empty(seq))), !tail(seq), seq);
82+
list<int> newSeq3 = !if(!or(containsStr, -1), seq, !tail(seq));
83+
list<int> newSeq4 = !if(!or(-1, containsStr), seq, !tail(seq));
8084
}
8185

8286
def rec8 : Foo<>;

0 commit comments

Comments
 (0)