[llvm] [TableGen] Make `!and` short-circuit when either of the operand is zero (PR #113963)

via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 28 14:30:47 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-tablegen

Author: Min-Yih Hsu (mshockwave)

<details>
<summary>Changes</summary>

By preemptively simplifying the result of `!and`, we can fold some of the conditional operators, like `!if` or `!cond`, as early as possible.

---
Full diff: https://github.com/llvm/llvm-project/pull/113963.diff


2 Files Affected:

- (modified) llvm/lib/TableGen/Record.cpp (+17) 
- (modified) llvm/test/TableGen/true-false.td (+14) 


``````````diff
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 1d71482b020b22..1f01b82685718a 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -1543,6 +1543,23 @@ const Init *BinOpInit::resolveReferences(Resolver &R) const {
   const Init *lhs = LHS->resolveReferences(R);
   const Init *rhs = RHS->resolveReferences(R);
 
+  if (getOpcode() == AND) {
+    // Short-circuit. Regardless whether this is a logical or bitwise
+    // AND.
+    if (lhs != LHS)
+      if (const auto *LHSi = dyn_cast_or_null<IntInit>(
+              lhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
+        if (!LHSi->getValue())
+          return LHSi;
+      }
+    if (rhs != RHS)
+      if (const auto *RHSi = dyn_cast_or_null<IntInit>(
+              rhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {
+        if (!RHSi->getValue())
+          return RHSi;
+      }
+  }
+
   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 597ad9f5ecc8e7..a9094884dbdb9f 100644
--- a/llvm/test/TableGen/true-false.td
+++ b/llvm/test/TableGen/true-false.td
@@ -67,6 +67,20 @@ def rec7 {
   bits<3> flags = { true, false, true };
 }
 
+// The `!and` should be short-circuit such that `!tail` on empty list will never
+// be evaluated.
+// CHECK: def rec8
+// CHECK:   list<int> newSeq = [];
+// CHECK:   list<int> newSeq2 = [];
+
+class Foo <list<int> seq = []> {
+  bit containsStr = !ne(!find(NAME, "BAR"), -1);
+  list<int> newSeq  = !if(!and(!not(!empty(seq)), containsStr), !tail(seq), seq);
+  list<int> newSeq2 = !if(!and(containsStr, !not(!empty(seq))), !tail(seq), seq);
+}
+
+def rec8 : Foo<>;
+
 #ifdef ERROR1
 // ERROR1: Record name '1' is not a string
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/113963


More information about the llvm-commits mailing list