Skip to content

[TableGen][GlobalISel] Add rule-wide type inference #66377

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
Nov 8, 2023
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
7 changes: 7 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

class GenericInstruction : StandardPseudoInstruction {
let isPreISelOpcode = true;

// When all variadic ops share a type with another operand,
// this is the type they share. Used by MIR patterns type inference.
TypedOperand variadicOpsType = ?;
}

// Provide a variant of an instruction with the same operands, but
Expand Down Expand Up @@ -1228,6 +1232,7 @@ def G_UNMERGE_VALUES : GenericInstruction {
let OutOperandList = (outs type0:$dst0, variable_ops);
let InOperandList = (ins type1:$src);
let hasSideEffects = false;
let variadicOpsType = type0;
}

// Insert a smaller register into a larger one at the specified bit-index.
Expand All @@ -1245,6 +1250,7 @@ def G_MERGE_VALUES : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$src0, variable_ops);
let hasSideEffects = false;
let variadicOpsType = type1;
}

/// Create a vector from multiple scalar registers. No implicit
Expand All @@ -1254,6 +1260,7 @@ def G_BUILD_VECTOR : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$src0, variable_ops);
let hasSideEffects = false;
let variadicOpsType = type1;
}

/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ def trunc_shift: GICombineRule <
def mul_by_neg_one: GICombineRule <
(defs root:$dst),
(match (G_MUL $dst, $x, -1)),
(apply (G_SUB $dst, (GITypeOf<"$x"> 0), $x))
(apply (G_SUB $dst, 0, $x))
>;

// Fold (xor (and x, y), y) -> (and (not x), y)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def bad_imm_too_many_args : GICombineRule<
(match (COPY $x, (i32 0, 0)):$d),
(apply (COPY $x, $b):$d)>;

// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: cannot parse immediate '(COPY 0)', 'COPY' is not a ValueType
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: cannot parse immediate '(COPY 0)': unknown type 'COPY'
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(COPY ?:$x, (COPY 0))
def bad_imm_not_a_valuetype : GICombineRule<
(defs root:$a),
Expand Down Expand Up @@ -186,7 +186,7 @@ def expected_op_name : GICombineRule<
(match (G_FNEG $x, i32)),
(apply (COPY $x, (i32 0)))>;

// CHECK: :[[@LINE+3]]:{{[0-9]+}}: error: invalid operand type: 'not_a_type' is not a ValueType
// CHECK: :[[@LINE+3]]:{{[0-9]+}}: error: cannot parse operand type: unknown type 'not_a_type'
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: Failed to parse pattern: '(G_FNEG ?:$x, not_a_type:$y)'
def not_a_type;
def bad_mo_type_not_a_valuetype : GICombineRule<
Expand Down
68 changes: 68 additions & 0 deletions llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \
// RUN: -gicombiner-debug-typeinfer -combiners=MyCombiner %s 2>&1 | \
// RUN: FileCheck %s

// Checks reasoning of the inference rules.

include "llvm/Target/Target.td"
include "llvm/Target/GlobalISel/Combine.td"

def MyTargetISA : InstrInfo;
def MyTarget : Target { let InstructionSet = MyTargetISA; }

// 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: 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])
def inference_mul_by_neg_one: GICombineRule <
(defs root:$dst),
(match (G_MUL $dst, $x, -1)),
(apply (G_SUB $dst, 0, $x))
>;

