From 94d08feaeff3591a36ed548ba7c732ddedd6f983 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 30 Dec 2019 12:05:25 -0500 Subject: [PATCH] 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. --- llvm/test/TableGen/predicate-patfags.td | 63 ++++++++++++++++++++++++++++++ llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 26 +++++++++--- 2 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 llvm/test/TableGen/predicate-patfags.td diff --git a/llvm/test/TableGen/predicate-patfags.td b/llvm/test/TableGen/predicate-patfags.td new file mode 100644 index 0000000..a6a44ff --- /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; + + +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 d01de33..7e0ba98 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"; -- 2.7.4