summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
authorJessica Paquette <jpaquette@apple.com>2019-08-28 20:12:31 +0000
committerJessica Paquette <jpaquette@apple.com>2019-08-28 20:12:31 +0000
commit7080ffa21a414ca279a1581f7fc96dfb5a08f01f (patch)
tree6e7ac2d8504f46fd8a7d4af4665278d41024deb7 /llvm/utils/TableGen/GlobalISelEmitter.cpp
parent6acfc7c587277a413bb06486a099e0d22da4f989 (diff)
downloadbcm5719-llvm-7080ffa21a414ca279a1581f7fc96dfb5a08f01f.tar.gz
bcm5719-llvm-7080ffa21a414ca279a1581f7fc96dfb5a08f01f.zip
[GlobalISel] Import patterns containing SUBREG_TO_REG
Reuse the logic for INSERT_SUBREG to also import SUBREG_TO_REG patterns. - Split `inferSuperRegisterClass` into two functions, one which tries to use an existing TreePatternNode (`inferSuperRegisterClassForNode`), and one that doesn't. SUBREG_TO_REG doesn't have a node to leverage, which is the cause for the split. - Rename GlobalISelEmitterInsertSubreg.td to GlobalISelEmitterSubreg.td and update it. - Update impacted tests in the AArch64 and X86 backends. This is kind of a hit/miss for code size improvements/regressions. E.g. in add-ext.ll, we now get some identity copies. This isn't really anything the importer can handle, since it's caused by a later pass introducing the copy for the sake of correctness. Differential Revision: https://reviews.llvm.org/D66769 llvm-svn: 370254
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp104
1 files changed, 85 insertions, 19 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 0fb6a9c95e6..60fa0ac69ba 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -3169,8 +3169,14 @@ private:
/// \p SubRegNode, and the subregister index defined by \p SubRegIdxNode.
/// If no register class is found, return None.
Optional<const CodeGenRegisterClass *>
+ inferSuperRegisterClassForNode(const TypeSetByHwMode &Ty,
+ TreePatternNode *SuperRegNode,
+ TreePatternNode *SubRegIdxNode);
+
+ /// Infer a CodeGenRegisterClass which suppoorts \p Ty and \p SubRegIdxNode.
+ /// Return None if no such class exists.
+ Optional<const CodeGenRegisterClass *>
inferSuperRegisterClass(const TypeSetByHwMode &Ty,
- TreePatternNode *SuperRegNode,
TreePatternNode *SubRegIdxNode);
/// Return the CodeGenRegisterClass associated with \p Leaf if it has one.
@@ -3864,8 +3870,9 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
if (!SubClass)
return failedImport(
"Cannot infer register class from INSERT_SUBREG operand #1");
- Optional<const CodeGenRegisterClass *> SuperClass = inferSuperRegisterClass(
- Dst->getExtType(0), Dst->getChild(0), Dst->getChild(2));
+ Optional<const CodeGenRegisterClass *> SuperClass =
+ inferSuperRegisterClassForNode(Dst->getExtType(0), Dst->getChild(0),
+ Dst->getChild(2));
if (!SuperClass)
return failedImport(
"Cannot infer register class for INSERT_SUBREG operand #0");
@@ -3880,6 +3887,26 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
return InsertPtOrError.get();
}
+ // Similar to INSERT_SUBREG, we also have to handle SUBREG_TO_REG as a
+ // subinstruction.
+ if (Target.getInstruction(Dst->getOperator()).TheDef->getName() ==
+ "SUBREG_TO_REG") {
+ auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
+ if (!SubClass)
+ return failedImport(
+ "Cannot infer register class from SUBREG_TO_REG child #1");
+ auto SuperClass = inferSuperRegisterClass(Dst->getExtType(0),
+ Dst->getChild(2));
+ if (!SuperClass)
+ return failedImport(
+ "Cannot infer register class for SUBREG_TO_REG operand #0");
+ M.insertAction<ConstrainOperandToRegClassAction>(
+ InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass);
+ M.insertAction<ConstrainOperandToRegClassAction>(
+ InsertPt, DstMIBuilder.getInsnID(), 2, **SubClass);
+ return InsertPtOrError.get();
+}
+
M.insertAction<ConstrainOperandsToDefinitionAction>(InsertPt,
DstMIBuilder.getInsnID());
return InsertPtOrError.get();
@@ -4128,23 +4155,11 @@ GlobalISelEmitter::inferRegClassFromPattern(TreePatternNode *N) {
Optional<const CodeGenRegisterClass *>
GlobalISelEmitter::inferSuperRegisterClass(const TypeSetByHwMode &Ty,
- TreePatternNode *SuperRegNode,
TreePatternNode *SubRegIdxNode) {
- // Check if we already have a defined register class for the super register
- // node. If we do, then we should preserve that rather than inferring anything
- // from the subregister index node. We can assume that whoever wrote the
- // pattern in the first place made sure that the super register and
- // subregister are compatible.
- if (Optional<const CodeGenRegisterClass *> SuperRegisterClass =
- inferRegClassFromPattern(SuperRegNode))
- return SuperRegisterClass;
-
+ assert(SubRegIdxNode && "Expected subregister index node!");
// We need a ValueTypeByHwMode for getSuperRegForSubReg.
if (!Ty.isValueTypeByHwMode(false))
return None;
-
- // We don't know anything about the super register. Try to use the subregister
- // index to infer an appropriate register class.
if (!SubRegIdxNode->isLeaf())
return None;
DefInit *SubRegInit = dyn_cast<DefInit>(SubRegIdxNode->getLeafValue());
@@ -4161,6 +4176,22 @@ GlobalISelEmitter::inferSuperRegisterClass(const TypeSetByHwMode &Ty,
return *RC;
}
+Optional<const CodeGenRegisterClass *>
+GlobalISelEmitter::inferSuperRegisterClassForNode(
+ const TypeSetByHwMode &Ty, TreePatternNode *SuperRegNode,
+ TreePatternNode *SubRegIdxNode) {
+ assert(SuperRegNode && "Expected super register node!");
+ // Check if we already have a defined register class for the super register
+ // node. If we do, then we should preserve that rather than inferring anything
+ // from the subregister index node. We can assume that whoever wrote the
+ // pattern in the first place made sure that the super register and
+ // subregister are compatible.
+ if (Optional<const CodeGenRegisterClass *> SuperRegisterClass =
+ inferRegClassFromPattern(SuperRegNode))
+ return *SuperRegisterClass;
+ return inferSuperRegisterClass(Ty, SubRegIdxNode);
+}
+
Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
// Keep track of the matchers and actions to emit.
int Score = P.getPatternComplexity(CGP);
@@ -4281,8 +4312,8 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
if (DstIOpRec == nullptr)
return failedImport("EXTRACT_SUBREG operand #0 isn't a register class");
} else if (DstI.TheDef->getName() == "INSERT_SUBREG") {
- auto MaybeSuperClass =
- inferSuperRegisterClass(VTy, Dst->getChild(0), Dst->getChild(2));
+ auto MaybeSuperClass = inferSuperRegisterClassForNode(
+ VTy, Dst->getChild(0), Dst->getChild(2));
if (!MaybeSuperClass)
return failedImport(
"Cannot infer register class for INSERT_SUBREG operand #0");
@@ -4295,6 +4326,17 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
OM.addPredicate<RegisterBankOperandMatcher>(**MaybeSuperClass);
++OpIdx;
continue;
+ } else if (DstI.TheDef->getName() == "SUBREG_TO_REG") {
+ auto MaybeRegClass = inferSuperRegisterClass(VTy, Dst->getChild(2));
+ if (!MaybeRegClass)
+ return failedImport(
+ "Cannot infer register class for SUBREG_TO_REG operand #0");
+ OperandMatcher &OM = InsnMatcher.getOperand(OpIdx);
+ OM.setSymbolicName(DstIOperand.Name);
+ M.defineOperand(OM.getSymbolicName(), OM);
+ OM.addPredicate<RegisterBankOperandMatcher>(**MaybeRegClass);
+ ++OpIdx;
+ continue;
} else if (DstIOpRec->isSubClassOf("RegisterOperand"))
DstIOpRec = DstIOpRec->getValueAsDef("RegClass");
else if (!DstIOpRec->isSubClassOf("RegisterClass"))
@@ -4393,7 +4435,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
if (!SubClass)
return failedImport(
"Cannot infer register class from INSERT_SUBREG operand #1");
- auto SuperClass = inferSuperRegisterClass(
+ auto SuperClass = inferSuperRegisterClassForNode(
Src->getExtType(0), Dst->getChild(0), Dst->getChild(2));
if (!SuperClass)
return failedImport(
@@ -4405,6 +4447,30 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
return std::move(M);
}
+ if (DstI.TheDef->getName() == "SUBREG_TO_REG") {
+ // We need to constrain the destination and subregister source.
+ assert(Src->getExtTypes().size() == 1 &&
+ "Expected Src of SUBREG_TO_REG to have one result type");
+
+ // Attempt to infer the subregister source from the first child. If it has
+ // an explicitly given register class, we'll use that. Otherwise, we will
+ // fail.
+ auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
+ if (!SubClass)
+ return failedImport(
+ "Cannot infer register class from SUBREG_TO_REG child #1");
+ // We don't have a child to look at that might have a super register node.
+ auto SuperClass =
+ inferSuperRegisterClass(Src->getExtType(0), Dst->getChild(2));
+ if (!SuperClass)
+ return failedImport(
+ "Cannot infer register class for SUBREG_TO_REG operand #0");
+ M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass);
+ M.addAction<ConstrainOperandToRegClassAction>(0, 2, **SubClass);
+ ++NumPatternImported;
+ return std::move(M);
+ }
+
M.addAction<ConstrainOperandsToDefinitionAction>(0);
// We're done with this pattern! It's eligible for GISel emission; return it.
OpenPOWER on IntegriCloud