public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [0/9] Make more use of opt_mode
@ 2017-09-04 11:24 Richard Sandiford
  2017-09-04 11:26 ` [1/9] Make more use of int_mode_for_mode Richard Sandiford
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:24 UTC (permalink / raw)
  To: gcc-patches

The 77-patch machine-mode series originally targetted only the places
that needed to change for variable-sized modes, but as Richard B.
said on IRC, it meant that the interfaces of mode_for_size vs.
int_mode_for_size were inconsistent: the former still returns BLKmode
on failure, while the latter returns an opt_mode.

This series of patches tries to make the machine_mode functions
consistent.  Tested on aarch64-linux-gmu, x86_64-linux-gnu,
powerpc64le-linux-gnu, and by checking that there were no extra
warnings or changes in testsuite output for one target per CPU.

Richard

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [1/9] Make more use of int_mode_for_mode
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
@ 2017-09-04 11:26 ` Richard Sandiford
  2017-09-05 11:22   ` Richard Biener
  2017-09-04 11:31 ` [2/9] Make more use of int_mode_for_size Richard Sandiford
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:26 UTC (permalink / raw)
  To: gcc-patches

This patch converts more places that could use int_mode_for_mode
instead of mode_for_size.  This is in preparation for an upcoming
patch that makes mode_for_size itself return an opt_mode.

The reason for using required () in exp2_immediate_p is that
we go on to do:

    trunc_int_for_mode (..., int_mode)

which would be invalid for (and have failed for) BLKmode.

