mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
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.
This commit is contained in:
parent
b7ed3128ec
commit
295d2fea14
63
test/TableGen/predicate-patfags.td
Normal file
63
test/TableGen/predicate-patfags.td
Normal file
@ -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))]>;
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user