[llvm-branch-commits] [llvm] TableGen: Parenthesize negated predicate-dag leaves with operators (PR #210652)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Jul 20 01:05:46 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/210652

>From 146fb5bce897a68ce4c940880d27ec654f35a602 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sun, 19 Jul 2026 09:35:43 +0200
Subject: [PATCH 1/2] TableGen: Parenthesize negated predicate-dag leaves with
 operators

Allows writing more general expressions in the predicate code. Previously
not ("a == b") would be emitted as !a == b.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
 .../RuntimeLibcallEmitter-predicate-dag.td    | 24 ++++++++++++++-----
 .../TableGen/Basic/PredicateExpanderDag.h     |  4 +++-
 llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp |  2 +-
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
index 252bba6b00392..5eb89be0fe7a0 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
@@ -9,18 +9,24 @@ def FUNC1 : RuntimeLibcall;
 def FUNC2 : RuntimeLibcall;
 def FUNC3 : RuntimeLibcall;
 def FUNC4 : RuntimeLibcall;
+def FUNC5 : RuntimeLibcall;
 
 def impl0 : RuntimeLibcallImpl<FUNC0>;
 def impl1 : RuntimeLibcallImpl<FUNC1>;
 def impl2 : RuntimeLibcallImpl<FUNC2>;
 def impl3 : RuntimeLibcallImpl<FUNC3>;
 def impl4 : RuntimeLibcallImpl<FUNC4>;
+def impl5 : RuntimeLibcallImpl<FUNC5>;
 
 def IsAArch64        : LibcallPredicate<[{TT.isAArch64()}]>;
 def IsOSDarwin       : LibcallPredicate<[{TT.isOSDarwin()}]>;
 def IsGNUEnv         : LibcallPredicate<[{TT.isGNUEnvironment()}]>;
 def IsWindowsArm64EC : LibcallPredicate<[{TT.isWindowsArm64EC()}]>;
 
+// A leaf whose Cond itself contains an operator; make sure this is
+// emitted as !(a == b), rather than !a == b.
+def IsX86_32 : LibcallPredicate<[{TT.getArch() == Triple::x86}]>;
+
 def isAArch64_ExceptArm64EC
     : RuntimeLibcallAvailabilityDag<(all_of IsAArch64, (not IsWindowsArm64EC))>;
 
@@ -36,6 +42,9 @@ def isAArch64DarwinOrGNU : RuntimeLibcallAvailabilityDag<
 def isAArch64OrNotDarwinGNU : RuntimeLibcallAvailabilityDag<
   (any_of IsAArch64, (not (any_of IsOSDarwin, IsGNUEnv)))>;
 
+// Negated leaf whose Cond contains an operator: `!(TT.getArch() == ...)`.
+def isNotX86_32 : RuntimeLibcallAvailabilityDag<(not IsX86_32)>;
+
 def isTargetArch : RuntimeLibcallAvailability<[{isTargetArch()}]>;
 
 def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch,
@@ -43,18 +52,21 @@ def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch,
        LibcallImpls<(add impl1), isDarwinOrGNU>,
        LibcallImpls<(add impl2), isNotDarwin>,
        LibcallImpls<(add impl3), isAArch64DarwinOrGNU>,
-       LibcallImpls<(add impl4), isAArch64OrNotDarwinGNU>)
+       LibcallImpls<(add impl4), isAArch64OrNotDarwinGNU>,
+       LibcallImpls<(add impl5), isNotX86_32>)
 >;
 
 // Predicate groups emit sorted by predicate def name
 
-// CHECK: if (TT.isAArch64() && (TT.isOSDarwin() || TT.isGNUEnvironment()) && !TT.isWindowsArm64EC()) {
+// CHECK: if ((TT.isAArch64()) && ((TT.isOSDarwin()) || (TT.isGNUEnvironment())) && !(TT.isWindowsArm64EC())) {
 // CHECK: RTLIB::impl_impl3
