diff options
author | Jessica Paquette <jpaquette@apple.com> | 2019-08-28 20:12:31 +0000 |
---|---|---|
committer | Jessica Paquette <jpaquette@apple.com> | 2019-08-28 20:12:31 +0000 |
commit | 7080ffa21a414ca279a1581f7fc96dfb5a08f01f (patch) | |
tree | 6e7ac2d8504f46fd8a7d4af4665278d41024deb7 /llvm/utils/TableGen/GlobalISelEmitter.cpp | |
parent | 6acfc7c587277a413bb06486a099e0d22da4f989 (diff) | |
download | bcm5719-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.cpp | 104 |
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. |