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.

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.
---
 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 245ba357b5e..8a01b0e1854 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 02d902c8c93..346a9a8021d 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -5976,6 +5976,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.  */
@@ -8330,6 +8361,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 2cfaf1f54ca..13d3df1cce1 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4302,6 +4302,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 efa6243f23d..37f39158467 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3360,6 +3360,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 95dd8724244..fbb8c17fd9d 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -5464,6 +5464,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
@@ -5617,6 +5622,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 9358787b262..e34ca1346e7 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 becab55cd62..baa8a1f748a 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.  */
-- 
2.54.0

Reply via email to