diff --git a/llvm/test/TableGen/dag-isel-complexpattern.td b/llvm/test/TableGen/dag-isel-complexpattern.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/dag-isel-complexpattern.td @@ -0,0 +1,30 @@ +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s | FileCheck %s + +include "llvm/Target/Target.td" + +def TestTargetInstrInfo : InstrInfo; + +def TestTarget : Target { + let InstructionSet = TestTargetInstrInfo; +} + +def REG32 : Register<"REG32">; +def REG64 : Register<"REG64">; +def GPR32 : RegisterClass<"TestTarget", [i32], 32, (add REG32)>; +def GPR64 : RegisterClass<"TestTarget", [i64], 64, (add REG64)>; + +def CP32 : ComplexPattern; + +// Without using ComplexPattern's type, this pattern would be ambiguous as to +// what integer type is being used, since both i32 and i64 are legal, and used +// to erroneously happen, whilst using a leaf value like CP32:$a/b instead of +// (CP32) still worked. +def INSTR : Instruction { +// CHECK-LABEL: OPC_CheckOpcode, TARGET_VAL(ISD::STORE) +// CHECK: OPC_CheckType, MVT::i32 +// CHECK: OPC_CheckComplexPat, /*CP*/0, /*#*/1, // SelectCP32:$ +// CHECK: Src: (st (add:{ *:[i32] } (CP32:{ *:[i32] }), (CP32:{ *:[i32] })), i64:{ *:[i64] }:$addr) + let OutOperandList = (outs); + let InOperandList = (ins GPR64:$addr); + let Pattern = [(store (add (CP32), (CP32)), i64:$addr)]; +} diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2255,7 +2255,9 @@ assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?"); if (NotRegisters) return TypeSetByHwMode(); // Unknown. - return TypeSetByHwMode(CDP.getComplexPattern(R).getValueType()); + Record *T = CDP.getComplexPattern(R).getValueType(); + const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); + return TypeSetByHwMode(getValueTypeByHwMode(T, CGH)); } if (R->isSubClassOf("PointerLikeRegClass")) { assert(ResNo == 0 && "Regclass can only have one result!"); @@ -2660,6 +2662,22 @@ if (getOperator()->isSubClassOf("ComplexPattern")) { bool MadeChange = false; + if (!NotRegisters) { + assert(Types.size() == 1 && "ComplexPatterns only produce one result!"); + Record *T = CDP.getComplexPattern(getOperator()).getValueType(); + const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); + const ValueTypeByHwMode VVT = getValueTypeByHwMode(T, CGH); + // TODO: AArch64 and AMDGPU use ComplexPattern and then + // exclusively use those as non-leaf nodes with explicit type casts, so + // for backwards compatibility we do no inference in that case. This is + // not supported when the ComplexPattern is used as a leaf value, + // however; this inconsistency should be resolved, either by adding this + // case there or by altering the backends to not do this (e.g. using Any + // instead may work). + if (!VVT.isSimple() || VVT.getSimple() != MVT::Untyped) + MadeChange |= UpdateNodeType(0, VVT, TP); + } + for (unsigned i = 0; i < getNumChildren(); ++i) MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); diff --git a/llvm/utils/TableGen/CodeGenTarget.h b/llvm/utils/TableGen/CodeGenTarget.h --- a/llvm/utils/TableGen/CodeGenTarget.h +++ b/llvm/utils/TableGen/CodeGenTarget.h @@ -202,7 +202,7 @@ /// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern /// tablegen class in TargetSelectionDAG.td class ComplexPattern { - MVT::SimpleValueType Ty; + Record *Ty; unsigned NumOperands; std::string SelectFunc; std::vector RootNodes; @@ -211,7 +211,7 @@ public: ComplexPattern(Record *R); - MVT::SimpleValueType getValueType() const { return Ty; } + Record *getValueType() const { return Ty; } unsigned getNumOperands() const { return NumOperands; } const std::string &getSelectFunc() const { return SelectFunc; } const std::vector &getRootNodes() const { diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -576,7 +576,7 @@ // ComplexPattern implementation // ComplexPattern::ComplexPattern(Record *R) { - Ty = ::getValueType(R->getValueAsDef("Ty")); + Ty = R->getValueAsDef("Ty"); NumOperands = R->getValueAsInt("NumOperands"); SelectFunc = std::string(R->getValueAsString("SelectFunc")); RootNodes = R->getValueAsListOfDefs("RootNodes");