diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td index c9ffe4e7adb3d..ed4e0e411c7af 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td @@ -1,5 +1,5 @@ // RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \ -// RUN: -gicombiner-debug-typeinfer -combiners=MyCombiner %s 2>&1 | \ +// RUN: -gicombiner-debug-typeinfer -combiners=MyCombiner %s 2>&1 >/dev/null | \ // RUN: FileCheck %s // Checks reasoning of the inference rules. @@ -10,13 +10,15 @@ include "llvm/Target/GlobalISel/Combine.td" def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } +// This also checks that the type of a def is preferred when inferring the type +// of an immediate. // CHECK: Rule Operand Type Equivalence Classes for inference_mul_by_neg_one: // CHECK-NEXT: Groups for __inference_mul_by_neg_one_match_0: [dst, x] // CHECK-NEXT: Groups for __inference_mul_by_neg_one_apply_0: [dst, x] // CHECK-NEXT: Final Type Equivalence Classes: [dst, x] -// CHECK-NEXT: INFER: imm 0 -> GITypeOf<$x> +// CHECK-NEXT: INFER: imm 0 -> GITypeOf<$dst> // CHECK-NEXT: Apply patterns for rule inference_mul_by_neg_one after inference: -// CHECK-NEXT: (CodeGenInstructionPattern name:__inference_mul_by_neg_one_apply_0 G_SUB operands:[$dst, (GITypeOf<$x> 0), $x]) +// CHECK-NEXT: (CodeGenInstructionPattern name:__inference_mul_by_neg_one_apply_0 G_SUB operands:[$dst, (GITypeOf<$dst> 0), $x]) def inference_mul_by_neg_one: GICombineRule < (defs root:$dst), (match (G_MUL $dst, $x, -1)), @@ -61,8 +63,25 @@ def infer_variadic_outs: GICombineRule < (COPY $dst, $tmp)) >; +// Check that the type of an immediate is inferred when there is just one +// element in the corresponding equivalence class. +// CHECK: Rule Operand Type Equivalence Classes for infer_imm_0: +// CHECK-NEXT: Groups for __infer_imm_0_match_0: [dst] +// CHECK-NEXT: Groups for __infer_imm_0_apply_0: [dst] +// CHECK-NEXT: Final Type Equivalence Classes: [dst] +// CHECK-NEXT: INFER: imm 1 -> GITypeOf<$dst> +// CHECK-NEXT: INFER: imm 2 -> GITypeOf<$dst> +// CHECK-NEXT: Apply patterns for rule infer_imm_0 after inference: +// CHECK-NEXT: (CodeGenInstructionPattern name:__infer_imm_0_apply_0 G_ADD operands:[$dst, (GITypeOf<$dst> 1), (GITypeOf<$dst> 2)]) +def infer_imm_0 : GICombineRule< + (defs root:$dst), + (match (G_ADD $dst, 0, 3)), + (apply (G_ADD $dst, 1, 2)) +>; + def MyCombiner: GICombiner<"GenMyCombiner", [ inference_mul_by_neg_one, infer_complex_tempreg, - infer_variadic_outs + infer_variadic_outs, + infer_imm_0, ]>; diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index 89aca87a28ec0..348b3b3e08984 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -284,7 +284,8 @@ class CombineRuleOperandTypeChecker : private OperandTypeChecker { /// succeed. PatternType inferNamedOperandType(const InstructionPattern &IP, StringRef OpName, - const TypeEquivalenceClasses &TECs) const; + const TypeEquivalenceClasses &TECs, + bool AllowSelf = false) const; const Record &RuleDef; SmallVector MatchPats; @@ -427,8 +428,8 @@ PatternType CombineRuleOperandTypeChecker::inferImmediateType( continue; // Named operand with the same name, try to infer that. - if (PatternType InferTy = - inferNamedOperandType(IP, Op.getOperandName(), TECs)) + if (PatternType InferTy = inferNamedOperandType(IP, Op.getOperandName(), + TECs, /*AllowSelf=*/true)) return InferTy; } } @@ -438,16 +439,17 @@ PatternType CombineRuleOperandTypeChecker::inferImmediateType( PatternType CombineRuleOperandTypeChecker::inferNamedOperandType( const InstructionPattern &IP, StringRef OpName, - const TypeEquivalenceClasses &TECs) const { + const TypeEquivalenceClasses &TECs, bool AllowSelf) const { // This is the simplest possible case, we just need to find a TEC that - // contains OpName. Look at all other operands in equivalence class and try to - // find a suitable one. + // contains OpName. Look at all operands in equivalence class and try to + // find a suitable one. If `AllowSelf` is true, the operand itself is also + // considered suitable. // Check for a def of a matched pattern. This is guaranteed to always // be a register so we can blindly use that. StringRef GoodOpName; for (auto It = TECs.findLeader(OpName); It != TECs.member_end(); ++It) { - if (*It == OpName) + if (!AllowSelf && *It == OpName) continue; const auto LookupRes = MatchOpTable.lookup(*It);