[llvm] 94d08fe - TableGen: Fix assert on PatFrags with predicate code

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 30 11:24:58 PST 2019


Author: Matt Arsenault
Date: 2019-12-30T14:24:25-05:00
New Revision: 94d08feaeff3591a36ed548ba7c732ddedd6f983

URL: https://github.com/llvm/llvm-project/commit/94d08feaeff3591a36ed548ba7c732ddedd6f983
DIFF: https://github.com/llvm/llvm-project/commit/94d08feaeff3591a36ed548ba7c732ddedd6f983.diff

LOG: TableGen: Fix assert on PatFrags with predicate code

This assumed a single pattern if there was a predicate. Relax this a
bit, and allow multiple patterns as long as they have the same class.

This was only broken for the DAG path. GlobalISel seems to have
handled this correctly already.

Added: 
    llvm/test/TableGen/predicate-patfags.td

Modified: 
    llvm/utils/TableGen/CodeGenDAGPatterns.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/TableGen/predicate-patfags.td b/llvm/test/TableGen/predicate-patfags.td
new file mode 100644
index 000000000000..a6a44ff6938f
--- /dev/null
+++ b/llvm/test/TableGen/predicate-patfags.td
@@ -0,0 +1,63 @@
+// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include -I %p/Common %s 2>&1 | FileCheck -check-prefix=SDAG %s
+// RUN: llvm-tblgen -gen-global-isel -I %p/../../include -I %p/Common %s 2>&1 | FileCheck -check-prefix=GISEL %s
+
+include "llvm/Target/Target.td"
+include "GlobalISelEmitterCommon.td"
+
+// Test that a predicate works when there are multiple pattern trees
+// in a PatFrags.
+
+def int_tgt_mul24 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty]>;
+def int_tgt_mul24_2 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty]>;
+
+def TGTmul24_impl : SDNode<"TargetISD::MUL24", SDTIntBinOp>;
+
+def TGTmul24 : PatFrags<(ops node:$src0, node:$src1),
+  [(int_tgt_mul24 node:$src0, node:$src1),
+   (TGTmul24_impl node:$src0, node:$src1)]>;
+
+
+def G_TGT_MUL24 : GenericInstruction {
+  let Namespace = "MyTarget";
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type0:$src1, type0:$src2);
+  let hasSideEffects = 0;
+  let isCommutable = 1;
+}
+
+
+def : GINodeEquiv<G_TGT_MUL24, TGTmul24_impl>;
+
+
+def TGTmul24_oneuse : PatFrag<
+  (ops node:$src0, node:$src1),
+  (TGTmul24 $src0, $src1),
+  [{ return N->hasOneUse(); }]> {
+  let GISelPredicateCode = [{
+    return MRI->hasOneNonDBGUse(MI.getOperand(0).getReg());
+  }];
+}
+
+// SDAG: OPC_CheckOpcode, TARGET_VAL(ISD::INTRINSIC_W_CHAIN),
+// SDAG: OPC_CheckPredicate, 0, // Predicate_TGTmul24_oneuse
+
+// SDAG: OPC_CheckOpcode, TARGET_VAL(TargetISD::MUL24),
+// SDAG: OPC_CheckPredicate, 0, // Predicate_TGTmul24_oneuse
+
+// GISEL: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS,
+// GISEL: GIM_CheckIntrinsicID, /*MI*/1, /*Op*/1, Intrinsic::tgt_mul24,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+
+// GISEL: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS,
+// GISEL: GIM_CheckIntrinsicID, /*MI*/1, /*Op*/1, Intrinsic::tgt_mul24,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+
+// GISEL: GIM_CheckOpcode, /*MI*/1, MyTarget::G_TGT_MUL24,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+
+// GISEL: GIM_CheckOpcode, /*MI*/1, MyTarget::G_TGT_MUL24,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+def inst_mad24 : I<
+  (outs GPR32:$dst),
+  (ins GPR32:$src0, GPR32:$src1, GPR32:$src2),
+  [(set GPR32:$dst, (add (TGTmul24_oneuse i32:$src0, i32:$src1), i32:$src2))]>;

diff  --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index d01de3317ff4..7e0ba98da94a 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1315,13 +1315,29 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const {
 
   // Handle arbitrary node predicates.
   assert(hasPredCode() && "Don't have any predicate code!");
+
+  // If this is using PatFrags, there are multiple trees to search. They should
+  // all have the same class.  FIXME: Is there a way to find a common
+  // superclass?
   StringRef ClassName;
-  if (PatFragRec->getOnlyTree()->isLeaf())
-    ClassName = "SDNode";
-  else {
-    Record *Op = PatFragRec->getOnlyTree()->getOperator();
-    ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName();
+  for (const auto &Tree : PatFragRec->getTrees()) {
+    StringRef TreeClassName;
+    if (Tree->isLeaf())
+      TreeClassName = "SDNode";
+    else {
+      Record *Op = Tree->getOperator();
+      const SDNodeInfo &Info = PatFragRec->getDAGPatterns().getSDNodeInfo(Op);
+      TreeClassName = Info.getSDClassName();
+    }
+
+    if (ClassName.empty())
+      ClassName = TreeClassName;
+    else if (ClassName != TreeClassName) {
+      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
+                      "PatFrags trees do not have consistent class");
+    }
   }
+
   std::string Result;
   if (ClassName == "SDNode")
     Result = "    SDNode *N = Node;\n";


        


More information about the llvm-commits mailing list