// CHECK: Rule Operand Type Equivalence Classes for infer_complex_tempreg:
// CHECK-NEXT: Groups for __infer_complex_tempreg_match_0: [dst] [x, y, z]
// CHECK-NEXT: Groups for __infer_complex_tempreg_apply_0: [tmp2] [x, y]
// CHECK-NEXT: Groups for __infer_complex_tempreg_apply_1: [tmp, tmp2]
// CHECK-NEXT: Groups for __infer_complex_tempreg_apply_2: [dst, tmp]
// CHECK-NEXT: Final Type Equivalence Classes: [dst, tmp, tmp2] [x, y, z]
// CHECK-NEXT: INFER: MachineOperand $tmp2 -> GITypeOf<$dst>
// CHECK-NEXT: INFER: MachineOperand $tmp -> GITypeOf<$dst>
// CHECK-NEXT: Apply patterns for rule infer_complex_tempreg after inference:
// CHECK-NEXT: (CodeGenInstructionPattern name:__infer_complex_tempreg_apply_0 G_BUILD_VECTOR operands:[<def>GITypeOf<$dst>:$tmp2, $x, $y])
// CHECK-NEXT: (CodeGenInstructionPattern name:__infer_complex_tempreg_apply_1 G_FNEG operands:[<def>GITypeOf<$dst>:$tmp, GITypeOf<$dst>:$tmp2])
// CHECK-NEXT: (CodeGenInstructionPattern name:__infer_complex_tempreg_apply_2 G_FNEG operands:[<def>$dst, GITypeOf<$dst>:$tmp])
def infer_complex_tempreg: GICombineRule <
(defs root:$dst),
(match (G_MERGE_VALUES $dst, $x, $y, $z)),
(apply (G_BUILD_VECTOR $tmp2, $x, $y),
(G_FNEG $tmp, $tmp2),
(G_FNEG $dst, $tmp))
>;

// CHECK: Rule Operand Type Equivalence Classes for infer_variadic_outs:
// CHECK-NEXT: Groups for __infer_variadic_outs_match_0: [x, y] [vec]
// CHECK-NEXT: Groups for __infer_variadic_outs_match_1: [dst, x]
// CHECK-NEXT: Groups for __infer_variadic_outs_apply_0: [tmp, y]
// CHECK-NEXT: Groups for __infer_variadic_outs_apply_1:
// CHECK-NEXT: Final Type Equivalence Classes: [tmp, dst, x, y] [vec]
// CHECK-NEXT: INFER: MachineOperand $tmp -> GITypeOf<$dst>
// CHECK-NEXT: Apply patterns for rule infer_variadic_outs after inference:
// CHECK-NEXT: (CodeGenInstructionPattern name:__infer_variadic_outs_apply_0 G_FNEG operands:[<def>GITypeOf<$dst>:$tmp, $y])
// CHECK-NEXT: (CodeGenInstructionPattern name:__infer_variadic_outs_apply_1 COPY operands:[<def>$dst, GITypeOf<$dst>:$tmp])
def infer_variadic_outs: GICombineRule <
(defs root:$dst),
(match (G_UNMERGE_VALUES $x, $y, $vec),
(G_FNEG $dst, $x)),
(apply (G_FNEG $tmp, $y),
(COPY $dst, $tmp))
>;

def MyCombiner: GICombiner<"GenMyCombiner", [
inference_mul_by_neg_one,
infer_complex_tempreg,
infer_variadic_outs
]>;
7 changes: 5 additions & 2 deletions llvm/test/TableGen/GlobalISelCombinerEmitter/typeof-errors.td
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ include "llvm/Target/GlobalISel/Combine.td"
def MyTargetISA : InstrInfo;
def MyTarget : Target { let InstructionSet = MyTargetISA; }

// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: invalid operand name format 'unknown' in GITypeOf: expected '$' followed by an operand name
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: cannot parse immediate '(anonymous_7029 0)': invalid operand name format 'unknown' in GITypeOf: expected '$' followed by an operand name
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(G_ANYEXT ?:$dst, (anonymous_
def NoDollarSign : GICombineRule<
(defs root:$dst),
(match (G_ZEXT $dst, $src)),
Expand Down Expand Up @@ -47,7 +48,9 @@ def InferredUseInMatch : GICombineRule<
(match (G_ZEXT $dst, $src)),
(apply (G_ANYEXT $dst, GITypeOf<"$dst">:$src))>;

// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: conflicting types for operand 'src': first seen with 'i32' in '__InferenceConflict_match_0, now seen with 'GITypeOf<$dst>' in '__InferenceConflict_apply_0'
// CHECK: :[[@LINE+3]]:{{[0-9]+}}: error: conflicting types for operand 'src': 'i32' vs 'GITypeOf<$dst>'
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: note: 'src' seen with type 'GITypeOf<$dst>' in '__InferenceConflict_apply_0'
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: note: 'src' seen with type 'i32' in '__InferenceConflict_match_0'
def InferenceConflict : GICombineRule<
(defs root:$dst),
(match (G_ZEXT $dst, i32:$src)),
Expand Down
Loading