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