-// CHECK: if (TT.isAArch64() || !(TT.isOSDarwin() || TT.isGNUEnvironment())) {
+// CHECK: if ((TT.isAArch64()) || !((TT.isOSDarwin()) || (TT.isGNUEnvironment()))) {
 // CHECK: RTLIB::impl_impl4
-// CHECK: if (TT.isAArch64() && !TT.isWindowsArm64EC()) {
+// CHECK: if ((TT.isAArch64()) && !(TT.isWindowsArm64EC())) {
 // CHECK: RTLIB::impl_impl0
-// CHECK: if (TT.isOSDarwin() || TT.isGNUEnvironment()) {
+// CHECK: if ((TT.isOSDarwin()) || (TT.isGNUEnvironment())) {
 // CHECK: RTLIB::impl_impl1
-// CHECK: if (!TT.isOSDarwin()) {
+// CHECK: if (!(TT.isOSDarwin())) {
 // CHECK: RTLIB::impl_impl2
+// CHECK: if (!(TT.getArch() == Triple::x86)) {
+// CHECK: RTLIB::impl_impl5
diff --git a/llvm/utils/TableGen/Basic/PredicateExpanderDag.h b/llvm/utils/TableGen/Basic/PredicateExpanderDag.h
index 10ee4cc6cfde8..5269a2e0c3703 100644
--- a/llvm/utils/TableGen/Basic/PredicateExpanderDag.h
+++ b/llvm/utils/TableGen/Basic/PredicateExpanderDag.h
@@ -31,7 +31,9 @@ class raw_ostream;
 /// EmitLeaf, which emits the leaf test and returns true on error.
 ///
 /// If \p ParenIfBinOp is true, a surrounding pair of parentheses is emitted
-/// when \p Val lowers to a binary (`&&` / `||`) expression.
+/// when \p Val lowers to a binary (`&&` / `||`) expression.  when \p Val lowers
+/// to a binary (`&&` / `||`) expression. \p EmitLeaf is expected to
+/// parenthesize its emitted leaf.
 bool emitPredicateDag(const Record *Owner, const Init &Val, bool ParenIfBinOp,
                       raw_ostream &OS,
                       function_ref<bool(const Init &, raw_ostream &)> EmitLeaf);
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
index 9c4a9107a6849..c17cad5fece4c 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
@@ -23,7 +23,7 @@ std::string AvailabilityPredicate::lowerCondDag(const Record *Owner,
     if (!DI || !DI->getDef()->isSubClassOf("LibcallPredicate"))
       PrintFatalError(Owner, "predicate dag leaf '" + Leaf.getAsString() +
                                  "' is not a LibcallPredicate");
-    OS << DI->getDef()->getValueAsString("Cond");
+    OS << '(' << DI->getDef()->getValueAsString("Cond") << ')';
     return false;
   };
 

>From f9a440b869c737294ccea96db34c7a3a65fb4e77 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 20 Jul 2026 10:02:37 +0200
Subject: [PATCH 2/2] Only apply parens to not

---
 llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td | 8 ++++----
 llvm/utils/TableGen/Basic/PredicateExpanderDag.cpp        | 8 +++++---
 llvm/utils/TableGen/Basic/PredicateExpanderDag.h          | 5 ++---
 llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp             | 2 +-
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
index 5eb89be0fe7a0..573ab1af1105c 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
@@ -58,13 +58,13 @@ def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch,
 
 // Predicate groups emit sorted by predicate def name
 
-// CHECK: if ((TT.isAArch64()) && ((TT.isOSDarwin()) || (TT.isGNUEnvironment())) && !(TT.isWindowsArm64EC())) {
+// CHECK: if (TT.isAArch64() && (TT.isOSDarwin() || TT.isGNUEnvironment()) && !(TT.isWindowsArm64EC())) {
 // CHECK: RTLIB::impl_impl3
