Skip to content

[GISel] Infer the type of an immediate when there is one element in TEC #77399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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:[<def>$dst, (GITypeOf<$x> 0), $x])
// CHECK-NEXT: (CodeGenInstructionPattern name:__inference_mul_by_neg_one_apply_0 G_SUB operands:[<def>$dst, (GITypeOf<$dst> 0), $x])
def inference_mul_by_neg_one: GICombineRule <
(defs root:$dst),
(match (G_MUL $dst, $x, -1)),
Expand Down Expand Up @@ -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:[<def>$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,
]>;
16 changes: 9 additions & 7 deletions llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<InstructionPattern *, 8> MatchPats;
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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);
Expand Down