mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
ae65e281f3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
530 lines
17 KiB
C++
530 lines
17 KiB
C++
//===--------------------- PredicateExpander.cpp --------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
/// Functionalities used by the Tablegen backends to expand machine predicates.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "PredicateExpander.h"
|
|
#include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
|
|
|
|
namespace llvm {
|
|
|
|
void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
|
|
void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
|
|
|
|
void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
|
|
int ImmVal,
|
|
StringRef FunctionMapper) {
|
|
if (!FunctionMapper.empty())
|
|
OS << FunctionMapper << "(";
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
|
<< ").getImm()";
|
|
if (!FunctionMapper.empty())
|
|
OS << ")";
|
|
OS << (shouldNegate() ? " != " : " == ") << ImmVal;
|
|
}
|
|
|
|
void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
|
|
StringRef ImmVal,
|
|
StringRef FunctionMapper) {
|
|
if (ImmVal.empty())
|
|
expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
|
|
|
|
if (!FunctionMapper.empty())
|
|
OS << FunctionMapper << "(";
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
|
<< ").getImm()";
|
|
if (!FunctionMapper.empty())
|
|
OS << ")";
|
|
OS << (shouldNegate() ? " != " : " == ") << ImmVal;
|
|
}
|
|
|
|
void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
|
|
int OpIndex,
|
|
StringRef FunctionMapper) {
|
|
if (shouldNegate())
|
|
OS << "!";
|
|
if (!FunctionMapper.empty())
|
|
OS << FunctionMapper << "(";
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
|
<< ").getImm()";
|
|
if (!FunctionMapper.empty())
|
|
OS << ")";
|
|
}
|
|
|
|
void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
|
|
const Record *Reg,
|
|
StringRef FunctionMapper) {
|
|
assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
|
|
|
|
if (!FunctionMapper.empty())
|
|
OS << FunctionMapper << "(";
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
|
<< ").getReg()";
|
|
if (!FunctionMapper.empty())
|
|
OS << ")";
|
|
OS << (shouldNegate() ? " != " : " == ");
|
|
const StringRef Str = Reg->getValueAsString("Namespace");
|
|
if (!Str.empty())
|
|
OS << Str << "::";
|
|
OS << Reg->getName();
|
|
}
|
|
|
|
|
|
void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
|
|
int OpIndex,
|
|
StringRef FunctionMapper) {
|
|
if (shouldNegate())
|
|
OS << "!";
|
|
if (!FunctionMapper.empty())
|
|
OS << FunctionMapper << "(";
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
|
<< ").getReg()";
|
|
if (!FunctionMapper.empty())
|
|
OS << ")";
|
|
}
|
|
|
|
void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
|
|
int OpIndex) {
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
|
<< ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
|
|
}
|
|
|
|
void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
|
|
int Second) {
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
|
|
<< ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
|
|
<< (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
|
|
}
|
|
|
|
void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
|
|
<< (shouldNegate() ? "!= " : "== ") << NumOps;
|
|
}
|
|
|
|
void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
|
|
<< (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
|
|
<< "::" << Inst->getName();
|
|
}
|
|
|
|
void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
|
|
const RecVec &Opcodes) {
|
|
assert(!Opcodes.empty() && "Expected at least one opcode to check!");
|
|
bool First = true;
|
|
|
|
if (Opcodes.size() == 1) {
|
|
OS << "( ";
|
|
expandCheckOpcode(OS, Opcodes[0]);
|
|
OS << " )";
|
|
return;
|
|
}
|
|
|
|
OS << '(';
|
|
increaseIndentLevel();
|
|
for (const Record *Rec : Opcodes) {
|
|
OS << '\n';
|
|
OS.indent(getIndentLevel() * 2);
|
|
if (!First)
|
|
OS << (shouldNegate() ? "&& " : "|| ");
|
|
|
|
expandCheckOpcode(OS, Rec);
|
|
First = false;
|
|
}
|
|
|
|
OS << '\n';
|
|
decreaseIndentLevel();
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << ')';
|
|
}
|
|
|
|
void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
|
|
const RecVec &Opcodes) {
|
|
if (shouldExpandForMC())
|
|
expandFalse(OS);
|
|
else
|
|
expandCheckOpcode(OS, Opcodes);
|
|
}
|
|
|
|
void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
|
|
const RecVec &Sequence,
|
|
bool IsCheckAll) {
|
|
assert(!Sequence.empty() && "Found an invalid empty predicate set!");
|
|
if (Sequence.size() == 1)
|
|
return expandPredicate(OS, Sequence[0]);
|
|
|
|
// Okay, there is more than one predicate in the set.
|
|
bool First = true;
|
|
OS << (shouldNegate() ? "!(" : "(");
|
|
increaseIndentLevel();
|
|
|
|
bool OldValue = shouldNegate();
|
|
setNegatePredicate(false);
|
|
for (const Record *Rec : Sequence) {
|
|
OS << '\n';
|
|
OS.indent(getIndentLevel() * 2);
|
|
if (!First)
|
|
OS << (IsCheckAll ? "&& " : "|| ");
|
|
expandPredicate(OS, Rec);
|
|
First = false;
|
|
}
|
|
OS << '\n';
|
|
decreaseIndentLevel();
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << ')';
|
|
setNegatePredicate(OldValue);
|
|
}
|
|
|
|
void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
|
|
StringRef MethodName) {
|
|
OS << (shouldNegate() ? "!" : "");
|
|
OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
|
|
OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
|
|
}
|
|
|
|
void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
|
|
OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
|
|
<< "getOperand(" << OpIndex << ").isReg() ";
|
|
}
|
|
|
|
void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
|
|
OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
|
|
<< "getOperand(" << OpIndex << ").isImm() ";
|
|
}
|
|
|
|
void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
|
|
StringRef MCInstFn,
|
|
StringRef MachineInstrFn) {
|
|
OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
|
|
<< (isByRef() ? "(MI)" : "(*MI)");
|
|
}
|
|
|
|
void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
|
|
StringRef Code) {
|
|
if (shouldExpandForMC())
|
|
return expandFalse(OS);
|
|
|
|
OS << '(' << Code << ')';
|
|
}
|
|
|
|
void PredicateExpander::expandReturnStatement(raw_ostream &OS,
|
|
const Record *Rec) {
|
|
std::string Buffer;
|
|
raw_string_ostream SS(Buffer);
|
|
|
|
SS << "return ";
|
|
expandPredicate(SS, Rec);
|
|
SS << ";";
|
|
SS.flush();
|
|
OS << Buffer;
|
|
}
|
|
|
|
void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
|
|
const Record *Rec) {
|
|
const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
|
|
for (const Record *Opcode : Opcodes) {
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << "case " << Opcode->getValueAsString("Namespace")
|
|
<< "::" << Opcode->getName() << ":\n";
|
|
}
|
|
|
|
increaseIndentLevel();
|
|
OS.indent(getIndentLevel() * 2);
|
|
expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
|
|
decreaseIndentLevel();
|
|
}
|
|
|
|
void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
|
|
const RecVec &Cases,
|
|
const Record *Default) {
|
|
std::string Buffer;
|
|
raw_string_ostream SS(Buffer);
|
|
|
|
SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
|
|
for (const Record *Rec : Cases) {
|
|
expandOpcodeSwitchCase(SS, Rec);
|
|
SS << '\n';
|
|
}
|
|
|
|
// Expand the default case.
|
|
SS.indent(getIndentLevel() * 2);
|
|
SS << "default:\n";
|
|
|
|
increaseIndentLevel();
|
|
SS.indent(getIndentLevel() * 2);
|
|
expandStatement(SS, Default);
|
|
decreaseIndentLevel();
|
|
SS << '\n';
|
|
|
|
SS.indent(getIndentLevel() * 2);
|
|
SS << "} // end of switch-stmt";
|
|
SS.flush();
|
|
OS << Buffer;
|
|
}
|
|
|
|
void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
|
|
// Assume that padding has been added by the caller.
|
|
if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
|
|
expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
|
|
Rec->getValueAsDef("DefaultCase"));
|
|
return;
|
|
}
|
|
|
|
if (Rec->isSubClassOf("MCReturnStatement")) {
|
|
expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
|
|
return;
|
|
}
|
|
|
|
llvm_unreachable("No known rules to expand this MCStatement");
|
|
}
|
|
|
|
void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
|
|
// Assume that padding has been added by the caller.
|
|
if (Rec->isSubClassOf("MCTrue")) {
|
|
if (shouldNegate())
|
|
return expandFalse(OS);
|
|
return expandTrue(OS);
|
|
}
|
|
|
|
if (Rec->isSubClassOf("MCFalse")) {
|
|
if (shouldNegate())
|
|
return expandTrue(OS);
|
|
return expandFalse(OS);
|
|
}
|
|
|
|
if (Rec->isSubClassOf("CheckNot")) {
|
|
flipNegatePredicate();
|
|
expandPredicate(OS, Rec->getValueAsDef("Pred"));
|
|
flipNegatePredicate();
|
|
return;
|
|
}
|
|
|
|
if (Rec->isSubClassOf("CheckIsRegOperand"))
|
|
return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
|
|
|
|
if (Rec->isSubClassOf("CheckIsImmOperand"))
|
|
return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
|
|
|
|
if (Rec->isSubClassOf("CheckRegOperand"))
|
|
return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
|
|
Rec->getValueAsDef("Reg"),
|
|
Rec->getValueAsString("FunctionMapper"));
|
|
|
|
if (Rec->isSubClassOf("CheckRegOperandSimple"))
|
|
return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
|
|
Rec->getValueAsString("FunctionMapper"));
|
|
|
|
if (Rec->isSubClassOf("CheckInvalidRegOperand"))
|
|
return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
|
|
|
|
if (Rec->isSubClassOf("CheckImmOperand"))
|
|
return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
|
|
Rec->getValueAsInt("ImmVal"),
|
|
Rec->getValueAsString("FunctionMapper"));
|
|
|
|
if (Rec->isSubClassOf("CheckImmOperand_s"))
|
|
return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
|
|
Rec->getValueAsString("ImmVal"),
|
|
Rec->getValueAsString("FunctionMapper"));
|
|
|
|
if (Rec->isSubClassOf("CheckImmOperandSimple"))
|
|
return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
|
|
Rec->getValueAsString("FunctionMapper"));
|
|
|
|
if (Rec->isSubClassOf("CheckSameRegOperand"))
|
|
return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
|
|
Rec->getValueAsInt("SecondIndex"));
|
|
|
|
if (Rec->isSubClassOf("CheckNumOperands"))
|
|
return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
|
|
|
|
if (Rec->isSubClassOf("CheckPseudo"))
|
|
return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
|
|
|
|
if (Rec->isSubClassOf("CheckOpcode"))
|
|
return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
|
|
|
|
if (Rec->isSubClassOf("CheckAll"))
|
|
return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
|
|
/* AllOf */ true);
|
|
|
|
if (Rec->isSubClassOf("CheckAny"))
|
|
return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
|
|
/* AllOf */ false);
|
|
|
|
if (Rec->isSubClassOf("CheckFunctionPredicate"))
|
|
return expandCheckFunctionPredicate(
|
|
OS, Rec->getValueAsString("MCInstFnName"),
|
|
Rec->getValueAsString("MachineInstrFnName"));
|
|
|
|
if (Rec->isSubClassOf("CheckNonPortable"))
|
|
return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
|
|
|
|
if (Rec->isSubClassOf("TIIPredicate"))
|
|
return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
|
|
|
|
llvm_unreachable("No known rules to expand this MCInstPredicate");
|
|
}
|
|
|
|
void STIPredicateExpander::expandHeader(raw_ostream &OS,
|
|
const STIPredicateFunction &Fn) {
|
|
const Record *Rec = Fn.getDeclaration();
|
|
StringRef FunctionName = Rec->getValueAsString("Name");
|
|
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << "bool ";
|
|
if (shouldExpandDefinition())
|
|
OS << getClassPrefix() << "::";
|
|
OS << FunctionName << "(";
|
|
if (shouldExpandForMC())
|
|
OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
|
|
else
|
|
OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
|
|
if (Rec->getValueAsBit("UpdatesOpcodeMask"))
|
|
OS << ", APInt &Mask";
|
|
OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
|
|
if (shouldExpandDefinition()) {
|
|
OS << "{\n";
|
|
return;
|
|
}
|
|
|
|
if (Rec->getValueAsBit("OverridesBaseClassMember"))
|
|
OS << "override";
|
|
OS << ";\n";
|
|
}
|
|
|
|
void STIPredicateExpander::expandPrologue(raw_ostream &OS,
|
|
const STIPredicateFunction &Fn) {
|
|
RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
|
|
bool UpdatesOpcodeMask =
|
|
Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
|
|
|
|
increaseIndentLevel();
|
|
unsigned IndentLevel = getIndentLevel();
|
|
for (const Record *Delegate : Delegates) {
|
|
OS.indent(IndentLevel * 2);
|
|
OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
|
|
if (UpdatesOpcodeMask)
|
|
OS << ", Mask";
|
|
if (shouldExpandForMC())
|
|
OS << ", ProcessorID";
|
|
OS << "))\n";
|
|
OS.indent((1 + IndentLevel) * 2);
|
|
OS << "return true;\n\n";
|
|
}
|
|
|
|
if (shouldExpandForMC())
|
|
return;
|
|
|
|
OS.indent(IndentLevel * 2);
|
|
OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
|
|
}
|
|
|
|
void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
|
|
bool ShouldUpdateOpcodeMask) {
|
|
const OpcodeInfo &OI = Group.getOpcodeInfo();
|
|
for (const PredicateInfo &PI : OI.getPredicates()) {
|
|
const APInt &ProcModelMask = PI.ProcModelMask;
|
|
bool FirstProcID = true;
|
|
for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
|
|
if (!ProcModelMask[I])
|
|
continue;
|
|
|
|
if (FirstProcID) {
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << "if (ProcessorID == " << I;
|
|
} else {
|
|
OS << " || ProcessorID == " << I;
|
|
}
|
|
FirstProcID = false;
|
|
}
|
|
|
|
OS << ") {\n";
|
|
|
|
increaseIndentLevel();
|
|
OS.indent(getIndentLevel() * 2);
|
|
if (ShouldUpdateOpcodeMask) {
|
|
if (PI.OperandMask.isNullValue())
|
|
OS << "Mask.clearAllBits();\n";
|
|
else
|
|
OS << "Mask = " << PI.OperandMask << ";\n";
|
|
OS.indent(getIndentLevel() * 2);
|
|
}
|
|
OS << "return ";
|
|
expandPredicate(OS, PI.Predicate);
|
|
OS << ";\n";
|
|
decreaseIndentLevel();
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << "}\n";
|
|
}
|
|
}
|
|
|
|
void STIPredicateExpander::expandBody(raw_ostream &OS,
|
|
const STIPredicateFunction &Fn) {
|
|
bool UpdatesOpcodeMask =
|
|
Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
|
|
|
|
unsigned IndentLevel = getIndentLevel();
|
|
OS.indent(IndentLevel * 2);
|
|
OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
|
|
OS.indent(IndentLevel * 2);
|
|
OS << "default:\n";
|
|
OS.indent(IndentLevel * 2);
|
|
OS << " break;";
|
|
|
|
for (const OpcodeGroup &Group : Fn.getGroups()) {
|
|
for (const Record *Opcode : Group.getOpcodes()) {
|
|
OS << '\n';
|
|
OS.indent(IndentLevel * 2);
|
|
OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
|
|
}
|
|
|
|
OS << '\n';
|
|
increaseIndentLevel();
|
|
expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
|
|
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << "break;\n";
|
|
decreaseIndentLevel();
|
|
}
|
|
|
|
OS.indent(IndentLevel * 2);
|
|
OS << "}\n";
|
|
}
|
|
|
|
void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
|
|
const STIPredicateFunction &Fn) {
|
|
OS << '\n';
|
|
OS.indent(getIndentLevel() * 2);
|
|
OS << "return ";
|
|
expandPredicate(OS, Fn.getDefaultReturnPredicate());
|
|
OS << ";\n";
|
|
|
|
decreaseIndentLevel();
|
|
OS.indent(getIndentLevel() * 2);
|
|
StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
|
|
OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
|
|
}
|
|
|
|
void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
|
|
const STIPredicateFunction &Fn) {
|
|
const Record *Rec = Fn.getDeclaration();
|
|
if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
|
|
return;
|
|
|
|
expandHeader(OS, Fn);
|
|
if (shouldExpandDefinition()) {
|
|
expandPrologue(OS, Fn);
|
|
expandBody(OS, Fn);
|
|
expandEpilogue(OS, Fn);
|
|
}
|
|
}
|
|
|
|
} // namespace llvm
|