The reason for using required () in spu_convert_move and
resolve_simple_move is that we go on to use registers of
the returned mode in non-call rtl instructions, which would
be invalid for BLKmode.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* config/spu/spu.c (exp2_immediate_p): Use int_mode_for_mode.
	(spu_convert_move): Likewise.
	* lower-subreg.c (resolve_simple_move): Likewise.

Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2017-09-04 11:50:24.563372530 +0100
+++ gcc/config/spu/spu.c	2017-09-04 12:18:41.572976650 +0100
@@ -3372,7 +3372,7 @@ arith_immediate_p (rtx op, machine_mode
   constant_to_array (mode, op, arr);
 
   bytes = GET_MODE_UNIT_SIZE (mode);
-  mode = mode_for_size (GET_MODE_UNIT_BITSIZE (mode), MODE_INT, 0);
+  mode = int_mode_for_mode (GET_MODE_INNER (mode)).require ();
 
   /* Check that bytes are repeated. */
   for (i = bytes; i < 16; i += bytes)
@@ -3415,7 +3415,7 @@ exp2_immediate_p (rtx op, machine_mode m
   mode = GET_MODE_INNER (mode);
 
   bytes = GET_MODE_SIZE (mode);
-  int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
+  int_mode = int_mode_for_mode (mode).require ();
 
   /* Check that bytes are repeated. */
   for (i = bytes; i < 16; i += bytes)
@@ -4503,7 +4503,7 @@ spu_expand_mov (rtx * ops, machine_mode
 spu_convert_move (rtx dst, rtx src)
 {
   machine_mode mode = GET_MODE (dst);
-  machine_mode int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
+  machine_mode int_mode = int_mode_for_mode (mode).require ();
   rtx reg;
   gcc_assert (GET_MODE (src) == TImode);
   reg = int_mode != mode ? gen_reg_rtx (int_mode) : dst;
Index: gcc/lower-subreg.c
===================================================================
--- gcc/lower-subreg.c	2017-09-04 11:50:08.544543511 +0100
+++ gcc/lower-subreg.c	2017-09-04 12:18:41.572976650 +0100
@@ -956,11 +956,7 @@ resolve_simple_move (rtx set, rtx_insn *
       if (real_dest == NULL_RTX)
 	real_dest = dest;
       if (!SCALAR_INT_MODE_P (dest_mode))
-	{
-	  dest_mode = mode_for_size (GET_MODE_SIZE (dest_mode) * BITS_PER_UNIT,
-				     MODE_INT, 0);
-	  gcc_assert (dest_mode != BLKmode);
-	}
+	dest_mode = int_mode_for_mode (dest_mode).require ();
       dest = gen_reg_rtx (dest_mode);
       if (REG_P (real_dest))
 	REG_ATTRS (dest) = REG_ATTRS (real_dest);

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [2/9] Make more use of int_mode_for_size
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
  2017-09-04 11:26 ` [1/9] Make more use of int_mode_for_mode Richard Sandiford
@ 2017-09-04 11:31 ` Richard Sandiford
  2017-09-05 11:23   ` Richard Biener
  2017-09-04 11:32 ` [3/9] (decimal_)float_mode_for_size in real.h Richard Sandiford
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:31 UTC (permalink / raw)
  To: gcc-patches

This patch converts more places that could use int_mode_for_size instead
of mode_for_size.  This is in preparation for an upcoming patch that
makes mode_for_size itself return an opt_mode.

require () seems like the right choice in expand_builtin_powi
because we have got past the point of backing out.  We go on to do:

  op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
  if (GET_MODE (op1) != mode2)
    op1 = convert_to_mode (mode2, op1, 0);

which would be invalid for (and have failed for) BLKmode.

In get_builtin_sync_mode and expand_ifn_atomic_compare_exchange,
the possible bitsizes are {8, 16, 32, 64, 128}, all of which give
target-independent integer modes (up to TImode).  The comment above
the call in get_builtin_sync_mode makes clear that an integer mode
must be found.

We can use require () in expand_builtin_atomic_clear and
expand_builtin_atomic_test_and_set because there's always an integer
mode for the boolean type.  The same goes for the POINTER_SIZE request
in layout_type.  Similarly we can use require () in combine_instructions
and gen_lowpart_common because there's always an integer mode for
HOST_BITS_PER_WIDE_INT (DImode when BITS_PER_UNIT == 8), and
HOST_BITS_PER_DOUBLE_INT (TImode).

The calls in aarch64_function_value, arm_function_value,
aapcs_allocate_return_reg and mips_function_value_1 are handling
cases in which a big-endian target passes or returns values at
the most significant end of a register.  In each case the ABI
constrains the size to a small amount and does not handle
non-power-of-2 sizes wider than a word.

The calls in c6x_expand_movmem, i386.c:emit_memset,
lm32_block_move_inline, microblaze_block_move_straight and
mips_block_move_straight are dealing with expansions of
block memory operations using register-wise operations,
and those registers must have non-BLK mode.

The reason for using require () in ix86_expand_sse_cmp,
mips_expand_ins_as_unaligned_store, spu.c:adjust_operand and
spu_emit_branch_and_set is that we go on to emit non-call
instructions that use registers of that mode, which wouldn't
be valid for BLKmode.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* builtins.c (expand_builtin_powi): Use int_mode_for_size.
	(get_builtin_sync_mode): Likewise.
	(expand_ifn_atomic_compare_exchange): Likewise.
	(expand_builtin_atomic_clear): Likewise.
	(expand_builtin_atomic_test_and_set): Likewise.
	(fold_builtin_atomic_always_lock_free): Likewise.
	* calls.c (compute_argument_addresses): Likewise.
	(emit_library_call_value_1): Likewise.
	(store_one_arg): Likewise.
	* combine.c (combine_instructions): Likewise.
	* config/aarch64/aarch64.c (aarch64_function_value): Likewise.
	* config/arm/arm.c (arm_function_value): Likewise.
	(aapcs_allocate_return_reg): Likewise.
	* config/c6x/c6x.c (c6x_expand_movmem): Likewise.
	* config/i386/i386.c (construct_container): Likewise.
	(ix86_gimplify_va_arg): Likewise.
	(ix86_expand_sse_cmp): Likewise.
	(emit_memmov): Likewise.
	(emit_memset): Likewise.
	(expand_small_movmem_or_setmem): Likewise.
	(ix86_expand_pextr): Likewise.
	(ix86_expand_pinsr): Likewise.
	* config/lm32/lm32.c (lm32_block_move_inline): Likewise.
	* config/microblaze/microblaze.c (microblaze_block_move_straight):
	Likewise.
	* config/mips/mips.c (mips_function_value_1) Likewise.
	(mips_block_move_straight): Likewise.
	(mips_expand_ins_as_unaligned_store): Likewise.
	* config/powerpcspe/powerpcspe.c
	(rs6000_darwin64_record_arg_advance_flush): Likewise.
	(rs6000_darwin64_record_arg_flush): Likewise.
	* config/rs6000/rs6000.c
	(rs6000_darwin64_record_arg_advance_flush): Likewise.
	(rs6000_darwin64_record_arg_flush): Likewise.
	* config/sparc/sparc.c (sparc_function_arg_1): Likewise.
	(sparc_function_value_1): Likewise.
	* config/spu/spu.c (adjust_operand): Likewise.
	(spu_emit_branch_or_set): Likewise.
	(arith_immediate_p): Likewise.
	* emit-rtl.c (gen_lowpart_common): Likewise.
	* expr.c (expand_expr_real_1): Likewise.
	* function.c (assign_parm_setup_block): Likewise.
	* gimple-ssa-store-merging.c (encode_tree_to_bitpos): Likewise.
	* reload1.c (alter_reg): Likewise.
	* stor-layout.c (mode_for_vector): Likewise.
	(layout_type): Likewise.

gcc/ada/
	* gcc-interface/utils2.c (build_load_modify_store):
	Use int_mode_for_size.

Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	2017-09-04 08:30:09.328308115 +0100
+++ gcc/builtins.c	2017-09-04 12:18:44.865115639 +0100
@@ -2755,7 +2755,7 @@ expand_builtin_powi (tree exp, rtx targe
   /* Emit a libcall to libgcc.  */
 
   /* Mode of the 2nd argument must match that of an int.  */
-  mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
+  mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
 
   if (target == NULL_RTX)
     target = gen_reg_rtx (mode);
@@ -5477,7 +5477,7 @@ get_builtin_sync_mode (int fcode_diff)
 {
   /* The size is not negotiable, so ask not to get BLKmode in return
      if the target indicates that a smaller size would be better.  */
-  return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
+  return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
 }
 
 /* Expand the memory expression LOC and return the appropriate memory operand
@@ -5858,7 +5858,7 @@ expand_ifn_atomic_compare_exchange (gcal
 {
   int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
   gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
-  machine_mode mode = mode_for_size (BITS_PER_UNIT * size, MODE_INT, 0);
+  machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
   rtx expect, desired, mem, oldval, boolret;
   enum memmodel success, failure;
   tree lhs;
@@ -6154,7 +6154,7 @@ expand_builtin_atomic_clear (tree exp)
   rtx mem, ret;
   enum memmodel model;
 
-  mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
+  mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
 
@@ -6189,7 +6189,7 @@ expand_builtin_atomic_test_and_set (tree
   enum memmodel model;
   machine_mode mode;
 
-  mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
+  mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
 
@@ -6210,8 +6210,11 @@ fold_builtin_atomic_always_lock_free (tr
   if (TREE_CODE (arg0) != INTEGER_CST)
     return NULL_TREE;
 
+  /* We need a corresponding integer mode for the access to be lock-free.  */
   size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
-  mode = mode_for_size (size, MODE_INT, 0);
+  if (!int_mode_for_size (size, 0).exists (&mode))
+    return boolean_false_node;
+
   mode_align = GET_MODE_ALIGNMENT (mode);
 
   if (TREE_CODE (arg1) == INTEGER_CST)
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2017-09-04 11:50:24.542663572 +0100
+++ gcc/calls.c	2017-09-04 12:18:44.866121179 +0100
@@ -2209,8 +2209,8 @@ compute_argument_addresses (struct arg_d
 	      /* Only part of the parameter is being passed on the stack.
 		 Generate a simple memory reference of the correct size.  */
 	      units_on_stack = args[i].locate.size.constant;
-	      partial_mode = mode_for_size (units_on_stack * BITS_PER_UNIT,
-					    MODE_INT, 1);
+	      unsigned int bits_on_stack = units_on_stack * BITS_PER_UNIT;
+	      partial_mode = int_mode_for_size (bits_on_stack, 1).else_blk ();
 	      args[i].stack = gen_rtx_MEM (partial_mode, addr);
 	      set_mem_size (args[i].stack, units_on_stack);
 	    }
@@ -4818,7 +4818,7 @@ emit_library_call_value_1 (int retval, r
 		  unsigned int size
 		    = argvec[argnum].locate.size.constant * BITS_PER_UNIT;
 		  machine_mode save_mode
-		    = mode_for_size (size, MODE_INT, 1);
+		    = int_mode_for_size (size, 1).else_blk ();
 		  rtx adr
 		    = plus_constant (Pmode, argblock,
 				     argvec[argnum].locate.offset.constant);
@@ -5271,7 +5271,8 @@ store_one_arg (struct arg_data *arg, rtx
 	    {
 	      /* We need to make a save area.  */
 	      unsigned int size = arg->locate.size.constant * BITS_PER_UNIT;
-	      machine_mode save_mode = mode_for_size (size, MODE_INT, 1);
+	      machine_mode save_mode
+		= int_mode_for_size (size, 1).else_blk ();
 	      rtx adr = memory_address (save_mode, XEXP (arg->stack_slot, 0));
 	      rtx stack_area = gen_rtx_MEM (save_mode, adr);
 
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2017-09-04 11:50:08.502225206 +0100
+++ gcc/combine.c	2017-09-04 12:18:44.871148881 +0100
@@ -370,7 +370,7 @@ alloc_insn_link (rtx_insn *insn, unsigne
 /* Mode used to compute significance in reg_stat[].nonzero_bits.  It is the
    largest integer mode that can fit in HOST_BITS_PER_WIDE_INT.  */
 
-static machine_mode nonzero_bits_mode;
+static scalar_int_mode nonzero_bits_mode;
 
 /* Nonzero when reg_stat[].nonzero_bits and reg_stat[].sign_bit_copies can
    be safely used.  It is zero while computing them and after combine has
@@ -1157,7 +1157,7 @@ combine_instructions (rtx_insn *f, unsig
   uid_insn_cost = XCNEWVEC (int, max_uid_known + 1);
   gcc_obstack_init (&insn_link_obstack);
 
-  nonzero_bits_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
+  nonzero_bits_mode = int_mode_for_size (HOST_BITS_PER_WIDE_INT, 0).require ();
 
   /* Don't use reg_stat[].nonzero_bits when computing it.  This can cause
      problems when, for example, we have j <<= 1 in a loop.  */
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2017-09-04 11:50:24.544464351 +0100
+++ gcc/config/aarch64/aarch64.c	2017-09-04 12:18:44.874165502 +0100
@@ -2235,7 +2235,7 @@ aarch64_function_value (const_tree type,
       if (size % UNITS_PER_WORD != 0)
 	{
 	  size += UNITS_PER_WORD - size % UNITS_PER_WORD;
-	  mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+	  mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
 	}
     }
 
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2017-09-04 11:50:24.546265130 +0100
+++ gcc/config/arm/arm.c	2017-09-04 12:18:44.886231985 +0100
@@ -5358,7 +5358,7 @@ arm_function_value(const_tree type, cons
       if (size % UNITS_PER_WORD != 0)
 	{
 	  size += UNITS_PER_WORD - size % UNITS_PER_WORD;
-	  mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+	  mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
 	}
     }
 
@@ -6315,7 +6315,7 @@ aapcs_allocate_return_reg (machine_mode
       if (size % UNITS_PER_WORD != 0)
 	{
 	  size += UNITS_PER_WORD - size % UNITS_PER_WORD;
-	  mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+	  mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
 	}
     }
 
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	2017-09-04 11:50:08.509428322 +0100
+++ gcc/config/c6x/c6x.c	2017-09-04 12:18:44.887237526 +0100
@@ -1758,8 +1758,8 @@ c6x_expand_movmem (rtx dst, rtx src, rtx
       if (dst_size > src_size)
 	dst_size = src_size;
 
-      srcmode = mode_for_size (src_size * BITS_PER_UNIT, MODE_INT, 0);
-      dstmode = mode_for_size (dst_size * BITS_PER_UNIT, MODE_INT, 0);
+      srcmode = int_mode_for_size (src_size * BITS_PER_UNIT, 0).require ();
+      dstmode = int_mode_for_size (dst_size * BITS_PER_UNIT, 0).require ();
       if (src_size >= 4)
 	reg_lowpart = reg = gen_reg_rtx (srcmode);
       else
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-09-04 11:50:08.515731048 +0100
+++ gcc/config/i386/i386.c	2017-09-04 12:18:44.903326171 +0100
@@ -9892,16 +9892,17 @@ construct_container (machine_mode mode,
 	  case X86_64_INTEGERSI_CLASS:
 	    /* Merge TImodes on aligned occasions here too.  */
 	    if (i * 8 + 8 > bytes)
-	      tmpmode
-		= mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
+	      {
+		unsigned int tmpbits = (bytes - i * 8) * BITS_PER_UNIT;
+		if (!int_mode_for_size (tmpbits, 0).exists (&tmpmode))
+		  /* We've requested 24 bytes we
+		     don't have mode for.  Use DImode.  */
+		  tmpmode = DImode;
+	      }
 	    else if (regclass[i] == X86_64_INTEGERSI_CLASS)
 	      tmpmode = SImode;
 	    else
 	      tmpmode = DImode;
-	    /* We've requested 24 bytes we
-	       don't have mode for.  Use DImode.  */
-	    if (tmpmode == BLKmode)
-	      tmpmode = DImode;
 	    exp [nexps++]
 	      = gen_rtx_EXPR_LIST (VOIDmode,
 				   gen_rtx_REG (tmpmode, *intreg),
@@ -11880,8 +11881,8 @@ ix86_gimplify_va_arg (tree valist, tree
 	      if (prev_size + cur_size > size)
 		{
 		  cur_size = size - prev_size;
-		  mode = mode_for_size (cur_size * BITS_PER_UNIT, MODE_INT, 1);
-		  if (mode == BLKmode)
+		  unsigned int nbits = cur_size * BITS_PER_UNIT;
+		  if (!int_mode_for_size (nbits, 1).exists (&mode))
 		    mode = QImode;
 		}
 	      piece_type = lang_hooks.types.type_for_mode (mode, 1);
@@ -24807,9 +24808,8 @@ ix86_expand_sse_cmp (rtx dest, enum rtx_
 
   if (GET_MODE_SIZE (cmp_ops_mode) == 64)
     {
-      cmp_mode = mode_for_size (GET_MODE_NUNITS (cmp_ops_mode), MODE_INT, 0);
-      gcc_assert (cmp_mode != BLKmode);
-
+      unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode);
+      cmp_mode = int_mode_for_size (nbits, 0).require ();
       maskcmp = true;
     }
   else
@@ -27408,13 +27408,11 @@ emit_memmov (rtx destmem, rtx *srcmem, r
      Start with the biggest power of 2 less than SIZE_TO_MOVE and half
      it until move of such size is supported.  */
   piece_size = 1 << floor_log2 (size_to_move);
-  move_mode = mode_for_size (piece_size * BITS_PER_UNIT, MODE_INT, 0);
-  code = optab_handler (mov_optab, move_mode);
-  while (code == CODE_FOR_nothing && piece_size > 1)
+  while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
+	 || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
     {
+      gcc_assert (piece_size > 1);
       piece_size >>= 1;
-      move_mode = mode_for_size (piece_size * BITS_PER_UNIT, MODE_INT, 0);
-      code = optab_handler (mov_optab, move_mode);
     }
 
   /* Find the corresponding vector mode with the same size as MOVE_MODE.
@@ -27597,7 +27595,8 @@ emit_memset (rtx destmem, rtx destptr, r
     move_mode = QImode;
   if (size_to_move < GET_MODE_SIZE (move_mode))
     {
-      move_mode = mode_for_size (size_to_move * BITS_PER_UNIT, MODE_INT, 0);
+      unsigned int move_bits = size_to_move * BITS_PER_UNIT;
+      move_mode = int_mode_for_size (move_bits, 0).require ();
       promoted_val = gen_lowpart (move_mode, promoted_val);
     }
   piece_size = GET_MODE_SIZE (move_mode);
@@ -27792,7 +27791,7 @@ expand_small_movmem_or_setmem (rtx destm
 			       rtx done_label, bool issetmem)
 {
   rtx_code_label *label = ix86_expand_aligntest (count, size, false);
-  machine_mode mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 1);
+  machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
   rtx modesize;
   int n;
 
@@ -50453,7 +50452,8 @@ ix86_expand_pextr (rtx *operands)
 	machine_mode srcmode, dstmode;
 	rtx d, pat;
 
-	dstmode = mode_for_size (size, MODE_INT, 0);
+	if (!int_mode_for_size (size, 0).exists (&dstmode))
+	  return false;
 
 	switch (dstmode)
 	  {
@@ -50549,7 +50549,8 @@ ix86_expand_pinsr (rtx *operands)
 	rtx (*pinsr)(rtx, rtx, rtx, rtx);
 	rtx d;
 
-	srcmode = mode_for_size (size, MODE_INT, 0);
+	if (!int_mode_for_size (size, 0).exists (&srcmode))
+	  return false;
 
 	switch (srcmode)
 	  {
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	2017-09-04 11:50:08.517531827 +0100
+++ gcc/config/lm32/lm32.c	2017-09-04 12:18:44.903326171 +0100
@@ -836,7 +836,7 @@ lm32_block_move_inline (rtx dest, rtx sr
       break;
     }
 
-  mode = mode_for_size (bits, MODE_INT, 0);
+  mode = int_mode_for_size (bits, 0).require ();
   delta = bits / BITS_PER_UNIT;
 
   /* Allocate a buffer for the temporary registers.  */
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	2017-09-04 11:50:08.520232996 +0100
+++ gcc/config/microblaze/microblaze.c	2017-09-04 12:18:44.904331711 +0100
@@ -1087,7 +1087,7 @@ microblaze_block_move_straight (rtx dest
   rtx *regs;
 
   bits = BITS_PER_WORD;
-  mode = mode_for_size (bits, MODE_INT, 0);
+  mode = int_mode_for_size (bits, 0).require ();
   delta = bits / BITS_PER_UNIT;
 
   /* Allocate a buffer for the temporary registers.  */
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2017-09-04 11:50:24.550767077 +0100
+++ gcc/config/mips/mips.c	2017-09-04 12:18:44.906342792 +0100
@@ -6384,7 +6384,7 @@ mips_function_value_1 (const_tree valtyp
 	  if (size % UNITS_PER_WORD != 0)
 	    {
 	      size += UNITS_PER_WORD - size % UNITS_PER_WORD;
-	      mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+	      mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
 	    }
 	}
 
@@ -7992,7 +7992,7 @@ mips_block_move_straight (rtx dest, rtx
 	bits = BITS_PER_WORD;
     }
 
-  mode = mode_for_size (bits, MODE_INT, 0);
+  mode = int_mode_for_size (bits, 0).require ();
   delta = bits / BITS_PER_UNIT;
 
   /* Allocate a buffer for the temporary registers.  */
@@ -8397,7 +8397,7 @@ mips_expand_ins_as_unaligned_store (rtx
   if (!mips_get_unaligned_mem (dest, width, bitpos, &left, &right))
     return false;
 
-  mode = mode_for_size (width, MODE_INT, 0);
+  mode = int_mode_for_size (width, 0).require ();
   src = gen_lowpart (mode, src);
   if (mode == DImode)
     {
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-09-04 11:50:24.557069804 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-09-04 12:18:44.919414816 +0100
@@ -12222,7 +12222,6 @@ rs6000_darwin64_record_arg_advance_flush
 {
   unsigned int startbit, endbit;
   int intregs, intoffset;
-  machine_mode mode;
 
   /* Handle the situations where a float is taking up the first half
      of the GPR, and the other half is empty (typically due to
@@ -12246,9 +12245,8 @@ rs6000_darwin64_record_arg_advance_flush
 
   if (intoffset % BITS_PER_WORD != 0)
     {
-      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
-			    MODE_INT, 0);
-      if (mode == BLKmode)
+      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
+      if (!int_mode_for_size (bits, 0).exists ())
 	{
 	  /* We couldn't find an appropriate mode, which happens,
 	     e.g., in packed structs when there are 3 bytes to load.
@@ -12714,9 +12712,8 @@ rs6000_darwin64_record_arg_flush (CUMULA
 
   if (intoffset % BITS_PER_WORD != 0)
     {
-      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
-			  MODE_INT, 0);
-      if (mode == BLKmode)
+      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
+      if (!int_mode_for_size (bits, 0).exists (&mode))
 	{
 	  /* We couldn't find an appropriate mode, which happens,
 	     e.g., in packed structs when there are 3 bytes to load.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-09-04 11:50:24.560671361 +0100
+++ gcc/config/rs6000/rs6000.c	2017-09-04 12:18:44.929470219 +0100
@@ -11654,7 +11654,6 @@ rs6000_darwin64_record_arg_advance_flush
 {
   unsigned int startbit, endbit;
   int intregs, intoffset;
-  machine_mode mode;
 
   /* Handle the situations where a float is taking up the first half
      of the GPR, and the other half is empty (typically due to
@@ -11678,9 +11677,8 @@ rs6000_darwin64_record_arg_advance_flush
 
   if (intoffset % BITS_PER_WORD != 0)
     {
-      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
-			    MODE_INT, 0);
-      if (mode == BLKmode)
+      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
+      if (!int_mode_for_size (bits, 0).exists ())
 	{
 	  /* We couldn't find an appropriate mode, which happens,
 	     e.g., in packed structs when there are 3 bytes to load.
@@ -12049,9 +12047,8 @@ rs6000_darwin64_record_arg_flush (CUMULA
 
   if (intoffset % BITS_PER_WORD != 0)
     {
-      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
-			  MODE_INT, 0);
-      if (mode == BLKmode)
+      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
+      if (!int_mode_for_size (bits, 0).exists (&mode))
 	{
 	  /* We couldn't find an appropriate mode, which happens,
 	     e.g., in packed structs when there are 3 bytes to load.
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2017-09-04 11:50:24.562472140 +0100
+++ gcc/config/sparc/sparc.c	2017-09-04 12:18:44.932486840 +0100
@@ -7123,7 +7123,7 @@ sparc_function_arg_1 (cumulative_args_t
       HOST_WIDE_INT size = int_size_in_bytes (type);
       gcc_assert (size <= 16);
 
-      mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+      mode = int_mode_for_size (size * BITS_PER_UNIT, 0).else_blk ();
     }
 
   return gen_rtx_REG (mode, regno);
@@ -7499,7 +7499,7 @@ sparc_function_value_1 (const_tree type,
 	  HOST_WIDE_INT size = int_size_in_bytes (type);
 	  gcc_assert (size <= 32);
 
-	  mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+	  mode = int_mode_for_size (size * BITS_PER_UNIT, 0).else_blk ();
 
 	  /* ??? We probably should have made the same ABI change in
 	     3.4.0 as the one we made for unions.   The latter was
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2017-09-04 12:18:41.572976650 +0100
+++ gcc/config/spu/spu.c	2017-09-04 12:18:44.934497920 +0100
@@ -368,7 +368,7 @@ adjust_operand (rtx op, HOST_WIDE_INT *
       op_size = 32;
     }
   /* If it is not a MODE_INT (and/or it is smaller than SI) add a SUBREG. */
-  mode = mode_for_size (op_size, MODE_INT, 0);
+  mode = int_mode_for_size (op_size, 0).require ();
   if (mode != GET_MODE (op))
     op = gen_rtx_SUBREG (mode, op, 0);
   return op;
@@ -935,7 +935,7 @@ spu_emit_branch_or_set (int is_set, rtx
       rtx target = operands[0];
       int compare_size = GET_MODE_BITSIZE (comp_mode);
       int target_size = GET_MODE_BITSIZE (GET_MODE (target));
-      machine_mode mode = mode_for_size (target_size, MODE_INT, 0);
+      machine_mode mode = int_mode_for_size (target_size, 0).require ();
       rtx select_mask;
       rtx op_t = operands[2];
       rtx op_f = operands[3];
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2017-09-04 11:48:27.399539901 +0100
+++ gcc/emit-rtl.c	2017-09-04 12:18:44.935503461 +0100
@@ -1430,9 +1430,9 @@ gen_lowpart_common (machine_mode mode, r
   innermode = GET_MODE (x);
   if (CONST_INT_P (x)
       && msize * BITS_PER_UNIT <= HOST_BITS_PER_WIDE_INT)
-    innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
+    innermode = int_mode_for_size (HOST_BITS_PER_WIDE_INT, 0).require ();
   else if (innermode == VOIDmode)
-    innermode = mode_for_size (HOST_BITS_PER_DOUBLE_INT, MODE_INT, 0);
+    innermode = int_mode_for_size (HOST_BITS_PER_DOUBLE_INT, 0).require ();
 
   xsize = GET_MODE_SIZE (innermode);
 
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-09-04 11:50:24.566974088 +0100
+++ gcc/expr.c	2017-09-04 12:18:44.938520082 +0100
@@ -10680,7 +10680,7 @@ expand_expr_real_1 (tree exp, rtx target
 		&& ! (target != 0 && MEM_P (op0)
 		      && MEM_P (target)
 		      && bitpos % BITS_PER_UNIT == 0))
-	      ext_mode = mode_for_size (bitsize, MODE_INT, 1);
+	      ext_mode = int_mode_for_size (bitsize, 1).else_blk ();
 
 	    if (ext_mode == BLKmode)
 	      {
Index: gcc/function.c
===================================================================
--- gcc/function.c	2017-09-04 11:50:24.567874477 +0100
+++ gcc/function.c	2017-09-04 12:18:44.940531162 +0100
@@ -2978,8 +2978,8 @@ assign_parm_setup_block (struct assign_p
 	 that mode's store operation.  */
       else if (size <= UNITS_PER_WORD)
 	{
-	  machine_mode mode
-	    = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+	  unsigned int bits = size * BITS_PER_UNIT;
+	  machine_mode mode = int_mode_for_size (bits, 0).else_blk ();
 
 	  if (mode != BLKmode
 #ifdef BLOCK_REG_PADDING
Index: gcc/gimple-ssa-store-merging.c
===================================================================
--- gcc/gimple-ssa-store-merging.c	2017-07-27 10:37:56.776048721 +0100
+++ gcc/gimple-ssa-store-merging.c	2017-09-04 12:18:44.941536703 +0100
@@ -354,7 +354,7 @@ encode_tree_to_bitpos (tree expr, unsign
   tree tmp_int = expr;
   bool sub_byte_op_p = ((bitlen % BITS_PER_UNIT)
 			|| (bitpos % BITS_PER_UNIT)
-			|| mode_for_size (bitlen, MODE_INT, 0) == BLKmode);
+			|| !int_mode_for_size (bitlen, 0).exists ());
 
   if (!sub_byte_op_p)
     return (native_encode_expr (tmp_int, ptr + first_byte, total_bytes, 0)
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c	2017-09-04 11:49:42.942500722 +0100
+++ gcc/reload1.c	2017-09-04 12:18:44.943547783 +0100
@@ -2189,11 +2189,12 @@ alter_reg (int i, int from_reg, bool don
 	    {
 	      adjust = inherent_size - total_size;
 	      if (adjust)
-		stack_slot
-		  = adjust_address_nv (x, mode_for_size (total_size
-						         * BITS_PER_UNIT,
-						         MODE_INT, 1),
-				       adjust);
+		{
+		  unsigned int total_bits = total_size * BITS_PER_UNIT;
+		  machine_mode mem_mode
+		    = int_mode_for_size (total_bits, 1).else_blk ();
+		  stack_slot = adjust_address_nv (x, mem_mode, adjust);
+		}
 	    }
 
 	  if (! dont_share_p && ira_conflicts_p)
@@ -2240,11 +2241,12 @@ alter_reg (int i, int from_reg, bool don
 	    {
 	      adjust = GET_MODE_SIZE (mode) - total_size;
 	      if (adjust)
-		stack_slot
-		  = adjust_address_nv (x, mode_for_size (total_size
-							 * BITS_PER_UNIT,
-							 MODE_INT, 1),
-				       adjust);
+		{
+		  unsigned int total_bits = total_size * BITS_PER_UNIT;
+		  machine_mode mem_mode
+		    = int_mode_for_size (total_bits, 1).else_blk ();
+		  stack_slot = adjust_address_nv (x, mem_mode, adjust);
+		}
 	    }
 
 	  spill_stack_slot[from_reg] = stack_slot;
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-08-30 12:20:41.643620906 +0100
+++ gcc/stor-layout.c	2017-09-04 12:18:44.944553324 +0100
@@ -506,8 +506,10 @@ mode_for_vector (scalar_mode innermode,
   /* For integers, try mapping it to a same-sized scalar mode.  */
   if (mode == VOIDmode
       && GET_MODE_CLASS (innermode) == MODE_INT)
-    mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
-			  MODE_INT, 0);
+    {
+      unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);
+      mode = int_mode_for_size (nbits, 0).else_blk ();
+    }
 
   if (mode == VOIDmode
       || (GET_MODE_CLASS (mode) == MODE_INT
@@ -2295,7 +2297,7 @@ layout_type (tree type)
       TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE_UNITS);
       /* A pointer might be MODE_PARTIAL_INT, but ptrdiff_t must be
 	 integral, which may be an __intN.  */
-      SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0));
+      SET_TYPE_MODE (type, int_mode_for_size (POINTER_SIZE, 0).require ());
       TYPE_PRECISION (type) = POINTER_SIZE;
       break;
 
@@ -2304,7 +2306,8 @@ layout_type (tree type)
       /* It's hard to see what the mode and size of a function ought to
 	 be, but we do know the alignment is FUNCTION_BOUNDARY, so
 	 make it consistent with that.  */
-      SET_TYPE_MODE (type, mode_for_size (FUNCTION_BOUNDARY, MODE_INT, 0));
+      SET_TYPE_MODE (type,
+		     int_mode_for_size (FUNCTION_BOUNDARY, 0).else_blk ());
       TYPE_SIZE (type) = bitsize_int (FUNCTION_BOUNDARY);
       TYPE_SIZE_UNIT (type) = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
       break;
Index: gcc/ada/gcc-interface/utils2.c
===================================================================
--- gcc/ada/gcc-interface/utils2.c	2017-05-31 10:02:29.736972972 +0100
+++ gcc/ada/gcc-interface/utils2.c	2017-09-04 12:18:44.864110098 +0100
@@ -800,7 +800,8 @@ build_load_modify_store (tree dest, tree
 		{
 		  unsigned int size = tree_to_uhwi (TYPE_SIZE (type));
 		  type = copy_type (type);
-		  SET_TYPE_MODE (type, mode_for_size (size, MODE_INT, 0));
+		  machine_mode mode = int_mode_for_size (size, 0).else_blk ();
+		  SET_TYPE_MODE (type, mode);
 		}
 
 	      /* Create the temporary by inserting a SAVE_EXPR.  */

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [3/9] (decimal_)float_mode_for_size in real.h
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
  2017-09-04 11:26 ` [1/9] Make more use of int_mode_for_mode Richard Sandiford
  2017-09-04 11:31 ` [2/9] Make more use of int_mode_for_size Richard Sandiford
@ 2017-09-04 11:32 ` Richard Sandiford
  2017-09-05 11:24   ` Richard Biener
  2017-09-04 11:35 ` [4/9] Make mode_for_size return an opt_mode Richard Sandiford
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:32 UTC (permalink / raw)
  To: gcc-patches

This patch makes the binary float macros in real.h use
float_mode_for_size and adds a corresponding decimal_float_mode_for_size
for the decimal macros.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* machmode.h (decimal_float_mode_for_size): New function.
	* real.h (REAL_VALUE_TO_TARGET_LONG_DOUBLE): Use float_mode_for_size.
	(REAL_VALUE_TO_TARGET_DOUBLE): Likewise.
	(REAL_VALUE_TO_TARGET_SINGLE): Likewise.
	(REAL_VALUE_TO_TARGET_DECIMAL128): Use decimal_float_mode_for_size.
	(REAL_VALUE_TO_TARGET_DECIMAL64): Likewise.
	(REAL_VALUE_TO_TARGET_DECIMAL32): Likewise.

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-08-30 12:20:57.010045759 +0100
+++ gcc/machmode.h	2017-09-04 12:18:47.820398622 +0100
@@ -652,6 +652,15 @@ float_mode_for_size (unsigned int size)
   return dyn_cast <scalar_float_mode> (mode_for_size (size, MODE_FLOAT, 0));
 }
 
+/* Likewise for MODE_DECIMAL_FLOAT.  */
+
+inline opt_scalar_float_mode
+decimal_float_mode_for_size (unsigned int size)
+{
+  return dyn_cast <scalar_float_mode>
+    (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
+}
+
 /* Similar to mode_for_size, but find the smallest mode for a given width.  */
 
 extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);
Index: gcc/real.h
===================================================================
--- gcc/real.h	2017-08-30 12:09:02.416468293 +0100
+++ gcc/real.h	2017-09-04 12:18:47.820398622 +0100
@@ -383,27 +383,28 @@ #define REAL_VALUE_MINUS_ZERO(x)	real_is
 /* IN is a REAL_VALUE_TYPE.  OUT is an array of longs.  */
 #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT)			\
   real_to_target (OUT, &(IN),						\
-		  mode_for_size (LONG_DOUBLE_TYPE_SIZE, MODE_FLOAT, 0))
+		  float_mode_for_size (LONG_DOUBLE_TYPE_SIZE).require ())
 
 #define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
-  real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0))
+  real_to_target (OUT, &(IN), float_mode_for_size (64).require ())
 
 /* IN is a REAL_VALUE_TYPE.  OUT is a long.  */
 #define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
-  ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_FLOAT, 0)))
+  ((OUT) = real_to_target (NULL, &(IN), float_mode_for_size (32).require ()))
 
 /* Real values to IEEE 754 decimal floats.  */
 
 /* IN is a REAL_VALUE_TYPE.  OUT is an array of longs.  */
 #define REAL_VALUE_TO_TARGET_DECIMAL128(IN, OUT) \
-  real_to_target (OUT, &(IN), mode_for_size (128, MODE_DECIMAL_FLOAT, 0))
+  real_to_target (OUT, &(IN), decimal_float_mode_for_size (128).require ())
 
 #define REAL_VALUE_TO_TARGET_DECIMAL64(IN, OUT) \
-  real_to_target (OUT, &(IN), mode_for_size (64, MODE_DECIMAL_FLOAT, 0))
+  real_to_target (OUT, &(IN), decimal_float_mode_for_size (64).require ())
 
 /* IN is a REAL_VALUE_TYPE.  OUT is a long.  */
 #define REAL_VALUE_TO_TARGET_DECIMAL32(IN, OUT) \
-  ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_DECIMAL_FLOAT, 0)))
+  ((OUT) = real_to_target (NULL, &(IN), \
+			   decimal_float_mode_for_size (32).require ()))
 
 extern REAL_VALUE_TYPE real_value_truncate (format_helper, REAL_VALUE_TYPE);
 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [4/9] Make mode_for_size return an opt_mode
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
                   ` (2 preceding siblings ...)
  2017-09-04 11:32 ` [3/9] (decimal_)float_mode_for_size in real.h Richard Sandiford
@ 2017-09-04 11:35 ` Richard Sandiford
  2017-09-05 11:25   ` Richard Biener
  2017-09-04 11:37 ` [5/9] Add mode_for_int_vector helper functions Richard Sandiford
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:35 UTC (permalink / raw)
  To: gcc-patches

...to make it consistent with int_mode_for_size etc.

require () seems like the right choice in replace_reg_with_saved_mem
because we use the chosen mode for saving and restoring registers,
which cannot be done in BLKmode.  Similarly require () seems like
the right choice in calls related to secondary memory reloads (the ones
in config/, and in get_secondary_mem) because the reload must always
have a defined mode, which e.g. determines the size of the slot.

We can use require () in simplify_subreg_concatn and assemble_integer
because it isn't meaningful to create a subreg with BLKmode (for one
thing, we couldn't tell then whether it was partial, paradoxical, etc.).

make_fract_type and make_accum_type must find a mode because that's
what distinguishes accumulator FIXED_POINT_TYPEs from fractional
FIXED_POINT_TYPEs.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* machmode.h (opt_machine_mode): New type.
	(opt_mode<T>): Allow construction from anything that can be
	converted to a T.
	(is_a, as_a, dyn_cast): Add overloads for opt_mode.
	(mode_for_size): Return an opt_machine_mode.
	* stor-layout.c (mode_for_size): Likewise.
	(mode_for_size_tree): Update call accordingly.
	(bitwise_mode_for_mode): Likewise.
	(make_fract_type): Likewise.
	(make_accum_type): Likewise.
	* caller-save.c (replace_reg_with_saved_mem): Update call
	accordingly.
	* config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
	* config/i386/i386.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
	* config/s390/s390.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
	* config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
	* expmed.c (extract_bit_field_1): Likewise.
	* reload.c (get_secondary_mem): Likewise.
	* varasm.c (assemble_integer): Likewise.
	* lower-subreg.c (simplify_subreg_concatn): Likewise.  Move
	early-out.

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-09-04 12:18:47.820398622 +0100
+++ gcc/machmode.h	2017-09-04 12:18:50.674859598 +0100
@@ -20,6 +20,8 @@ Software Foundation; either version 3, o
 #ifndef HAVE_MACHINE_MODES
 #define HAVE_MACHINE_MODES
 
+typedef opt_mode<machine_mode> opt_machine_mode;
+
 extern CONST_MODE_SIZE unsigned short mode_size[NUM_MACHINE_MODES];
 extern const unsigned short mode_precision[NUM_MACHINE_MODES];
 extern const unsigned char mode_inner[NUM_MACHINE_MODES];
@@ -237,6 +239,8 @@ #define POINTER_BOUNDS_MODE_P(MODE)
 
   ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
   ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
+  template<typename U>
+  ALWAYS_INLINE opt_mode (const U &m) : m_mode (T (m)) {}
   ALWAYS_INLINE opt_mode (from_int m) : m_mode (machine_mode (m)) {}
 
   machine_mode else_void () const;
@@ -325,6 +329,13 @@ is_a (machine_mode m)
   return T::includes_p (m);
 }
 
+template<typename T, typename U>
+inline bool
+is_a (const opt_mode<U> &m)
+{
+  return T::includes_p (m.else_void ());
+}
+
 /* Assert that mode M has type T, and return it in that form.  */
 
 template<typename T>
@@ -335,6 +346,13 @@ as_a (machine_mode m)
   return typename mode_traits<T>::from_int (m);
 }
 
+template<typename T, typename U>
+inline T
+as_a (const opt_mode<U> &m)
+{
+  return as_a <T> (m.else_void ());
+}
+
 /* Convert M to an opt_mode<T>.  */
 
 template<typename T>
@@ -346,6 +364,13 @@ dyn_cast (machine_mode m)
   return opt_mode<T> ();
 }
 
+template<typename T, typename U>
+inline opt_mode<T>
+dyn_cast (const opt_mode<U> &m)
+{
+  return dyn_cast <T> (m.else_void ());
+}
+
 /* Return true if mode M has type T, storing it as a T in *RESULT
    if so.  */
 
@@ -627,11 +652,7 @@ GET_MODE_2XWIDER_MODE (const T &m)
 extern const unsigned char mode_complex[NUM_MACHINE_MODES];
 #define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
 
-/* Return the mode for data of a given size SIZE and mode class CLASS.
-   If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
-   The value is BLKmode if no other mode is found.  */
-
-extern machine_mode mode_for_size (unsigned int, enum mode_class, int);
+extern opt_machine_mode mode_for_size (unsigned int, enum mode_class, int);
 
 /* Return the machine mode to use for a MODE_INT of SIZE bits, if one
    exists.  If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-09-04 12:18:44.944553324 +0100
+++ gcc/stor-layout.c	2017-09-04 12:18:50.675762071 +0100
@@ -291,19 +291,19 @@ finalize_size_functions (void)
   vec_free (size_functions);
 }
 \f
-/* Return the machine mode to use for a nonscalar of SIZE bits.  The
-   mode must be in class MCLASS, and have exactly that many value bits;
-   it may have padding as well.  If LIMIT is nonzero, modes of wider
-   than MAX_FIXED_MODE_SIZE will not be used.  */
+/* Return a machine mode of class MCLASS with SIZE bits of precision,
+   if one exists.  The mode may have padding bits as well the SIZE
+   value bits.  If LIMIT is nonzero, disregard modes wider than
+   MAX_FIXED_MODE_SIZE.  */
 
-machine_mode
+opt_machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
   machine_mode mode;
   int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
-    return BLKmode;
+    return opt_machine_mode ();
 
   /* Get the first mode which has this size, in the specified class.  */
   FOR_EACH_MODE_IN_CLASS (mode, mclass)
@@ -316,7 +316,7 @@ mode_for_size (unsigned int size, enum m
 	  && int_n_enabled_p[i])
 	return int_n_data[i].m;
 
-  return BLKmode;
+  return opt_machine_mode ();
 }
 
 /* Similar, except passed a tree node.  */
@@ -333,11 +333,11 @@ mode_for_size_tree (const_tree size, enu
   ui = uhwi;
   if (uhwi != ui)
     return BLKmode;
-  return mode_for_size (ui, mclass, limit);
+  return mode_for_size (ui, mclass, limit).else_blk ();
 }
 
-/* Similar, but never return BLKmode; return the narrowest mode that
-   contains at least the requested number of value bits.  */
+/* Return the narrowest mode of class MCLASS that contains at least
+   SIZE bits.  Abort if no such mode exists.  */
 
 machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
@@ -426,9 +426,8 @@ bitwise_mode_for_mode (machine_mode mode
   if (COMPLEX_MODE_P (mode))
     {
       machine_mode trial = mode;
-      if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT)
-	trial = mode_for_size (bitsize, MODE_COMPLEX_INT, false);
-      if (trial != BLKmode
+      if ((GET_MODE_CLASS (trial) == MODE_COMPLEX_INT
+	   || mode_for_size (bitsize, MODE_COMPLEX_INT, false).exists (&trial))
 	  && have_regs_of_mode[GET_MODE_INNER (trial)])
 	return trial;
     }
@@ -438,16 +437,15 @@ bitwise_mode_for_mode (machine_mode mode
   if (VECTOR_MODE_P (mode) || bitsize > MAX_FIXED_MODE_SIZE)
     {
       machine_mode trial = mode;
-      if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
-	trial = mode_for_size (bitsize, MODE_VECTOR_INT, 0);
-      if (trial != BLKmode
+      if ((GET_MODE_CLASS (trial) == MODE_VECTOR_INT
+	   || mode_for_size (bitsize, MODE_VECTOR_INT, 0).exists (&trial))
 	  && have_regs_of_mode[trial]
 	  && targetm.vector_mode_supported_p (trial))
 	return trial;
     }
 
   /* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE.  */
-  return mode_for_size (bitsize, MODE_INT, true);
+  return mode_for_size (bitsize, MODE_INT, true).else_blk ();
 }
 
 /* Find a type that can be used for efficient bitwise operations on MODE.
@@ -2543,13 +2541,9 @@ make_fract_type (int precision, int unsi
     TYPE_SATURATING (type) = 1;
 
   /* Lay out the type: set its alignment, size, etc.  */
-  if (unsignedp)
-    {
-      TYPE_UNSIGNED (type) = 1;
-      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UFRACT, 0));
-    }
-  else
-    SET_TYPE_MODE (type, mode_for_size (precision, MODE_FRACT, 0));
+  TYPE_UNSIGNED (type) = unsignedp;
+  enum mode_class mclass = unsignedp ? MODE_UFRACT : MODE_FRACT;
+  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
   layout_type (type);
 
   return type;
@@ -2569,13 +2563,9 @@ make_accum_type (int precision, int unsi
     TYPE_SATURATING (type) = 1;
 
   /* Lay out the type: set its alignment, size, etc.  */
-  if (unsignedp)
-    {
-      TYPE_UNSIGNED (type) = 1;
-      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UACCUM, 0));
-    }
-  else
-    SET_TYPE_MODE (type, mode_for_size (precision, MODE_ACCUM, 0));
+  TYPE_UNSIGNED (type) = unsignedp;
+  enum mode_class mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
+  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
   layout_type (type);
 
   return type;
Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	2017-09-04 11:49:42.884500727 +0100
+++ gcc/caller-save.c	2017-09-04 12:18:50.672152181 +0100
@@ -1161,7 +1161,7 @@ replace_reg_with_saved_mem (rtx *loc,
 	    gcc_assert (smode != VOIDmode);
 	    if (hard_regno_nregs [regno][smode] > 1)
 	      smode = mode_for_size (GET_MODE_SIZE (mode) / nregs,
-				     GET_MODE_CLASS (mode), 0);
+				     GET_MODE_CLASS (mode), 0).require ();
 	    XVECEXP (mem, 0, i) = gen_rtx_REG (smode, regno + i);
 	  }
     }
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	2017-09-04 11:50:08.504926375 +0100
+++ gcc/config/alpha/alpha.h	2017-09-04 12:18:50.672152181 +0100
@@ -508,7 +508,7 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,C
 #define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
   (GET_MODE_CLASS (MODE) == MODE_FLOAT ? (MODE)		\
    : GET_MODE_SIZE (MODE) >= 4 ? (MODE)			\
-   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0))
+   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require ())
 
 /* Return the class of registers that cannot change mode from FROM to TO.  */
 
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	2017-09-04 11:50:08.515731048 +0100
+++ gcc/config/i386/i386.h	2017-09-04 12:18:50.672152181 +0100
@@ -1548,7 +1548,7 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
    for integral modes that can be moved using 32 bit move.  */
 #define SECONDARY_MEMORY_NEEDED_MODE(MODE)			\
   (GET_MODE_BITSIZE (MODE) < 32 && INTEGRAL_MODE_P (MODE)	\
-   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)		\
+   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()	\
    : MODE)
 
 /* Return a class of registers that cannot change FROM mode to TO mode.  */
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-09-04 11:50:24.561571751 +0100
+++ gcc/config/s390/s390.h	2017-09-04 12:18:50.673054653 +0100
@@ -624,9 +624,9 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
 
 /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
    because the movsi and movsf patterns don't handle r/f moves.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
- (GET_MODE_BITSIZE (MODE) < 32				\
-  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)	\
+#define SECONDARY_MEMORY_NEEDED_MODE(MODE)			\
+ (GET_MODE_BITSIZE (MODE) < 32					\
+  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()	\
   : (MODE))
 
 
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	2017-09-04 11:50:24.563372530 +0100
+++ gcc/config/sparc/sparc.h	2017-09-04 12:18:50.673054653 +0100
@@ -1077,13 +1077,13 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
 /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
    because the movsi and movsf patterns don't handle r/f moves.
    For v8 we copy the default definition.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
-  (TARGET_ARCH64						\
-   ? (GET_MODE_BITSIZE (MODE) < 32				\
-      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)		\
-      : MODE)							\
-   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD			\
-      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0)	\
+#define SECONDARY_MEMORY_NEEDED_MODE(MODE)				   \
+  (TARGET_ARCH64							   \
+   ? (GET_MODE_BITSIZE (MODE) < 32					   \
+      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()		   \
+      : MODE)								   \
+   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD				   \
+      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require () \
       : MODE))
 
 /* Return the maximum number of consecutive registers
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2017-09-04 11:50:08.544543511 +0100
+++ gcc/expmed.c	2017-09-04 12:18:50.673054653 +0100
@@ -1711,14 +1711,9 @@ extract_bit_field_1 (rtx str_rtx, unsign
 
   /* Get the mode of the field to use for atomic access or subreg
      conversion.  */
-  mode1 = mode;
-  if (SCALAR_INT_MODE_P (tmode))
-    {
-      machine_mode try_mode = mode_for_size (bitsize,
-						  GET_MODE_CLASS (tmode), 0);
-      if (try_mode != BLKmode)
-	mode1 = try_mode;
-    }
+  if (!SCALAR_INT_MODE_P (tmode)
+      || !mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0).exists (&mode1))
+    mode1 = mode;
   gcc_assert (mode1 != BLKmode);
 
   /* Extraction of a full MODE1 value can be done with a subreg as long
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2017-09-04 11:49:42.941500722 +0100
+++ gcc/reload.c	2017-09-04 12:18:50.675762071 +0100
@@ -578,7 +578,8 @@ get_secondary_mem (rtx x ATTRIBUTE_UNUSE
   mode = SECONDARY_MEMORY_NEEDED_MODE (mode);
 #else
   if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
-    mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
+    mode = mode_for_size (BITS_PER_WORD,
+			  GET_MODE_CLASS (mode), 0).require ();
 #endif
 
   /* If we already have made a MEM for this operand in MODE, return it.  */
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	2017-09-04 11:49:42.944500722 +0100
+++ gcc/varasm.c	2017-09-04 12:18:50.676664544 +0100
@@ -2780,8 +2780,8 @@ assemble_integer (rtx x, unsigned int si
       else
 	mclass = MODE_INT;
 
-      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0);
-      imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0);
+      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0).require ();
+      imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0).require ();
 
       for (i = 0; i < size; i += subsize)
 	{
Index: gcc/lower-subreg.c
===================================================================
--- gcc/lower-subreg.c	2017-09-04 12:18:41.572976650 +0100
+++ gcc/lower-subreg.c	2017-09-04 12:18:50.674859598 +0100
@@ -616,20 +616,18 @@ simplify_subreg_concatn (machine_mode ou
   part = XVECEXP (op, 0, byte / inner_size);
   partmode = GET_MODE (part);
 
+  final_offset = byte % inner_size;
+  if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
+    return NULL_RTX;
+
   /* VECTOR_CSTs in debug expressions are expanded into CONCATN instead of
      regular CONST_VECTORs.  They have vector or integer modes, depending
      on the capabilities of the target.  Cope with them.  */
   if (partmode == VOIDmode && VECTOR_MODE_P (innermode))
     partmode = GET_MODE_INNER (innermode);
   else if (partmode == VOIDmode)
-    {
-      enum mode_class mclass = GET_MODE_CLASS (innermode);
-      partmode = mode_for_size (inner_size * BITS_PER_UNIT, mclass, 0);
-    }
-
-  final_offset = byte % inner_size;
-  if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
-    return NULL_RTX;
+    partmode = mode_for_size (inner_size * BITS_PER_UNIT,
+			      GET_MODE_CLASS (innermode), 0).require ();
 
   return simplify_gen_subreg (outermode, part, partmode, final_offset);
 }

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [5/9] Add mode_for_int_vector helper functions
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
                   ` (3 preceding siblings ...)
  2017-09-04 11:35 ` [4/9] Make mode_for_size return an opt_mode Richard Sandiford
@ 2017-09-04 11:37 ` Richard Sandiford
  2017-09-05 11:35   ` Richard Biener
  2017-09-04 11:39 ` [6/9] Make mode_for_vector return an opt_mode Richard Sandiford
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:37 UTC (permalink / raw)
  To: gcc-patches

There are at least a few places that want to create an integer vector
with a specified element size and element count, or to create the
integer equivalent of an existing mode.  This patch adds helpers
for doing that.

The require ()s are all used in functions that go on to emit
instructions that use the result as a vector mode.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* machmode.h (mode_for_int_vector): New function.
	* stor-layout.c (mode_for_int_vector): Likewise.
	* config/aarch64/aarch64.c (aarch64_emit_approx_sqrt): Use it.
	* config/powerpcspe/powerpcspe.c (rs6000_do_expand_vec_perm): Likewise.
	* config/rs6000/rs6000.c (rs6000_do_expand_vec_perm): Likewise.
	* config/s390/s390.c (s390_expand_vec_compare_cc): Likewise.
	(s390_expand_vcond): Likewise.

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-09-04 12:18:50.674859598 +0100
+++ gcc/machmode.h	2017-09-04 12:18:53.153306182 +0100
@@ -706,6 +706,21 @@ extern machine_mode bitwise_mode_for_mod
 
 extern machine_mode mode_for_vector (scalar_mode, unsigned);
 
+extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
+
+/* Return the integer vector equivalent of MODE, if one exists.  In other
+   words, return the mode for an integer vector that has the same number
+   of bits as MODE and the same number of elements as MODE, with the
+   latter being 1 if MODE is scalar.  The returned mode can be either
+   an integer mode or a vector mode.  */
+
+inline opt_machine_mode
+mode_for_int_vector (machine_mode mode)
+{
+  return mode_for_int_vector (GET_MODE_UNIT_BITSIZE (mode),
+			      GET_MODE_NUNITS (mode));
+}
+
 /* A class for iterating through possible bitfield modes.  */
 class bit_field_mode_iterator
 {
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-09-04 12:18:50.675762071 +0100
+++ gcc/stor-layout.c	2017-09-04 12:18:53.153306182 +0100
@@ -517,6 +517,23 @@ mode_for_vector (scalar_mode innermode,
   return mode;
 }
 
+/* Return the mode for a vector that has NUNITS integer elements of
+   INT_BITS bits each, if such a mode exists.  The mode can be either
+   an integer mode or a vector mode.  */
+
+opt_machine_mode
+mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
+{
+  scalar_int_mode int_mode;
+  if (int_mode_for_size (int_bits, 0).exists (&int_mode))
+    {
+      machine_mode vec_mode = mode_for_vector (int_mode, nunits);
+      if (vec_mode != BLKmode)
+	return vec_mode;
+    }
+  return opt_machine_mode ();
+}
+
 /* Return the alignment of MODE. This will be bounded by 1 and
    BIGGEST_ALIGNMENT.  */
 
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2017-09-04 12:18:44.874165502 +0100
+++ gcc/config/aarch64/aarch64.c	2017-09-04 12:18:53.144272229 +0100
@@ -8282,9 +8282,6 @@ aarch64_emit_approx_sqrt (rtx dst, rtx s
       return false;
     }
 
-  machine_mode mmsk
-    = mode_for_vector (int_mode_for_mode (GET_MODE_INNER (mode)).require (),
-		       GET_MODE_NUNITS (mode));
   if (!recp)
     {
       if (!(flag_mlow_precision_sqrt
@@ -8302,7 +8299,7 @@ aarch64_emit_approx_sqrt (rtx dst, rtx s
     /* Caller assumes we cannot fail.  */
     gcc_assert (use_rsqrt_p (mode));
 
-
+  machine_mode mmsk = mode_for_int_vector (mode).require ();
   rtx xmsk = gen_reg_rtx (mmsk);
   if (!recp)
     /* When calculating the approximate square root, compare the
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-09-04 12:18:44.919414816 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-09-04 12:18:53.148287319 +0100
@@ -38739,8 +38739,7 @@ rs6000_do_expand_vec_perm (rtx target, r
 
   imode = vmode;
   if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
-    imode = mode_for_vector
-      (int_mode_for_mode (GET_MODE_INNER (vmode)).require (), nelt);
+    imode = mode_for_int_vector (vmode).require ();
 
   x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
   x = expand_vec_perm (vmode, op0, op1, x, target);
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-09-04 12:18:44.929470219 +0100
+++ gcc/config/rs6000/rs6000.c	2017-09-04 12:18:53.151298637 +0100
@@ -35584,8 +35584,7 @@ rs6000_do_expand_vec_perm (rtx target, r
 
   imode = vmode;
   if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
-    imode = mode_for_vector
-      (int_mode_for_mode (GET_MODE_INNER (vmode)).require (), nelt);
+    imode = mode_for_int_vector (vmode).require ();
 
   x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
   x = expand_vec_perm (vmode, op0, op1, x, target);
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2017-09-04 11:50:24.561571751 +0100
+++ gcc/config/s390/s390.c	2017-09-04 12:18:53.153306182 +0100
@@ -6472,10 +6472,7 @@ s390_expand_vec_compare_cc (rtx target,
 	case LE:   cc_producer_mode = CCVFHEmode; code = GE; swap_p = true; break;
 	default: gcc_unreachable ();
 	}
-      scratch_mode = mode_for_vector
-	(int_mode_for_mode (GET_MODE_INNER (GET_MODE (cmp1))).require (),
-	 GET_MODE_NUNITS (GET_MODE (cmp1)));
-      gcc_assert (scratch_mode != BLKmode);
+      scratch_mode = mode_for_int_vector (GET_MODE (cmp1)).require ();
 
       if (inv_p)
 	all_p = !all_p;
@@ -6581,9 +6578,7 @@ s390_expand_vcond (rtx target, rtx then,
 
   /* We always use an integral type vector to hold the comparison
      result.  */
-  result_mode = mode_for_vector
-    (int_mode_for_mode (GET_MODE_INNER (cmp_mode)).require (),
-     GET_MODE_NUNITS (cmp_mode));
+  result_mode = mode_for_int_vector (cmp_mode).require ();
   result_target = gen_reg_rtx (result_mode);
 
   /* We allow vector immediates as comparison operands that

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [6/9] Make mode_for_vector return an opt_mode
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
                   ` (4 preceding siblings ...)
  2017-09-04 11:37 ` [5/9] Add mode_for_int_vector helper functions Richard Sandiford
@ 2017-09-04 11:39 ` Richard Sandiford
  2017-09-05 11:37   ` Richard Biener
  2017-09-04 11:41 ` [7/9] Make targetm.get_mask_mode " Richard Sandiford
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:39 UTC (permalink / raw)
  To: gcc-patches

...following on from the mode_for_size change.  The patch also removes
machmode.h versions of the stor-layout.c comments, since the comments
in the .c file are more complete.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* machmode.h (mode_for_vector): Return an opt_mode.
	* stor-layout.c (mode_for_vector): Likewise.
	(mode_for_int_vector): Update accordingly.
	(layout_type): Likewise.
	* config/i386/i386.c (emit_memmov): Likewise.
	(ix86_expand_set_or_movmem): Likewise.
	(ix86_expand_vector_init): Likewise.
	(ix86_get_mask_mode): Likewise.
	* config/powerpcspe/powerpcspe.c (rs6000_expand_vec_perm_const_1):
	Likewise.
	* config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Likewise.
	* expmed.c (extract_bit_field_1): Likewise.
	* expr.c (expand_expr_real_2): Likewise.
	* optabs-query.c (can_vec_perm_p): Likewise.
	(can_vec_mask_load_store_p): Likewise.
	* optabs.c (expand_vec_perm): Likewise.
	* targhooks.c (default_get_mask_mode): Likewise.
	* tree-vect-stmts.c (vectorizable_store): Likewise.
	(vectorizable_load): Likewise.
	(get_vectype_for_scalar_type_and_size): Likewise.

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-09-04 12:18:53.153306182 +0100
+++ gcc/machmode.h	2017-09-04 12:18:55.821333642 +0100
@@ -682,8 +682,6 @@ decimal_float_mode_for_size (unsigned in
     (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
 }
 
-/* Similar to mode_for_size, but find the smallest mode for a given width.  */
-
 extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);
 
 /* Find the narrowest integer mode that contains at least SIZE bits.
@@ -695,17 +693,9 @@ smallest_int_mode_for_size (unsigned int
   return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
 }
 
-/* Return an integer mode of exactly the same size as the input mode.  */
-
 extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
-
 extern machine_mode bitwise_mode_for_mode (machine_mode);
-
-/* Return a mode that is suitable for representing a vector,
-   or BLKmode on failure.  */
-
-extern machine_mode mode_for_vector (scalar_mode, unsigned);
-
+extern opt_machine_mode mode_for_vector (scalar_mode, unsigned);
 extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
 
 /* Return the integer vector equivalent of MODE, if one exists.  In other
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-09-04 12:18:53.153306182 +0100
+++ gcc/stor-layout.c	2017-09-04 12:18:55.824344959 +0100
@@ -471,11 +471,11 @@ bitwise_type_for_mode (machine_mode mode
   return inner_type;
 }
 
-/* Find a mode that is suitable for representing a vector with
-   NUNITS elements of mode INNERMODE.  Returns BLKmode if there
-   is no suitable mode.  */
+/* Find a mode that is suitable for representing a vector with NUNITS
+   elements of mode INNERMODE, if one exists.  The returned mode can be
+   either an integer mode or a vector mode.  */
 
-machine_mode
+opt_machine_mode
 mode_for_vector (scalar_mode innermode, unsigned nunits)
 {
   machine_mode mode;
@@ -499,22 +499,18 @@ mode_for_vector (scalar_mode innermode,
   FOR_EACH_MODE_FROM (mode, mode)
     if (GET_MODE_NUNITS (mode) == nunits
 	&& GET_MODE_INNER (mode) == innermode)
-      break;
+      return mode;
 
   /* For integers, try mapping it to a same-sized scalar mode.  */
-  if (mode == VOIDmode
-      && GET_MODE_CLASS (innermode) == MODE_INT)
+  if (GET_MODE_CLASS (innermode) == MODE_INT)
     {
       unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);
-      mode = int_mode_for_size (nbits, 0).else_blk ();
+      if (int_mode_for_size (nbits, 0).exists (&mode)
+	  && have_regs_of_mode[mode])
+	return mode;
     }
 
-  if (mode == VOIDmode
-      || (GET_MODE_CLASS (mode) == MODE_INT
-	  && !have_regs_of_mode[mode]))
-    return BLKmode;
-
-  return mode;
+  return opt_machine_mode ();
 }
 
 /* Return the mode for a vector that has NUNITS integer elements of
@@ -525,12 +521,10 @@ mode_for_vector (scalar_mode innermode,
 mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
 {
   scalar_int_mode int_mode;
-  if (int_mode_for_size (int_bits, 0).exists (&int_mode))
-    {
-      machine_mode vec_mode = mode_for_vector (int_mode, nunits);
-      if (vec_mode != BLKmode)
-	return vec_mode;
-    }
+  machine_mode vec_mode;
+  if (int_mode_for_size (int_bits, 0).exists (&int_mode)
+      && mode_for_vector (int_mode, nunits).exists (&vec_mode))
+    return vec_mode;
   return opt_machine_mode ();
 }
 
@@ -2264,7 +2258,7 @@ layout_type (tree type)
 	if (TYPE_MODE (type) == VOIDmode)
 	  SET_TYPE_MODE (type,
 			 mode_for_vector (SCALAR_TYPE_MODE (innertype),
-					  nunits));
+					  nunits).else_blk ());
 
 	TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-09-04 12:18:44.903326171 +0100
+++ gcc/config/i386/i386.c	2017-09-04 12:18:55.808284598 +0100
@@ -27420,9 +27420,8 @@ emit_memmov (rtx destmem, rtx *srcmem, r
   if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
     {
       int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
-      move_mode = mode_for_vector (word_mode, nunits);
-      code = optab_handler (mov_optab, move_mode);
-      if (code == CODE_FOR_nothing)
+      if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
+	  || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
 	{
 	  move_mode = word_mode;
 	  piece_size = GET_MODE_SIZE (move_mode);
@@ -28654,8 +28653,8 @@ ix86_expand_set_or_movmem (rtx dst, rtx
       if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
 	{
 	  int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
-	  move_mode = mode_for_vector (word_mode, nunits);
-	  if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
+	  if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
+	      || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
 	    move_mode = word_mode;
 	}
       gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
@@ -44497,11 +44496,9 @@ ix86_expand_vector_init (bool mmx_ok, rt
 	  rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
 	  if (inner_mode == QImode || inner_mode == HImode)
 	    {
-	      mode = mode_for_vector (SImode,
-				      n_elts * GET_MODE_SIZE (inner_mode) / 4);
-	      inner_mode
-		= mode_for_vector (SImode,
-				   n_elts * GET_MODE_SIZE (inner_mode) / 8);
+	      unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
+	      mode = mode_for_vector (SImode, n_bits / 4).require ();
+	      inner_mode = mode_for_vector (SImode, n_bits / 8).require ();
 	      ops[0] = gen_lowpart (inner_mode, ops[0]);
 	      ops[1] = gen_lowpart (inner_mode, ops[1]);
 	      subtarget = gen_reg_rtx (mode);
@@ -51619,7 +51616,7 @@ ix86_get_mask_mode (unsigned nunits, uns
 
   gcc_assert (elem_size * nunits == vector_size);
 
-  return mode_for_vector (elem_mode, nunits);
+  return mode_for_vector (elem_mode, nunits).else_blk ();
 }
 
 \f
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-09-04 12:18:53.148287319 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-09-04 12:18:55.812299689 +0100
@@ -38679,7 +38679,7 @@ rs6000_expand_vec_perm_const_1 (rtx targ
 
       vmode = GET_MODE (target);
       gcc_assert (GET_MODE_NUNITS (vmode) == 2);
-      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
       x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
       v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
       x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-09-04 12:18:53.151298637 +0100
+++ gcc/config/rs6000/rs6000.c	2017-09-04 12:18:55.815311006 +0100
@@ -35525,7 +35525,7 @@ rs6000_expand_vec_perm_const_1 (rtx targ
 
       vmode = GET_MODE (target);
       gcc_assert (GET_MODE_NUNITS (vmode) == 2);
-      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
       x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
       v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
       x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2017-09-04 12:18:50.673054653 +0100
+++ gcc/expmed.c	2017-09-04 12:18:55.817318551 +0100
@@ -1578,10 +1578,11 @@ extract_bit_field_1 (rtx str_rtx, unsign
       machine_mode new_mode = GET_MODE (op0);
       if (GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode))
 	{
-	  new_mode = mode_for_vector (GET_MODE_INNER (tmode),
-				      GET_MODE_BITSIZE (GET_MODE (op0))
-				      / GET_MODE_UNIT_BITSIZE (tmode));
-	  if (!VECTOR_MODE_P (new_mode)
+	  scalar_mode inner_mode = GET_MODE_INNER (tmode);
+	  unsigned int nunits = (GET_MODE_BITSIZE (GET_MODE (op0))
+				 / GET_MODE_UNIT_BITSIZE (tmode));
+	  if (!mode_for_vector (inner_mode, nunits).exists (&new_mode)
+	      || !VECTOR_MODE_P (new_mode)
 	      || GET_MODE_SIZE (new_mode) != GET_MODE_SIZE (GET_MODE (op0))
 	      || GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode)
 	      || !targetm.vector_mode_supported_p (new_mode))
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-09-04 12:18:44.938520082 +0100
+++ gcc/expr.c	2017-09-04 12:18:55.820329869 +0100
@@ -9445,7 +9445,7 @@ #define REDUCE_BIT_FIELD(expr)	(reduce_b
 	  tree sel_type = TREE_TYPE (treeop2);
 	  machine_mode vmode
 	    = mode_for_vector (SCALAR_TYPE_MODE (TREE_TYPE (sel_type)),
-			       TYPE_VECTOR_SUBPARTS (sel_type));
+			       TYPE_VECTOR_SUBPARTS (sel_type)).require ();
 	  gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
 	  op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
 	  gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);
Index: gcc/optabs-query.c
===================================================================
--- gcc/optabs-query.c	2017-08-30 12:20:31.700622400 +0100
+++ gcc/optabs-query.c	2017-09-04 12:18:55.821333642 +0100
@@ -376,10 +376,9 @@ can_vec_perm_p (machine_mode mode, bool
     return true;
 
   /* We allow fallback to a QI vector mode, and adjust the mask.  */
-  if (GET_MODE_INNER (mode) == QImode)
-    return false;
-  qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
-  if (!VECTOR_MODE_P (qimode))
+  if (GET_MODE_INNER (mode) == QImode
+      || !mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode)
+      || !VECTOR_MODE_P (qimode))
     return false;
 
   /* ??? For completeness, we ought to check the QImode version of
@@ -547,12 +546,14 @@ can_vec_mask_load_store_p (machine_mode
       vector_sizes &= ~cur;
       if (cur <= GET_MODE_SIZE (smode))
 	continue;
-      vmode = mode_for_vector (smode, cur / GET_MODE_SIZE (smode));
-      mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
-						   cur);
-      if (VECTOR_MODE_P (vmode)
-	  && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
-	return true;
+      unsigned int nunits = cur / GET_MODE_SIZE (smode);
+      if (mode_for_vector (smode, nunits).exists (&vmode)
+	  && VECTOR_MODE_P (vmode))
+	{
+	  mask_mode = targetm.vectorize.get_mask_mode (nunits, cur);
+	  if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
+	    return true;
+	}
     }
   return false;
 }
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2017-09-04 11:48:08.609549644 +0100
+++ gcc/optabs.c	2017-09-04 12:18:55.823341187 +0100
@@ -5434,13 +5434,10 @@ expand_vec_perm (machine_mode mode, rtx
 
   /* Set QIMODE to a different vector mode with byte elements.
      If no such mode, or if MODE already has byte elements, use VOIDmode.  */
-  qimode = VOIDmode;
-  if (GET_MODE_INNER (mode) != QImode)
-    {
-      qimode = mode_for_vector (QImode, w);
-      if (!VECTOR_MODE_P (qimode))
-	qimode = VOIDmode;
-    }
+  if (GET_MODE_INNER (mode) == QImode
+      || !mode_for_vector (QImode, w).exists (&qimode)
+      || !VECTOR_MODE_P (qimode))
+    qimode = VOIDmode;
 
   /* If the input is a constant, expand it specially.  */
   gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-09-04 11:50:24.568774867 +0100
+++ gcc/targhooks.c	2017-09-04 12:18:55.825348732 +0100
@@ -1210,8 +1210,8 @@ default_get_mask_mode (unsigned nunits,
 
   gcc_assert (elem_size * nunits == vector_size);
 
-  vector_mode = mode_for_vector (elem_mode, nunits);
-  if (!VECTOR_MODE_P (vector_mode)
+  if (!mode_for_vector (elem_mode, nunits).exists (&vector_mode)
+      || !VECTOR_MODE_P (vector_mode)
       || !targetm.vector_mode_supported_p (vector_mode))
     vector_mode = BLKmode;
 
Index: gcc/tree-vect-stmts.c
===================================================================
--- gcc/tree-vect-stmts.c	2017-08-31 07:32:43.676061469 +0100
+++ gcc/tree-vect-stmts.c	2017-09-04 12:18:55.828360049 +0100
@@ -6032,8 +6032,9 @@ vectorizable_store (gimple *stmt, gimple
 	      /* First check if vec_extract optab doesn't support extraction
 		 of vector elts directly.  */
 	      scalar_mode elmode = SCALAR_TYPE_MODE (elem_type);
-	      machine_mode vmode = mode_for_vector (elmode, group_size);
-	      if (! VECTOR_MODE_P (vmode)
+	      machine_mode vmode;
+	      if (!mode_for_vector (elmode, group_size).exists (&vmode)
+		  || !VECTOR_MODE_P (vmode)
 		  || (convert_optab_handler (vec_extract_optab,
 					     TYPE_MODE (vectype), vmode)
 		      == CODE_FOR_nothing))
@@ -6046,11 +6047,12 @@ vectorizable_store (gimple *stmt, gimple
 		  unsigned lsize
 		    = group_size * GET_MODE_BITSIZE (elmode);
 		  elmode = int_mode_for_size (lsize, 0).require ();
-		  vmode = mode_for_vector (elmode, nunits / group_size);
 		  /* If we can't construct such a vector fall back to
 		     element extracts from the original vector type and
 		     element size stores.  */
-		  if (VECTOR_MODE_P (vmode)
+		  if (mode_for_vector (elmode,
+				       nunits / group_size).exists (&vmode)
+		      && VECTOR_MODE_P (vmode)
 		      && (convert_optab_handler (vec_extract_optab,
 						 vmode, elmode)
 			  != CODE_FOR_nothing))
@@ -7070,8 +7072,9 @@ vectorizable_load (gimple *stmt, gimple_
 	      /* First check if vec_init optab supports construction from
 		 vector elts directly.  */
 	      scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vectype));
-	      machine_mode vmode = mode_for_vector (elmode, group_size);
-	      if (VECTOR_MODE_P (vmode)
+	      machine_mode vmode;
+	      if (mode_for_vector (elmode, group_size).exists (&vmode)
+		  && VECTOR_MODE_P (vmode)
 		  && (convert_optab_handler (vec_init_optab,
 					     TYPE_MODE (vectype), vmode)
 		      != CODE_FOR_nothing))
@@ -7092,10 +7095,11 @@ vectorizable_load (gimple *stmt, gimple_
 		  unsigned lsize
 		    = group_size * TYPE_PRECISION (TREE_TYPE (vectype));
 		  elmode = int_mode_for_size (lsize, 0).require ();
-		  vmode = mode_for_vector (elmode, nunits / group_size);
 		  /* If we can't construct such a vector fall back to
 		     element loads of the original vector type.  */
-		  if (VECTOR_MODE_P (vmode)
+		  if (mode_for_vector (elmode,
+				       nunits / group_size).exists (&vmode)
+		      && VECTOR_MODE_P (vmode)
 		      && (convert_optab_handler (vec_init_optab, vmode, elmode)
 			  != CODE_FOR_nothing))
 		    {
@@ -9098,8 +9102,8 @@ get_vectype_for_scalar_type_and_size (tr
      lookup a vector mode of the specified size.  */
   if (size == 0)
     simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
-  else
-    simd_mode = mode_for_vector (inner_mode, size / nbytes);
+  else if (!mode_for_vector (inner_mode, size / nbytes).exists (&simd_mode))
+    return NULL_TREE;
   nunits = GET_MODE_SIZE (simd_mode) / nbytes;
   /* NOTE: nunits == 1 is allowed to support single element vector types.  */
   if (nunits < 1)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [7/9] Make targetm.get_mask_mode return an opt_mode
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
                   ` (5 preceding siblings ...)
  2017-09-04 11:39 ` [6/9] Make mode_for_vector return an opt_mode Richard Sandiford
@ 2017-09-04 11:41 ` Richard Sandiford
  2017-09-05 11:37   ` Richard Biener
  2017-09-04 11:42 ` [8/9] Make mode_for_size_tree " Richard Sandiford
  2017-09-04 11:43 ` [9/9] Make bitsize_mode_for_mode " Richard Sandiford
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:41 UTC (permalink / raw)
  To: gcc-patches

...for consistency with mode_for_vector.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* target.def (get_mask_mode): Change return type to opt_mode.
	Expand commentary.
	* doc/tm.texi: Regenerate.
	* targhooks.h (default_get_mask_mode): Return an opt_mode.
	* targhooks.c (default_get_mask_mode): Likewise.
	* config/i386/i386.c (ix86_get_mask_mode): Likewise.
	* optabs-query.c (can_vec_mask_load_store_p): Update use of
	targetm.get_mask_mode.
	* tree.c (build_truth_vector_type): Likewise.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-09-04 11:50:24.568774867 +0100
+++ gcc/target.def	2017-09-04 12:18:58.594757220 +0100
@@ -1877,10 +1877,16 @@ The default is zero which means to not i
 /* Function to get a target mode for a vector mask.  */
 DEFHOOK
 (get_mask_mode,
- "This hook returns mode to be used for a mask to be used for a vector\n\
-of specified @var{length} with @var{nunits} elements.  By default an integer\n\
-vector mode of a proper size is returned.",
- machine_mode,
+ "A vector mask is a value that holds one boolean result for every element\n\
+in a vector.  This hook returns the machine mode that should be used to\n\
+represent such a mask when the vector in question is @var{length} bytes\n\
+long and contains @var{nunits} elements.  The hook returns an empty\n\
+@code{opt_machine_mode} if no such mode exists.\n\
+\n\
+The default implementation returns the mode of an integer vector that\n\
+is @var{length} bytes long and that contains @var{nunits} elements,\n\
+if such a mode exists.",
+ opt_machine_mode,
  (unsigned nunits, unsigned length),
  default_get_mask_mode)
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-09-04 11:50:24.566073698 +0100
+++ gcc/doc/tm.texi	2017-09-04 12:18:58.593753447 +0100
@@ -5820,10 +5820,16 @@ mode returned by @code{TARGET_VECTORIZE_
 The default is zero which means to not iterate over other vector sizes.
 @end deftypefn
 
-@deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_GET_MASK_MODE (unsigned @var{nunits}, unsigned @var{length})
-This hook returns mode to be used for a mask to be used for a vector
-of specified @var{length} with @var{nunits} elements.  By default an integer
-vector mode of a proper size is returned.
+@deftypefn {Target Hook} opt_machine_mode TARGET_VECTORIZE_GET_MASK_MODE (unsigned @var{nunits}, unsigned @var{length})
+A vector mask is a value that holds one boolean result for every element
+in a vector.  This hook returns the machine mode that should be used to
+represent such a mask when the vector in question is @var{length} bytes
+long and contains @var{nunits} elements.  The hook returns an empty
+@code{opt_machine_mode} if no such mode exists.
+
+The default implementation returns the mode of an integer vector that
+is @var{length} bytes long and that contains @var{nunits} elements,
+if such a mode exists.
 @end deftypefn
 
 @deftypefn {Target Hook} {void *} TARGET_VECTORIZE_INIT_COST (struct loop *@var{loop_info})
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2017-09-04 11:50:24.568774867 +0100
+++ gcc/targhooks.h	2017-09-04 12:18:58.594757220 +0100
@@ -102,7 +102,7 @@ default_builtin_support_vector_misalignm
 					     int, bool);
 extern machine_mode default_preferred_simd_mode (scalar_mode mode);
 extern unsigned int default_autovectorize_vector_sizes (void);
-extern machine_mode default_get_mask_mode (unsigned, unsigned);
+extern opt_machine_mode default_get_mask_mode (unsigned, unsigned);
 extern void *default_init_cost (struct loop *);
 extern unsigned default_add_stmt_cost (void *, int, enum vect_cost_for_stmt,
 				       struct _stmt_vec_info *, int,
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-09-04 12:18:55.825348732 +0100
+++ gcc/targhooks.c	2017-09-04 12:18:58.594757220 +0100
@@ -1200,7 +1200,7 @@ default_autovectorize_vector_sizes (void
 
 /* By defaults a vector of integers is used as a mask.  */
 
-machine_mode
+opt_machine_mode
 default_get_mask_mode (unsigned nunits, unsigned vector_size)
 {
   unsigned elem_size = vector_size / nunits;
@@ -1210,12 +1210,12 @@ default_get_mask_mode (unsigned nunits,
 
   gcc_assert (elem_size * nunits == vector_size);
 
-  if (!mode_for_vector (elem_mode, nunits).exists (&vector_mode)
-      || !VECTOR_MODE_P (vector_mode)
-      || !targetm.vector_mode_supported_p (vector_mode))
-    vector_mode = BLKmode;
+  if (mode_for_vector (elem_mode, nunits).exists (&vector_mode)
+      && VECTOR_MODE_P (vector_mode)
+      && targetm.vector_mode_supported_p (vector_mode))
+    return vector_mode;
 
-  return vector_mode;
+  return opt_machine_mode ();
 }
 
 /* By default, the cost model accumulates three separate costs (prologue,
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-09-04 12:18:55.808284598 +0100
+++ gcc/config/i386/i386.c	2017-09-04 12:18:58.592749675 +0100
@@ -51598,7 +51598,7 @@ ix86_autovectorize_vector_sizes (void)
 
 /* Implemenation of targetm.vectorize.get_mask_mode.  */
 
-static machine_mode
+static opt_machine_mode
 ix86_get_mask_mode (unsigned nunits, unsigned vector_size)
 {
   unsigned elem_size = vector_size / nunits;
@@ -51616,7 +51616,7 @@ ix86_get_mask_mode (unsigned nunits, uns
 
   gcc_assert (elem_size * nunits == vector_size);
 
-  return mode_for_vector (elem_mode, nunits).else_blk ();
+  return mode_for_vector (elem_mode, nunits);
 }
 
 \f
Index: gcc/optabs-query.c
===================================================================
--- gcc/optabs-query.c	2017-09-04 12:18:55.821333642 +0100
+++ gcc/optabs-query.c	2017-09-04 12:18:58.593753447 +0100
@@ -531,12 +531,9 @@ can_vec_mask_load_store_p (machine_mode
   if (!VECTOR_MODE_P (vmode))
     return false;
 
-  mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
-					       GET_MODE_SIZE (vmode));
-  if (mask_mode == VOIDmode)
-    return false;
-
-  if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
+  if ((targetm.vectorize.get_mask_mode
+       (GET_MODE_NUNITS (vmode), GET_MODE_SIZE (vmode)).exists (&mask_mode))
+      && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
     return true;
 
   vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
@@ -548,12 +545,10 @@ can_vec_mask_load_store_p (machine_mode
 	continue;
       unsigned int nunits = cur / GET_MODE_SIZE (smode);
       if (mode_for_vector (smode, nunits).exists (&vmode)
-	  && VECTOR_MODE_P (vmode))
-	{
-	  mask_mode = targetm.vectorize.get_mask_mode (nunits, cur);
-	  if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
-	    return true;
-	}
+	  && VECTOR_MODE_P (vmode)
+	  && targetm.vectorize.get_mask_mode (nunits, cur).exists (&mask_mode)
+	  && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
+	return true;
     }
   return false;
 }
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	2017-08-30 12:19:19.721220029 +0100
+++ gcc/tree.c	2017-09-04 12:18:58.595760992 +0100
@@ -10243,10 +10243,8 @@ build_vector_type (tree innertype, int n
 tree
 build_truth_vector_type (unsigned nunits, unsigned vector_size)
 {
-  machine_mode mask_mode = targetm.vectorize.get_mask_mode (nunits,
-							    vector_size);
-
-  gcc_assert (mask_mode != VOIDmode);
+  machine_mode mask_mode
+    = targetm.vectorize.get_mask_mode (nunits, vector_size).else_blk ();
 
   unsigned HOST_WIDE_INT vsize;
   if (mask_mode == BLKmode)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [8/9] Make mode_for_size_tree return an opt_mode
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
                   ` (6 preceding siblings ...)
  2017-09-04 11:41 ` [7/9] Make targetm.get_mask_mode " Richard Sandiford
@ 2017-09-04 11:42 ` Richard Sandiford
  2017-09-05 11:38   ` Richard Biener
  2017-09-04 11:43 ` [9/9] Make bitsize_mode_for_mode " Richard Sandiford
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:42 UTC (permalink / raw)
  To: gcc-patches

...for consistency with mode_for_size

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* stor-layout.h (mode_for_size_tree): Return an opt_mode.
	* stor-layout.c (mode_for_size_tree): Likewise.
	(mode_for_array): Update accordingly.
	(layout_decl): Likewise.
	(compute_record_mode): Likewise.  Only set the mode once.

gcc/ada/
	* gcc-interface/utils.c (make_packable_type): Update call to
	mode_for_size_tree.

Index: gcc/stor-layout.h
===================================================================
--- gcc/stor-layout.h	2017-08-21 12:14:47.158835574 +0100
+++ gcc/stor-layout.h	2017-09-04 12:19:01.144339518 +0100
@@ -99,7 +99,7 @@ extern tree make_unsigned_type (int);
    If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
    The value is BLKmode if no other mode is found.  This is like
    mode_for_size, but is passed a tree.  */
-extern machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
+extern opt_machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
 
 extern tree bitwise_type_for_mode (machine_mode);
 
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-09-04 12:18:55.824344959 +0100
+++ gcc/stor-layout.c	2017-09-04 12:19:01.144339518 +0100
@@ -321,19 +321,19 @@ mode_for_size (unsigned int size, enum m
 
 /* Similar, except passed a tree node.  */
 
-machine_mode
+opt_machine_mode
 mode_for_size_tree (const_tree size, enum mode_class mclass, int limit)
 {
   unsigned HOST_WIDE_INT uhwi;
   unsigned int ui;
 
   if (!tree_fits_uhwi_p (size))
-    return BLKmode;
+    return opt_machine_mode ();
   uhwi = tree_to_uhwi (size);
   ui = uhwi;
   if (uhwi != ui)
-    return BLKmode;
-  return mode_for_size (ui, mclass, limit).else_blk ();
+    return opt_machine_mode ();
+  return mode_for_size (ui, mclass, limit);
 }
 
 /* Return the narrowest mode of class MCLASS that contains at least
@@ -563,7 +563,7 @@ mode_for_array (tree elem_type, tree siz
 					     int_size / int_elem_size))
 	limit_p = false;
     }
-  return mode_for_size_tree (size, MODE_INT, limit_p);
+  return mode_for_size_tree (size, MODE_INT, limit_p).else_blk ();
 }
 \f
 /* Subroutine of layout_decl: Force alignment required for the data type.
@@ -683,17 +683,18 @@ layout_decl (tree decl, unsigned int kno
 	      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 	      && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
 	    {
-	      machine_mode xmode
-		= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
-	      unsigned int xalign = GET_MODE_ALIGNMENT (xmode);
-
-	      if (xmode != BLKmode
-		  && !(xalign > BITS_PER_UNIT && DECL_PACKED (decl))
-		  && (known_align == 0 || known_align >= xalign))
+	      machine_mode xmode;
+	      if (mode_for_size_tree (DECL_SIZE (decl),
+				      MODE_INT, 1).exists (&xmode))
 		{
-		  SET_DECL_ALIGN (decl, MAX (xalign, DECL_ALIGN (decl)));
-		  SET_DECL_MODE (decl, xmode);
-		  DECL_BIT_FIELD (decl) = 0;
+		  unsigned int xalign = GET_MODE_ALIGNMENT (xmode);
+		  if (!(xalign > BITS_PER_UNIT && DECL_PACKED (decl))
+		      && (known_align == 0 || known_align >= xalign))
+		    {
+		      SET_DECL_ALIGN (decl, MAX (xalign, DECL_ALIGN (decl)));
+		      SET_DECL_MODE (decl, xmode);
+		      DECL_BIT_FIELD (decl) = 0;
+		    }
 		}
 	    }
 
@@ -1756,22 +1757,24 @@ compute_record_mode (tree type)
   if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode
       && tree_fits_uhwi_p (TYPE_SIZE (type))
       && GET_MODE_BITSIZE (mode) == tree_to_uhwi (TYPE_SIZE (type)))
-    SET_TYPE_MODE (type, mode);
+    ;
   else
-    SET_TYPE_MODE (type, mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1));
+    mode = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1).else_blk ();
 
   /* If structure's known alignment is less than what the scalar
      mode would need, and it matters, then stick with BLKmode.  */
-  if (TYPE_MODE (type) != BLKmode
+  if (mode != BLKmode
       && STRICT_ALIGNMENT
       && ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
-	    || TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
+	    || TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (mode)))
     {
       /* If this is the only reason this type is BLKmode, then
 	 don't force containing types to be BLKmode.  */
       TYPE_NO_FORCE_BLK (type) = 1;
-      SET_TYPE_MODE (type, BLKmode);
+      mode = BLKmode;
     }
+
+  SET_TYPE_MODE (type, mode);
 }
 
 /* Compute TYPE_SIZE and TYPE_ALIGN for TYPE, once it has been laid
Index: gcc/ada/gcc-interface/utils.c
===================================================================
--- gcc/ada/gcc-interface/utils.c	2017-08-30 12:10:52.658405667 +0100
+++ gcc/ada/gcc-interface/utils.c	2017-09-04 12:19:01.143335745 +0100
@@ -1076,7 +1076,8 @@ make_packable_type (tree type, bool in_r
      in case the record itself contains a BLKmode field.  */
   if (in_record && TYPE_MODE (new_type) == BLKmode)
     SET_TYPE_MODE (new_type,
-		   mode_for_size_tree (TYPE_SIZE (new_type), MODE_INT, 1));
+		   mode_for_size_tree (TYPE_SIZE (new_type),
+				       MODE_INT, 1).else_blk ());
 
   /* If neither mode nor size nor alignment shrunk, return the old type.  */
   if (TYPE_MODE (new_type) == BLKmode && new_size >= size && max_align == 0)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [9/9] Make bitsize_mode_for_mode return an opt_mode
  2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
                   ` (7 preceding siblings ...)
  2017-09-04 11:42 ` [8/9] Make mode_for_size_tree " Richard Sandiford
@ 2017-09-04 11:43 ` Richard Sandiford
  2017-09-05 11:39   ` Richard Biener
  8 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-04 11:43 UTC (permalink / raw)
  To: gcc-patches

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* machmode.h (bitwise_mode_for_mode): Return opt_mode.
	* stor-layout.c (bitwise_mode_for_mode): Likewise.
	(bitwise_type_for_mode): Update accordingly.

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-09-04 12:18:55.821333642 +0100
+++ gcc/machmode.h	2017-09-04 12:19:42.856108173 +0100
@@ -694,7 +694,7 @@ smallest_int_mode_for_size (unsigned int
 }
 
 extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
-extern machine_mode bitwise_mode_for_mode (machine_mode);
+extern opt_machine_mode bitwise_mode_for_mode (machine_mode);
 extern opt_machine_mode mode_for_vector (scalar_mode, unsigned);
 extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
 
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-09-04 12:19:01.144339518 +0100
+++ gcc/stor-layout.c	2017-09-04 12:19:42.856108173 +0100
@@ -404,10 +404,10 @@ int_mode_for_mode (machine_mode mode)
     }
 }
 
-/* Find a mode that can be used for efficient bitwise operations on MODE.
-   Return BLKmode if no such mode exists.  */
+/* Find a mode that can be used for efficient bitwise operations on MODE,
+   if one exists.  */
 
-machine_mode
+opt_machine_mode
 bitwise_mode_for_mode (machine_mode mode)
 {
   /* Quick exit if we already have a suitable mode.  */
@@ -445,7 +445,7 @@ bitwise_mode_for_mode (machine_mode mode
     }
 
   /* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE.  */
-  return mode_for_size (bitsize, MODE_INT, true).else_blk ();
+  return mode_for_size (bitsize, MODE_INT, true);
 }
 
 /* Find a type that can be used for efficient bitwise operations on MODE.
@@ -454,8 +454,7 @@ bitwise_mode_for_mode (machine_mode mode
 tree
 bitwise_type_for_mode (machine_mode mode)
 {
-  mode = bitwise_mode_for_mode (mode);
-  if (mode == BLKmode)
+  if (!bitwise_mode_for_mode (mode).exists (&mode))
     return NULL_TREE;
 
   unsigned int inner_size = GET_MODE_UNIT_BITSIZE (mode);

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [1/9] Make more use of int_mode_for_mode
  2017-09-04 11:26 ` [1/9] Make more use of int_mode_for_mode Richard Sandiford
@ 2017-09-05 11:22   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:22 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:26 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch converts more places that could use int_mode_for_mode
> instead of mode_for_size.  This is in preparation for an upcoming
> patch that makes mode_for_size itself return an opt_mode.
>
> The reason for using required () in exp2_immediate_p is that
> we go on to do:
>
>     trunc_int_for_mode (..., int_mode)
>
> which would be invalid for (and have failed for) BLKmode.
>
> The reason for using required () in spu_convert_move and
> resolve_simple_move is that we go on to use registers of
> the returned mode in non-call rtl instructions, which would
> be invalid for BLKmode.

Ok.

Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * config/spu/spu.c (exp2_immediate_p): Use int_mode_for_mode.
>         (spu_convert_move): Likewise.
>         * lower-subreg.c (resolve_simple_move): Likewise.
>
> Index: gcc/config/spu/spu.c
> ===================================================================
> --- gcc/config/spu/spu.c        2017-09-04 11:50:24.563372530 +0100
> +++ gcc/config/spu/spu.c        2017-09-04 12:18:41.572976650 +0100
> @@ -3372,7 +3372,7 @@ arith_immediate_p (rtx op, machine_mode
>    constant_to_array (mode, op, arr);
>
>    bytes = GET_MODE_UNIT_SIZE (mode);
> -  mode = mode_for_size (GET_MODE_UNIT_BITSIZE (mode), MODE_INT, 0);
> +  mode = int_mode_for_mode (GET_MODE_INNER (mode)).require ();
>
>    /* Check that bytes are repeated. */
>    for (i = bytes; i < 16; i += bytes)
> @@ -3415,7 +3415,7 @@ exp2_immediate_p (rtx op, machine_mode m
>    mode = GET_MODE_INNER (mode);
>
>    bytes = GET_MODE_SIZE (mode);
> -  int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
> +  int_mode = int_mode_for_mode (mode).require ();
>
>    /* Check that bytes are repeated. */
>    for (i = bytes; i < 16; i += bytes)
> @@ -4503,7 +4503,7 @@ spu_expand_mov (rtx * ops, machine_mode
>  spu_convert_move (rtx dst, rtx src)
>  {
>    machine_mode mode = GET_MODE (dst);
> -  machine_mode int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
> +  machine_mode int_mode = int_mode_for_mode (mode).require ();
>    rtx reg;
>    gcc_assert (GET_MODE (src) == TImode);
>    reg = int_mode != mode ? gen_reg_rtx (int_mode) : dst;
> Index: gcc/lower-subreg.c
> ===================================================================
> --- gcc/lower-subreg.c  2017-09-04 11:50:08.544543511 +0100
> +++ gcc/lower-subreg.c  2017-09-04 12:18:41.572976650 +0100
> @@ -956,11 +956,7 @@ resolve_simple_move (rtx set, rtx_insn *
>        if (real_dest == NULL_RTX)
>         real_dest = dest;
>        if (!SCALAR_INT_MODE_P (dest_mode))
> -       {
> -         dest_mode = mode_for_size (GET_MODE_SIZE (dest_mode) * BITS_PER_UNIT,
> -                                    MODE_INT, 0);
> -         gcc_assert (dest_mode != BLKmode);
> -       }
> +       dest_mode = int_mode_for_mode (dest_mode).require ();
>        dest = gen_reg_rtx (dest_mode);
>        if (REG_P (real_dest))
>         REG_ATTRS (dest) = REG_ATTRS (real_dest);

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [2/9] Make more use of int_mode_for_size
  2017-09-04 11:31 ` [2/9] Make more use of int_mode_for_size Richard Sandiford
@ 2017-09-05 11:23   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:23 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:31 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch converts more places that could use int_mode_for_size instead
> of mode_for_size.  This is in preparation for an upcoming patch that
> makes mode_for_size itself return an opt_mode.
>
> require () seems like the right choice in expand_builtin_powi
> because we have got past the point of backing out.  We go on to do:
>
>   op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
>   if (GET_MODE (op1) != mode2)
>     op1 = convert_to_mode (mode2, op1, 0);
>
> which would be invalid for (and have failed for) BLKmode.
>
> In get_builtin_sync_mode and expand_ifn_atomic_compare_exchange,
> the possible bitsizes are {8, 16, 32, 64, 128}, all of which give
> target-independent integer modes (up to TImode).  The comment above
> the call in get_builtin_sync_mode makes clear that an integer mode
> must be found.
>
> We can use require () in expand_builtin_atomic_clear and
> expand_builtin_atomic_test_and_set because there's always an integer
> mode for the boolean type.  The same goes for the POINTER_SIZE request
> in layout_type.  Similarly we can use require () in combine_instructions
> and gen_lowpart_common because there's always an integer mode for
> HOST_BITS_PER_WIDE_INT (DImode when BITS_PER_UNIT == 8), and
> HOST_BITS_PER_DOUBLE_INT (TImode).
>
> The calls in aarch64_function_value, arm_function_value,
> aapcs_allocate_return_reg and mips_function_value_1 are handling
> cases in which a big-endian target passes or returns values at
> the most significant end of a register.  In each case the ABI
> constrains the size to a small amount and does not handle
> non-power-of-2 sizes wider than a word.
>
> The calls in c6x_expand_movmem, i386.c:emit_memset,
> lm32_block_move_inline, microblaze_block_move_straight and
> mips_block_move_straight are dealing with expansions of
> block memory operations using register-wise operations,
> and those registers must have non-BLK mode.
>
> The reason for using require () in ix86_expand_sse_cmp,
> mips_expand_ins_as_unaligned_store, spu.c:adjust_operand and
> spu_emit_branch_and_set is that we go on to emit non-call
> instructions that use registers of that mode, which wouldn't
> be valid for BLKmode.

Ok.

Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * builtins.c (expand_builtin_powi): Use int_mode_for_size.
>         (get_builtin_sync_mode): Likewise.
>         (expand_ifn_atomic_compare_exchange): Likewise.
>         (expand_builtin_atomic_clear): Likewise.
>         (expand_builtin_atomic_test_and_set): Likewise.
>         (fold_builtin_atomic_always_lock_free): Likewise.
>         * calls.c (compute_argument_addresses): Likewise.
>         (emit_library_call_value_1): Likewise.
>         (store_one_arg): Likewise.
>         * combine.c (combine_instructions): Likewise.
>         * config/aarch64/aarch64.c (aarch64_function_value): Likewise.
>         * config/arm/arm.c (arm_function_value): Likewise.
>         (aapcs_allocate_return_reg): Likewise.
>         * config/c6x/c6x.c (c6x_expand_movmem): Likewise.
>         * config/i386/i386.c (construct_container): Likewise.
>         (ix86_gimplify_va_arg): Likewise.
>         (ix86_expand_sse_cmp): Likewise.
>         (emit_memmov): Likewise.
>         (emit_memset): Likewise.
>         (expand_small_movmem_or_setmem): Likewise.
>         (ix86_expand_pextr): Likewise.
>         (ix86_expand_pinsr): Likewise.
>         * config/lm32/lm32.c (lm32_block_move_inline): Likewise.
>         * config/microblaze/microblaze.c (microblaze_block_move_straight):
>         Likewise.
>         * config/mips/mips.c (mips_function_value_1) Likewise.
>         (mips_block_move_straight): Likewise.
>         (mips_expand_ins_as_unaligned_store): Likewise.
>         * config/powerpcspe/powerpcspe.c
>         (rs6000_darwin64_record_arg_advance_flush): Likewise.
>         (rs6000_darwin64_record_arg_flush): Likewise.
>         * config/rs6000/rs6000.c
>         (rs6000_darwin64_record_arg_advance_flush): Likewise.
>         (rs6000_darwin64_record_arg_flush): Likewise.
>         * config/sparc/sparc.c (sparc_function_arg_1): Likewise.
>         (sparc_function_value_1): Likewise.
>         * config/spu/spu.c (adjust_operand): Likewise.
>         (spu_emit_branch_or_set): Likewise.
>         (arith_immediate_p): Likewise.
>         * emit-rtl.c (gen_lowpart_common): Likewise.
>         * expr.c (expand_expr_real_1): Likewise.
>         * function.c (assign_parm_setup_block): Likewise.
>         * gimple-ssa-store-merging.c (encode_tree_to_bitpos): Likewise.
>         * reload1.c (alter_reg): Likewise.
>         * stor-layout.c (mode_for_vector): Likewise.
>         (layout_type): Likewise.
>
> gcc/ada/
>         * gcc-interface/utils2.c (build_load_modify_store):
>         Use int_mode_for_size.
>
> Index: gcc/builtins.c
> ===================================================================
> --- gcc/builtins.c      2017-09-04 08:30:09.328308115 +0100
> +++ gcc/builtins.c      2017-09-04 12:18:44.865115639 +0100
> @@ -2755,7 +2755,7 @@ expand_builtin_powi (tree exp, rtx targe
>    /* Emit a libcall to libgcc.  */
>
>    /* Mode of the 2nd argument must match that of an int.  */
> -  mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
> +  mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
>
>    if (target == NULL_RTX)
>      target = gen_reg_rtx (mode);
> @@ -5477,7 +5477,7 @@ get_builtin_sync_mode (int fcode_diff)
>  {
>    /* The size is not negotiable, so ask not to get BLKmode in return
>       if the target indicates that a smaller size would be better.  */
> -  return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
> +  return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
>  }
>
>  /* Expand the memory expression LOC and return the appropriate memory operand
> @@ -5858,7 +5858,7 @@ expand_ifn_atomic_compare_exchange (gcal
>  {
>    int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
>    gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
> -  machine_mode mode = mode_for_size (BITS_PER_UNIT * size, MODE_INT, 0);
> +  machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
>    rtx expect, desired, mem, oldval, boolret;
>    enum memmodel success, failure;
>    tree lhs;
> @@ -6154,7 +6154,7 @@ expand_builtin_atomic_clear (tree exp)
>    rtx mem, ret;
>    enum memmodel model;
>
> -  mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
> +  mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
>    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
>    model = get_memmodel (CALL_EXPR_ARG (exp, 1));
>
> @@ -6189,7 +6189,7 @@ expand_builtin_atomic_test_and_set (tree
>    enum memmodel model;
>    machine_mode mode;
>
> -  mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
> +  mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
>    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
>    model = get_memmodel (CALL_EXPR_ARG (exp, 1));
>
> @@ -6210,8 +6210,11 @@ fold_builtin_atomic_always_lock_free (tr
>    if (TREE_CODE (arg0) != INTEGER_CST)
>      return NULL_TREE;
>
> +  /* We need a corresponding integer mode for the access to be lock-free.  */
>    size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
> -  mode = mode_for_size (size, MODE_INT, 0);
> +  if (!int_mode_for_size (size, 0).exists (&mode))
> +    return boolean_false_node;
> +
>    mode_align = GET_MODE_ALIGNMENT (mode);
>
>    if (TREE_CODE (arg1) == INTEGER_CST)
> Index: gcc/calls.c
> ===================================================================
> --- gcc/calls.c 2017-09-04 11:50:24.542663572 +0100
> +++ gcc/calls.c 2017-09-04 12:18:44.866121179 +0100
> @@ -2209,8 +2209,8 @@ compute_argument_addresses (struct arg_d
>               /* Only part of the parameter is being passed on the stack.
>                  Generate a simple memory reference of the correct size.  */
>               units_on_stack = args[i].locate.size.constant;
> -             partial_mode = mode_for_size (units_on_stack * BITS_PER_UNIT,
> -                                           MODE_INT, 1);
> +             unsigned int bits_on_stack = units_on_stack * BITS_PER_UNIT;
> +             partial_mode = int_mode_for_size (bits_on_stack, 1).else_blk ();
>               args[i].stack = gen_rtx_MEM (partial_mode, addr);
>               set_mem_size (args[i].stack, units_on_stack);
>             }
> @@ -4818,7 +4818,7 @@ emit_library_call_value_1 (int retval, r
>                   unsigned int size
>                     = argvec[argnum].locate.size.constant * BITS_PER_UNIT;
>                   machine_mode save_mode
> -                   = mode_for_size (size, MODE_INT, 1);
> +                   = int_mode_for_size (size, 1).else_blk ();
>                   rtx adr
>                     = plus_constant (Pmode, argblock,
>                                      argvec[argnum].locate.offset.constant);
> @@ -5271,7 +5271,8 @@ store_one_arg (struct arg_data *arg, rtx
>             {
>               /* We need to make a save area.  */
>               unsigned int size = arg->locate.size.constant * BITS_PER_UNIT;
> -             machine_mode save_mode = mode_for_size (size, MODE_INT, 1);
> +             machine_mode save_mode
> +               = int_mode_for_size (size, 1).else_blk ();
>               rtx adr = memory_address (save_mode, XEXP (arg->stack_slot, 0));
>               rtx stack_area = gen_rtx_MEM (save_mode, adr);
>
> Index: gcc/combine.c
> ===================================================================
> --- gcc/combine.c       2017-09-04 11:50:08.502225206 +0100
> +++ gcc/combine.c       2017-09-04 12:18:44.871148881 +0100
> @@ -370,7 +370,7 @@ alloc_insn_link (rtx_insn *insn, unsigne
>  /* Mode used to compute significance in reg_stat[].nonzero_bits.  It is the
>     largest integer mode that can fit in HOST_BITS_PER_WIDE_INT.  */
>
> -static machine_mode nonzero_bits_mode;
> +static scalar_int_mode nonzero_bits_mode;
>
>  /* Nonzero when reg_stat[].nonzero_bits and reg_stat[].sign_bit_copies can
>     be safely used.  It is zero while computing them and after combine has
> @@ -1157,7 +1157,7 @@ combine_instructions (rtx_insn *f, unsig
>    uid_insn_cost = XCNEWVEC (int, max_uid_known + 1);
>    gcc_obstack_init (&insn_link_obstack);
>
> -  nonzero_bits_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
> +  nonzero_bits_mode = int_mode_for_size (HOST_BITS_PER_WIDE_INT, 0).require ();
>
>    /* Don't use reg_stat[].nonzero_bits when computing it.  This can cause
>       problems when, for example, we have j <<= 1 in a loop.  */
> Index: gcc/config/aarch64/aarch64.c
> ===================================================================
> --- gcc/config/aarch64/aarch64.c        2017-09-04 11:50:24.544464351 +0100
> +++ gcc/config/aarch64/aarch64.c        2017-09-04 12:18:44.874165502 +0100
> @@ -2235,7 +2235,7 @@ aarch64_function_value (const_tree type,
>        if (size % UNITS_PER_WORD != 0)
>         {
>           size += UNITS_PER_WORD - size % UNITS_PER_WORD;
> -         mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
> +         mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
>         }
>      }
>
> Index: gcc/config/arm/arm.c
> ===================================================================
> --- gcc/config/arm/arm.c        2017-09-04 11:50:24.546265130 +0100
> +++ gcc/config/arm/arm.c        2017-09-04 12:18:44.886231985 +0100
> @@ -5358,7 +5358,7 @@ arm_function_value(const_tree type, cons
>        if (size % UNITS_PER_WORD != 0)
>         {
>           size += UNITS_PER_WORD - size % UNITS_PER_WORD;
> -         mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
> +         mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
>         }
>      }
>
> @@ -6315,7 +6315,7 @@ aapcs_allocate_return_reg (machine_mode
>        if (size % UNITS_PER_WORD != 0)
>         {
>           size += UNITS_PER_WORD - size % UNITS_PER_WORD;
> -         mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
> +         mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
>         }
>      }
>
> Index: gcc/config/c6x/c6x.c
> ===================================================================
> --- gcc/config/c6x/c6x.c        2017-09-04 11:50:08.509428322 +0100
> +++ gcc/config/c6x/c6x.c        2017-09-04 12:18:44.887237526 +0100
> @@ -1758,8 +1758,8 @@ c6x_expand_movmem (rtx dst, rtx src, rtx
>        if (dst_size > src_size)
>         dst_size = src_size;
>
> -      srcmode = mode_for_size (src_size * BITS_PER_UNIT, MODE_INT, 0);
> -      dstmode = mode_for_size (dst_size * BITS_PER_UNIT, MODE_INT, 0);
> +      srcmode = int_mode_for_size (src_size * BITS_PER_UNIT, 0).require ();
> +      dstmode = int_mode_for_size (dst_size * BITS_PER_UNIT, 0).require ();
>        if (src_size >= 4)
>         reg_lowpart = reg = gen_reg_rtx (srcmode);
>        else
> Index: gcc/config/i386/i386.c
> ===================================================================
> --- gcc/config/i386/i386.c      2017-09-04 11:50:08.515731048 +0100
> +++ gcc/config/i386/i386.c      2017-09-04 12:18:44.903326171 +0100
> @@ -9892,16 +9892,17 @@ construct_container (machine_mode mode,
>           case X86_64_INTEGERSI_CLASS:
>             /* Merge TImodes on aligned occasions here too.  */
>             if (i * 8 + 8 > bytes)
> -             tmpmode
> -               = mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
> +             {
> +               unsigned int tmpbits = (bytes - i * 8) * BITS_PER_UNIT;
> +               if (!int_mode_for_size (tmpbits, 0).exists (&tmpmode))
> +                 /* We've requested 24 bytes we
> +                    don't have mode for.  Use DImode.  */
> +                 tmpmode = DImode;
> +             }
>             else if (regclass[i] == X86_64_INTEGERSI_CLASS)
>               tmpmode = SImode;
>             else
>               tmpmode = DImode;
> -           /* We've requested 24 bytes we
> -              don't have mode for.  Use DImode.  */
> -           if (tmpmode == BLKmode)
> -             tmpmode = DImode;
>             exp [nexps++]
>               = gen_rtx_EXPR_LIST (VOIDmode,
>                                    gen_rtx_REG (tmpmode, *intreg),
> @@ -11880,8 +11881,8 @@ ix86_gimplify_va_arg (tree valist, tree
>               if (prev_size + cur_size > size)
>                 {
>                   cur_size = size - prev_size;
> -                 mode = mode_for_size (cur_size * BITS_PER_UNIT, MODE_INT, 1);
> -                 if (mode == BLKmode)
> +                 unsigned int nbits = cur_size * BITS_PER_UNIT;
> +                 if (!int_mode_for_size (nbits, 1).exists (&mode))
>                     mode = QImode;
>                 }
>               piece_type = lang_hooks.types.type_for_mode (mode, 1);
> @@ -24807,9 +24808,8 @@ ix86_expand_sse_cmp (rtx dest, enum rtx_
>
>    if (GET_MODE_SIZE (cmp_ops_mode) == 64)
>      {
> -      cmp_mode = mode_for_size (GET_MODE_NUNITS (cmp_ops_mode), MODE_INT, 0);
> -      gcc_assert (cmp_mode != BLKmode);
> -
> +      unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode);
> +      cmp_mode = int_mode_for_size (nbits, 0).require ();
>        maskcmp = true;
>      }
>    else
> @@ -27408,13 +27408,11 @@ emit_memmov (rtx destmem, rtx *srcmem, r
>       Start with the biggest power of 2 less than SIZE_TO_MOVE and half
>       it until move of such size is supported.  */
>    piece_size = 1 << floor_log2 (size_to_move);
> -  move_mode = mode_for_size (piece_size * BITS_PER_UNIT, MODE_INT, 0);
> -  code = optab_handler (mov_optab, move_mode);
> -  while (code == CODE_FOR_nothing && piece_size > 1)
> +  while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
> +        || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
>      {
> +      gcc_assert (piece_size > 1);
>        piece_size >>= 1;
> -      move_mode = mode_for_size (piece_size * BITS_PER_UNIT, MODE_INT, 0);
> -      code = optab_handler (mov_optab, move_mode);
>      }
>
>    /* Find the corresponding vector mode with the same size as MOVE_MODE.
> @@ -27597,7 +27595,8 @@ emit_memset (rtx destmem, rtx destptr, r
>      move_mode = QImode;
>    if (size_to_move < GET_MODE_SIZE (move_mode))
>      {
> -      move_mode = mode_for_size (size_to_move * BITS_PER_UNIT, MODE_INT, 0);
> +      unsigned int move_bits = size_to_move * BITS_PER_UNIT;
> +      move_mode = int_mode_for_size (move_bits, 0).require ();
>        promoted_val = gen_lowpart (move_mode, promoted_val);
>      }
>    piece_size = GET_MODE_SIZE (move_mode);
> @@ -27792,7 +27791,7 @@ expand_small_movmem_or_setmem (rtx destm
>                                rtx done_label, bool issetmem)
>  {
>    rtx_code_label *label = ix86_expand_aligntest (count, size, false);
> -  machine_mode mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 1);
> +  machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
>    rtx modesize;
>    int n;
>
> @@ -50453,7 +50452,8 @@ ix86_expand_pextr (rtx *operands)
>         machine_mode srcmode, dstmode;
>         rtx d, pat;
>
> -       dstmode = mode_for_size (size, MODE_INT, 0);
> +       if (!int_mode_for_size (size, 0).exists (&dstmode))
> +         return false;
>
>         switch (dstmode)
>           {
> @@ -50549,7 +50549,8 @@ ix86_expand_pinsr (rtx *operands)
>         rtx (*pinsr)(rtx, rtx, rtx, rtx);
>         rtx d;
>
> -       srcmode = mode_for_size (size, MODE_INT, 0);
> +       if (!int_mode_for_size (size, 0).exists (&srcmode))
> +         return false;
>
>         switch (srcmode)
>           {
> Index: gcc/config/lm32/lm32.c
> ===================================================================
> --- gcc/config/lm32/lm32.c      2017-09-04 11:50:08.517531827 +0100
> +++ gcc/config/lm32/lm32.c      2017-09-04 12:18:44.903326171 +0100
> @@ -836,7 +836,7 @@ lm32_block_move_inline (rtx dest, rtx sr
>        break;
>      }
>
> -  mode = mode_for_size (bits, MODE_INT, 0);
> +  mode = int_mode_for_size (bits, 0).require ();
>    delta = bits / BITS_PER_UNIT;
>
>    /* Allocate a buffer for the temporary registers.  */
> Index: gcc/config/microblaze/microblaze.c
> ===================================================================
> --- gcc/config/microblaze/microblaze.c  2017-09-04 11:50:08.520232996 +0100
> +++ gcc/config/microblaze/microblaze.c  2017-09-04 12:18:44.904331711 +0100
> @@ -1087,7 +1087,7 @@ microblaze_block_move_straight (rtx dest
>    rtx *regs;
>
>    bits = BITS_PER_WORD;
> -  mode = mode_for_size (bits, MODE_INT, 0);
> +  mode = int_mode_for_size (bits, 0).require ();
>    delta = bits / BITS_PER_UNIT;
>
>    /* Allocate a buffer for the temporary registers.  */
> Index: gcc/config/mips/mips.c
> ===================================================================
> --- gcc/config/mips/mips.c      2017-09-04 11:50:24.550767077 +0100
> +++ gcc/config/mips/mips.c      2017-09-04 12:18:44.906342792 +0100
> @@ -6384,7 +6384,7 @@ mips_function_value_1 (const_tree valtyp
>           if (size % UNITS_PER_WORD != 0)
>             {
>               size += UNITS_PER_WORD - size % UNITS_PER_WORD;
> -             mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
> +             mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
>             }
>         }
>
> @@ -7992,7 +7992,7 @@ mips_block_move_straight (rtx dest, rtx
>         bits = BITS_PER_WORD;
>      }
>
> -  mode = mode_for_size (bits, MODE_INT, 0);
> +  mode = int_mode_for_size (bits, 0).require ();
>    delta = bits / BITS_PER_UNIT;
>
>    /* Allocate a buffer for the temporary registers.  */
> @@ -8397,7 +8397,7 @@ mips_expand_ins_as_unaligned_store (rtx
>    if (!mips_get_unaligned_mem (dest, width, bitpos, &left, &right))
>      return false;
>
> -  mode = mode_for_size (width, MODE_INT, 0);
> +  mode = int_mode_for_size (width, 0).require ();
>    src = gen_lowpart (mode, src);
>    if (mode == DImode)
>      {
> Index: gcc/config/powerpcspe/powerpcspe.c
> ===================================================================
> --- gcc/config/powerpcspe/powerpcspe.c  2017-09-04 11:50:24.557069804 +0100
> +++ gcc/config/powerpcspe/powerpcspe.c  2017-09-04 12:18:44.919414816 +0100
> @@ -12222,7 +12222,6 @@ rs6000_darwin64_record_arg_advance_flush
>  {
>    unsigned int startbit, endbit;
>    int intregs, intoffset;
> -  machine_mode mode;
>
>    /* Handle the situations where a float is taking up the first half
>       of the GPR, and the other half is empty (typically due to
> @@ -12246,9 +12245,8 @@ rs6000_darwin64_record_arg_advance_flush
>
>    if (intoffset % BITS_PER_WORD != 0)
>      {
> -      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
> -                           MODE_INT, 0);
> -      if (mode == BLKmode)
> +      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
> +      if (!int_mode_for_size (bits, 0).exists ())
>         {
>           /* We couldn't find an appropriate mode, which happens,
>              e.g., in packed structs when there are 3 bytes to load.
> @@ -12714,9 +12712,8 @@ rs6000_darwin64_record_arg_flush (CUMULA
>
>    if (intoffset % BITS_PER_WORD != 0)
>      {
> -      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
> -                         MODE_INT, 0);
> -      if (mode == BLKmode)
> +      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
> +      if (!int_mode_for_size (bits, 0).exists (&mode))
>         {
>           /* We couldn't find an appropriate mode, which happens,
>              e.g., in packed structs when there are 3 bytes to load.
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  2017-09-04 11:50:24.560671361 +0100
> +++ gcc/config/rs6000/rs6000.c  2017-09-04 12:18:44.929470219 +0100
> @@ -11654,7 +11654,6 @@ rs6000_darwin64_record_arg_advance_flush
>  {
>    unsigned int startbit, endbit;
>    int intregs, intoffset;
> -  machine_mode mode;
>
>    /* Handle the situations where a float is taking up the first half
>       of the GPR, and the other half is empty (typically due to
> @@ -11678,9 +11677,8 @@ rs6000_darwin64_record_arg_advance_flush
>
>    if (intoffset % BITS_PER_WORD != 0)
>      {
> -      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
> -                           MODE_INT, 0);
> -      if (mode == BLKmode)
> +      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
> +      if (!int_mode_for_size (bits, 0).exists ())
>         {
>           /* We couldn't find an appropriate mode, which happens,
>              e.g., in packed structs when there are 3 bytes to load.
> @@ -12049,9 +12047,8 @@ rs6000_darwin64_record_arg_flush (CUMULA
>
>    if (intoffset % BITS_PER_WORD != 0)
>      {
> -      mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
> -                         MODE_INT, 0);
> -      if (mode == BLKmode)
> +      unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD;
> +      if (!int_mode_for_size (bits, 0).exists (&mode))
>         {
>           /* We couldn't find an appropriate mode, which happens,
>              e.g., in packed structs when there are 3 bytes to load.
> Index: gcc/config/sparc/sparc.c
> ===================================================================
> --- gcc/config/sparc/sparc.c    2017-09-04 11:50:24.562472140 +0100
> +++ gcc/config/sparc/sparc.c    2017-09-04 12:18:44.932486840 +0100
> @@ -7123,7 +7123,7 @@ sparc_function_arg_1 (cumulative_args_t
>        HOST_WIDE_INT size = int_size_in_bytes (type);
>        gcc_assert (size <= 16);
>
> -      mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
> +      mode = int_mode_for_size (size * BITS_PER_UNIT, 0).else_blk ();
>      }
>
>    return gen_rtx_REG (mode, regno);
> @@ -7499,7 +7499,7 @@ sparc_function_value_1 (const_tree type,
>           HOST_WIDE_INT size = int_size_in_bytes (type);
>           gcc_assert (size <= 32);
>
> -         mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
> +         mode = int_mode_for_size (size * BITS_PER_UNIT, 0).else_blk ();
>
>           /* ??? We probably should have made the same ABI change in
>              3.4.0 as the one we made for unions.   The latter was
> Index: gcc/config/spu/spu.c
> ===================================================================
> --- gcc/config/spu/spu.c        2017-09-04 12:18:41.572976650 +0100
> +++ gcc/config/spu/spu.c        2017-09-04 12:18:44.934497920 +0100
> @@ -368,7 +368,7 @@ adjust_operand (rtx op, HOST_WIDE_INT *
>        op_size = 32;
>      }
>    /* If it is not a MODE_INT (and/or it is smaller than SI) add a SUBREG. */
> -  mode = mode_for_size (op_size, MODE_INT, 0);
> +  mode = int_mode_for_size (op_size, 0).require ();
>    if (mode != GET_MODE (op))
>      op = gen_rtx_SUBREG (mode, op, 0);
>    return op;
> @@ -935,7 +935,7 @@ spu_emit_branch_or_set (int is_set, rtx
>        rtx target = operands[0];
>        int compare_size = GET_MODE_BITSIZE (comp_mode);
>        int target_size = GET_MODE_BITSIZE (GET_MODE (target));
> -      machine_mode mode = mode_for_size (target_size, MODE_INT, 0);
> +      machine_mode mode = int_mode_for_size (target_size, 0).require ();
>        rtx select_mask;
>        rtx op_t = operands[2];
>        rtx op_f = operands[3];
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c      2017-09-04 11:48:27.399539901 +0100
> +++ gcc/emit-rtl.c      2017-09-04 12:18:44.935503461 +0100
> @@ -1430,9 +1430,9 @@ gen_lowpart_common (machine_mode mode, r
>    innermode = GET_MODE (x);
>    if (CONST_INT_P (x)
>        && msize * BITS_PER_UNIT <= HOST_BITS_PER_WIDE_INT)
> -    innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
> +    innermode = int_mode_for_size (HOST_BITS_PER_WIDE_INT, 0).require ();
>    else if (innermode == VOIDmode)
> -    innermode = mode_for_size (HOST_BITS_PER_DOUBLE_INT, MODE_INT, 0);
> +    innermode = int_mode_for_size (HOST_BITS_PER_DOUBLE_INT, 0).require ();
>
>    xsize = GET_MODE_SIZE (innermode);
>
> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c  2017-09-04 11:50:24.566974088 +0100
> +++ gcc/expr.c  2017-09-04 12:18:44.938520082 +0100
> @@ -10680,7 +10680,7 @@ expand_expr_real_1 (tree exp, rtx target
>                 && ! (target != 0 && MEM_P (op0)
>                       && MEM_P (target)
>                       && bitpos % BITS_PER_UNIT == 0))
> -             ext_mode = mode_for_size (bitsize, MODE_INT, 1);
> +             ext_mode = int_mode_for_size (bitsize, 1).else_blk ();
>
>             if (ext_mode == BLKmode)
>               {
> Index: gcc/function.c
> ===================================================================
> --- gcc/function.c      2017-09-04 11:50:24.567874477 +0100
> +++ gcc/function.c      2017-09-04 12:18:44.940531162 +0100
> @@ -2978,8 +2978,8 @@ assign_parm_setup_block (struct assign_p
>          that mode's store operation.  */
>        else if (size <= UNITS_PER_WORD)
>         {
> -         machine_mode mode
> -           = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
> +         unsigned int bits = size * BITS_PER_UNIT;
> +         machine_mode mode = int_mode_for_size (bits, 0).else_blk ();
>
>           if (mode != BLKmode
>  #ifdef BLOCK_REG_PADDING
> Index: gcc/gimple-ssa-store-merging.c
> ===================================================================
> --- gcc/gimple-ssa-store-merging.c      2017-07-27 10:37:56.776048721 +0100
> +++ gcc/gimple-ssa-store-merging.c      2017-09-04 12:18:44.941536703 +0100
> @@ -354,7 +354,7 @@ encode_tree_to_bitpos (tree expr, unsign
>    tree tmp_int = expr;
>    bool sub_byte_op_p = ((bitlen % BITS_PER_UNIT)
>                         || (bitpos % BITS_PER_UNIT)
> -                       || mode_for_size (bitlen, MODE_INT, 0) == BLKmode);
> +                       || !int_mode_for_size (bitlen, 0).exists ());
>
>    if (!sub_byte_op_p)
>      return (native_encode_expr (tmp_int, ptr + first_byte, total_bytes, 0)
> Index: gcc/reload1.c
> ===================================================================
> --- gcc/reload1.c       2017-09-04 11:49:42.942500722 +0100
> +++ gcc/reload1.c       2017-09-04 12:18:44.943547783 +0100
> @@ -2189,11 +2189,12 @@ alter_reg (int i, int from_reg, bool don
>             {
>               adjust = inherent_size - total_size;
>               if (adjust)
> -               stack_slot
> -                 = adjust_address_nv (x, mode_for_size (total_size
> -                                                        * BITS_PER_UNIT,
> -                                                        MODE_INT, 1),
> -                                      adjust);
> +               {
> +                 unsigned int total_bits = total_size * BITS_PER_UNIT;
> +                 machine_mode mem_mode
> +                   = int_mode_for_size (total_bits, 1).else_blk ();
> +                 stack_slot = adjust_address_nv (x, mem_mode, adjust);
> +               }
>             }
>
>           if (! dont_share_p && ira_conflicts_p)
> @@ -2240,11 +2241,12 @@ alter_reg (int i, int from_reg, bool don
>             {
>               adjust = GET_MODE_SIZE (mode) - total_size;
>               if (adjust)
> -               stack_slot
> -                 = adjust_address_nv (x, mode_for_size (total_size
> -                                                        * BITS_PER_UNIT,
> -                                                        MODE_INT, 1),
> -                                      adjust);
> +               {
> +                 unsigned int total_bits = total_size * BITS_PER_UNIT;
> +                 machine_mode mem_mode
> +                   = int_mode_for_size (total_bits, 1).else_blk ();
> +                 stack_slot = adjust_address_nv (x, mem_mode, adjust);
> +               }
>             }
>
>           spill_stack_slot[from_reg] = stack_slot;
> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c   2017-08-30 12:20:41.643620906 +0100
> +++ gcc/stor-layout.c   2017-09-04 12:18:44.944553324 +0100
> @@ -506,8 +506,10 @@ mode_for_vector (scalar_mode innermode,
>    /* For integers, try mapping it to a same-sized scalar mode.  */
>    if (mode == VOIDmode
>        && GET_MODE_CLASS (innermode) == MODE_INT)
> -    mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
> -                         MODE_INT, 0);
> +    {
> +      unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);
> +      mode = int_mode_for_size (nbits, 0).else_blk ();
> +    }
>
>    if (mode == VOIDmode
>        || (GET_MODE_CLASS (mode) == MODE_INT
> @@ -2295,7 +2297,7 @@ layout_type (tree type)
>        TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE_UNITS);
>        /* A pointer might be MODE_PARTIAL_INT, but ptrdiff_t must be
>          integral, which may be an __intN.  */
> -      SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0));
> +      SET_TYPE_MODE (type, int_mode_for_size (POINTER_SIZE, 0).require ());
>        TYPE_PRECISION (type) = POINTER_SIZE;
>        break;
>
> @@ -2304,7 +2306,8 @@ layout_type (tree type)
>        /* It's hard to see what the mode and size of a function ought to
>          be, but we do know the alignment is FUNCTION_BOUNDARY, so
>          make it consistent with that.  */
> -      SET_TYPE_MODE (type, mode_for_size (FUNCTION_BOUNDARY, MODE_INT, 0));
> +      SET_TYPE_MODE (type,
> +                    int_mode_for_size (FUNCTION_BOUNDARY, 0).else_blk ());
>        TYPE_SIZE (type) = bitsize_int (FUNCTION_BOUNDARY);
>        TYPE_SIZE_UNIT (type) = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
>        break;
> Index: gcc/ada/gcc-interface/utils2.c
> ===================================================================
> --- gcc/ada/gcc-interface/utils2.c      2017-05-31 10:02:29.736972972 +0100
> +++ gcc/ada/gcc-interface/utils2.c      2017-09-04 12:18:44.864110098 +0100
> @@ -800,7 +800,8 @@ build_load_modify_store (tree dest, tree
>                 {
>                   unsigned int size = tree_to_uhwi (TYPE_SIZE (type));
>                   type = copy_type (type);
> -                 SET_TYPE_MODE (type, mode_for_size (size, MODE_INT, 0));
> +                 machine_mode mode = int_mode_for_size (size, 0).else_blk ();
> +                 SET_TYPE_MODE (type, mode);
>                 }
>
>               /* Create the temporary by inserting a SAVE_EXPR.  */

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [3/9] (decimal_)float_mode_for_size in real.h
  2017-09-04 11:32 ` [3/9] (decimal_)float_mode_for_size in real.h Richard Sandiford
@ 2017-09-05 11:24   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:24 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:31 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch makes the binary float macros in real.h use
> float_mode_for_size and adds a corresponding decimal_float_mode_for_size
> for the decimal macros.

Ok.

Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * machmode.h (decimal_float_mode_for_size): New function.
>         * real.h (REAL_VALUE_TO_TARGET_LONG_DOUBLE): Use float_mode_for_size.
>         (REAL_VALUE_TO_TARGET_DOUBLE): Likewise.
>         (REAL_VALUE_TO_TARGET_SINGLE): Likewise.
>         (REAL_VALUE_TO_TARGET_DECIMAL128): Use decimal_float_mode_for_size.
>         (REAL_VALUE_TO_TARGET_DECIMAL64): Likewise.
>         (REAL_VALUE_TO_TARGET_DECIMAL32): Likewise.
>
> Index: gcc/machmode.h
> ===================================================================
> --- gcc/machmode.h      2017-08-30 12:20:57.010045759 +0100
> +++ gcc/machmode.h      2017-09-04 12:18:47.820398622 +0100
> @@ -652,6 +652,15 @@ float_mode_for_size (unsigned int size)
>    return dyn_cast <scalar_float_mode> (mode_for_size (size, MODE_FLOAT, 0));
>  }
>
> +/* Likewise for MODE_DECIMAL_FLOAT.  */
> +
> +inline opt_scalar_float_mode
> +decimal_float_mode_for_size (unsigned int size)
> +{
> +  return dyn_cast <scalar_float_mode>
> +    (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
> +}
> +
>  /* Similar to mode_for_size, but find the smallest mode for a given width.  */
>
>  extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);
> Index: gcc/real.h
> ===================================================================
> --- gcc/real.h  2017-08-30 12:09:02.416468293 +0100
> +++ gcc/real.h  2017-09-04 12:18:47.820398622 +0100
> @@ -383,27 +383,28 @@ #define REAL_VALUE_MINUS_ZERO(x)  real_is
>  /* IN is a REAL_VALUE_TYPE.  OUT is an array of longs.  */
>  #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT)                      \
>    real_to_target (OUT, &(IN),                                          \
> -                 mode_for_size (LONG_DOUBLE_TYPE_SIZE, MODE_FLOAT, 0))
> +                 float_mode_for_size (LONG_DOUBLE_TYPE_SIZE).require ())
>
>  #define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
> -  real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0))
> +  real_to_target (OUT, &(IN), float_mode_for_size (64).require ())
>
>  /* IN is a REAL_VALUE_TYPE.  OUT is a long.  */
>  #define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
> -  ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_FLOAT, 0)))
> +  ((OUT) = real_to_target (NULL, &(IN), float_mode_for_size (32).require ()))
>
>  /* Real values to IEEE 754 decimal floats.  */
>
>  /* IN is a REAL_VALUE_TYPE.  OUT is an array of longs.  */
>  #define REAL_VALUE_TO_TARGET_DECIMAL128(IN, OUT) \
> -  real_to_target (OUT, &(IN), mode_for_size (128, MODE_DECIMAL_FLOAT, 0))
> +  real_to_target (OUT, &(IN), decimal_float_mode_for_size (128).require ())
>
>  #define REAL_VALUE_TO_TARGET_DECIMAL64(IN, OUT) \
> -  real_to_target (OUT, &(IN), mode_for_size (64, MODE_DECIMAL_FLOAT, 0))
> +  real_to_target (OUT, &(IN), decimal_float_mode_for_size (64).require ())
>
>  /* IN is a REAL_VALUE_TYPE.  OUT is a long.  */
>  #define REAL_VALUE_TO_TARGET_DECIMAL32(IN, OUT) \
> -  ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_DECIMAL_FLOAT, 0)))
> +  ((OUT) = real_to_target (NULL, &(IN), \
> +                          decimal_float_mode_for_size (32).require ()))
>
>  extern REAL_VALUE_TYPE real_value_truncate (format_helper, REAL_VALUE_TYPE);
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [4/9] Make mode_for_size return an opt_mode
  2017-09-04 11:35 ` [4/9] Make mode_for_size return an opt_mode Richard Sandiford
@ 2017-09-05 11:25   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:25 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:35 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> ...to make it consistent with int_mode_for_size etc.
>
> require () seems like the right choice in replace_reg_with_saved_mem
> because we use the chosen mode for saving and restoring registers,
> which cannot be done in BLKmode.  Similarly require () seems like
> the right choice in calls related to secondary memory reloads (the ones
> in config/, and in get_secondary_mem) because the reload must always
> have a defined mode, which e.g. determines the size of the slot.
>
> We can use require () in simplify_subreg_concatn and assemble_integer
> because it isn't meaningful to create a subreg with BLKmode (for one
> thing, we couldn't tell then whether it was partial, paradoxical, etc.).
>
> make_fract_type and make_accum_type must find a mode because that's
> what distinguishes accumulator FIXED_POINT_TYPEs from fractional
> FIXED_POINT_TYPEs.

Ok.

Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * machmode.h (opt_machine_mode): New type.
>         (opt_mode<T>): Allow construction from anything that can be
>         converted to a T.
>         (is_a, as_a, dyn_cast): Add overloads for opt_mode.
>         (mode_for_size): Return an opt_machine_mode.
>         * stor-layout.c (mode_for_size): Likewise.
>         (mode_for_size_tree): Update call accordingly.
>         (bitwise_mode_for_mode): Likewise.
>         (make_fract_type): Likewise.
>         (make_accum_type): Likewise.
>         * caller-save.c (replace_reg_with_saved_mem): Update call
>         accordingly.
>         * config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
>         * config/i386/i386.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
>         * config/s390/s390.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
>         * config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
>         * expmed.c (extract_bit_field_1): Likewise.
>         * reload.c (get_secondary_mem): Likewise.
>         * varasm.c (assemble_integer): Likewise.
>         * lower-subreg.c (simplify_subreg_concatn): Likewise.  Move
>         early-out.
>
> Index: gcc/machmode.h
> ===================================================================
> --- gcc/machmode.h      2017-09-04 12:18:47.820398622 +0100
> +++ gcc/machmode.h      2017-09-04 12:18:50.674859598 +0100
> @@ -20,6 +20,8 @@ Software Foundation; either version 3, o
>  #ifndef HAVE_MACHINE_MODES
>  #define HAVE_MACHINE_MODES
>
> +typedef opt_mode<machine_mode> opt_machine_mode;
> +
>  extern CONST_MODE_SIZE unsigned short mode_size[NUM_MACHINE_MODES];
>  extern const unsigned short mode_precision[NUM_MACHINE_MODES];
>  extern const unsigned char mode_inner[NUM_MACHINE_MODES];
> @@ -237,6 +239,8 @@ #define POINTER_BOUNDS_MODE_P(MODE)
>
>    ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
>    ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
> +  template<typename U>
> +  ALWAYS_INLINE opt_mode (const U &m) : m_mode (T (m)) {}
>    ALWAYS_INLINE opt_mode (from_int m) : m_mode (machine_mode (m)) {}
>
>    machine_mode else_void () const;
> @@ -325,6 +329,13 @@ is_a (machine_mode m)
>    return T::includes_p (m);
>  }
>
> +template<typename T, typename U>
> +inline bool
> +is_a (const opt_mode<U> &m)
> +{
> +  return T::includes_p (m.else_void ());
> +}
> +
>  /* Assert that mode M has type T, and return it in that form.  */
>
>  template<typename T>
> @@ -335,6 +346,13 @@ as_a (machine_mode m)
>    return typename mode_traits<T>::from_int (m);
>  }
>
> +template<typename T, typename U>
> +inline T
> +as_a (const opt_mode<U> &m)
> +{
> +  return as_a <T> (m.else_void ());
> +}
> +
>  /* Convert M to an opt_mode<T>.  */
>
>  template<typename T>
> @@ -346,6 +364,13 @@ dyn_cast (machine_mode m)
>    return opt_mode<T> ();
>  }
>
> +template<typename T, typename U>
> +inline opt_mode<T>
> +dyn_cast (const opt_mode<U> &m)
> +{
> +  return dyn_cast <T> (m.else_void ());
> +}
> +
>  /* Return true if mode M has type T, storing it as a T in *RESULT
>     if so.  */
>
> @@ -627,11 +652,7 @@ GET_MODE_2XWIDER_MODE (const T &m)
>  extern const unsigned char mode_complex[NUM_MACHINE_MODES];
>  #define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
>
> -/* Return the mode for data of a given size SIZE and mode class CLASS.
> -   If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
> -   The value is BLKmode if no other mode is found.  */
> -
> -extern machine_mode mode_for_size (unsigned int, enum mode_class, int);
> +extern opt_machine_mode mode_for_size (unsigned int, enum mode_class, int);
>
>  /* Return the machine mode to use for a MODE_INT of SIZE bits, if one
>     exists.  If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE
> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c   2017-09-04 12:18:44.944553324 +0100
> +++ gcc/stor-layout.c   2017-09-04 12:18:50.675762071 +0100
> @@ -291,19 +291,19 @@ finalize_size_functions (void)
>    vec_free (size_functions);
>  }
>
> -/* Return the machine mode to use for a nonscalar of SIZE bits.  The
> -   mode must be in class MCLASS, and have exactly that many value bits;
> -   it may have padding as well.  If LIMIT is nonzero, modes of wider
> -   than MAX_FIXED_MODE_SIZE will not be used.  */
> +/* Return a machine mode of class MCLASS with SIZE bits of precision,
> +   if one exists.  The mode may have padding bits as well the SIZE
> +   value bits.  If LIMIT is nonzero, disregard modes wider than
> +   MAX_FIXED_MODE_SIZE.  */
>
> -machine_mode
> +opt_machine_mode
>  mode_for_size (unsigned int size, enum mode_class mclass, int limit)
>  {
>    machine_mode mode;
>    int i;
>
>    if (limit && size > MAX_FIXED_MODE_SIZE)
> -    return BLKmode;
> +    return opt_machine_mode ();
>
>    /* Get the first mode which has this size, in the specified class.  */
>    FOR_EACH_MODE_IN_CLASS (mode, mclass)
> @@ -316,7 +316,7 @@ mode_for_size (unsigned int size, enum m
>           && int_n_enabled_p[i])
>         return int_n_data[i].m;
>
> -  return BLKmode;
> +  return opt_machine_mode ();
>  }
>
>  /* Similar, except passed a tree node.  */
> @@ -333,11 +333,11 @@ mode_for_size_tree (const_tree size, enu
>    ui = uhwi;
>    if (uhwi != ui)
>      return BLKmode;
> -  return mode_for_size (ui, mclass, limit);
> +  return mode_for_size (ui, mclass, limit).else_blk ();
>  }
>
> -/* Similar, but never return BLKmode; return the narrowest mode that
> -   contains at least the requested number of value bits.  */
> +/* Return the narrowest mode of class MCLASS that contains at least
> +   SIZE bits.  Abort if no such mode exists.  */
>
>  machine_mode
>  smallest_mode_for_size (unsigned int size, enum mode_class mclass)
> @@ -426,9 +426,8 @@ bitwise_mode_for_mode (machine_mode mode
>    if (COMPLEX_MODE_P (mode))
>      {
>        machine_mode trial = mode;
> -      if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT)
> -       trial = mode_for_size (bitsize, MODE_COMPLEX_INT, false);
> -      if (trial != BLKmode
> +      if ((GET_MODE_CLASS (trial) == MODE_COMPLEX_INT
> +          || mode_for_size (bitsize, MODE_COMPLEX_INT, false).exists (&trial))
>           && have_regs_of_mode[GET_MODE_INNER (trial)])
>         return trial;
>      }
> @@ -438,16 +437,15 @@ bitwise_mode_for_mode (machine_mode mode
>    if (VECTOR_MODE_P (mode) || bitsize > MAX_FIXED_MODE_SIZE)
>      {
>        machine_mode trial = mode;
> -      if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
> -       trial = mode_for_size (bitsize, MODE_VECTOR_INT, 0);
> -      if (trial != BLKmode
> +      if ((GET_MODE_CLASS (trial) == MODE_VECTOR_INT
> +          || mode_for_size (bitsize, MODE_VECTOR_INT, 0).exists (&trial))
>           && have_regs_of_mode[trial]
>           && targetm.vector_mode_supported_p (trial))
>         return trial;
>      }
>
>    /* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE.  */
> -  return mode_for_size (bitsize, MODE_INT, true);
> +  return mode_for_size (bitsize, MODE_INT, true).else_blk ();
>  }
>
>  /* Find a type that can be used for efficient bitwise operations on MODE.
> @@ -2543,13 +2541,9 @@ make_fract_type (int precision, int unsi
>      TYPE_SATURATING (type) = 1;
>
>    /* Lay out the type: set its alignment, size, etc.  */
> -  if (unsignedp)
> -    {
> -      TYPE_UNSIGNED (type) = 1;
> -      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UFRACT, 0));
> -    }
> -  else
> -    SET_TYPE_MODE (type, mode_for_size (precision, MODE_FRACT, 0));
> +  TYPE_UNSIGNED (type) = unsignedp;
> +  enum mode_class mclass = unsignedp ? MODE_UFRACT : MODE_FRACT;
> +  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
>    layout_type (type);
>
>    return type;
> @@ -2569,13 +2563,9 @@ make_accum_type (int precision, int unsi
>      TYPE_SATURATING (type) = 1;
>
>    /* Lay out the type: set its alignment, size, etc.  */
> -  if (unsignedp)
> -    {
> -      TYPE_UNSIGNED (type) = 1;
> -      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UACCUM, 0));
> -    }
> -  else
> -    SET_TYPE_MODE (type, mode_for_size (precision, MODE_ACCUM, 0));
> +  TYPE_UNSIGNED (type) = unsignedp;
> +  enum mode_class mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
> +  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
>    layout_type (type);
>
>    return type;
> Index: gcc/caller-save.c
> ===================================================================
> --- gcc/caller-save.c   2017-09-04 11:49:42.884500727 +0100
> +++ gcc/caller-save.c   2017-09-04 12:18:50.672152181 +0100
> @@ -1161,7 +1161,7 @@ replace_reg_with_saved_mem (rtx *loc,
>             gcc_assert (smode != VOIDmode);
>             if (hard_regno_nregs [regno][smode] > 1)
>               smode = mode_for_size (GET_MODE_SIZE (mode) / nregs,
> -                                    GET_MODE_CLASS (mode), 0);
> +                                    GET_MODE_CLASS (mode), 0).require ();
>             XVECEXP (mem, 0, i) = gen_rtx_REG (smode, regno + i);
>           }
>      }
> Index: gcc/config/alpha/alpha.h
> ===================================================================
> --- gcc/config/alpha/alpha.h    2017-09-04 11:50:08.504926375 +0100
> +++ gcc/config/alpha/alpha.h    2017-09-04 12:18:50.672152181 +0100
> @@ -508,7 +508,7 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,C
>  #define SECONDARY_MEMORY_NEEDED_MODE(MODE)             \
>    (GET_MODE_CLASS (MODE) == MODE_FLOAT ? (MODE)                \
>     : GET_MODE_SIZE (MODE) >= 4 ? (MODE)                        \
> -   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0))
> +   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require ())
>
>  /* Return the class of registers that cannot change mode from FROM to TO.  */
>
> Index: gcc/config/i386/i386.h
> ===================================================================
> --- gcc/config/i386/i386.h      2017-09-04 11:50:08.515731048 +0100
> +++ gcc/config/i386/i386.h      2017-09-04 12:18:50.672152181 +0100
> @@ -1548,7 +1548,7 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
>     for integral modes that can be moved using 32 bit move.  */
>  #define SECONDARY_MEMORY_NEEDED_MODE(MODE)                     \
>    (GET_MODE_BITSIZE (MODE) < 32 && INTEGRAL_MODE_P (MODE)      \
> -   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)              \
> +   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()   \
>     : MODE)
>
>  /* Return a class of registers that cannot change FROM mode to TO mode.  */
> Index: gcc/config/s390/s390.h
> ===================================================================
> --- gcc/config/s390/s390.h      2017-09-04 11:50:24.561571751 +0100
> +++ gcc/config/s390/s390.h      2017-09-04 12:18:50.673054653 +0100
> @@ -624,9 +624,9 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
>
>  /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
>     because the movsi and movsf patterns don't handle r/f moves.  */
> -#define SECONDARY_MEMORY_NEEDED_MODE(MODE)             \
> - (GET_MODE_BITSIZE (MODE) < 32                         \
> -  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)       \
> +#define SECONDARY_MEMORY_NEEDED_MODE(MODE)                     \
> + (GET_MODE_BITSIZE (MODE) < 32                                 \
> +  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()    \
>    : (MODE))
>
>
> Index: gcc/config/sparc/sparc.h
> ===================================================================
> --- gcc/config/sparc/sparc.h    2017-09-04 11:50:24.563372530 +0100
> +++ gcc/config/sparc/sparc.h    2017-09-04 12:18:50.673054653 +0100
> @@ -1077,13 +1077,13 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
>  /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
>     because the movsi and movsf patterns don't handle r/f moves.
>     For v8 we copy the default definition.  */
> -#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
> -  (TARGET_ARCH64                                               \
> -   ? (GET_MODE_BITSIZE (MODE) < 32                             \
> -      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)           \
> -      : MODE)                                                  \
> -   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD                  \
> -      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0)        \
> +#define SECONDARY_MEMORY_NEEDED_MODE(MODE)                                \
> +  (TARGET_ARCH64                                                          \
> +   ? (GET_MODE_BITSIZE (MODE) < 32                                        \
> +      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()                   \
> +      : MODE)                                                             \
> +   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD                             \
> +      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require () \
>        : MODE))
>
>  /* Return the maximum number of consecutive registers
> Index: gcc/expmed.c
> ===================================================================
> --- gcc/expmed.c        2017-09-04 11:50:08.544543511 +0100
> +++ gcc/expmed.c        2017-09-04 12:18:50.673054653 +0100
> @@ -1711,14 +1711,9 @@ extract_bit_field_1 (rtx str_rtx, unsign
>
>    /* Get the mode of the field to use for atomic access or subreg
>       conversion.  */
> -  mode1 = mode;
> -  if (SCALAR_INT_MODE_P (tmode))
> -    {
> -      machine_mode try_mode = mode_for_size (bitsize,
> -                                                 GET_MODE_CLASS (tmode), 0);
> -      if (try_mode != BLKmode)
> -       mode1 = try_mode;
> -    }
> +  if (!SCALAR_INT_MODE_P (tmode)
> +      || !mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0).exists (&mode1))
> +    mode1 = mode;
>    gcc_assert (mode1 != BLKmode);
>
>    /* Extraction of a full MODE1 value can be done with a subreg as long
> Index: gcc/reload.c
> ===================================================================
> --- gcc/reload.c        2017-09-04 11:49:42.941500722 +0100
> +++ gcc/reload.c        2017-09-04 12:18:50.675762071 +0100
> @@ -578,7 +578,8 @@ get_secondary_mem (rtx x ATTRIBUTE_UNUSE
>    mode = SECONDARY_MEMORY_NEEDED_MODE (mode);
>  #else
>    if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
> -    mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
> +    mode = mode_for_size (BITS_PER_WORD,
> +                         GET_MODE_CLASS (mode), 0).require ();
>  #endif
>
>    /* If we already have made a MEM for this operand in MODE, return it.  */
> Index: gcc/varasm.c
> ===================================================================
> --- gcc/varasm.c        2017-09-04 11:49:42.944500722 +0100
> +++ gcc/varasm.c        2017-09-04 12:18:50.676664544 +0100
> @@ -2780,8 +2780,8 @@ assemble_integer (rtx x, unsigned int si
>        else
>         mclass = MODE_INT;
>
> -      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0);
> -      imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0);
> +      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0).require ();
> +      imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0).require ();
>
>        for (i = 0; i < size; i += subsize)
>         {
> Index: gcc/lower-subreg.c
> ===================================================================
> --- gcc/lower-subreg.c  2017-09-04 12:18:41.572976650 +0100
> +++ gcc/lower-subreg.c  2017-09-04 12:18:50.674859598 +0100
> @@ -616,20 +616,18 @@ simplify_subreg_concatn (machine_mode ou
>    part = XVECEXP (op, 0, byte / inner_size);
>    partmode = GET_MODE (part);
>
> +  final_offset = byte % inner_size;
> +  if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
> +    return NULL_RTX;
> +
>    /* VECTOR_CSTs in debug expressions are expanded into CONCATN instead of
>       regular CONST_VECTORs.  They have vector or integer modes, depending
>       on the capabilities of the target.  Cope with them.  */
>    if (partmode == VOIDmode && VECTOR_MODE_P (innermode))
>      partmode = GET_MODE_INNER (innermode);
>    else if (partmode == VOIDmode)
> -    {
> -      enum mode_class mclass = GET_MODE_CLASS (innermode);
> -      partmode = mode_for_size (inner_size * BITS_PER_UNIT, mclass, 0);
> -    }
> -
> -  final_offset = byte % inner_size;
> -  if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
> -    return NULL_RTX;
> +    partmode = mode_for_size (inner_size * BITS_PER_UNIT,
> +                             GET_MODE_CLASS (innermode), 0).require ();
>
>    return simplify_gen_subreg (outermode, part, partmode, final_offset);
>  }

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [5/9] Add mode_for_int_vector helper functions
  2017-09-04 11:37 ` [5/9] Add mode_for_int_vector helper functions Richard Sandiford
@ 2017-09-05 11:35   ` Richard Biener
  2017-09-05 12:33     ` Richard Sandiford
  0 siblings, 1 reply; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:35 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:36 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> There are at least a few places that want to create an integer vector
> with a specified element size and element count, or to create the
> integer equivalent of an existing mode.  This patch adds helpers
> for doing that.
>
> The require ()s are all used in functions that go on to emit
> instructions that use the result as a vector mode.
>
> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * machmode.h (mode_for_int_vector): New function.
>         * stor-layout.c (mode_for_int_vector): Likewise.
>         * config/aarch64/aarch64.c (aarch64_emit_approx_sqrt): Use it.
>         * config/powerpcspe/powerpcspe.c (rs6000_do_expand_vec_perm): Likewise.
>         * config/rs6000/rs6000.c (rs6000_do_expand_vec_perm): Likewise.
>         * config/s390/s390.c (s390_expand_vec_compare_cc): Likewise.
>         (s390_expand_vcond): Likewise.
>
> Index: gcc/machmode.h
> ===================================================================
> --- gcc/machmode.h      2017-09-04 12:18:50.674859598 +0100
> +++ gcc/machmode.h      2017-09-04 12:18:53.153306182 +0100
> @@ -706,6 +706,21 @@ extern machine_mode bitwise_mode_for_mod
>
>  extern machine_mode mode_for_vector (scalar_mode, unsigned);
>
> +extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
> +
> +/* Return the integer vector equivalent of MODE, if one exists.  In other
> +   words, return the mode for an integer vector that has the same number
> +   of bits as MODE and the same number of elements as MODE, with the
> +   latter being 1 if MODE is scalar.  The returned mode can be either
> +   an integer mode or a vector mode.  */
> +
> +inline opt_machine_mode
> +mode_for_int_vector (machine_mode mode)

So this is similar to int_mode_for_mode which means...

int_vector_mode_for_vector_mode?

> +{

Nothing prevents use with non-vector MODE here, can we place an assert here?

> +  return mode_for_int_vector (GET_MODE_UNIT_BITSIZE (mode),
> +                             GET_MODE_NUNITS (mode));
> +}
> +
>  /* A class for iterating through possible bitfield modes.  */
>  class bit_field_mode_iterator
>  {
> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c   2017-09-04 12:18:50.675762071 +0100
> +++ gcc/stor-layout.c   2017-09-04 12:18:53.153306182 +0100
> @@ -517,6 +517,23 @@ mode_for_vector (scalar_mode innermode,
>    return mode;
>  }
>
> +/* Return the mode for a vector that has NUNITS integer elements of
> +   INT_BITS bits each, if such a mode exists.  The mode can be either
> +   an integer mode or a vector mode.  */
> +
> +opt_machine_mode
> +mode_for_int_vector (unsigned int int_bits, unsigned int nunits)

That's more vector_int_mode_for_size (...), no?  Similar to int_mode_for_size
or mode_for_size.

Ok with those renamings.  I wonder if int_vector_mode_for_vector_mode
is necessary -- is calling vector_int_mode_for_size
(GET_MODE_UNIT_BITSIZE (mode),
GET_MODE_NUNITS (mode)) too cumbersome?

> +{
> +  scalar_int_mode int_mode;
> +  if (int_mode_for_size (int_bits, 0).exists (&int_mode))
> +    {
> +      machine_mode vec_mode = mode_for_vector (int_mode, nunits);

Uh, so we _do_ have an existing badly named 'mode_for_vector' ...

> +      if (vec_mode != BLKmode)
> +       return vec_mode;
> +    }
> +  return opt_machine_mode ();
> +}
> +
>  /* Return the alignment of MODE. This will be bounded by 1 and
>     BIGGEST_ALIGNMENT.  */
>
> Index: gcc/config/aarch64/aarch64.c
> ===================================================================
> --- gcc/config/aarch64/aarch64.c        2017-09-04 12:18:44.874165502 +0100
> +++ gcc/config/aarch64/aarch64.c        2017-09-04 12:18:53.144272229 +0100
> @@ -8282,9 +8282,6 @@ aarch64_emit_approx_sqrt (rtx dst, rtx s
>        return false;
>      }
>
> -  machine_mode mmsk
> -    = mode_for_vector (int_mode_for_mode (GET_MODE_INNER (mode)).require (),
> -                      GET_MODE_NUNITS (mode));
>    if (!recp)
>      {
>        if (!(flag_mlow_precision_sqrt
> @@ -8302,7 +8299,7 @@ aarch64_emit_approx_sqrt (rtx dst, rtx s
>      /* Caller assumes we cannot fail.  */
>      gcc_assert (use_rsqrt_p (mode));
>
> -
> +  machine_mode mmsk = mode_for_int_vector (mode).require ();
>    rtx xmsk = gen_reg_rtx (mmsk);
>    if (!recp)
>      /* When calculating the approximate square root, compare the
> Index: gcc/config/powerpcspe/powerpcspe.c
> ===================================================================
> --- gcc/config/powerpcspe/powerpcspe.c  2017-09-04 12:18:44.919414816 +0100
> +++ gcc/config/powerpcspe/powerpcspe.c  2017-09-04 12:18:53.148287319 +0100
> @@ -38739,8 +38739,7 @@ rs6000_do_expand_vec_perm (rtx target, r
>
>    imode = vmode;
>    if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
> -    imode = mode_for_vector
> -      (int_mode_for_mode (GET_MODE_INNER (vmode)).require (), nelt);
> +    imode = mode_for_int_vector (vmode).require ();
>
>    x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
>    x = expand_vec_perm (vmode, op0, op1, x, target);
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  2017-09-04 12:18:44.929470219 +0100
> +++ gcc/config/rs6000/rs6000.c  2017-09-04 12:18:53.151298637 +0100
> @@ -35584,8 +35584,7 @@ rs6000_do_expand_vec_perm (rtx target, r
>
>    imode = vmode;
>    if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
> -    imode = mode_for_vector
> -      (int_mode_for_mode (GET_MODE_INNER (vmode)).require (), nelt);
> +    imode = mode_for_int_vector (vmode).require ();
>
>    x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
>    x = expand_vec_perm (vmode, op0, op1, x, target);
> Index: gcc/config/s390/s390.c
> ===================================================================
> --- gcc/config/s390/s390.c      2017-09-04 11:50:24.561571751 +0100
> +++ gcc/config/s390/s390.c      2017-09-04 12:18:53.153306182 +0100
> @@ -6472,10 +6472,7 @@ s390_expand_vec_compare_cc (rtx target,
>         case LE:   cc_producer_mode = CCVFHEmode; code = GE; swap_p = true; break;
>         default: gcc_unreachable ();
>         }
> -      scratch_mode = mode_for_vector
> -       (int_mode_for_mode (GET_MODE_INNER (GET_MODE (cmp1))).require (),
> -        GET_MODE_NUNITS (GET_MODE (cmp1)));
> -      gcc_assert (scratch_mode != BLKmode);
> +      scratch_mode = mode_for_int_vector (GET_MODE (cmp1)).require ();
>
>        if (inv_p)
>         all_p = !all_p;
> @@ -6581,9 +6578,7 @@ s390_expand_vcond (rtx target, rtx then,
>
>    /* We always use an integral type vector to hold the comparison
>       result.  */
> -  result_mode = mode_for_vector
> -    (int_mode_for_mode (GET_MODE_INNER (cmp_mode)).require (),
> -     GET_MODE_NUNITS (cmp_mode));
> +  result_mode = mode_for_int_vector (cmp_mode).require ();
>    result_target = gen_reg_rtx (result_mode);
>
>    /* We allow vector immediates as comparison operands that

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [7/9] Make targetm.get_mask_mode return an opt_mode
  2017-09-04 11:41 ` [7/9] Make targetm.get_mask_mode " Richard Sandiford
@ 2017-09-05 11:37   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:37 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:41 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> ...for consistency with mode_for_vector.

Ok.

Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * target.def (get_mask_mode): Change return type to opt_mode.
>         Expand commentary.
>         * doc/tm.texi: Regenerate.
>         * targhooks.h (default_get_mask_mode): Return an opt_mode.
>         * targhooks.c (default_get_mask_mode): Likewise.
>         * config/i386/i386.c (ix86_get_mask_mode): Likewise.
>         * optabs-query.c (can_vec_mask_load_store_p): Update use of
>         targetm.get_mask_mode.
>         * tree.c (build_truth_vector_type): Likewise.
>
> Index: gcc/target.def
> ===================================================================
> --- gcc/target.def      2017-09-04 11:50:24.568774867 +0100
> +++ gcc/target.def      2017-09-04 12:18:58.594757220 +0100
> @@ -1877,10 +1877,16 @@ The default is zero which means to not i
>  /* Function to get a target mode for a vector mask.  */
>  DEFHOOK
>  (get_mask_mode,
> - "This hook returns mode to be used for a mask to be used for a vector\n\
> -of specified @var{length} with @var{nunits} elements.  By default an integer\n\
> -vector mode of a proper size is returned.",
> - machine_mode,
> + "A vector mask is a value that holds one boolean result for every element\n\
> +in a vector.  This hook returns the machine mode that should be used to\n\
> +represent such a mask when the vector in question is @var{length} bytes\n\
> +long and contains @var{nunits} elements.  The hook returns an empty\n\
> +@code{opt_machine_mode} if no such mode exists.\n\
> +\n\
> +The default implementation returns the mode of an integer vector that\n\
> +is @var{length} bytes long and that contains @var{nunits} elements,\n\
> +if such a mode exists.",
> + opt_machine_mode,
>   (unsigned nunits, unsigned length),
>   default_get_mask_mode)
>
> Index: gcc/doc/tm.texi
> ===================================================================
> --- gcc/doc/tm.texi     2017-09-04 11:50:24.566073698 +0100
> +++ gcc/doc/tm.texi     2017-09-04 12:18:58.593753447 +0100
> @@ -5820,10 +5820,16 @@ mode returned by @code{TARGET_VECTORIZE_
>  The default is zero which means to not iterate over other vector sizes.
>  @end deftypefn
>
> -@deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_GET_MASK_MODE (unsigned @var{nunits}, unsigned @var{length})
> -This hook returns mode to be used for a mask to be used for a vector
> -of specified @var{length} with @var{nunits} elements.  By default an integer
> -vector mode of a proper size is returned.
> +@deftypefn {Target Hook} opt_machine_mode TARGET_VECTORIZE_GET_MASK_MODE (unsigned @var{nunits}, unsigned @var{length})
> +A vector mask is a value that holds one boolean result for every element
> +in a vector.  This hook returns the machine mode that should be used to
> +represent such a mask when the vector in question is @var{length} bytes
> +long and contains @var{nunits} elements.  The hook returns an empty
> +@code{opt_machine_mode} if no such mode exists.
> +
> +The default implementation returns the mode of an integer vector that
> +is @var{length} bytes long and that contains @var{nunits} elements,
> +if such a mode exists.
>  @end deftypefn
>
>  @deftypefn {Target Hook} {void *} TARGET_VECTORIZE_INIT_COST (struct loop *@var{loop_info})
> Index: gcc/targhooks.h
> ===================================================================
> --- gcc/targhooks.h     2017-09-04 11:50:24.568774867 +0100
> +++ gcc/targhooks.h     2017-09-04 12:18:58.594757220 +0100
> @@ -102,7 +102,7 @@ default_builtin_support_vector_misalignm
>                                              int, bool);
>  extern machine_mode default_preferred_simd_mode (scalar_mode mode);
>  extern unsigned int default_autovectorize_vector_sizes (void);
> -extern machine_mode default_get_mask_mode (unsigned, unsigned);
> +extern opt_machine_mode default_get_mask_mode (unsigned, unsigned);
>  extern void *default_init_cost (struct loop *);
>  extern unsigned default_add_stmt_cost (void *, int, enum vect_cost_for_stmt,
>                                        struct _stmt_vec_info *, int,
> Index: gcc/targhooks.c
> ===================================================================
> --- gcc/targhooks.c     2017-09-04 12:18:55.825348732 +0100
> +++ gcc/targhooks.c     2017-09-04 12:18:58.594757220 +0100
> @@ -1200,7 +1200,7 @@ default_autovectorize_vector_sizes (void
>
>  /* By defaults a vector of integers is used as a mask.  */
>
> -machine_mode
> +opt_machine_mode
>  default_get_mask_mode (unsigned nunits, unsigned vector_size)
>  {
>    unsigned elem_size = vector_size / nunits;
> @@ -1210,12 +1210,12 @@ default_get_mask_mode (unsigned nunits,
>
>    gcc_assert (elem_size * nunits == vector_size);
>
> -  if (!mode_for_vector (elem_mode, nunits).exists (&vector_mode)
> -      || !VECTOR_MODE_P (vector_mode)
> -      || !targetm.vector_mode_supported_p (vector_mode))
> -    vector_mode = BLKmode;
> +  if (mode_for_vector (elem_mode, nunits).exists (&vector_mode)
> +      && VECTOR_MODE_P (vector_mode)
> +      && targetm.vector_mode_supported_p (vector_mode))
> +    return vector_mode;
>
> -  return vector_mode;
> +  return opt_machine_mode ();
>  }
>
>  /* By default, the cost model accumulates three separate costs (prologue,
> Index: gcc/config/i386/i386.c
> ===================================================================
> --- gcc/config/i386/i386.c      2017-09-04 12:18:55.808284598 +0100
> +++ gcc/config/i386/i386.c      2017-09-04 12:18:58.592749675 +0100
> @@ -51598,7 +51598,7 @@ ix86_autovectorize_vector_sizes (void)
>
>  /* Implemenation of targetm.vectorize.get_mask_mode.  */
>
> -static machine_mode
> +static opt_machine_mode
>  ix86_get_mask_mode (unsigned nunits, unsigned vector_size)
>  {
>    unsigned elem_size = vector_size / nunits;
> @@ -51616,7 +51616,7 @@ ix86_get_mask_mode (unsigned nunits, uns
>
>    gcc_assert (elem_size * nunits == vector_size);
>
> -  return mode_for_vector (elem_mode, nunits).else_blk ();
> +  return mode_for_vector (elem_mode, nunits);
>  }
>
>
> Index: gcc/optabs-query.c
> ===================================================================
> --- gcc/optabs-query.c  2017-09-04 12:18:55.821333642 +0100
> +++ gcc/optabs-query.c  2017-09-04 12:18:58.593753447 +0100
> @@ -531,12 +531,9 @@ can_vec_mask_load_store_p (machine_mode
>    if (!VECTOR_MODE_P (vmode))
>      return false;
>
> -  mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
> -                                              GET_MODE_SIZE (vmode));
> -  if (mask_mode == VOIDmode)
> -    return false;
> -
> -  if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
> +  if ((targetm.vectorize.get_mask_mode
> +       (GET_MODE_NUNITS (vmode), GET_MODE_SIZE (vmode)).exists (&mask_mode))
> +      && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
>      return true;
>
>    vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
> @@ -548,12 +545,10 @@ can_vec_mask_load_store_p (machine_mode
>         continue;
>        unsigned int nunits = cur / GET_MODE_SIZE (smode);
>        if (mode_for_vector (smode, nunits).exists (&vmode)
> -         && VECTOR_MODE_P (vmode))
> -       {
> -         mask_mode = targetm.vectorize.get_mask_mode (nunits, cur);
> -         if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
> -           return true;
> -       }
> +         && VECTOR_MODE_P (vmode)
> +         && targetm.vectorize.get_mask_mode (nunits, cur).exists (&mask_mode)
> +         && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
> +       return true;
>      }
>    return false;
>  }
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c  2017-08-30 12:19:19.721220029 +0100
> +++ gcc/tree.c  2017-09-04 12:18:58.595760992 +0100
> @@ -10243,10 +10243,8 @@ build_vector_type (tree innertype, int n
>  tree
>  build_truth_vector_type (unsigned nunits, unsigned vector_size)
>  {
> -  machine_mode mask_mode = targetm.vectorize.get_mask_mode (nunits,
> -                                                           vector_size);
> -
> -  gcc_assert (mask_mode != VOIDmode);
> +  machine_mode mask_mode
> +    = targetm.vectorize.get_mask_mode (nunits, vector_size).else_blk ();
>
>    unsigned HOST_WIDE_INT vsize;
>    if (mask_mode == BLKmode)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [6/9] Make mode_for_vector return an opt_mode
  2017-09-04 11:39 ` [6/9] Make mode_for_vector return an opt_mode Richard Sandiford
@ 2017-09-05 11:37   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:37 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:39 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> ...following on from the mode_for_size change.  The patch also removes
> machmode.h versions of the stor-layout.c comments, since the comments
> in the .c file are more complete.

Ok.

Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * machmode.h (mode_for_vector): Return an opt_mode.
>         * stor-layout.c (mode_for_vector): Likewise.
>         (mode_for_int_vector): Update accordingly.
>         (layout_type): Likewise.
>         * config/i386/i386.c (emit_memmov): Likewise.
>         (ix86_expand_set_or_movmem): Likewise.
>         (ix86_expand_vector_init): Likewise.
>         (ix86_get_mask_mode): Likewise.
>         * config/powerpcspe/powerpcspe.c (rs6000_expand_vec_perm_const_1):
>         Likewise.
>         * config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Likewise.
>         * expmed.c (extract_bit_field_1): Likewise.
>         * expr.c (expand_expr_real_2): Likewise.
>         * optabs-query.c (can_vec_perm_p): Likewise.
>         (can_vec_mask_load_store_p): Likewise.
>         * optabs.c (expand_vec_perm): Likewise.
>         * targhooks.c (default_get_mask_mode): Likewise.
>         * tree-vect-stmts.c (vectorizable_store): Likewise.
>         (vectorizable_load): Likewise.
>         (get_vectype_for_scalar_type_and_size): Likewise.
>
> Index: gcc/machmode.h
> ===================================================================
> --- gcc/machmode.h      2017-09-04 12:18:53.153306182 +0100
> +++ gcc/machmode.h      2017-09-04 12:18:55.821333642 +0100
> @@ -682,8 +682,6 @@ decimal_float_mode_for_size (unsigned in
>      (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
>  }
>
> -/* Similar to mode_for_size, but find the smallest mode for a given width.  */
> -
>  extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);
>
>  /* Find the narrowest integer mode that contains at least SIZE bits.
> @@ -695,17 +693,9 @@ smallest_int_mode_for_size (unsigned int
>    return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
>  }
>
> -/* Return an integer mode of exactly the same size as the input mode.  */
> -
>  extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
> -
>  extern machine_mode bitwise_mode_for_mode (machine_mode);
> -
> -/* Return a mode that is suitable for representing a vector,
> -   or BLKmode on failure.  */
> -
> -extern machine_mode mode_for_vector (scalar_mode, unsigned);
> -
> +extern opt_machine_mode mode_for_vector (scalar_mode, unsigned);
>  extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
>
>  /* Return the integer vector equivalent of MODE, if one exists.  In other
> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c   2017-09-04 12:18:53.153306182 +0100
> +++ gcc/stor-layout.c   2017-09-04 12:18:55.824344959 +0100
> @@ -471,11 +471,11 @@ bitwise_type_for_mode (machine_mode mode
>    return inner_type;
>  }
>
> -/* Find a mode that is suitable for representing a vector with
> -   NUNITS elements of mode INNERMODE.  Returns BLKmode if there
> -   is no suitable mode.  */
> +/* Find a mode that is suitable for representing a vector with NUNITS
> +   elements of mode INNERMODE, if one exists.  The returned mode can be
> +   either an integer mode or a vector mode.  */
>
> -machine_mode
> +opt_machine_mode
>  mode_for_vector (scalar_mode innermode, unsigned nunits)
>  {
>    machine_mode mode;
> @@ -499,22 +499,18 @@ mode_for_vector (scalar_mode innermode,
>    FOR_EACH_MODE_FROM (mode, mode)
>      if (GET_MODE_NUNITS (mode) == nunits
>         && GET_MODE_INNER (mode) == innermode)
> -      break;
> +      return mode;
>
>    /* For integers, try mapping it to a same-sized scalar mode.  */
> -  if (mode == VOIDmode
> -      && GET_MODE_CLASS (innermode) == MODE_INT)
> +  if (GET_MODE_CLASS (innermode) == MODE_INT)
>      {
>        unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);
> -      mode = int_mode_for_size (nbits, 0).else_blk ();
> +      if (int_mode_for_size (nbits, 0).exists (&mode)
> +         && have_regs_of_mode[mode])
> +       return mode;
>      }
>
> -  if (mode == VOIDmode
> -      || (GET_MODE_CLASS (mode) == MODE_INT
> -         && !have_regs_of_mode[mode]))
> -    return BLKmode;
> -
> -  return mode;
> +  return opt_machine_mode ();
>  }
>
>  /* Return the mode for a vector that has NUNITS integer elements of
> @@ -525,12 +521,10 @@ mode_for_vector (scalar_mode innermode,
>  mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
>  {
>    scalar_int_mode int_mode;
> -  if (int_mode_for_size (int_bits, 0).exists (&int_mode))
> -    {
> -      machine_mode vec_mode = mode_for_vector (int_mode, nunits);
> -      if (vec_mode != BLKmode)
> -       return vec_mode;
> -    }
> +  machine_mode vec_mode;
> +  if (int_mode_for_size (int_bits, 0).exists (&int_mode)
> +      && mode_for_vector (int_mode, nunits).exists (&vec_mode))
> +    return vec_mode;
>    return opt_machine_mode ();
>  }
>
> @@ -2264,7 +2258,7 @@ layout_type (tree type)
>         if (TYPE_MODE (type) == VOIDmode)
>           SET_TYPE_MODE (type,
>                          mode_for_vector (SCALAR_TYPE_MODE (innertype),
> -                                         nunits));
> +                                         nunits).else_blk ());
>
>         TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
>          TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
> Index: gcc/config/i386/i386.c
> ===================================================================
> --- gcc/config/i386/i386.c      2017-09-04 12:18:44.903326171 +0100
> +++ gcc/config/i386/i386.c      2017-09-04 12:18:55.808284598 +0100
> @@ -27420,9 +27420,8 @@ emit_memmov (rtx destmem, rtx *srcmem, r
>    if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
>      {
>        int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
> -      move_mode = mode_for_vector (word_mode, nunits);
> -      code = optab_handler (mov_optab, move_mode);
> -      if (code == CODE_FOR_nothing)
> +      if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
> +         || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
>         {
>           move_mode = word_mode;
>           piece_size = GET_MODE_SIZE (move_mode);
> @@ -28654,8 +28653,8 @@ ix86_expand_set_or_movmem (rtx dst, rtx
>        if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
>         {
>           int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
> -         move_mode = mode_for_vector (word_mode, nunits);
> -         if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
> +         if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
> +             || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
>             move_mode = word_mode;
>         }
>        gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
> @@ -44497,11 +44496,9 @@ ix86_expand_vector_init (bool mmx_ok, rt
>           rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
>           if (inner_mode == QImode || inner_mode == HImode)
>             {
> -             mode = mode_for_vector (SImode,
> -                                     n_elts * GET_MODE_SIZE (inner_mode) / 4);
> -             inner_mode
> -               = mode_for_vector (SImode,
> -                                  n_elts * GET_MODE_SIZE (inner_mode) / 8);
> +             unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
> +             mode = mode_for_vector (SImode, n_bits / 4).require ();
> +             inner_mode = mode_for_vector (SImode, n_bits / 8).require ();
>               ops[0] = gen_lowpart (inner_mode, ops[0]);
>               ops[1] = gen_lowpart (inner_mode, ops[1]);
>               subtarget = gen_reg_rtx (mode);
> @@ -51619,7 +51616,7 @@ ix86_get_mask_mode (unsigned nunits, uns
>
>    gcc_assert (elem_size * nunits == vector_size);
>
> -  return mode_for_vector (elem_mode, nunits);
> +  return mode_for_vector (elem_mode, nunits).else_blk ();
>  }
>
>
> Index: gcc/config/powerpcspe/powerpcspe.c
> ===================================================================
> --- gcc/config/powerpcspe/powerpcspe.c  2017-09-04 12:18:53.148287319 +0100
> +++ gcc/config/powerpcspe/powerpcspe.c  2017-09-04 12:18:55.812299689 +0100
> @@ -38679,7 +38679,7 @@ rs6000_expand_vec_perm_const_1 (rtx targ
>
>        vmode = GET_MODE (target);
>        gcc_assert (GET_MODE_NUNITS (vmode) == 2);
> -      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
> +      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
>        x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
>        v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
>        x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  2017-09-04 12:18:53.151298637 +0100
> +++ gcc/config/rs6000/rs6000.c  2017-09-04 12:18:55.815311006 +0100
> @@ -35525,7 +35525,7 @@ rs6000_expand_vec_perm_const_1 (rtx targ
>
>        vmode = GET_MODE (target);
>        gcc_assert (GET_MODE_NUNITS (vmode) == 2);
> -      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
> +      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
>        x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
>        v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
>        x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
> Index: gcc/expmed.c
> ===================================================================
> --- gcc/expmed.c        2017-09-04 12:18:50.673054653 +0100
> +++ gcc/expmed.c        2017-09-04 12:18:55.817318551 +0100
> @@ -1578,10 +1578,11 @@ extract_bit_field_1 (rtx str_rtx, unsign
>        machine_mode new_mode = GET_MODE (op0);
>        if (GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode))
>         {
> -         new_mode = mode_for_vector (GET_MODE_INNER (tmode),
> -                                     GET_MODE_BITSIZE (GET_MODE (op0))
> -                                     / GET_MODE_UNIT_BITSIZE (tmode));
> -         if (!VECTOR_MODE_P (new_mode)
> +         scalar_mode inner_mode = GET_MODE_INNER (tmode);
> +         unsigned int nunits = (GET_MODE_BITSIZE (GET_MODE (op0))
> +                                / GET_MODE_UNIT_BITSIZE (tmode));
> +         if (!mode_for_vector (inner_mode, nunits).exists (&new_mode)
> +             || !VECTOR_MODE_P (new_mode)
>               || GET_MODE_SIZE (new_mode) != GET_MODE_SIZE (GET_MODE (op0))
>               || GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode)
>               || !targetm.vector_mode_supported_p (new_mode))
> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c  2017-09-04 12:18:44.938520082 +0100
> +++ gcc/expr.c  2017-09-04 12:18:55.820329869 +0100
> @@ -9445,7 +9445,7 @@ #define REDUCE_BIT_FIELD(expr)    (reduce_b
>           tree sel_type = TREE_TYPE (treeop2);
>           machine_mode vmode
>             = mode_for_vector (SCALAR_TYPE_MODE (TREE_TYPE (sel_type)),
> -                              TYPE_VECTOR_SUBPARTS (sel_type));
> +                              TYPE_VECTOR_SUBPARTS (sel_type)).require ();
>           gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
>           op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
>           gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);
> Index: gcc/optabs-query.c
> ===================================================================
> --- gcc/optabs-query.c  2017-08-30 12:20:31.700622400 +0100
> +++ gcc/optabs-query.c  2017-09-04 12:18:55.821333642 +0100
> @@ -376,10 +376,9 @@ can_vec_perm_p (machine_mode mode, bool
>      return true;
>
>    /* We allow fallback to a QI vector mode, and adjust the mask.  */
> -  if (GET_MODE_INNER (mode) == QImode)
> -    return false;
> -  qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
> -  if (!VECTOR_MODE_P (qimode))
> +  if (GET_MODE_INNER (mode) == QImode
> +      || !mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode)
> +      || !VECTOR_MODE_P (qimode))
>      return false;
>
>    /* ??? For completeness, we ought to check the QImode version of
> @@ -547,12 +546,14 @@ can_vec_mask_load_store_p (machine_mode
>        vector_sizes &= ~cur;
>        if (cur <= GET_MODE_SIZE (smode))
>         continue;
> -      vmode = mode_for_vector (smode, cur / GET_MODE_SIZE (smode));
> -      mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
> -                                                  cur);
> -      if (VECTOR_MODE_P (vmode)
> -         && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
> -       return true;
> +      unsigned int nunits = cur / GET_MODE_SIZE (smode);
> +      if (mode_for_vector (smode, nunits).exists (&vmode)
> +         && VECTOR_MODE_P (vmode))
> +       {
> +         mask_mode = targetm.vectorize.get_mask_mode (nunits, cur);
> +         if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
> +           return true;
> +       }
>      }
>    return false;
>  }
> Index: gcc/optabs.c
> ===================================================================
> --- gcc/optabs.c        2017-09-04 11:48:08.609549644 +0100
> +++ gcc/optabs.c        2017-09-04 12:18:55.823341187 +0100
> @@ -5434,13 +5434,10 @@ expand_vec_perm (machine_mode mode, rtx
>
>    /* Set QIMODE to a different vector mode with byte elements.
>       If no such mode, or if MODE already has byte elements, use VOIDmode.  */
> -  qimode = VOIDmode;
> -  if (GET_MODE_INNER (mode) != QImode)
> -    {
> -      qimode = mode_for_vector (QImode, w);
> -      if (!VECTOR_MODE_P (qimode))
> -       qimode = VOIDmode;
> -    }
> +  if (GET_MODE_INNER (mode) == QImode
> +      || !mode_for_vector (QImode, w).exists (&qimode)
> +      || !VECTOR_MODE_P (qimode))
> +    qimode = VOIDmode;
>
>    /* If the input is a constant, expand it specially.  */
>    gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);
> Index: gcc/targhooks.c
> ===================================================================
> --- gcc/targhooks.c     2017-09-04 11:50:24.568774867 +0100
> +++ gcc/targhooks.c     2017-09-04 12:18:55.825348732 +0100
> @@ -1210,8 +1210,8 @@ default_get_mask_mode (unsigned nunits,
>
>    gcc_assert (elem_size * nunits == vector_size);
>
> -  vector_mode = mode_for_vector (elem_mode, nunits);
> -  if (!VECTOR_MODE_P (vector_mode)
> +  if (!mode_for_vector (elem_mode, nunits).exists (&vector_mode)
> +      || !VECTOR_MODE_P (vector_mode)
>        || !targetm.vector_mode_supported_p (vector_mode))
>      vector_mode = BLKmode;
>
> Index: gcc/tree-vect-stmts.c
> ===================================================================
> --- gcc/tree-vect-stmts.c       2017-08-31 07:32:43.676061469 +0100
> +++ gcc/tree-vect-stmts.c       2017-09-04 12:18:55.828360049 +0100
> @@ -6032,8 +6032,9 @@ vectorizable_store (gimple *stmt, gimple
>               /* First check if vec_extract optab doesn't support extraction
>                  of vector elts directly.  */
>               scalar_mode elmode = SCALAR_TYPE_MODE (elem_type);
> -             machine_mode vmode = mode_for_vector (elmode, group_size);
> -             if (! VECTOR_MODE_P (vmode)
> +             machine_mode vmode;
> +             if (!mode_for_vector (elmode, group_size).exists (&vmode)
> +                 || !VECTOR_MODE_P (vmode)
>                   || (convert_optab_handler (vec_extract_optab,
>                                              TYPE_MODE (vectype), vmode)
>                       == CODE_FOR_nothing))
> @@ -6046,11 +6047,12 @@ vectorizable_store (gimple *stmt, gimple
>                   unsigned lsize
>                     = group_size * GET_MODE_BITSIZE (elmode);
>                   elmode = int_mode_for_size (lsize, 0).require ();
> -                 vmode = mode_for_vector (elmode, nunits / group_size);
>                   /* If we can't construct such a vector fall back to
>                      element extracts from the original vector type and
>                      element size stores.  */
> -                 if (VECTOR_MODE_P (vmode)
> +                 if (mode_for_vector (elmode,
> +                                      nunits / group_size).exists (&vmode)
> +                     && VECTOR_MODE_P (vmode)
>                       && (convert_optab_handler (vec_extract_optab,
>                                                  vmode, elmode)
>                           != CODE_FOR_nothing))
> @@ -7070,8 +7072,9 @@ vectorizable_load (gimple *stmt, gimple_
>               /* First check if vec_init optab supports construction from
>                  vector elts directly.  */
>               scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vectype));
> -             machine_mode vmode = mode_for_vector (elmode, group_size);
> -             if (VECTOR_MODE_P (vmode)
> +             machine_mode vmode;
> +             if (mode_for_vector (elmode, group_size).exists (&vmode)
> +                 && VECTOR_MODE_P (vmode)
>                   && (convert_optab_handler (vec_init_optab,
>                                              TYPE_MODE (vectype), vmode)
>                       != CODE_FOR_nothing))
> @@ -7092,10 +7095,11 @@ vectorizable_load (gimple *stmt, gimple_
>                   unsigned lsize
>                     = group_size * TYPE_PRECISION (TREE_TYPE (vectype));
>                   elmode = int_mode_for_size (lsize, 0).require ();
> -                 vmode = mode_for_vector (elmode, nunits / group_size);
>                   /* If we can't construct such a vector fall back to
>                      element loads of the original vector type.  */
> -                 if (VECTOR_MODE_P (vmode)
> +                 if (mode_for_vector (elmode,
> +                                      nunits / group_size).exists (&vmode)
> +                     && VECTOR_MODE_P (vmode)
>                       && (convert_optab_handler (vec_init_optab, vmode, elmode)
>                           != CODE_FOR_nothing))
>                     {
> @@ -9098,8 +9102,8 @@ get_vectype_for_scalar_type_and_size (tr
>       lookup a vector mode of the specified size.  */
>    if (size == 0)
>      simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
> -  else
> -    simd_mode = mode_for_vector (inner_mode, size / nbytes);
> +  else if (!mode_for_vector (inner_mode, size / nbytes).exists (&simd_mode))
> +    return NULL_TREE;
>    nunits = GET_MODE_SIZE (simd_mode) / nbytes;
>    /* NOTE: nunits == 1 is allowed to support single element vector types.  */
>    if (nunits < 1)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [8/9] Make mode_for_size_tree return an opt_mode
  2017-09-04 11:42 ` [8/9] Make mode_for_size_tree " Richard Sandiford
@ 2017-09-05 11:38   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:38 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:42 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> ...for consistency with mode_for_size

Ok.

Thanks,
Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * stor-layout.h (mode_for_size_tree): Return an opt_mode.
>         * stor-layout.c (mode_for_size_tree): Likewise.
>         (mode_for_array): Update accordingly.
>         (layout_decl): Likewise.
>         (compute_record_mode): Likewise.  Only set the mode once.
>
> gcc/ada/
>         * gcc-interface/utils.c (make_packable_type): Update call to
>         mode_for_size_tree.
>
> Index: gcc/stor-layout.h
> ===================================================================
> --- gcc/stor-layout.h   2017-08-21 12:14:47.158835574 +0100
> +++ gcc/stor-layout.h   2017-09-04 12:19:01.144339518 +0100
> @@ -99,7 +99,7 @@ extern tree make_unsigned_type (int);
>     If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
>     The value is BLKmode if no other mode is found.  This is like
>     mode_for_size, but is passed a tree.  */
> -extern machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
> +extern opt_machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
>
>  extern tree bitwise_type_for_mode (machine_mode);
>
> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c   2017-09-04 12:18:55.824344959 +0100
> +++ gcc/stor-layout.c   2017-09-04 12:19:01.144339518 +0100
> @@ -321,19 +321,19 @@ mode_for_size (unsigned int size, enum m
>
>  /* Similar, except passed a tree node.  */
>
> -machine_mode
> +opt_machine_mode
>  mode_for_size_tree (const_tree size, enum mode_class mclass, int limit)
>  {
>    unsigned HOST_WIDE_INT uhwi;
>    unsigned int ui;
>
>    if (!tree_fits_uhwi_p (size))
> -    return BLKmode;
> +    return opt_machine_mode ();
>    uhwi = tree_to_uhwi (size);
>    ui = uhwi;
>    if (uhwi != ui)
> -    return BLKmode;
> -  return mode_for_size (ui, mclass, limit).else_blk ();
> +    return opt_machine_mode ();
> +  return mode_for_size (ui, mclass, limit);
>  }
>
>  /* Return the narrowest mode of class MCLASS that contains at least
> @@ -563,7 +563,7 @@ mode_for_array (tree elem_type, tree siz
>                                              int_size / int_elem_size))
>         limit_p = false;
>      }
> -  return mode_for_size_tree (size, MODE_INT, limit_p);
> +  return mode_for_size_tree (size, MODE_INT, limit_p).else_blk ();
>  }
>
>  /* Subroutine of layout_decl: Force alignment required for the data type.
> @@ -683,17 +683,18 @@ layout_decl (tree decl, unsigned int kno
>               && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
>               && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
>             {
> -             machine_mode xmode
> -               = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
> -             unsigned int xalign = GET_MODE_ALIGNMENT (xmode);
> -
> -             if (xmode != BLKmode
> -                 && !(xalign > BITS_PER_UNIT && DECL_PACKED (decl))
> -                 && (known_align == 0 || known_align >= xalign))
> +             machine_mode xmode;
> +             if (mode_for_size_tree (DECL_SIZE (decl),
> +                                     MODE_INT, 1).exists (&xmode))
>                 {
> -                 SET_DECL_ALIGN (decl, MAX (xalign, DECL_ALIGN (decl)));
> -                 SET_DECL_MODE (decl, xmode);
> -                 DECL_BIT_FIELD (decl) = 0;
> +                 unsigned int xalign = GET_MODE_ALIGNMENT (xmode);
> +                 if (!(xalign > BITS_PER_UNIT && DECL_PACKED (decl))
> +                     && (known_align == 0 || known_align >= xalign))
> +                   {
> +                     SET_DECL_ALIGN (decl, MAX (xalign, DECL_ALIGN (decl)));
> +                     SET_DECL_MODE (decl, xmode);
> +                     DECL_BIT_FIELD (decl) = 0;
> +                   }
>                 }
>             }
>
> @@ -1756,22 +1757,24 @@ compute_record_mode (tree type)
>    if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode
>        && tree_fits_uhwi_p (TYPE_SIZE (type))
>        && GET_MODE_BITSIZE (mode) == tree_to_uhwi (TYPE_SIZE (type)))
> -    SET_TYPE_MODE (type, mode);
> +    ;
>    else
> -    SET_TYPE_MODE (type, mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1));
> +    mode = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1).else_blk ();
>
>    /* If structure's known alignment is less than what the scalar
>       mode would need, and it matters, then stick with BLKmode.  */
> -  if (TYPE_MODE (type) != BLKmode
> +  if (mode != BLKmode
>        && STRICT_ALIGNMENT
>        && ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
> -           || TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
> +           || TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (mode)))
>      {
>        /* If this is the only reason this type is BLKmode, then
>          don't force containing types to be BLKmode.  */
>        TYPE_NO_FORCE_BLK (type) = 1;
> -      SET_TYPE_MODE (type, BLKmode);
> +      mode = BLKmode;
>      }
> +
> +  SET_TYPE_MODE (type, mode);
>  }
>
>  /* Compute TYPE_SIZE and TYPE_ALIGN for TYPE, once it has been laid
> Index: gcc/ada/gcc-interface/utils.c
> ===================================================================
> --- gcc/ada/gcc-interface/utils.c       2017-08-30 12:10:52.658405667 +0100
> +++ gcc/ada/gcc-interface/utils.c       2017-09-04 12:19:01.143335745 +0100
> @@ -1076,7 +1076,8 @@ make_packable_type (tree type, bool in_r
>       in case the record itself contains a BLKmode field.  */
>    if (in_record && TYPE_MODE (new_type) == BLKmode)
>      SET_TYPE_MODE (new_type,
> -                  mode_for_size_tree (TYPE_SIZE (new_type), MODE_INT, 1));
> +                  mode_for_size_tree (TYPE_SIZE (new_type),
> +                                      MODE_INT, 1).else_blk ());
>
>    /* If neither mode nor size nor alignment shrunk, return the old type.  */
>    if (TYPE_MODE (new_type) == BLKmode && new_size >= size && max_align == 0)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [9/9] Make bitsize_mode_for_mode return an opt_mode
  2017-09-04 11:43 ` [9/9] Make bitsize_mode_for_mode " Richard Sandiford
@ 2017-09-05 11:39   ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 11:39 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Mon, Sep 4, 2017 at 1:43 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

Ok.

Richard.

> gcc/
>         * machmode.h (bitwise_mode_for_mode): Return opt_mode.
>         * stor-layout.c (bitwise_mode_for_mode): Likewise.
>         (bitwise_type_for_mode): Update accordingly.
>
> Index: gcc/machmode.h
> ===================================================================
> --- gcc/machmode.h      2017-09-04 12:18:55.821333642 +0100
> +++ gcc/machmode.h      2017-09-04 12:19:42.856108173 +0100
> @@ -694,7 +694,7 @@ smallest_int_mode_for_size (unsigned int
>  }
>
>  extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
> -extern machine_mode bitwise_mode_for_mode (machine_mode);
> +extern opt_machine_mode bitwise_mode_for_mode (machine_mode);
>  extern opt_machine_mode mode_for_vector (scalar_mode, unsigned);
>  extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
>
> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c   2017-09-04 12:19:01.144339518 +0100
> +++ gcc/stor-layout.c   2017-09-04 12:19:42.856108173 +0100
> @@ -404,10 +404,10 @@ int_mode_for_mode (machine_mode mode)
>      }
>  }
>
> -/* Find a mode that can be used for efficient bitwise operations on MODE.
> -   Return BLKmode if no such mode exists.  */
> +/* Find a mode that can be used for efficient bitwise operations on MODE,
> +   if one exists.  */
>
> -machine_mode
> +opt_machine_mode
>  bitwise_mode_for_mode (machine_mode mode)
>  {
>    /* Quick exit if we already have a suitable mode.  */
> @@ -445,7 +445,7 @@ bitwise_mode_for_mode (machine_mode mode
>      }
>
>    /* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE.  */
> -  return mode_for_size (bitsize, MODE_INT, true).else_blk ();
> +  return mode_for_size (bitsize, MODE_INT, true);
>  }
>
>  /* Find a type that can be used for efficient bitwise operations on MODE.
> @@ -454,8 +454,7 @@ bitwise_mode_for_mode (machine_mode mode
>  tree
>  bitwise_type_for_mode (machine_mode mode)
>  {
> -  mode = bitwise_mode_for_mode (mode);
> -  if (mode == BLKmode)
> +  if (!bitwise_mode_for_mode (mode).exists (&mode))
>      return NULL_TREE;
>
>    unsigned int inner_size = GET_MODE_UNIT_BITSIZE (mode);

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [5/9] Add mode_for_int_vector helper functions
  2017-09-05 11:35   ` Richard Biener
@ 2017-09-05 12:33     ` Richard Sandiford
  2017-09-05 12:58       ` Richard Biener
  0 siblings, 1 reply; 21+ messages in thread
From: Richard Sandiford @ 2017-09-05 12:33 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

Richard Biener <richard.guenther@gmail.com> writes:
> On Mon, Sep 4, 2017 at 1:36 PM, Richard Sandiford
> <richard.sandiford@linaro.org> wrote:
>> There are at least a few places that want to create an integer vector
>> with a specified element size and element count, or to create the
>> integer equivalent of an existing mode.  This patch adds helpers
>> for doing that.
>>
>> The require ()s are all used in functions that go on to emit
>> instructions that use the result as a vector mode.
>>
>> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>>
>> gcc/
>>         * machmode.h (mode_for_int_vector): New function.
>>         * stor-layout.c (mode_for_int_vector): Likewise.
>>         * config/aarch64/aarch64.c (aarch64_emit_approx_sqrt): Use it.
>>         * config/powerpcspe/powerpcspe.c (rs6000_do_expand_vec_perm): Likewise.
>>         * config/rs6000/rs6000.c (rs6000_do_expand_vec_perm): Likewise.
>>         * config/s390/s390.c (s390_expand_vec_compare_cc): Likewise.
>>         (s390_expand_vcond): Likewise.
>>
>> Index: gcc/machmode.h
>> ===================================================================
>> --- gcc/machmode.h      2017-09-04 12:18:50.674859598 +0100
>> +++ gcc/machmode.h      2017-09-04 12:18:53.153306182 +0100
>> @@ -706,6 +706,21 @@ extern machine_mode bitwise_mode_for_mod
>>
>>  extern machine_mode mode_for_vector (scalar_mode, unsigned);
>>
>> +extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
>> +
>> +/* Return the integer vector equivalent of MODE, if one exists.  In other
>> +   words, return the mode for an integer vector that has the same number
>> +   of bits as MODE and the same number of elements as MODE, with the
>> +   latter being 1 if MODE is scalar.  The returned mode can be either
>> +   an integer mode or a vector mode.  */
>> +
>> +inline opt_machine_mode
>> +mode_for_int_vector (machine_mode mode)
>
> So this is similar to int_mode_for_mode which means...
>
> int_vector_mode_for_vector_mode?

I'd used that style of name originally, but didn't like it because
it gave the impression that the result would be a VECTOR_MODE_P.

mode_for_int_vector was supposed to be consistent with mode_for_vector.

>> +{
>
> Nothing prevents use with non-vector MODE here, can we place an assert here?

That was deliberate.  I wanted it to work with scalars too, returning
a V1xx in that case.

>> +  return mode_for_int_vector (GET_MODE_UNIT_BITSIZE (mode),
>> +                             GET_MODE_NUNITS (mode));
>> +}
>> +
>>  /* A class for iterating through possible bitfield modes.  */
>>  class bit_field_mode_iterator
>>  {
>> Index: gcc/stor-layout.c
>> ===================================================================
>> --- gcc/stor-layout.c   2017-09-04 12:18:50.675762071 +0100
>> +++ gcc/stor-layout.c   2017-09-04 12:18:53.153306182 +0100
>> @@ -517,6 +517,23 @@ mode_for_vector (scalar_mode innermode,
>>    return mode;
>>  }
>>
>> +/* Return the mode for a vector that has NUNITS integer elements of
>> +   INT_BITS bits each, if such a mode exists.  The mode can be either
>> +   an integer mode or a vector mode.  */
>> +
>> +opt_machine_mode
>> +mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
>
> That's more vector_int_mode_for_size (...), no?  Similar to int_mode_for_size
> or mode_for_size.
>
> Ok with those renamings.  I wonder if int_vector_mode_for_vector_mode
> is necessary -- is calling vector_int_mode_for_size
> (GET_MODE_UNIT_BITSIZE (mode),
> GET_MODE_NUNITS (mode)) too cumbersome?

IMO yes :-)  It's certainly longer than the equivalent int_mode_for_mode
expansion.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [5/9] Add mode_for_int_vector helper functions
  2017-09-05 12:33     ` Richard Sandiford
@ 2017-09-05 12:58       ` Richard Biener
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Biener @ 2017-09-05 12:58 UTC (permalink / raw)
  To: Richard Biener, GCC Patches, Richard Sandiford

On Tue, Sep 5, 2017 at 2:33 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> Richard Biener <richard.guenther@gmail.com> writes:
>> On Mon, Sep 4, 2017 at 1:36 PM, Richard Sandiford
>> <richard.sandiford@linaro.org> wrote:
>>> There are at least a few places that want to create an integer vector
>>> with a specified element size and element count, or to create the
>>> integer equivalent of an existing mode.  This patch adds helpers
>>> for doing that.
>>>
>>> The require ()s are all used in functions that go on to emit
>>> instructions that use the result as a vector mode.
>>>
>>> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>
>>>
>>> gcc/
>>>         * machmode.h (mode_for_int_vector): New function.
>>>         * stor-layout.c (mode_for_int_vector): Likewise.
>>>         * config/aarch64/aarch64.c (aarch64_emit_approx_sqrt): Use it.
>>>         * config/powerpcspe/powerpcspe.c (rs6000_do_expand_vec_perm): Likewise.
>>>         * config/rs6000/rs6000.c (rs6000_do_expand_vec_perm): Likewise.
>>>         * config/s390/s390.c (s390_expand_vec_compare_cc): Likewise.
>>>         (s390_expand_vcond): Likewise.
>>>
>>> Index: gcc/machmode.h
>>> ===================================================================
>>> --- gcc/machmode.h      2017-09-04 12:18:50.674859598 +0100
>>> +++ gcc/machmode.h      2017-09-04 12:18:53.153306182 +0100
>>> @@ -706,6 +706,21 @@ extern machine_mode bitwise_mode_for_mod
>>>
>>>  extern machine_mode mode_for_vector (scalar_mode, unsigned);
>>>
>>> +extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
>>> +
>>> +/* Return the integer vector equivalent of MODE, if one exists.  In other
>>> +   words, return the mode for an integer vector that has the same number
>>> +   of bits as MODE and the same number of elements as MODE, with the
>>> +   latter being 1 if MODE is scalar.  The returned mode can be either
>>> +   an integer mode or a vector mode.  */
>>> +
>>> +inline opt_machine_mode
>>> +mode_for_int_vector (machine_mode mode)
>>
>> So this is similar to int_mode_for_mode which means...
>>
>> int_vector_mode_for_vector_mode?
>
> I'd used that style of name originally, but didn't like it because
> it gave the impression that the result would be a VECTOR_MODE_P.

Oh, it isn't?  Ah, yes, it can be an integer mode...

> mode_for_int_vector was supposed to be consistent with mode_for_vector.
>
>>> +{
>>
>> Nothing prevents use with non-vector MODE here, can we place an assert here?
>
> That was deliberate.  I wanted it to work with scalars too, returning
> a V1xx in that case.

Ok.

>>> +  return mode_for_int_vector (GET_MODE_UNIT_BITSIZE (mode),
>>> +                             GET_MODE_NUNITS (mode));
>>> +}
>>> +
>>>  /* A class for iterating through possible bitfield modes.  */
>>>  class bit_field_mode_iterator
>>>  {
>>> Index: gcc/stor-layout.c
>>> ===================================================================
>>> --- gcc/stor-layout.c   2017-09-04 12:18:50.675762071 +0100
>>> +++ gcc/stor-layout.c   2017-09-04 12:18:53.153306182 +0100
>>> @@ -517,6 +517,23 @@ mode_for_vector (scalar_mode innermode,
>>>    return mode;
>>>  }
>>>
>>> +/* Return the mode for a vector that has NUNITS integer elements of
>>> +   INT_BITS bits each, if such a mode exists.  The mode can be either
>>> +   an integer mode or a vector mode.  */
>>> +
>>> +opt_machine_mode
>>> +mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
>>
>> That's more vector_int_mode_for_size (...), no?  Similar to int_mode_for_size
>> or mode_for_size.
>>
>> Ok with those renamings.  I wonder if int_vector_mode_for_vector_mode
>> is necessary -- is calling vector_int_mode_for_size
>> (GET_MODE_UNIT_BITSIZE (mode),
>> GET_MODE_NUNITS (mode)) too cumbersome?
>
> IMO yes :-)  It's certainly longer than the equivalent int_mode_for_mode
> expansion.

I see.

Patch is ok as-is then.

Thanks,
Richard.

> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2017-09-05 12:58 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-04 11:24 [0/9] Make more use of opt_mode Richard Sandiford
2017-09-04 11:26 ` [1/9] Make more use of int_mode_for_mode Richard Sandiford
2017-09-05 11:22   ` Richard Biener
2017-09-04 11:31 ` [2/9] Make more use of int_mode_for_size Richard Sandiford
2017-09-05 11:23   ` Richard Biener
2017-09-04 11:32 ` [3/9] (decimal_)float_mode_for_size in real.h Richard Sandiford
2017-09-05 11:24   ` Richard Biener
2017-09-04 11:35 ` [4/9] Make mode_for_size return an opt_mode Richard Sandiford
2017-09-05 11:25   ` Richard Biener
2017-09-04 11:37 ` [5/9] Add mode_for_int_vector helper functions Richard Sandiford
2017-09-05 11:35   ` Richard Biener
2017-09-05 12:33     ` Richard Sandiford
2017-09-05 12:58       ` Richard Biener
2017-09-04 11:39 ` [6/9] Make mode_for_vector return an opt_mode Richard Sandiford
2017-09-05 11:37   ` Richard Biener
2017-09-04 11:41 ` [7/9] Make targetm.get_mask_mode " Richard Sandiford
2017-09-05 11:37   ` Richard Biener
2017-09-04 11:42 ` [8/9] Make mode_for_size_tree " Richard Sandiford
2017-09-05 11:38   ` Richard Biener
2017-09-04 11:43 ` [9/9] Make bitsize_mode_for_mode " Richard Sandiford
2017-09-05 11:39   ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).