https://gcc.gnu.org/g:20df8b77035ca1e0f35019c9cb1c59e385d36217
commit 20df8b77035ca1e0f35019c9cb1c59e385d36217 Author: Andrew Stubbs <[email protected]> Date: Wed Sep 2 10:16:05 2026 +0000 Add TARGET_SIMT_STACK_VARIABLE hooks In SIMT mode, we want N copies of each stack variable -- one for each thread. Since the SIMT implementation is primarily in the backend the adjustments need to happen there also. These hooks achieve the goal by allowing each variable to be wider than it appears to need to be (padding), and by inserting a variable offset element into the address loading code -- the offset calculation will end up being different in each thread. The same treatment is applied to stack-passed parameters, on both the caller (emit_push_insn) and callee (assign_parm_find_stack_rtl) sides. For amdgcn in SIMT mode, each variable is padded to 64 times its size, and the offset is the lane ID (held in v1) multiplied by the size of the type. gcc/ChangeLog: * target.def (TARGET_SIMT_STACK_VARIABLE_PADDING) (TARGET_SIMT_STACK_VARIABLE_OFFSET): New target hooks. * doc/tm.texi.in (TARGET_SIMT_STACK_VARIABLE_PADDING) (TARGET_SIMT_STACK_VARIABLE_OFFSET): Add hook placeholders. * doc/tm.texi: Regenerate. * cfgexpand.cc (add_stack_var): Adjust the variable size using TARGET_SIMT_STACK_VARIABLE_PADDING. (expand_one_stack_var_at): Offset the variable address using TARGET_SIMT_STACK_VARIABLE_OFFSET. (expand_one_stack_var_1): Adjust the variable size using TARGET_SIMT_STACK_VARIABLE_PADDING. * expr.cc (emit_push_insn): Offset the destination address using TARGET_SIMT_STACK_VARIABLE_OFFSET. * function.cc (assign_parm_find_stack_rtl): Likewise, for incoming stack parameters. (locate_and_pad_parm): Adjust the parameter size using TARGET_SIMT_STACK_VARIABLE_PADDING. * config/gcn/gcn.cc (gcn_simt_stack_variable_padding): New function. (gcn_simt_stack_variable_offset): New function. (TARGET_SIMT_STACK_VARIABLE_PADDING): Define. (TARGET_SIMT_STACK_VARIABLE_OFFSET): Define. Diff: --- gcc/cfgexpand.cc | 14 ++++++++++++++ gcc/config/gcn/gcn.cc | 35 +++++++++++++++++++++++++++++++++++ gcc/doc/tm.texi | 17 +++++++++++++++++ gcc/doc/tm.texi.in | 4 ++++ gcc/expr.cc | 13 +++++++++++++ gcc/function.cc | 12 ++++++++++++ gcc/target.def | 22 ++++++++++++++++++++++ 7 files changed, 117 insertions(+) diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc index 777bff0f82b2..2e2030f84ef2 100644 --- a/gcc/cfgexpand.cc +++ b/gcc/cfgexpand.cc @@ -488,6 +488,10 @@ add_stack_var (tree decl, bool really_expand) /* All variables initially conflict with no other. */ v->conflicts = NULL; + /* Apply target hooks. */ + if (targetm.simt.stack_variable_padding) + v->size = targetm.simt.stack_variable_padding (v->size); + /* Ensure that this decl doesn't get put onto the list twice. */ set_rtl (decl, pc_rtx); @@ -1345,6 +1349,13 @@ expand_one_stack_var_at (tree decl, rtx base, unsigned base_align, else x = plus_constant (Pmode, base, offset); + if (targetm.simt.stack_variable_offset) + { + rtx val = targetm.simt.stack_variable_offset (TREE_TYPE (decl)); + if (val) + x = gen_rtx_PLUS (Pmode, x, val); + } + x = gen_rtx_MEM (TREE_CODE (decl) == SSA_NAME ? TYPE_MODE (TREE_TYPE (decl)) : DECL_MODE (decl), x); @@ -1743,6 +1754,9 @@ expand_one_stack_var_1 (tree var) else size = tree_to_poly_uint64 (DECL_SIZE_UNIT (var)); + if (targetm.simt.stack_variable_padding) + size = targetm.simt.stack_variable_padding (size); + byte_align = align_local_variable (var, true); /* We handle highly aligned variables in expand_stack_vars. */ diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index 7363c0b66f1d..287584651a9e 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -5944,6 +5944,37 @@ gcn_prefer_gather_scatter (machine_mode ARG_UNUSED (mode), } /* }}} */ +/* {{{ SIMT. */ + +/* Implement TARGET_STACK_VARIABLE_PADDING. */ + +poly_uint64 +gcn_simt_stack_variable_padding (poly_uint64 default_size) +{ + if (!flag_simt_mode) + return default_size; + + return default_size * 64; +} + +/* Implement TARGET_STACK_VARIABLE_OFFSET. */ + +rtx +gcn_simt_stack_variable_offset (const_tree type) +{ + if (!flag_simt_mode) + return const0_rtx; + + poly_uint64 unit_size = tree_to_poly_int64 (TYPE_SIZE_UNIT (type)); + + rtx _0_1_2_3 = gen_rtx_REG (SImode, VGPR_REGNO (1)); + rtx _0_1_2_3_di = gen_rtx_ZERO_EXTEND (DImode, _0_1_2_3); + rtx result = gen_rtx_MULT (DImode, _0_1_2_3_di, GEN_INT (unit_size)); + + return result; +} + +/* }}} */ /* {{{ md_reorg pass. */ /* Identify VMEM instructions from their "type" attribute. */ @@ -8300,6 +8331,10 @@ gcn_dwarf_register_span (rtx rtl) gcn_small_register_classes_for_mode_p #undef TARGET_SPILL_CLASS #define TARGET_SPILL_CLASS gcn_spill_class +#undef TARGET_SIMT_STACK_VARIABLE_PADDING +#define TARGET_SIMT_STACK_VARIABLE_PADDING gcn_simt_stack_variable_padding +#undef TARGET_SIMT_STACK_VARIABLE_OFFSET +#define TARGET_SIMT_STACK_VARIABLE_OFFSET gcn_simt_stack_variable_offset #undef TARGET_STRICT_ARGUMENT_NAMING #define TARGET_STRICT_ARGUMENT_NAMING gcn_strict_argument_naming #undef TARGET_TRAMPOLINE_INIT diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index c7d0fd19006b..2e720bc9d4b0 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4331,6 +4331,23 @@ definition that is usually appropriate, refer to @file{expr.h} for additional documentation. @end deftypefn +@deftypefn {Target Hook} poly_uint64 TARGET_SIMT_STACK_VARIABLE_PADDING (poly_uint64 @var{default_size}) +This target hook can modify the padding around stack variables and stack +parameters. The hook should return the required total size, with padding. +The primary use case is to support SIMT, where there must be a copy of each +variable for each thread. See also @code{TARGET_SIMT_STACK_VARIABLE_OFFSET}. +@end deftypefn + +@deftypefn {Target Hook} rtx TARGET_SIMT_STACK_VARIABLE_OFFSET (const_tree @var{type}) +This target hook can modify the use of padding around stack variables and +stack parameters. The amount of padding should have been specified with +@code{TARGET_SIMT_STACK_VARIABLE_PADDING}. The hook should return an offset +into the padding space as an RTL expression. The offset may be a constant, +or may be computed at runtime, and may give a different result for each SIMT +thread. The primary use case is to support SIMT, where there must be a copy +of each variable for each thread. The default is to use no offset. +@end deftypefn + @deftypefn {Target Hook} rtx TARGET_FUNCTION_INCOMING_ARG (cumulative_args_t @var{ca}, const function_arg_info @var{&arg}) Define this hook if the caller and callee on the target have different views of where arguments are passed. Also define this hook if there are diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index cef9c6fa8eae..79a3a8d0a542 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3363,6 +3363,10 @@ the stack. @hook TARGET_MUST_PASS_IN_STACK +@hook TARGET_SIMT_STACK_VARIABLE_PADDING + +@hook TARGET_SIMT_STACK_VARIABLE_OFFSET + @hook TARGET_FUNCTION_INCOMING_ARG @hook TARGET_USE_PSEUDO_PIC_REG diff --git a/gcc/expr.cc b/gcc/expr.cc index a0c239ad19a6..cac11b650bc2 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -5440,6 +5440,11 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size, temp = copy_to_reg (temp); } + if (targetm.simt.stack_variable_offset) + temp = simplify_gen_binary (PLUS, Pmode, temp, + targetm.simt.stack_variable_offset + (type)); + target = gen_rtx_MEM (BLKmode, temp); /* We do *not* set_mem_attributes here, because incoming arguments @@ -5593,6 +5598,14 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size, #endif { addr = simplify_gen_binary (PLUS, Pmode, args_addr, args_so_far); + + if (targetm.simt.stack_variable_offset) + { + rtx offset = targetm.simt.stack_variable_offset (type); + if (offset) + addr = simplify_gen_binary (PLUS, Pmode, addr, offset); + } + dest = gen_rtx_MEM (mode, memory_address (mode, addr)); /* We do *not* set_mem_attributes here, because incoming arguments diff --git a/gcc/function.cc b/gcc/function.cc index 109821c16fc9..325558d41184 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -2676,6 +2676,14 @@ assign_parm_find_stack_rtl (tree parm, struct assign_parm_data_one *data) stack_parm = crtl->args.internal_arg_pointer; if (offset_rtx != const0_rtx) stack_parm = gen_rtx_PLUS (Pmode, stack_parm, offset_rtx); + + if (targetm.simt.stack_variable_offset) + { + rtx hook_offset = targetm.simt.stack_variable_offset (TREE_TYPE (parm)); + if (hook_offset) + stack_parm = gen_rtx_PLUS (Pmode, stack_parm, hook_offset); + } + stack_parm = gen_rtx_MEM (data->arg.mode, stack_parm); if (!data->arg.pass_by_reference) @@ -4068,6 +4076,10 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs, type); locate->where_pad = where_pad; + if (targetm.simt.stack_variable_padding) + sizetree = size_int (targetm.simt.stack_variable_padding + (tree_to_uhwi (sizetree))); + /* Alignment can't exceed MAX_SUPPORTED_STACK_ALIGNMENT. */ if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) boundary = MAX_SUPPORTED_STACK_ALIGNMENT; diff --git a/gcc/target.def b/gcc/target.def index 8177ca66c621..711f050ad203 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1662,6 +1662,28 @@ DEFHOOK "Return number of threads in SIMT thread group on the target.", int, (void), NULL) +/* Allow the target to pad stack variables. */ +DEFHOOK +(stack_variable_padding, + "This target hook can modify the padding around stack variables and stack\n\ +parameters. The hook should return the required total size, with padding.\n\ +The primary use case is to support SIMT, where there must be a copy of each\n\ +variable for each thread. See also @code{TARGET_SIMT_STACK_VARIABLE_OFFSET}.", +poly_uint64, (poly_uint64 default_size), NULL) + +/* Allow the target to use custom offset within the padding of + stack variables. */ +DEFHOOK +(stack_variable_offset, + "This target hook can modify the use of padding around stack variables and\n\ +stack parameters. The amount of padding should have been specified with\n\ +@code{TARGET_SIMT_STACK_VARIABLE_PADDING}. The hook should return an offset\n\ +into the padding space as an RTL expression. The offset may be a constant,\n\ +or may be computed at runtime, and may give a different result for each SIMT\n\ +thread. The primary use case is to support SIMT, where there must be a copy\n\ +of each variable for each thread. The default is to use no offset.", +rtx, (const_tree type), NULL) + HOOK_VECTOR_END (simt) /* Functions relating to OpenMP. */
