mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[GISel] Teach TableGen to check predicates of immediate operands in patterns
Reviewed By: dsanders Differential Revision: https://reviews.llvm.org/D91703
This commit is contained in:
parent
9a7b0c7836
commit
4115608e9d
@ -140,6 +140,11 @@ enum {
|
||||
/// - InsnID - Instruction ID
|
||||
/// - The predicate to test
|
||||
GIM_CheckAPFloatImmPredicate,
|
||||
/// Check an immediate predicate on the specified instruction
|
||||
/// - InsnID - Instruction ID
|
||||
/// - OpIdx - Operand index
|
||||
/// - The predicate to test
|
||||
GIM_CheckImmOperandPredicate,
|
||||
/// Check a memory operation has the specified atomic ordering.
|
||||
/// - InsnID - Instruction ID
|
||||
/// - Ordering - The AtomicOrdering value
|
||||
|
@ -263,22 +263,27 @@ bool InstructionSelector::executeMatchTable(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GIM_CheckI64ImmPredicate: {
|
||||
case GIM_CheckI64ImmPredicate:
|
||||
case GIM_CheckImmOperandPredicate: {
|
||||
int64_t InsnID = MatchTable[CurrentIdx++];
|
||||
int64_t OpIdx = MatcherOpcode == GIM_CheckImmOperandPredicate
|
||||
? MatchTable[CurrentIdx++]
|
||||
: 1;
|
||||
int64_t Predicate = MatchTable[CurrentIdx++];
|
||||
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
|
||||
dbgs()
|
||||
<< CurrentIdx << ": GIM_CheckI64ImmPredicate(MIs["
|
||||
<< InsnID << "], Predicate=" << Predicate << ")\n");
|
||||
dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs["
|
||||
<< InsnID << "]->getOperand(" << OpIdx
|
||||
<< "), Predicate=" << Predicate << ")\n");
|
||||
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
|
||||
assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
|
||||
"Expected G_CONSTANT");
|
||||
assert((State.MIs[InsnID]->getOperand(OpIdx).isImm() ||
|
||||
State.MIs[InsnID]->getOperand(OpIdx).isCImm()) &&
|
||||
"Expected immediate operand");
|
||||
assert(Predicate > GIPFP_I64_Invalid && "Expected a valid predicate");
|
||||
int64_t Value = 0;
|
||||
if (State.MIs[InsnID]->getOperand(1).isCImm())
|
||||
Value = State.MIs[InsnID]->getOperand(1).getCImm()->getSExtValue();
|
||||
else if (State.MIs[InsnID]->getOperand(1).isImm())
|
||||
Value = State.MIs[InsnID]->getOperand(1).getImm();
|
||||
if (State.MIs[InsnID]->getOperand(OpIdx).isCImm())
|
||||
Value = State.MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue();
|
||||
else if (State.MIs[InsnID]->getOperand(OpIdx).isImm())
|
||||
Value = State.MIs[InsnID]->getOperand(OpIdx).getImm();
|
||||
else
|
||||
llvm_unreachable("Expected Imm or CImm operand");
|
||||
|
||||
|
@ -50,6 +50,7 @@ def : GINodeEquiv<G_BITCAST, bitconvert>;
|
||||
// G_INTTOPTR - SelectionDAG has no equivalent.
|
||||
// G_PTRTOINT - SelectionDAG has no equivalent.
|
||||
def : GINodeEquiv<G_CONSTANT, imm>;
|
||||
// timm must not be materialized and therefore has no GlobalISel equivalent
|
||||
def : GINodeEquiv<G_FCONSTANT, fpimm>;
|
||||
def : GINodeEquiv<G_IMPLICIT_DEF, undef>;
|
||||
def : GINodeEquiv<G_FRAME_INDEX, frameindex>;
|
||||
|
22
test/TableGen/immarg-predicated.td
Normal file
22
test/TableGen/immarg-predicated.td
Normal file
@ -0,0 +1,22 @@
|
||||
// RUN: llvm-tblgen -gen-global-isel -optimize-match-table=false -I %p/Common -I %p/../../include %s -o - < %s | FileCheck -check-prefix=GISEL %s
|
||||
|
||||
include "llvm/Target/Target.td"
|
||||
include "GlobalISelEmitterCommon.td"
|
||||
|
||||
let TargetPrefix = "mytarget" in {
|
||||
def int_mytarget_sleep0 : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>;
|
||||
}
|
||||
|
||||
// GISEL: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS,
|
||||
// GISEL-NEXT: // MIs[0] Operand 0
|
||||
// GISEL-NEXT: GIM_CheckIntrinsicID, /*MI*/0, /*Op*/0, Intrinsic::mytarget_sleep0,
|
||||
// GISEL-NEXT: // MIs[0] src
|
||||
// GISEL-NEXT: GIM_CheckIsImm, /*MI*/0, /*Op*/1,
|
||||
// GISEL-NEXT: GIM_CheckImmOperandPredicate, /*MI*/0, /*MO*/1, /*Predicate*/GIPFP_I64_Predicate_tuimm9,
|
||||
// GISEL-NEXT: // (intrinsic_void {{[0-9]+}}:{ *:[iPTR] }, (timm:{ *:[i32] })<<P:Predicate_tuimm9>>:$src) => (SLEEP0 (timm:{ *:[i32] }):$src)
|
||||
// GISEL-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SLEEP0,
|
||||
// GISEL-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src
|
||||
def tuimm9 : TImmLeaf<i32, [{ return isUInt<9>(Imm); }]>;
|
||||
def SLEEP0 : I<(outs), (ins i32imm:$src),
|
||||
[(int_mytarget_sleep0 tuimm9:$src)]
|
||||
>;
|
@ -90,7 +90,7 @@ std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) {
|
||||
}
|
||||
|
||||
/// Get the opcode used to check this predicate.
|
||||
std::string getMatchOpcodeForPredicate(const TreePredicateFn &Predicate) {
|
||||
std::string getMatchOpcodeForImmPredicate(const TreePredicateFn &Predicate) {
|
||||
return "GIM_Check" + Predicate.getImmTypeIdentifier().str() + "ImmPredicate";
|
||||
}
|
||||
|
||||
@ -1562,6 +1562,40 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Generates code to check that this operand is an immediate whose value meets
|
||||
/// an immediate predicate.
|
||||
class OperandImmPredicateMatcher : public OperandPredicateMatcher {
|
||||
protected:
|
||||
TreePredicateFn Predicate;
|
||||
|
||||
public:
|
||||
OperandImmPredicateMatcher(unsigned InsnVarID, unsigned OpIdx,
|
||||
const TreePredicateFn &Predicate)
|
||||
: OperandPredicateMatcher(IPM_ImmPredicate, InsnVarID, OpIdx),
|
||||
Predicate(Predicate) {}
|
||||
|
||||
bool isIdentical(const PredicateMatcher &B) const override {
|
||||
return OperandPredicateMatcher::isIdentical(B) &&
|
||||
Predicate.getOrigPatFragRecord() ==
|
||||
cast<OperandImmPredicateMatcher>(&B)
|
||||
->Predicate.getOrigPatFragRecord();
|
||||
}
|
||||
|
||||
static bool classof(const PredicateMatcher *P) {
|
||||
return P->getKind() == IPM_ImmPredicate;
|
||||
}
|
||||
|
||||
void emitPredicateOpcodes(MatchTable &Table,
|
||||
RuleMatcher &Rule) const override {
|
||||
Table << MatchTable::Opcode("GIM_CheckImmOperandPredicate")
|
||||
<< MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
|
||||
<< MatchTable::Comment("MO") << MatchTable::IntValue(OpIdx)
|
||||
<< MatchTable::Comment("Predicate")
|
||||
<< MatchTable::NamedValue(getEnumNameForPredicate(Predicate))
|
||||
<< MatchTable::LineBreak;
|
||||
}
|
||||
};
|
||||
|
||||
/// Generates code to check that a set of predicates match for a particular
|
||||
/// operand.
|
||||
class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> {
|
||||
@ -1924,7 +1958,7 @@ public:
|
||||
|
||||
void emitPredicateOpcodes(MatchTable &Table,
|
||||
RuleMatcher &Rule) const override {
|
||||
Table << MatchTable::Opcode(getMatchOpcodeForPredicate(Predicate))
|
||||
Table << MatchTable::Opcode(getMatchOpcodeForImmPredicate(Predicate))
|
||||
<< MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
|
||||
<< MatchTable::Comment("Predicate")
|
||||
<< MatchTable::NamedValue(getEnumNameForPredicate(Predicate))
|
||||
@ -4152,6 +4186,17 @@ Error GlobalISelEmitter::importChildMatcher(
|
||||
}
|
||||
if (SrcChild->getOperator()->getName() == "timm") {
|
||||
OM.addPredicate<ImmOperandMatcher>();
|
||||
|
||||
// Add predicates, if any
|
||||
for (const TreePredicateCall &Call : SrcChild->getPredicateCalls()) {
|
||||
const TreePredicateFn &Predicate = Call.Fn;
|
||||
|
||||
// Only handle immediate patterns for now
|
||||
if (Predicate.isImmediatePattern()) {
|
||||
OM.addPredicate<OperandImmPredicateMatcher>(Predicate);
|
||||
}
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user