1
0
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:
Dominik Montada 2021-03-29 15:21:46 +02:00
parent 9a7b0c7836
commit 4115608e9d
5 changed files with 90 additions and 12 deletions

View File

@ -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

View File

@ -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");

View File

@ -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>;

View 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)]
>;

View File

@ -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();
}
}