123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- //===--------------------- PredicateExpander.cpp --------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- /// Functionalities used by the Tablegen backends to expand machine predicates.
- //
- //===----------------------------------------------------------------------===//
- #include "PredicateExpander.h"
- #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
- namespace llvm {
- void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
- void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
- void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
- int ImmVal,
- StringRef FunctionMapper) {
- if (!FunctionMapper.empty())
- OS << FunctionMapper << "(";
- OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
- << ").getImm()";
- if (!FunctionMapper.empty())
- OS << ")";
- OS << (shouldNegate() ? " != " : " == ") << ImmVal;
- }
- void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
- StringRef ImmVal,
- StringRef FunctionMapper) {
- if (ImmVal.empty())
- expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
- if (!FunctionMapper.empty())
- OS << FunctionMapper << "(";
- OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
- << ").getImm()";
- if (!FunctionMapper.empty())
- OS << ")";
- OS << (shouldNegate() ? " != " : " == ") << ImmVal;
- }
- void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
- int OpIndex,
- StringRef FunctionMapper) {
- if (shouldNegate())
- OS << "!";
- if (!FunctionMapper.empty())
- OS << FunctionMapper << "(";
- OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
- << ").getImm()";
- if (!FunctionMapper.empty())
- OS << ")";
- }
- void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
- const Record *Reg,
- StringRef FunctionMapper) {
- assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
- if (!FunctionMapper.empty())
- OS << FunctionMapper << "(";
- OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
- << ").getReg()";
- if (!FunctionMapper.empty())
- OS << ")";
- OS << (shouldNegate() ? " != " : " == ");
- const StringRef Str = Reg->getValueAsString("Namespace");
- if (!Str.empty())
- OS << Str << "::";
- OS << Reg->getName();
- }
- void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
- int OpIndex,
- StringRef FunctionMapper) {
- if (shouldNegate())
- OS << "!";
- if (!FunctionMapper.empty())
- OS << FunctionMapper << "(";
- OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
- << ").getReg()";
- if (!FunctionMapper.empty())
- OS << ")";
- }
- void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
- int OpIndex) {
- OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
- << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
- }
- void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
- int Second) {
- OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
- << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
- << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
- }
- void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
- OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
- << (shouldNegate() ? "!= " : "== ") << NumOps;
- }
- void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
- OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
- << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
- << "::" << Inst->getName();
- }
- void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
- const RecVec &Opcodes) {
- assert(!Opcodes.empty() && "Expected at least one opcode to check!");
- bool First = true;
- if (Opcodes.size() == 1) {
- OS << "( ";
- expandCheckOpcode(OS, Opcodes[0]);
- OS << " )";
- return;
- }
- OS << '(';
- increaseIndentLevel();
- for (const Record *Rec : Opcodes) {
- OS << '\n';
- OS.indent(getIndentLevel() * 2);
- if (!First)
- OS << (shouldNegate() ? "&& " : "|| ");
- expandCheckOpcode(OS, Rec);
- First = false;
- }
- OS << '\n';
- decreaseIndentLevel();
- OS.indent(getIndentLevel() * 2);
- OS << ')';
- }
- void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
- const RecVec &Opcodes) {
- if (shouldExpandForMC())
- expandFalse(OS);
- else
- expandCheckOpcode(OS, Opcodes);
- }
- void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
- const RecVec &Sequence,
- bool IsCheckAll) {
- assert(!Sequence.empty() && "Found an invalid empty predicate set!");
- if (Sequence.size() == 1)
- return expandPredicate(OS, Sequence[0]);
- // Okay, there is more than one predicate in the set.
- bool First = true;
- OS << (shouldNegate() ? "!(" : "(");
- increaseIndentLevel();
- bool OldValue = shouldNegate();
- setNegatePredicate(false);
- for (const Record *Rec : Sequence) {
- OS << '\n';
- OS.indent(getIndentLevel() * 2);
- if (!First)
- OS << (IsCheckAll ? "&& " : "|| ");
- expandPredicate(OS, Rec);
- First = false;
- }
- OS << '\n';
- decreaseIndentLevel();
- OS.indent(getIndentLevel() * 2);
- OS << ')';
- setNegatePredicate(OldValue);
- }
- void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
- StringRef MethodName) {
- OS << (shouldNegate() ? "!" : "");
- OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
- OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
- }
- void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
- OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
- << "getOperand(" << OpIndex << ").isReg() ";
- }
- void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
- OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
- << "getOperand(" << OpIndex << ").isImm() ";
- }
- void PredicateExpander::expandCheckFunctionPredicateWithTII(
- raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
- StringRef TIIPtr) {
- if (!shouldExpandForMC()) {
- OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
- OS << (isByRef() ? "(MI)" : "(*MI)");
- return;
- }
- OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
- }
- void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
- StringRef MCInstFn,
- StringRef MachineInstrFn) {
- OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
- << (isByRef() ? "(MI)" : "(*MI)");
- }
- void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
- StringRef Code) {
- if (shouldExpandForMC())
- return expandFalse(OS);
- OS << '(' << Code << ')';
- }
- void PredicateExpander::expandReturnStatement(raw_ostream &OS,
- const Record *Rec) {
- std::string Buffer;
- raw_string_ostream SS(Buffer);
- SS << "return ";
- expandPredicate(SS, Rec);
- SS << ";";
- OS << Buffer;
- }
- void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
- const Record *Rec) {
- const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
- for (const Record *Opcode : Opcodes) {
- OS.indent(getIndentLevel() * 2);
- OS << "case " << Opcode->getValueAsString("Namespace")
- << "::" << Opcode->getName() << ":\n";
- }
- increaseIndentLevel();
- OS.indent(getIndentLevel() * 2);
- expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
- decreaseIndentLevel();
- }
- void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
- const RecVec &Cases,
- const Record *Default) {
- std::string Buffer;
- raw_string_ostream SS(Buffer);
- SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
- for (const Record *Rec : Cases) {
- expandOpcodeSwitchCase(SS, Rec);
- SS << '\n';
- }
- // Expand the default case.
- SS.indent(getIndentLevel() * 2);
- SS << "default:\n";
- increaseIndentLevel();
- SS.indent(getIndentLevel() * 2);
- expandStatement(SS, Default);
- decreaseIndentLevel();
- SS << '\n';
- SS.indent(getIndentLevel() * 2);
- SS << "} // end of switch-stmt";
- OS << Buffer;
- }
- void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
- // Assume that padding has been added by the caller.
- if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
- expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
- Rec->getValueAsDef("DefaultCase"));
- return;
- }
- if (Rec->isSubClassOf("MCReturnStatement")) {
- expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
- return;
- }
- llvm_unreachable("No known rules to expand this MCStatement");
- }
- void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
- // Assume that padding has been added by the caller.
- if (Rec->isSubClassOf("MCTrue")) {
- if (shouldNegate())
- return expandFalse(OS);
- return expandTrue(OS);
- }
- if (Rec->isSubClassOf("MCFalse")) {
- if (shouldNegate())
- return expandTrue(OS);
- return expandFalse(OS);
- }
- if (Rec->isSubClassOf("CheckNot")) {
- flipNegatePredicate();
- expandPredicate(OS, Rec->getValueAsDef("Pred"));
- flipNegatePredicate();
- return;
- }
- if (Rec->isSubClassOf("CheckIsRegOperand"))
- return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
- if (Rec->isSubClassOf("CheckIsImmOperand"))
- return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
- if (Rec->isSubClassOf("CheckRegOperand"))
- return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
- Rec->getValueAsDef("Reg"),
- Rec->getValueAsString("FunctionMapper"));
- if (Rec->isSubClassOf("CheckRegOperandSimple"))
- return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
- Rec->getValueAsString("FunctionMapper"));
- if (Rec->isSubClassOf("CheckInvalidRegOperand"))
- return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
- if (Rec->isSubClassOf("CheckImmOperand"))
- return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
- Rec->getValueAsInt("ImmVal"),
- Rec->getValueAsString("FunctionMapper"));
- if (Rec->isSubClassOf("CheckImmOperand_s"))
- return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
- Rec->getValueAsString("ImmVal"),
- Rec->getValueAsString("FunctionMapper"));
- if (Rec->isSubClassOf("CheckImmOperandSimple"))
- return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
- Rec->getValueAsString("FunctionMapper"));
- if (Rec->isSubClassOf("CheckSameRegOperand"))
- return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
- Rec->getValueAsInt("SecondIndex"));
- if (Rec->isSubClassOf("CheckNumOperands"))
- return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
- if (Rec->isSubClassOf("CheckPseudo"))
- return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
- if (Rec->isSubClassOf("CheckOpcode"))
- return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
- if (Rec->isSubClassOf("CheckAll"))
- return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
- /* AllOf */ true);
- if (Rec->isSubClassOf("CheckAny"))
- return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
- /* AllOf */ false);
- if (Rec->isSubClassOf("CheckFunctionPredicate")) {
- return expandCheckFunctionPredicate(
- OS, Rec->getValueAsString("MCInstFnName"),
- Rec->getValueAsString("MachineInstrFnName"));
- }
- if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
- return expandCheckFunctionPredicateWithTII(
- OS, Rec->getValueAsString("MCInstFnName"),
- Rec->getValueAsString("MachineInstrFnName"),
- Rec->getValueAsString("TIIPtrName"));
- }
- if (Rec->isSubClassOf("CheckNonPortable"))
- return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
- if (Rec->isSubClassOf("TIIPredicate"))
- return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
- llvm_unreachable("No known rules to expand this MCInstPredicate");
- }
- void STIPredicateExpander::expandHeader(raw_ostream &OS,
- const STIPredicateFunction &Fn) {
- const Record *Rec = Fn.getDeclaration();
- StringRef FunctionName = Rec->getValueAsString("Name");
- OS.indent(getIndentLevel() * 2);
- OS << "bool ";
- if (shouldExpandDefinition())
- OS << getClassPrefix() << "::";
- OS << FunctionName << "(";
- if (shouldExpandForMC())
- OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
- else
- OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
- if (Rec->getValueAsBit("UpdatesOpcodeMask"))
- OS << ", APInt &Mask";
- OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
- if (shouldExpandDefinition()) {
- OS << "{\n";
- return;
- }
- if (Rec->getValueAsBit("OverridesBaseClassMember"))
- OS << "override";
- OS << ";\n";
- }
- void STIPredicateExpander::expandPrologue(raw_ostream &OS,
- const STIPredicateFunction &Fn) {
- RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
- bool UpdatesOpcodeMask =
- Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
- increaseIndentLevel();
- unsigned IndentLevel = getIndentLevel();
- for (const Record *Delegate : Delegates) {
- OS.indent(IndentLevel * 2);
- OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
- if (UpdatesOpcodeMask)
- OS << ", Mask";
- if (shouldExpandForMC())
- OS << ", ProcessorID";
- OS << "))\n";
- OS.indent((1 + IndentLevel) * 2);
- OS << "return true;\n\n";
- }
- if (shouldExpandForMC())
- return;
- OS.indent(IndentLevel * 2);
- OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
- }
- void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
- bool ShouldUpdateOpcodeMask) {
- const OpcodeInfo &OI = Group.getOpcodeInfo();
- for (const PredicateInfo &PI : OI.getPredicates()) {
- const APInt &ProcModelMask = PI.ProcModelMask;
- bool FirstProcID = true;
- for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
- if (!ProcModelMask[I])
- continue;
- if (FirstProcID) {
- OS.indent(getIndentLevel() * 2);
- OS << "if (ProcessorID == " << I;
- } else {
- OS << " || ProcessorID == " << I;
- }
- FirstProcID = false;
- }
- OS << ") {\n";
- increaseIndentLevel();
- OS.indent(getIndentLevel() * 2);
- if (ShouldUpdateOpcodeMask) {
- if (PI.OperandMask.isZero())
- OS << "Mask.clearAllBits();\n";
- else
- OS << "Mask = " << PI.OperandMask << ";\n";
- OS.indent(getIndentLevel() * 2);
- }
- OS << "return ";
- expandPredicate(OS, PI.Predicate);
- OS << ";\n";
- decreaseIndentLevel();
- OS.indent(getIndentLevel() * 2);
- OS << "}\n";
- }
- }
- void STIPredicateExpander::expandBody(raw_ostream &OS,
- const STIPredicateFunction &Fn) {
- bool UpdatesOpcodeMask =
- Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
- unsigned IndentLevel = getIndentLevel();
- OS.indent(IndentLevel * 2);
- OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
- OS.indent(IndentLevel * 2);
- OS << "default:\n";
- OS.indent(IndentLevel * 2);
- OS << " break;";
- for (const OpcodeGroup &Group : Fn.getGroups()) {
- for (const Record *Opcode : Group.getOpcodes()) {
- OS << '\n';
- OS.indent(IndentLevel * 2);
- OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
- }
- OS << '\n';
- increaseIndentLevel();
- expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
- OS.indent(getIndentLevel() * 2);
- OS << "break;\n";
- decreaseIndentLevel();
- }
- OS.indent(IndentLevel * 2);
- OS << "}\n";
- }
- void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
- const STIPredicateFunction &Fn) {
- OS << '\n';
- OS.indent(getIndentLevel() * 2);
- OS << "return ";
- expandPredicate(OS, Fn.getDefaultReturnPredicate());
- OS << ";\n";
- decreaseIndentLevel();
- OS.indent(getIndentLevel() * 2);
- StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
- OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
- }
- void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
- const STIPredicateFunction &Fn) {
- const Record *Rec = Fn.getDeclaration();
- if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
- return;
- expandHeader(OS, Fn);
- if (shouldExpandDefinition()) {
- expandPrologue(OS, Fn);
- expandBody(OS, Fn);
- expandEpilogue(OS, Fn);
- }
- }
- } // namespace llvm
|