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