diff --git a/llvm/test/TableGen/GlobalISelEmitter/undef-tied-input.td b/llvm/test/TableGen/GlobalISelEmitter/undef-tied-input.td index a2ee3dc311772..323aea9e396d1 100644 --- a/llvm/test/TableGen/GlobalISelEmitter/undef-tied-input.td +++ b/llvm/test/TableGen/GlobalISelEmitter/undef-tied-input.td @@ -1,14 +1,25 @@ -// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common %s | FileCheck %s +// RUN: llvm-tblgen -gen-global-isel -warn-on-skipped-patterns \ +// RUN: -I %p/../../../include -I %p/../Common %s 2> %t | FileCheck %s +// RUN: FileCheck -check-prefix=ERR %s < %t include "llvm/Target/Target.td" include "GlobalISelEmitterCommon.td" -def undef_tied : OperandWithDefaultOps { +def undef_tied_1 : OperandWithDefaultOps { let MIOperandInfo = (ops GPR32:$inactive); } +def undef_tied_2 : OperandWithDefaultOps { + let MIOperandInfo = (ops GPR32:$inactive); +} + +let Constraints = "$opt.inactive = $rd" in +def I1 : I<(outs GPR32:$rd), (ins GPR32:$rs, undef_tied_1:$opt), + [(set GPR32:$rd, (abs i32:$rs))]>; + +// ERR: [[#@LINE+2]]:5: warning: Skipped pattern: unsupported type let Constraints = "$opt.inactive = $rd" in -def I1 : I<(outs GPR32:$rd), (ins GPR32:$rs, undef_tied:$opt), +def I2 : I<(outs GPR32:$rd), (ins GPR32:$rs, undef_tied_2:$opt), [(set GPR32:$rd, (abs i32:$rs))]>; // CHECK-LABEL: // (abs:{ *:[i32] } i32:{ *:[i32] }:$rs) => (I1:{ *:[i32] } i32:{ *:[i32] }:$rs) diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 092cdd4ad5b43..9f6d3a506dceb 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -418,7 +418,8 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter { const TreePatternNode &N) const; Error importLeafNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder, - const TreePatternNode &N) const; + const TreePatternNode &N, + action_iterator InsertPt) const; Error importXFormNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const; @@ -431,9 +432,6 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter { const TreePatternNode &N, action_iterator &InsertPt) const; - Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M, - BuildMIAction &DstMIBuilder, - const DAGDefaultOperand &DefaultOp) const; Error importImplicitDefRenderers(BuildMIAction &DstMIBuilder, ArrayRef ImplicitDefs) const; @@ -1291,7 +1289,8 @@ Error GlobalISelEmitter::importNamedNodeRenderer( // Equivalent of MatcherGen::EmitResultLeafAsOperand. Error GlobalISelEmitter::importLeafNodeRenderer( - RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const { + RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N, + action_iterator InsertPt) const { if (const auto *II = dyn_cast(N.getLeafValue())) { MIBuilder.addRenderer(II->getValue()); return Error::success(); @@ -1300,11 +1299,29 @@ Error GlobalISelEmitter::importLeafNodeRenderer( if (const auto *DI = dyn_cast(N.getLeafValue())) { const Record *R = DI->getDef(); - if (R->isSubClassOf("Register")) { + if (R->isSubClassOf("Register") || R->getName() == "zero_reg") { MIBuilder.addRenderer(Target, R); return Error::success(); } + if (R->getName() == "undef_tied_input") { + std::optional OpTyOrNone = MVTToLLT(N.getSimpleType(0)); + if (!OpTyOrNone) + return failedImport("unsupported type"); + + unsigned TempRegID = M.allocateTempRegID(); + M.insertAction(InsertPt, *OpTyOrNone, TempRegID); + + auto I = M.insertAction( + InsertPt, M.allocateOutputInsnID(), + &Target.getInstruction(RK.getDef("IMPLICIT_DEF"))); + auto &ImpDefBuilder = static_cast(**I); + ImpDefBuilder.addRenderer(TempRegID, /*IsDef=*/true); + + MIBuilder.addRenderer(TempRegID); + return Error::success(); + } + if (R->isSubClassOf("SubRegIndex")) { const CodeGenSubRegIndex *SubRegIndex = CGRegs.getSubRegIdx(R); MIBuilder.addRenderer(SubRegIndex->EnumValue); @@ -1386,7 +1403,7 @@ Error GlobalISelEmitter::importNodeRenderer(RuleMatcher &M, return importNamedNodeRenderer(M, MIBuilder, N); if (N.isLeaf()) - return importLeafNodeRenderer(M, MIBuilder, N); + return importLeafNodeRenderer(M, MIBuilder, N, InsertPt); if (N.getOperator()->isSubClassOf("SDNodeXForm")) return importXFormNodeRenderer(M, MIBuilder, N); @@ -1707,11 +1724,11 @@ Expected GlobalISelEmitter::importExplicitUseRenderers( // This is a predicate or optional def operand which the pattern has not // overridden, or which we aren't letting it override; emit the 'default // ops' operands. - - const Record *OperandNode = DstI->Operands[InstOpNo].Rec; - if (auto Error = importDefaultOperandRenderers( - InsertPt, M, DstMIBuilder, CGP.getDefaultOperand(OperandNode))) - return std::move(Error); + for (const TreePatternNode &OpNode : + make_pointee_range(CGP.getDefaultOperand(OperandNode).DefaultOps)) { + if (Error Err = importNodeRenderer(M, DstMIBuilder, OpNode, InsertPt)) + return Err; + } ++NumDefaultOps; continue; @@ -1734,47 +1751,6 @@ Expected GlobalISelEmitter::importExplicitUseRenderers( return InsertPt; } -Error GlobalISelEmitter::importDefaultOperandRenderers( - action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder, - const DAGDefaultOperand &DefaultOp) const { - for (const auto &Op : DefaultOp.DefaultOps) { - const auto &N = *Op; - if (!N.isLeaf()) - return failedImport("Could not add default op"); - - const auto *DefaultOp = N.getLeafValue(); - - if (const DefInit *DefaultDefOp = dyn_cast(DefaultOp)) { - std::optional OpTyOrNone = MVTToLLT(N.getSimpleType(0)); - auto *Def = DefaultDefOp->getDef(); - if (Def->getName() == "undef_tied_input") { - unsigned TempRegID = M.allocateTempRegID(); - M.insertAction(InsertPt, *OpTyOrNone, - TempRegID); - InsertPt = M.insertAction( - InsertPt, M.allocateOutputInsnID(), - &Target.getInstruction(RK.getDef("IMPLICIT_DEF"))); - BuildMIAction &IDMIBuilder = - *static_cast(InsertPt->get()); - IDMIBuilder.addRenderer(TempRegID, /*IsDef=*/true); - DstMIBuilder.addRenderer(TempRegID); - } else { - DstMIBuilder.addRenderer(Target, Def); - } - continue; - } - - if (const IntInit *DefaultIntOp = dyn_cast(DefaultOp)) { - DstMIBuilder.addRenderer(DefaultIntOp->getValue()); - continue; - } - - return failedImport("Could not add default op"); - } - - return Error::success(); -} - Error GlobalISelEmitter::importImplicitDefRenderers( BuildMIAction &DstMIBuilder, ArrayRef ImplicitDefs) const { if (!ImplicitDefs.empty())