556 lines · cpp
1//===--------------------- PredicateExpander.cpp --------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// Functionalities used by the Tablegen backends to expand machine predicates.10//11//===----------------------------------------------------------------------===//12 13#include "PredicateExpander.h"14#include "CodeGenSchedule.h" // Definition of STIPredicateFunction.15#include "llvm/TableGen/Record.h"16 17using namespace llvm;18 19void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }20void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }21 22void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,23 int ImmVal,24 StringRef FunctionMapper) {25 if (!FunctionMapper.empty())26 OS << FunctionMapper << "(";27 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex28 << ").getImm()";29 if (!FunctionMapper.empty())30 OS << ")";31 OS << (shouldNegate() ? " != " : " == ") << ImmVal;32}33 34void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,35 StringRef ImmVal,36 StringRef FunctionMapper) {37 if (ImmVal.empty())38 expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);39 40 if (!FunctionMapper.empty())41 OS << FunctionMapper << "(";42 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex43 << ").getImm()";44 if (!FunctionMapper.empty())45 OS << ")";46 OS << (shouldNegate() ? " != " : " == ") << ImmVal;47}48 49void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,50 int OpIndex,51 StringRef FunctionMapper) {52 if (shouldNegate())53 OS << "!";54 if (!FunctionMapper.empty())55 OS << FunctionMapper << "(";56 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex57 << ").getImm()";58 if (!FunctionMapper.empty())59 OS << ")";60}61 62void PredicateExpander::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,63 int ImmVal,64 StringRef FunctionMapper) {65 if (!FunctionMapper.empty())66 OS << FunctionMapper << "(";67 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex68 << ").getImm()";69 if (!FunctionMapper.empty())70 OS << ")";71 OS << (shouldNegate() ? " >= " : " < ") << ImmVal;72}73 74void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,75 int ImmVal,76 StringRef FunctionMapper) {77 if (!FunctionMapper.empty())78 OS << FunctionMapper << "(";79 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex80 << ").getImm()";81 if (!FunctionMapper.empty())82 OS << ")";83 OS << (shouldNegate() ? " <= " : " > ") << ImmVal;84}85 86void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,87 const Record *Reg,88 StringRef FunctionMapper) {89 assert(Reg->isSubClassOf("Register") && "Expected a register Record!");90 91 if (!FunctionMapper.empty())92 OS << FunctionMapper << "(";93 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex94 << ").getReg()";95 if (!FunctionMapper.empty())96 OS << ")";97 OS << (shouldNegate() ? " != " : " == ");98 const StringRef Str = Reg->getValueAsString("Namespace");99 if (!Str.empty())100 OS << Str << "::";101 OS << Reg->getName();102}103 104void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,105 int OpIndex,106 StringRef FunctionMapper) {107 if (shouldNegate())108 OS << "!";109 if (!FunctionMapper.empty())110 OS << FunctionMapper << "(";111 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex112 << ").getReg()";113 if (!FunctionMapper.empty())114 OS << ")";115}116 117void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,118 int OpIndex) {119 if (!shouldNegate())120 OS << "!";121 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex122 << ").getReg().isValid()";123}124 125void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,126 int Second) {127 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First128 << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"129 << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";130}131 132void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {133 OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "134 << (shouldNegate() ? "!= " : "== ") << NumOps;135}136 137void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {138 OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "139 << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")140 << "::" << Inst->getName();141}142 143void PredicateExpander::expandCheckOpcode(raw_ostream &OS,144 ArrayRef<const Record *> Opcodes) {145 assert(!Opcodes.empty() && "Expected at least one opcode to check!");146 147 if (Opcodes.size() == 1) {148 OS << "( ";149 expandCheckOpcode(OS, Opcodes[0]);150 OS << " )";151 return;152 }153 154 if (shouldNegate())155 OS << '!';156 OS << "llvm::is_contained(";157 ListSeparator Sep;158 OS << '{';159 for (const Record *Inst : Opcodes)160 OS << Sep << Inst->getValueAsString("Namespace") << "::" << Inst->getName();161 OS << '}';162 OS << ", MI" << (isByRef() ? "." : "->") << "getOpcode())";163}164 165void PredicateExpander::expandCheckPseudo(raw_ostream &OS,166 ArrayRef<const Record *> Opcodes) {167 if (shouldExpandForMC())168 expandFalse(OS);169 else170 expandCheckOpcode(OS, Opcodes);171}172 173void PredicateExpander::expandPredicateSequence(174 raw_ostream &OS, ArrayRef<const Record *> Sequence, bool IsCheckAll) {175 assert(!Sequence.empty() && "Found an invalid empty predicate set!");176 if (Sequence.size() == 1)177 return expandPredicate(OS, Sequence[0]);178 179 // Okay, there is more than one predicate in the set.180 bool First = true;181 OS << (shouldNegate() ? "!(" : "(");182 ++Indent;183 184 bool OldValue = shouldNegate();185 setNegatePredicate(false);186 for (const Record *Rec : Sequence) {187 OS << '\n' << Indent;188 if (!First)189 OS << (IsCheckAll ? "&& " : "|| ");190 expandPredicate(OS, Rec);191 First = false;192 }193 --Indent;194 OS << '\n' << Indent << ')';195 setNegatePredicate(OldValue);196}197 198void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,199 StringRef MethodName) {200 OS << (shouldNegate() ? "!" : "");201 OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");202 OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");203}204 205void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {206 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")207 << "getOperand(" << OpIndex << ").isReg() ";208}209 210void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {211 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")212 << "getOperand(" << OpIndex << ").getReg().isVirtual()";213}214 215void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {216 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")217 << "getOperand(" << OpIndex << ").isImm() ";218}219 220void PredicateExpander::expandCheckFunctionPredicateWithTII(221 raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,222 StringRef TIIPtr) {223 if (!shouldExpandForMC()) {224 OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;225 OS << (isByRef() ? "(MI)" : "(*MI)");226 return;227 }228 229 OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";230}231 232void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,233 StringRef MCInstFn,234 StringRef MachineInstrFn) {235 OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)236 << (isByRef() ? "(MI)" : "(*MI)");237}238 239void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,240 StringRef Code) {241 if (shouldExpandForMC())242 return expandFalse(OS);243 244 OS << '(' << Code << ')';245}246 247void PredicateExpander::expandReturnStatement(raw_ostream &OS,248 const Record *Rec) {249 std::string Buffer;250 raw_string_ostream SS(Buffer);251 252 SS << "return ";253 expandPredicate(SS, Rec);254 SS << ";";255 OS << Buffer;256}257 258void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,259 const Record *Rec) {260 for (const Record *Opcode : Rec->getValueAsListOfDefs("Opcodes")) {261 OS << Indent << "case " << Opcode->getValueAsString("Namespace")262 << "::" << Opcode->getName() << ":\n";263 }264 265 ++Indent;266 OS << Indent;267 expandStatement(OS, Rec->getValueAsDef("CaseStmt"));268 --Indent;269}270 271void PredicateExpander::expandOpcodeSwitchStatement(272 raw_ostream &OS, ArrayRef<const Record *> Cases, const Record *Default) {273 std::string Buffer;274 raw_string_ostream SS(Buffer);275 276 SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";277 for (const Record *Rec : Cases) {278 expandOpcodeSwitchCase(SS, Rec);279 SS << '\n';280 }281 282 // Expand the default case.283 SS << Indent << "default:\n";284 285 ++Indent;286 SS << Indent;287 expandStatement(SS, Default);288 SS << '\n' << Indent << "} // end of switch-stmt";289 OS << Buffer;290}291 292void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {293 // Assume that padding has been added by the caller.294 if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {295 expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),296 Rec->getValueAsDef("DefaultCase"));297 return;298 }299 300 if (Rec->isSubClassOf("MCReturnStatement")) {301 expandReturnStatement(OS, Rec->getValueAsDef("Pred"));302 return;303 }304 305 llvm_unreachable("No known rules to expand this MCStatement");306}307 308void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {309 // Assume that padding has been added by the caller.310 if (Rec->isSubClassOf("MCTrue")) {311 if (shouldNegate())312 return expandFalse(OS);313 return expandTrue(OS);314 }315 316 if (Rec->isSubClassOf("MCFalse")) {317 if (shouldNegate())318 return expandTrue(OS);319 return expandFalse(OS);320 }321 322 if (Rec->isSubClassOf("CheckNot")) {323 flipNegatePredicate();324 expandPredicate(OS, Rec->getValueAsDef("Pred"));325 flipNegatePredicate();326 return;327 }328 329 if (Rec->isSubClassOf("CheckIsRegOperand"))330 return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));331 332 if (Rec->isSubClassOf("CheckIsVRegOperand"))333 return expandCheckIsVRegOperand(OS, Rec->getValueAsInt("OpIndex"));334 335 if (Rec->isSubClassOf("CheckIsImmOperand"))336 return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));337 338 if (Rec->isSubClassOf("CheckRegOperand"))339 return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),340 Rec->getValueAsDef("Reg"),341 Rec->getValueAsString("FunctionMapper"));342 343 if (Rec->isSubClassOf("CheckRegOperandSimple"))344 return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),345 Rec->getValueAsString("FunctionMapper"));346 347 if (Rec->isSubClassOf("CheckInvalidRegOperand"))348 return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));349 350 if (Rec->isSubClassOf("CheckImmOperand"))351 return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),352 Rec->getValueAsInt("ImmVal"),353 Rec->getValueAsString("FunctionMapper"));354 355 if (Rec->isSubClassOf("CheckImmOperand_s"))356 return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),357 Rec->getValueAsString("ImmVal"),358 Rec->getValueAsString("FunctionMapper"));359 360 if (Rec->isSubClassOf("CheckImmOperandLT"))361 return expandCheckImmOperandLT(OS, Rec->getValueAsInt("OpIndex"),362 Rec->getValueAsInt("ImmVal"),363 Rec->getValueAsString("FunctionMapper"));364 365 if (Rec->isSubClassOf("CheckImmOperandGT"))366 return expandCheckImmOperandGT(OS, Rec->getValueAsInt("OpIndex"),367 Rec->getValueAsInt("ImmVal"),368 Rec->getValueAsString("FunctionMapper"));369 370 if (Rec->isSubClassOf("CheckImmOperandSimple"))371 return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),372 Rec->getValueAsString("FunctionMapper"));373 374 if (Rec->isSubClassOf("CheckSameRegOperand"))375 return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),376 Rec->getValueAsInt("SecondIndex"));377 378 if (Rec->isSubClassOf("CheckNumOperands"))379 return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));380 381 if (Rec->isSubClassOf("CheckPseudo"))382 return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));383 384 if (Rec->isSubClassOf("CheckOpcode"))385 return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));386 387 if (Rec->isSubClassOf("CheckAll"))388 return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),389 /* AllOf */ true);390 391 if (Rec->isSubClassOf("CheckAny"))392 return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),393 /* AllOf */ false);394 395 if (Rec->isSubClassOf("CheckFunctionPredicate")) {396 return expandCheckFunctionPredicate(397 OS, Rec->getValueAsString("MCInstFnName"),398 Rec->getValueAsString("MachineInstrFnName"));399 }400 401 if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {402 return expandCheckFunctionPredicateWithTII(403 OS, Rec->getValueAsString("MCInstFnName"),404 Rec->getValueAsString("MachineInstrFnName"),405 Rec->getValueAsString("TIIPtrName"));406 }407 408 if (Rec->isSubClassOf("CheckNonPortable"))409 return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));410 411 if (Rec->isSubClassOf("TIIPredicate"))412 return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));413 414 llvm_unreachable("No known rules to expand this MCInstPredicate");415}416 417void STIPredicateExpander::expandHeader(raw_ostream &OS,418 const STIPredicateFunction &Fn) {419 const Record *Rec = Fn.getDeclaration();420 StringRef FunctionName = Rec->getValueAsString("Name");421 422 OS << Indent << "bool ";423 if (shouldExpandDefinition())424 OS << getClassPrefix() << "::";425 OS << FunctionName << "(";426 if (shouldExpandForMC())427 OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";428 else429 OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";430 if (Rec->getValueAsBit("UpdatesOpcodeMask"))431 OS << ", APInt &Mask";432 OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");433 if (shouldExpandDefinition()) {434 OS << "{\n";435 return;436 }437 438 if (Rec->getValueAsBit("OverridesBaseClassMember"))439 OS << "override";440 OS << ";\n";441}442 443void STIPredicateExpander::expandPrologue(raw_ostream &OS,444 const STIPredicateFunction &Fn) {445 bool UpdatesOpcodeMask =446 Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");447 448 ++Indent;449 for (const Record *Delegate :450 Fn.getDeclaration()->getValueAsListOfDefs("Delegates")) {451 OS << Indent << "if (" << Delegate->getValueAsString("Name") << "(MI";452 if (UpdatesOpcodeMask)453 OS << ", Mask";454 if (shouldExpandForMC())455 OS << ", ProcessorID";456 OS << "))\n";457 OS << Indent + 1 << "return true;\n\n";458 }459 460 if (shouldExpandForMC())461 return;462 463 OS << Indent << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";464}465 466void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS,467 const OpcodeGroup &Group,468 bool ShouldUpdateOpcodeMask) {469 const OpcodeInfo &OI = Group.getOpcodeInfo();470 for (const PredicateInfo &PI : OI.getPredicates()) {471 const APInt &ProcModelMask = PI.ProcModelMask;472 bool FirstProcID = true;473 for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {474 if (!ProcModelMask[I])475 continue;476 477 if (FirstProcID) {478 OS << Indent << "if (ProcessorID == " << I;479 } else {480 OS << " || ProcessorID == " << I;481 }482 FirstProcID = false;483 }484 485 OS << ") {\n";486 487 ++Indent;488 OS << Indent;489 if (ShouldUpdateOpcodeMask) {490 if (PI.OperandMask.isZero())491 OS << "Mask.clearAllBits();\n";492 else493 OS << "Mask = " << PI.OperandMask << ";\n";494 OS << Indent;495 }496 OS << "return ";497 expandPredicate(OS, PI.Predicate);498 OS << ";\n";499 --Indent;500 OS << Indent << "}\n";501 }502}503 504void STIPredicateExpander::expandBody(raw_ostream &OS,505 const STIPredicateFunction &Fn) {506 bool UpdatesOpcodeMask =507 Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");508 509 OS << Indent << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";510 OS << Indent << "default:\n";511 OS << Indent << " break;";512 513 for (const OpcodeGroup &Group : Fn.getGroups()) {514 for (const Record *Opcode : Group.getOpcodes()) {515 OS << '\n'516 << Indent << "case " << getTargetName() << "::" << Opcode->getName()517 << ":";518 }519 520 OS << '\n';521 ++Indent;522 expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);523 524 OS << Indent << "break;\n";525 --Indent;526 }527 528 OS << Indent << "}\n";529}530 531void STIPredicateExpander::expandEpilogue(raw_ostream &OS,532 const STIPredicateFunction &Fn) {533 OS << '\n' << Indent;534 OS << "return ";535 expandPredicate(OS, Fn.getDefaultReturnPredicate());536 OS << ";\n";537 538 --Indent;539 StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");540 OS << Indent << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";541}542 543void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,544 const STIPredicateFunction &Fn) {545 const Record *Rec = Fn.getDeclaration();546 if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))547 return;548 549 expandHeader(OS, Fn);550 if (shouldExpandDefinition()) {551 expandPrologue(OS, Fn);552 expandBody(OS, Fn);553 expandEpilogue(OS, Fn);554 }555}556