brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.8 KiB · 03252ed Raw
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