2018-05-25 23:55:37 +08:00
|
|
|
//===--------------------- PredicateExpander.cpp --------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2018-05-25 23:55:37 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
|
|
|
/// Functionalities used by the Tablegen backends to expand machine predicates.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "PredicateExpander.h"
|
[TableGen][SubtargetEmitter] Add the ability for processor models to describe dependency breaking instructions.
This patch adds the ability for processor models to describe dependency breaking
instructions.
Different processors may specify a different set of dependency-breaking
instructions.
That means, we cannot assume that all processors of the same target would use
the same rules to classify dependency breaking instructions.
The main goal of this patch is to provide the means to describe dependency
breaking instructions directly via tablegen, and have the following
TargetSubtargetInfo hooks redefined in overrides by tabegen'd
XXXGenSubtargetInfo classes (here, XXX is a Target name).
```
virtual bool isZeroIdiom(const MachineInstr *MI, APInt &Mask) const {
return false;
}
virtual bool isDependencyBreaking(const MachineInstr *MI, APInt &Mask) const {
return isZeroIdiom(MI);
}
```
An instruction MI is a dependency-breaking instruction if a call to method
isDependencyBreaking(MI) on the STI (TargetSubtargetInfo object) evaluates to
true. Similarly, an instruction MI is a special case of zero-idiom dependency
breaking instruction if a call to STI.isZeroIdiom(MI) returns true.
The extra APInt is used for those targets that may want to select which machine
operands have their dependency broken (see comments in code).
Note that by default, subtargets don't know about the existence of
dependency-breaking. In the absence of external information, those method calls
would always return false.
A new tablegen class named STIPredicate has been added by this patch to let
processor models classify instructions that have properties in common. The idea
is that, a MCInstrPredicate definition can be used to "generate" an instruction
equivalence class, with the idea that instructions of a same class all have a
property in common.
STIPredicate definitions are essentially a collection of instruction equivalence
classes.
Also, different processor models can specify a different variant of the same
STIPredicate with different rules (i.e. predicates) to classify instructions.
Tablegen backends (in this particular case, the SubtargetEmitter) will be able
to process STIPredicate definitions, and automatically generate functions in
XXXGenSubtargetInfo.
This patch introduces two special kind of STIPredicate classes named
IsZeroIdiomFunction and IsDepBreakingFunction in tablegen. It also adds a
definition for those in the BtVer2 scheduling model only.
This patch supersedes the one committed at r338372 (phabricator review: D49310).
The main advantages are:
- We can describe subtarget predicates via tablegen using STIPredicates.
- We can describe zero-idioms / dep-breaking instructions directly via
tablegen in the scheduling models.
In future, the STIPredicates framework can be used for solving other problems.
Examples of future developments are:
- Teach how to identify optimizable register-register moves
- Teach how to identify slow LEA instructions (each subtarget defining its own
concept of "slow" LEA).
- Teach how to identify instructions that have undocumented false dependencies
on the output registers on some processors only.
It is also (in my opinion) an elegant way to expose knowledge to both external
tools like llvm-mca, and codegen passes.
For example, machine schedulers in LLVM could reuse that information when
internally constructing the data dependency graph for a code region.
This new design feature is also an "opt-in" feature. Processor models don't have
to use the new STIPredicates. It has all been designed to be as unintrusive as
possible.
Differential Revision: https://reviews.llvm.org/D52174
llvm-svn: 342555
2018-09-19 23:57:45 +08:00
|
|
|
#include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
|
2018-05-25 23:55:37 +08:00
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
|
|
|
|
void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
|
2018-05-25 23:55:37 +08:00
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
int ImmVal,
|
|
|
|
StringRef FunctionMapper) {
|
|
|
|
if (!FunctionMapper.empty())
|
|
|
|
OS << FunctionMapper << "(";
|
2018-07-18 00:11:37 +08:00
|
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
<< ").getImm()";
|
2018-12-01 05:03:24 +08:00
|
|
|
if (!FunctionMapper.empty())
|
|
|
|
OS << ")";
|
|
|
|
OS << (shouldNegate() ? " != " : " == ") << ImmVal;
|
2018-05-25 23:55:37 +08:00
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
StringRef ImmVal,
|
|
|
|
StringRef FunctionMapper) {
|
2018-12-01 05:03:24 +08:00
|
|
|
if (ImmVal.empty())
|
|
|
|
expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
|
|
|
|
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
if (!FunctionMapper.empty())
|
|
|
|
OS << FunctionMapper << "(";
|
2018-07-18 00:11:37 +08:00
|
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
<< ").getImm()";
|
2018-12-01 05:03:24 +08:00
|
|
|
if (!FunctionMapper.empty())
|
|
|
|
OS << ")";
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
OS << (shouldNegate() ? " != " : " == ") << ImmVal;
|
2018-05-25 23:55:37 +08:00
|
|
|
}
|
|
|
|
|
2018-12-01 05:03:24 +08:00
|
|
|
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 << ")";
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
const Record *Reg,
|
|
|
|
StringRef FunctionMapper) {
|
2018-05-25 23:55:37 +08:00
|
|
|
assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
|
|
|
|
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
if (!FunctionMapper.empty())
|
|
|
|
OS << FunctionMapper << "(";
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
<< ").getReg()";
|
2018-12-01 05:03:24 +08:00
|
|
|
if (!FunctionMapper.empty())
|
|
|
|
OS << ")";
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
OS << (shouldNegate() ? " != " : " == ");
|
2018-05-25 23:55:37 +08:00
|
|
|
const StringRef Str = Reg->getValueAsString("Namespace");
|
|
|
|
if (!Str.empty())
|
|
|
|
OS << Str << "::";
|
|
|
|
OS << Reg->getName();
|
|
|
|
}
|
|
|
|
|
2018-12-01 05:03:24 +08:00
|
|
|
|
|
|
|
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 << ")";
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
|
2018-07-18 19:03:22 +08:00
|
|
|
int OpIndex) {
|
|
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
|
|
|
|
<< ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
|
|
|
|
int Second) {
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
|
|
|
|
<< ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
|
|
|
|
<< (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
|
|
|
|
<< (shouldNegate() ? "!= " : "== ") << NumOps;
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
|
|
|
|
<< (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
|
|
|
|
<< "::" << Inst->getName();
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
|
2018-05-25 23:55:37 +08:00
|
|
|
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';
|
2018-08-13 23:13:35 +08:00
|
|
|
OS.indent(getIndentLevel() * 2);
|
2018-05-25 23:55:37 +08:00
|
|
|
if (!First)
|
|
|
|
OS << (shouldNegate() ? "&& " : "|| ");
|
|
|
|
|
|
|
|
expandCheckOpcode(OS, Rec);
|
|
|
|
First = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << '\n';
|
|
|
|
decreaseIndentLevel();
|
2018-08-13 23:13:35 +08:00
|
|
|
OS.indent(getIndentLevel() * 2);
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << ')';
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
|
2018-05-25 23:55:37 +08:00
|
|
|
const RecVec &Opcodes) {
|
|
|
|
if (shouldExpandForMC())
|
|
|
|
expandFalse(OS);
|
|
|
|
else
|
|
|
|
expandCheckOpcode(OS, Opcodes);
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
|
2018-05-25 23:55:37 +08:00
|
|
|
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';
|
2018-08-13 23:13:35 +08:00
|
|
|
OS.indent(getIndentLevel() * 2);
|
2018-05-25 23:55:37 +08:00
|
|
|
if (!First)
|
|
|
|
OS << (IsCheckAll ? "&& " : "|| ");
|
|
|
|
expandPredicate(OS, Rec);
|
|
|
|
First = false;
|
|
|
|
}
|
|
|
|
OS << '\n';
|
|
|
|
decreaseIndentLevel();
|
2018-08-13 23:13:35 +08:00
|
|
|
OS.indent(getIndentLevel() * 2);
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << ')';
|
|
|
|
setNegatePredicate(OldValue);
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
|
2018-05-25 23:55:37 +08:00
|
|
|
StringRef MethodName) {
|
|
|
|
OS << (shouldNegate() ? "!" : "");
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
|
|
|
|
<< "getOperand(" << OpIndex << ").isReg() ";
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
|
2018-05-25 23:55:37 +08:00
|
|
|
OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
|
|
|
|
<< "getOperand(" << OpIndex << ").isImm() ";
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
|
2018-05-25 23:55:37 +08:00
|
|
|
StringRef MCInstFn,
|
|
|
|
StringRef MachineInstrFn) {
|
|
|
|
OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
|
|
|
|
<< (isByRef() ? "(MI)" : "(*MI)");
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
|
2018-05-25 23:55:37 +08:00
|
|
|
StringRef Code) {
|
|
|
|
if (shouldExpandForMC())
|
|
|
|
return expandFalse(OS);
|
|
|
|
|
|
|
|
OS << '(' << Code << ')';
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandReturnStatement(raw_ostream &OS,
|
2018-08-09 23:32:48 +08:00
|
|
|
const Record *Rec) {
|
2018-08-13 23:13:35 +08:00
|
|
|
std::string Buffer;
|
|
|
|
raw_string_ostream SS(Buffer);
|
|
|
|
|
|
|
|
SS << "return ";
|
|
|
|
expandPredicate(SS, Rec);
|
|
|
|
SS << ";";
|
|
|
|
SS.flush();
|
|
|
|
OS << Buffer;
|
2018-08-09 23:32:48 +08:00
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
|
2018-08-09 23:32:48 +08:00
|
|
|
const Record *Rec) {
|
|
|
|
const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
|
|
|
|
for (const Record *Opcode : Opcodes) {
|
2018-08-13 23:13:35 +08:00
|
|
|
OS.indent(getIndentLevel() * 2);
|
2018-08-09 23:32:48 +08:00
|
|
|
OS << "case " << Opcode->getValueAsString("Namespace")
|
2018-11-28 04:59:01 +08:00
|
|
|
<< "::" << Opcode->getName() << ":\n";
|
2018-08-09 23:32:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
increaseIndentLevel();
|
2018-08-13 23:13:35 +08:00
|
|
|
OS.indent(getIndentLevel() * 2);
|
2018-08-09 23:32:48 +08:00
|
|
|
expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
|
|
|
|
decreaseIndentLevel();
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
|
2018-08-09 23:32:48 +08:00
|
|
|
const RecVec &Cases,
|
|
|
|
const Record *Default) {
|
2018-08-13 23:13:35 +08:00
|
|
|
std::string Buffer;
|
|
|
|
raw_string_ostream SS(Buffer);
|
2018-08-09 23:32:48 +08:00
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
|
2018-08-09 23:32:48 +08:00
|
|
|
for (const Record *Rec : Cases) {
|
2018-08-13 23:13:35 +08:00
|
|
|
expandOpcodeSwitchCase(SS, Rec);
|
|
|
|
SS << '\n';
|
2018-08-09 23:32:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Expand the default case.
|
2018-08-13 23:13:35 +08:00
|
|
|
SS.indent(getIndentLevel() * 2);
|
2018-11-28 04:59:01 +08:00
|
|
|
SS << "default:\n";
|
2018-08-13 23:13:35 +08:00
|
|
|
|
2018-08-09 23:32:48 +08:00
|
|
|
increaseIndentLevel();
|
2018-08-13 23:13:35 +08:00
|
|
|
SS.indent(getIndentLevel() * 2);
|
|
|
|
expandStatement(SS, Default);
|
2018-08-09 23:32:48 +08:00
|
|
|
decreaseIndentLevel();
|
2018-08-13 23:13:35 +08:00
|
|
|
SS << '\n';
|
2018-08-09 23:32:48 +08:00
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
SS.indent(getIndentLevel() * 2);
|
|
|
|
SS << "} // end of switch-stmt";
|
|
|
|
SS.flush();
|
|
|
|
OS << Buffer;
|
2018-08-09 23:32:48 +08:00
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
|
|
|
|
// Assume that padding has been added by the caller.
|
2018-08-09 23:32:48 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2018-08-13 23:13:35 +08:00
|
|
|
void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
|
|
|
|
// Assume that padding has been added by the caller.
|
2018-05-25 23:55:37 +08:00
|
|
|
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"),
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
Rec->getValueAsDef("Reg"),
|
|
|
|
Rec->getValueAsString("FunctionMapper"));
|
|
|
|
|
|
|
|
if (Rec->isSubClassOf("CheckRegOperandSimple"))
|
2018-12-01 05:03:24 +08:00
|
|
|
return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
|
|
|
|
Rec->getValueAsString("FunctionMapper"));
|
2018-05-25 23:55:37 +08:00
|
|
|
|
2018-07-18 19:03:22 +08:00
|
|
|
if (Rec->isSubClassOf("CheckInvalidRegOperand"))
|
|
|
|
return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
|
|
|
|
|
2018-05-25 23:55:37 +08:00
|
|
|
if (Rec->isSubClassOf("CheckImmOperand"))
|
|
|
|
return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
Rec->getValueAsInt("ImmVal"),
|
|
|
|
Rec->getValueAsString("FunctionMapper"));
|
2018-05-25 23:55:37 +08:00
|
|
|
|
|
|
|
if (Rec->isSubClassOf("CheckImmOperand_s"))
|
|
|
|
return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
|
[tblgen][PredicateExpander] Add the ability to describe more complex constraints on instruction operands.
Before this patch, class PredicateExpander only knew how to expand simple
predicates that performed checks on instruction operands.
In particular, the new scheduling predicate syntax was not rich enough to
express checks like this one:
Foo(MI->getOperand(0).getImm()) == ExpectedVal;
Here, the immediate operand value at index zero is passed in input to function
Foo, and ExpectedVal is compared against the value returned by function Foo.
While this predicate pattern doesn't show up in any X86 model, it shows up in
other upstream targets. So, being able to support those predicates is
fundamental if we want to be able to modernize all the scheduling models
upstream.
With this patch, we allow users to specify if a register/immediate operand value
needs to be passed in input to a function as part of the predicate check. Now,
register/immediate operand checks all derive from base class CheckOperandBase.
This patch also changes where TIIPredicate definitions are expanded by the
instructon info emitter. Before, definitions were expanded in class
XXXGenInstrInfo (where XXX is a target name).
With the introduction of this new syntax, we may want to have TIIPredicates
expanded directly in XXXInstrInfo. That is because functions used by the new
operand predicates may only exist in the derived class (i.e. XXXInstrInfo).
This patch is a non functional change for the existing scheduling models.
In future, we will be able to use this richer syntax to better describe complex
scheduling predicates, and expose them to llvm-mca.
Differential Revision: https://reviews.llvm.org/D53880
llvm-svn: 345714
2018-10-31 20:28:05 +08:00
|
|
|
Rec->getValueAsString("ImmVal"),
|
|
|
|
Rec->getValueAsString("FunctionMapper"));
|
|
|
|
|
|
|
|
if (Rec->isSubClassOf("CheckImmOperandSimple"))
|
2018-12-01 05:03:24 +08:00
|
|
|
return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
|
|
|
|
Rec->getValueAsString("FunctionMapper"));
|
2018-05-25 23:55:37 +08:00
|
|
|
|
|
|
|
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"))
|
2018-08-15 02:36:54 +08:00
|
|
|
return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
|
2018-05-25 23:55:37 +08:00
|
|
|
|
|
|
|
llvm_unreachable("No known rules to expand this MCInstPredicate");
|
|
|
|
}
|
|
|
|
|
[TableGen][SubtargetEmitter] Add the ability for processor models to describe dependency breaking instructions.
This patch adds the ability for processor models to describe dependency breaking
instructions.
Different processors may specify a different set of dependency-breaking
instructions.
That means, we cannot assume that all processors of the same target would use
the same rules to classify dependency breaking instructions.
The main goal of this patch is to provide the means to describe dependency
breaking instructions directly via tablegen, and have the following
TargetSubtargetInfo hooks redefined in overrides by tabegen'd
XXXGenSubtargetInfo classes (here, XXX is a Target name).
```
virtual bool isZeroIdiom(const MachineInstr *MI, APInt &Mask) const {
return false;
}
virtual bool isDependencyBreaking(const MachineInstr *MI, APInt &Mask) const {
return isZeroIdiom(MI);
}
```
An instruction MI is a dependency-breaking instruction if a call to method
isDependencyBreaking(MI) on the STI (TargetSubtargetInfo object) evaluates to
true. Similarly, an instruction MI is a special case of zero-idiom dependency
breaking instruction if a call to STI.isZeroIdiom(MI) returns true.
The extra APInt is used for those targets that may want to select which machine
operands have their dependency broken (see comments in code).
Note that by default, subtargets don't know about the existence of
dependency-breaking. In the absence of external information, those method calls
would always return false.
A new tablegen class named STIPredicate has been added by this patch to let
processor models classify instructions that have properties in common. The idea
is that, a MCInstrPredicate definition can be used to "generate" an instruction
equivalence class, with the idea that instructions of a same class all have a
property in common.
STIPredicate definitions are essentially a collection of instruction equivalence
classes.
Also, different processor models can specify a different variant of the same
STIPredicate with different rules (i.e. predicates) to classify instructions.
Tablegen backends (in this particular case, the SubtargetEmitter) will be able
to process STIPredicate definitions, and automatically generate functions in
XXXGenSubtargetInfo.
This patch introduces two special kind of STIPredicate classes named
IsZeroIdiomFunction and IsDepBreakingFunction in tablegen. It also adds a
definition for those in the BtVer2 scheduling model only.
This patch supersedes the one committed at r338372 (phabricator review: D49310).
The main advantages are:
- We can describe subtarget predicates via tablegen using STIPredicates.
- We can describe zero-idioms / dep-breaking instructions directly via
tablegen in the scheduling models.
In future, the STIPredicates framework can be used for solving other problems.
Examples of future developments are:
- Teach how to identify optimizable register-register moves
- Teach how to identify slow LEA instructions (each subtarget defining its own
concept of "slow" LEA).
- Teach how to identify instructions that have undocumented false dependencies
on the output registers on some processors only.
It is also (in my opinion) an elegant way to expose knowledge to both external
tools like llvm-mca, and codegen passes.
For example, machine schedulers in LLVM could reuse that information when
internally constructing the data dependency graph for a code region.
This new design feature is also an "opt-in" feature. Processor models don't have
to use the new STIPredicates. It has all been designed to be as unintrusive as
possible.
Differential Revision: https://reviews.llvm.org/D52174
llvm-svn: 342555
2018-09-19 23:57:45 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-25 23:55:37 +08:00
|
|
|
} // namespace llvm
|