Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Common/PredicateExpander.cpp
35290 views
//===--------------------- PredicateExpander.cpp --------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8/// Functionalities used by the Tablegen backends to expand machine predicates.9//10//===----------------------------------------------------------------------===//1112#include "PredicateExpander.h"13#include "CodeGenSchedule.h" // Definition of STIPredicateFunction.14#include "llvm/TableGen/Record.h"1516namespace llvm {1718void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }19void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }2021void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,22int ImmVal,23StringRef FunctionMapper) {24if (!FunctionMapper.empty())25OS << FunctionMapper << "(";26OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex27<< ").getImm()";28if (!FunctionMapper.empty())29OS << ")";30OS << (shouldNegate() ? " != " : " == ") << ImmVal;31}3233void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,34StringRef ImmVal,35StringRef FunctionMapper) {36if (ImmVal.empty())37expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);3839if (!FunctionMapper.empty())40OS << FunctionMapper << "(";41OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex42<< ").getImm()";43if (!FunctionMapper.empty())44OS << ")";45OS << (shouldNegate() ? " != " : " == ") << ImmVal;46}4748void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,49int OpIndex,50StringRef FunctionMapper) {51if (shouldNegate())52OS << "!";53if (!FunctionMapper.empty())54OS << FunctionMapper << "(";55OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex56<< ").getImm()";57if (!FunctionMapper.empty())58OS << ")";59}6061void PredicateExpander::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,62int ImmVal,63StringRef FunctionMapper) {64if (!FunctionMapper.empty())65OS << FunctionMapper << "(";66OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex67<< ").getImm()";68if (!FunctionMapper.empty())69OS << ")";70OS << (shouldNegate() ? " >= " : " < ") << ImmVal;71}7273void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,74int ImmVal,75StringRef FunctionMapper) {76if (!FunctionMapper.empty())77OS << FunctionMapper << "(";78OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex79<< ").getImm()";80if (!FunctionMapper.empty())81OS << ")";82OS << (shouldNegate() ? " <= " : " > ") << ImmVal;83}8485void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,86const Record *Reg,87StringRef FunctionMapper) {88assert(Reg->isSubClassOf("Register") && "Expected a register Record!");8990if (!FunctionMapper.empty())91OS << FunctionMapper << "(";92OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex93<< ").getReg()";94if (!FunctionMapper.empty())95OS << ")";96OS << (shouldNegate() ? " != " : " == ");97const StringRef Str = Reg->getValueAsString("Namespace");98if (!Str.empty())99OS << Str << "::";100OS << Reg->getName();101}102103void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,104int OpIndex,105StringRef FunctionMapper) {106if (shouldNegate())107OS << "!";108if (!FunctionMapper.empty())109OS << FunctionMapper << "(";110OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex111<< ").getReg()";112if (!FunctionMapper.empty())113OS << ")";114}115116void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,117int OpIndex) {118OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex119<< ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";120}121122void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,123int Second) {124OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First125<< ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"126<< (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";127}128129void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {130OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "131<< (shouldNegate() ? "!= " : "== ") << NumOps;132}133134void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {135OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "136<< (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")137<< "::" << Inst->getName();138}139140void PredicateExpander::expandCheckOpcode(raw_ostream &OS,141const RecVec &Opcodes) {142assert(!Opcodes.empty() && "Expected at least one opcode to check!");143bool First = true;144145if (Opcodes.size() == 1) {146OS << "( ";147expandCheckOpcode(OS, Opcodes[0]);148OS << " )";149return;150}151152OS << '(';153increaseIndentLevel();154for (const Record *Rec : Opcodes) {155OS << '\n';156OS.indent(getIndentLevel() * 2);157if (!First)158OS << (shouldNegate() ? "&& " : "|| ");159160expandCheckOpcode(OS, Rec);161First = false;162}163164OS << '\n';165decreaseIndentLevel();166OS.indent(getIndentLevel() * 2);167OS << ')';168}169170void PredicateExpander::expandCheckPseudo(raw_ostream &OS,171const RecVec &Opcodes) {172if (shouldExpandForMC())173expandFalse(OS);174else175expandCheckOpcode(OS, Opcodes);176}177178void PredicateExpander::expandPredicateSequence(raw_ostream &OS,179const RecVec &Sequence,180bool IsCheckAll) {181assert(!Sequence.empty() && "Found an invalid empty predicate set!");182if (Sequence.size() == 1)183return expandPredicate(OS, Sequence[0]);184185// Okay, there is more than one predicate in the set.186bool First = true;187OS << (shouldNegate() ? "!(" : "(");188increaseIndentLevel();189190bool OldValue = shouldNegate();191setNegatePredicate(false);192for (const Record *Rec : Sequence) {193OS << '\n';194OS.indent(getIndentLevel() * 2);195if (!First)196OS << (IsCheckAll ? "&& " : "|| ");197expandPredicate(OS, Rec);198First = false;199}200OS << '\n';201decreaseIndentLevel();202OS.indent(getIndentLevel() * 2);203OS << ')';204setNegatePredicate(OldValue);205}206207void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,208StringRef MethodName) {209OS << (shouldNegate() ? "!" : "");210OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");211OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");212}213214void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {215OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")216<< "getOperand(" << OpIndex << ").isReg() ";217}218219void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {220OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")221<< "getOperand(" << OpIndex << ").getReg().isVirtual()";222}223224void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {225OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")226<< "getOperand(" << OpIndex << ").isImm() ";227}228229void PredicateExpander::expandCheckFunctionPredicateWithTII(230raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,231StringRef TIIPtr) {232if (!shouldExpandForMC()) {233OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;234OS << (isByRef() ? "(MI)" : "(*MI)");235return;236}237238OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";239}240241void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,242StringRef MCInstFn,243StringRef MachineInstrFn) {244OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)245<< (isByRef() ? "(MI)" : "(*MI)");246}247248void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,249StringRef Code) {250if (shouldExpandForMC())251return expandFalse(OS);252253OS << '(' << Code << ')';254}255256void PredicateExpander::expandReturnStatement(raw_ostream &OS,257const Record *Rec) {258std::string Buffer;259raw_string_ostream SS(Buffer);260261SS << "return ";262expandPredicate(SS, Rec);263SS << ";";264OS << Buffer;265}266267void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,268const Record *Rec) {269const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");270for (const Record *Opcode : Opcodes) {271OS.indent(getIndentLevel() * 2);272OS << "case " << Opcode->getValueAsString("Namespace")273<< "::" << Opcode->getName() << ":\n";274}275276increaseIndentLevel();277OS.indent(getIndentLevel() * 2);278expandStatement(OS, Rec->getValueAsDef("CaseStmt"));279decreaseIndentLevel();280}281282void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,283const RecVec &Cases,284const Record *Default) {285std::string Buffer;286raw_string_ostream SS(Buffer);287288SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";289for (const Record *Rec : Cases) {290expandOpcodeSwitchCase(SS, Rec);291SS << '\n';292}293294// Expand the default case.295SS.indent(getIndentLevel() * 2);296SS << "default:\n";297298increaseIndentLevel();299SS.indent(getIndentLevel() * 2);300expandStatement(SS, Default);301decreaseIndentLevel();302SS << '\n';303304SS.indent(getIndentLevel() * 2);305SS << "} // end of switch-stmt";306OS << Buffer;307}308309void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {310// Assume that padding has been added by the caller.311if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {312expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),313Rec->getValueAsDef("DefaultCase"));314return;315}316317if (Rec->isSubClassOf("MCReturnStatement")) {318expandReturnStatement(OS, Rec->getValueAsDef("Pred"));319return;320}321322llvm_unreachable("No known rules to expand this MCStatement");323}324325void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {326// Assume that padding has been added by the caller.327if (Rec->isSubClassOf("MCTrue")) {328if (shouldNegate())329return expandFalse(OS);330return expandTrue(OS);331}332333if (Rec->isSubClassOf("MCFalse")) {334if (shouldNegate())335return expandTrue(OS);336return expandFalse(OS);337}338339if (Rec->isSubClassOf("CheckNot")) {340flipNegatePredicate();341expandPredicate(OS, Rec->getValueAsDef("Pred"));342flipNegatePredicate();343return;344}345346if (Rec->isSubClassOf("CheckIsRegOperand"))347return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));348349if (Rec->isSubClassOf("CheckIsVRegOperand"))350return expandCheckIsVRegOperand(OS, Rec->getValueAsInt("OpIndex"));351352if (Rec->isSubClassOf("CheckIsImmOperand"))353return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));354355if (Rec->isSubClassOf("CheckRegOperand"))356return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),357Rec->getValueAsDef("Reg"),358Rec->getValueAsString("FunctionMapper"));359360if (Rec->isSubClassOf("CheckRegOperandSimple"))361return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),362Rec->getValueAsString("FunctionMapper"));363364if (Rec->isSubClassOf("CheckInvalidRegOperand"))365return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));366367if (Rec->isSubClassOf("CheckImmOperand"))368return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),369Rec->getValueAsInt("ImmVal"),370Rec->getValueAsString("FunctionMapper"));371372if (Rec->isSubClassOf("CheckImmOperand_s"))373return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),374Rec->getValueAsString("ImmVal"),375Rec->getValueAsString("FunctionMapper"));376377if (Rec->isSubClassOf("CheckImmOperandLT"))378return expandCheckImmOperandLT(OS, Rec->getValueAsInt("OpIndex"),379Rec->getValueAsInt("ImmVal"),380Rec->getValueAsString("FunctionMapper"));381382if (Rec->isSubClassOf("CheckImmOperandGT"))383return expandCheckImmOperandGT(OS, Rec->getValueAsInt("OpIndex"),384Rec->getValueAsInt("ImmVal"),385Rec->getValueAsString("FunctionMapper"));386387if (Rec->isSubClassOf("CheckImmOperandSimple"))388return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),389Rec->getValueAsString("FunctionMapper"));390391if (Rec->isSubClassOf("CheckSameRegOperand"))392return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),393Rec->getValueAsInt("SecondIndex"));394395if (Rec->isSubClassOf("CheckNumOperands"))396return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));397398if (Rec->isSubClassOf("CheckPseudo"))399return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));400401if (Rec->isSubClassOf("CheckOpcode"))402return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));403404if (Rec->isSubClassOf("CheckAll"))405return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),406/* AllOf */ true);407408if (Rec->isSubClassOf("CheckAny"))409return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),410/* AllOf */ false);411412if (Rec->isSubClassOf("CheckFunctionPredicate")) {413return expandCheckFunctionPredicate(414OS, Rec->getValueAsString("MCInstFnName"),415Rec->getValueAsString("MachineInstrFnName"));416}417418if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {419return expandCheckFunctionPredicateWithTII(420OS, Rec->getValueAsString("MCInstFnName"),421Rec->getValueAsString("MachineInstrFnName"),422Rec->getValueAsString("TIIPtrName"));423}424425if (Rec->isSubClassOf("CheckNonPortable"))426return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));427428if (Rec->isSubClassOf("TIIPredicate"))429return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));430431llvm_unreachable("No known rules to expand this MCInstPredicate");432}433434void STIPredicateExpander::expandHeader(raw_ostream &OS,435const STIPredicateFunction &Fn) {436const Record *Rec = Fn.getDeclaration();437StringRef FunctionName = Rec->getValueAsString("Name");438439OS.indent(getIndentLevel() * 2);440OS << "bool ";441if (shouldExpandDefinition())442OS << getClassPrefix() << "::";443OS << FunctionName << "(";444if (shouldExpandForMC())445OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";446else447OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";448if (Rec->getValueAsBit("UpdatesOpcodeMask"))449OS << ", APInt &Mask";450OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");451if (shouldExpandDefinition()) {452OS << "{\n";453return;454}455456if (Rec->getValueAsBit("OverridesBaseClassMember"))457OS << "override";458OS << ";\n";459}460461void STIPredicateExpander::expandPrologue(raw_ostream &OS,462const STIPredicateFunction &Fn) {463RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");464bool UpdatesOpcodeMask =465Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");466467increaseIndentLevel();468unsigned IndentLevel = getIndentLevel();469for (const Record *Delegate : Delegates) {470OS.indent(IndentLevel * 2);471OS << "if (" << Delegate->getValueAsString("Name") << "(MI";472if (UpdatesOpcodeMask)473OS << ", Mask";474if (shouldExpandForMC())475OS << ", ProcessorID";476OS << "))\n";477OS.indent((1 + IndentLevel) * 2);478OS << "return true;\n\n";479}480481if (shouldExpandForMC())482return;483484OS.indent(IndentLevel * 2);485OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";486}487488void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS,489const OpcodeGroup &Group,490bool ShouldUpdateOpcodeMask) {491const OpcodeInfo &OI = Group.getOpcodeInfo();492for (const PredicateInfo &PI : OI.getPredicates()) {493const APInt &ProcModelMask = PI.ProcModelMask;494bool FirstProcID = true;495for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {496if (!ProcModelMask[I])497continue;498499if (FirstProcID) {500OS.indent(getIndentLevel() * 2);501OS << "if (ProcessorID == " << I;502} else {503OS << " || ProcessorID == " << I;504}505FirstProcID = false;506}507508OS << ") {\n";509510increaseIndentLevel();511OS.indent(getIndentLevel() * 2);512if (ShouldUpdateOpcodeMask) {513if (PI.OperandMask.isZero())514OS << "Mask.clearAllBits();\n";515else516OS << "Mask = " << PI.OperandMask << ";\n";517OS.indent(getIndentLevel() * 2);518}519OS << "return ";520expandPredicate(OS, PI.Predicate);521OS << ";\n";522decreaseIndentLevel();523OS.indent(getIndentLevel() * 2);524OS << "}\n";525}526}527528void STIPredicateExpander::expandBody(raw_ostream &OS,529const STIPredicateFunction &Fn) {530bool UpdatesOpcodeMask =531Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");532533unsigned IndentLevel = getIndentLevel();534OS.indent(IndentLevel * 2);535OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";536OS.indent(IndentLevel * 2);537OS << "default:\n";538OS.indent(IndentLevel * 2);539OS << " break;";540541for (const OpcodeGroup &Group : Fn.getGroups()) {542for (const Record *Opcode : Group.getOpcodes()) {543OS << '\n';544OS.indent(IndentLevel * 2);545OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";546}547548OS << '\n';549increaseIndentLevel();550expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);551552OS.indent(getIndentLevel() * 2);553OS << "break;\n";554decreaseIndentLevel();555}556557OS.indent(IndentLevel * 2);558OS << "}\n";559}560561void STIPredicateExpander::expandEpilogue(raw_ostream &OS,562const STIPredicateFunction &Fn) {563OS << '\n';564OS.indent(getIndentLevel() * 2);565OS << "return ";566expandPredicate(OS, Fn.getDefaultReturnPredicate());567OS << ";\n";568569decreaseIndentLevel();570OS.indent(getIndentLevel() * 2);571StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");572OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";573}574575void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,576const STIPredicateFunction &Fn) {577const Record *Rec = Fn.getDeclaration();578if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))579return;580581expandHeader(OS, Fn);582if (shouldExpandDefinition()) {583expandPrologue(OS, Fn);584expandBody(OS, Fn);585expandEpilogue(OS, Fn);586}587}588589} // namespace llvm590591592