-// CHECK: if ((TT.isAArch64()) || !((TT.isOSDarwin()) || (TT.isGNUEnvironment()))) {
+// CHECK: if (TT.isAArch64() || !(TT.isOSDarwin() || TT.isGNUEnvironment())) {
 // CHECK: RTLIB::impl_impl4
-// CHECK: if ((TT.isAArch64()) && !(TT.isWindowsArm64EC())) {
+// CHECK: if (TT.isAArch64() && !(TT.isWindowsArm64EC())) {
 // CHECK: RTLIB::impl_impl0
-// CHECK: if ((TT.isOSDarwin()) || (TT.isGNUEnvironment())) {
+// CHECK: if (TT.isOSDarwin() || TT.isGNUEnvironment()) {
 // CHECK: RTLIB::impl_impl1
 // CHECK: if (!(TT.isOSDarwin())) {
 // CHECK: RTLIB::impl_impl2
diff --git a/llvm/utils/TableGen/Basic/PredicateExpanderDag.cpp b/llvm/utils/TableGen/Basic/PredicateExpanderDag.cpp
index e9f5c7a468458..15510abce6fef 100644
--- a/llvm/utils/TableGen/Basic/PredicateExpanderDag.cpp
+++ b/llvm/utils/TableGen/Basic/PredicateExpanderDag.cpp
@@ -25,9 +25,11 @@ bool llvm::emitPredicateDag(
     if (OpName == "not") {
       if (D->getNumArgs() != 1)
         PrintFatalError(Owner, "'not' takes exactly one operand");
-      OS << '!';
-      return emitPredicateDag(Owner, *D->getArg(0), /*ParenIfBinOp=*/true, OS,
-                              EmitLeaf);
+      OS << "!(";
+      bool Err = emitPredicateDag(Owner, *D->getArg(0), /*ParenIfBinOp=*/false,
+                                  OS, EmitLeaf);
+      OS << ')';
+      return Err;
     }
     if (OpName == "any_of" || OpName == "all_of") {
       if (D->getNumArgs() == 0)
diff --git a/llvm/utils/TableGen/Basic/PredicateExpanderDag.h b/llvm/utils/TableGen/Basic/PredicateExpanderDag.h
index 5269a2e0c3703..a24616e9eb8b4 100644
--- a/llvm/utils/TableGen/Basic/PredicateExpanderDag.h
+++ b/llvm/utils/TableGen/Basic/PredicateExpanderDag.h
@@ -31,9 +31,8 @@ class raw_ostream;
 /// EmitLeaf, which emits the leaf test and returns true on error.
 ///
 /// If \p ParenIfBinOp is true, a surrounding pair of parentheses is emitted
-/// when \p Val lowers to a binary (`&&` / `||`) expression.  when \p Val lowers
-/// to a binary (`&&` / `||`) expression. \p EmitLeaf is expected to
-/// parenthesize its emitted leaf.
+/// when \p Val lowers to a binary (`&&` / `||`) expression. A `(not X)` always
+/// parenthesizes its operand.
 bool emitPredicateDag(const Record *Owner, const Init &Val, bool ParenIfBinOp,
                       raw_ostream &OS,
                       function_ref<bool(const Init &, raw_ostream &)> EmitLeaf);
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
index c17cad5fece4c..9c4a9107a6849 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
@@ -23,7 +23,7 @@ std::string AvailabilityPredicate::lowerCondDag(const Record *Owner,
     if (!DI || !DI->getDef()->isSubClassOf("LibcallPredicate"))
       PrintFatalError(Owner, "predicate dag leaf '" + Leaf.getAsString() +
                                  "' is not a LibcallPredicate");
-    OS << '(' << DI->getDef()->getValueAsString("Cond") << ')';
+    OS << DI->getDef()->getValueAsString("Cond");
     return false;
   };
 



More information about the llvm-branch-commits mailing list