When used as a non-leaf node, TableGen does not currently use the type of a ComplexPattern for type inference, which also means it does not check it doesn't conflict with the use. This differs from when used as a leaf value, where the type is used for inference. This addresses that discrepancy. The test case is not representative of most real-world uses but is sufficient to demonstrate inference is working. Some of these uses also make use of ValueTypeByHwMode rather than SimpleValueType and so the existing type inference is extended to support that alongside the new type inference. There are also currently various cases of using ComplexPatterns with an untyped type, but only for non-leaf nodes. For compatibility this is permitted, and uses the old behaviour of not inferring for non-leaf nodes, but the existing logic is still used for leaf values. This remaining discrepancy should eventually be eliminated, either by removing all such uses of untyped so the special case goes away (I imagine Any, or a more specific type in certain cases, would be perfectly sufficient), or by copying it to the leaf value case so they're consistent with one another if this is something that does need to keep being supported. All non-experimental targets have been verified to produce bit-for-bit identical TableGen output with this change applied. Reviewed By: kparzysz Differential Revision: https://reviews.llvm.org/D109035
31 lines
1.1 KiB
TableGen
31 lines
1.1 KiB
TableGen
// 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<i32, 0, "SelectCP32">;
|
|
|
|
// 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)];
|
|
}
|