Skip to content

Commit f92b928

Browse files
authored
[GISel] Infer the type of an immediate when there is one element in TEC (#77399)
When there is just one element in the type equivalence class (TEC), `inferNamedOperandType` fails because it does not consider the passed operand as a suitable one. This is incorrect when inferring the type of an (unnamed) immediate operand.
1 parent 124efca commit f92b928

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \
2-
// RUN: -gicombiner-debug-typeinfer -combiners=MyCombiner %s 2>&1 | \
2+
// RUN: -gicombiner-debug-typeinfer -combiners=MyCombiner %s 2>&1 >/dev/null | \
33
// RUN: FileCheck %s
44

55
// Checks reasoning of the inference rules.
@@ -10,13 +10,15 @@ include "llvm/Target/GlobalISel/Combine.td"
1010
def MyTargetISA : InstrInfo;
1111
def MyTarget : Target { let InstructionSet = MyTargetISA; }
1212

13+
// This also checks that the type of a def is preferred when inferring the type
14+
// of an immediate.
1315
// CHECK: Rule Operand Type Equivalence Classes for inference_mul_by_neg_one:
1416
// CHECK-NEXT: Groups for __inference_mul_by_neg_one_match_0: [dst, x]
1517
// CHECK-NEXT: Groups for __inference_mul_by_neg_one_apply_0: [dst, x]
1618
// CHECK-NEXT: Final Type Equivalence Classes: [dst, x]
17-
// CHECK-NEXT: INFER: imm 0 -> GITypeOf<$x>
19+
// CHECK-NEXT: INFER: imm 0 -> GITypeOf<$dst>
1820
// CHECK-NEXT: Apply patterns for rule inference_mul_by_neg_one after inference:
19-
// CHECK-NEXT: (CodeGenInstructionPattern name:__inference_mul_by_neg_one_apply_0 G_SUB operands:[<def>$dst, (GITypeOf<$x> 0), $x])
21+
// CHECK-NEXT: (CodeGenInstructionPattern name:__inference_mul_by_neg_one_apply_0 G_SUB operands:[<def>$dst, (GITypeOf<$dst> 0), $x])
2022
def inference_mul_by_neg_one: GICombineRule <
2123
(defs root:$dst),
2224
(match (G_MUL $dst, $x, -1)),
@@ -61,8 +63,25 @@ def infer_variadic_outs: GICombineRule <
6163
(COPY $dst, $tmp))
6264
>;
6365

66+
// Check that the type of an immediate is inferred when there is just one
67+
// element in the corresponding equivalence class.
68+
// CHECK: Rule Operand Type Equivalence Classes for infer_imm_0:
69+
// CHECK-NEXT: Groups for __infer_imm_0_match_0: [dst]
70+
// CHECK-NEXT: Groups for __infer_imm_0_apply_0: [dst]
71+
// CHECK-NEXT: Final Type Equivalence Classes: [dst]
72+
// CHECK-NEXT: INFER: imm 1 -> GITypeOf<$dst>
73+
// CHECK-NEXT: INFER: imm 2 -> GITypeOf<$dst>
74+
// CHECK-NEXT: Apply patterns for rule infer_imm_0 after inference:
75+
// CHECK-NEXT: (CodeGenInstructionPattern name:__infer_imm_0_apply_0 G_ADD operands:[<def>$dst, (GITypeOf<$dst> 1), (GITypeOf<$dst> 2)])
76+
def infer_imm_0 : GICombineRule<
77+
(defs root:$dst),
78+
(match (G_ADD $dst, 0, 3)),
79+
(apply (G_ADD $dst, 1, 2))
80+
>;
81+
6482
def MyCombiner: GICombiner<"GenMyCombiner", [
6583
inference_mul_by_neg_one,
6684
infer_complex_tempreg,
67-
infer_variadic_outs
85+
infer_variadic_outs,
86+
infer_imm_0,
6887
]>;

llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ class CombineRuleOperandTypeChecker : private OperandTypeChecker {
284284
/// succeed.
285285
PatternType inferNamedOperandType(const InstructionPattern &IP,
286286
StringRef OpName,
287-
const TypeEquivalenceClasses &TECs) const;
287+
const TypeEquivalenceClasses &TECs,
288+
bool AllowSelf = false) const;
288289

289290
const Record &RuleDef;
290291
SmallVector<InstructionPattern *, 8> MatchPats;
@@ -427,8 +428,8 @@ PatternType CombineRuleOperandTypeChecker::inferImmediateType(
427428
continue;
428429

429430
// Named operand with the same name, try to infer that.
430-
if (PatternType InferTy =
431-
inferNamedOperandType(IP, Op.getOperandName(), TECs))
431+
if (PatternType InferTy = inferNamedOperandType(IP, Op.getOperandName(),
432+
TECs, /*AllowSelf=*/true))
432433
return InferTy;
433434
}
434435
}
@@ -438,16 +439,17 @@ PatternType CombineRuleOperandTypeChecker::inferImmediateType(
438439

439440
PatternType CombineRuleOperandTypeChecker::inferNamedOperandType(
440441
const InstructionPattern &IP, StringRef OpName,
441-
const TypeEquivalenceClasses &TECs) const {
442+
const TypeEquivalenceClasses &TECs, bool AllowSelf) const {
442443
// This is the simplest possible case, we just need to find a TEC that
443-
// contains OpName. Look at all other operands in equivalence class and try to
444-
// find a suitable one.
444+
// contains OpName. Look at all operands in equivalence class and try to
445+
// find a suitable one. If `AllowSelf` is true, the operand itself is also
446+
// considered suitable.
445447

446448
// Check for a def of a matched pattern. This is guaranteed to always
447449
// be a register so we can blindly use that.
448450
StringRef GoodOpName;
449451
for (auto It = TECs.findLeader(OpName); It != TECs.member_end(); ++It) {
450-
if (*It == OpName)
452+
if (!AllowSelf && *It == OpName)
451453
continue;
452454

453455
const auto LookupRes = MatchOpTable.lookup(*It);

0 commit comments

Comments
 (0)