diff mbox series

Refactoring the misaligned expansion bits

Message ID AM6PR10MB2566B085B56D089AD742FB76E4BA0@AM6PR10MB2566.EURPRD10.PROD.OUTLOOK.COM
State New
Headers show
Series Refactoring the misaligned expansion bits | expand

Commit Message

Bernd Edlinger Sept. 6, 2019, 6:02 a.m. UTC
Hi,


as discussed already I propose this little refactoring as a follow-up
which is not supposed to be doing any change to the code generation.

I tried to get the description of ALT_RTL right, since it changed
quite a lot recently what this weird parameter does, and nobody
cared to update the comments :-/

I stared a while at the VCE expansion, and I kind of think that
there is probably still something not quite right there,
since we expand

           orig_op0
              = expand_expr_real (tem,
                                  (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
                                   && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
                                       != INTEGER_CST)
                                   && modifier != EXPAND_STACK_PARM
                                   ? target : NULL_RTX),
                                  VOIDmode,
                                  modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier,
                                  NULL, true);

so inner_reference_p = true we want the memory address, maybe unaligned.
But later op0 is used in a context where it needs to be aligned:

      else if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (treeop0)))
        op0 = convert_modes (mode, GET_MODE (op0), op0,
                             TYPE_UNSIGNED (TREE_TYPE (treeop0)));

and especially this:

          if (modifier != EXPAND_WRITE
              && modifier != EXPAND_MEMORY
              && !inner_reference_p
              && mode != BLKmode
              && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
            {
                  [...]
                  if (GET_MODE (op0) == BLKmode)
                    {
                      rtx size_rtx = gen_int_mode (mode_size, Pmode);
                      emit_block_move (new_with_op0_mode, op0, size_rtx,
                                       (modifier == EXPAND_STACK_PARM
                                        ? BLOCK_OP_CALL_PARM
                                        : BLOCK_OP_NORMAL));
                    }
                  else
                    emit_move_insn (new_with_op0_mode, op0);

?

I think this kind of stuff happens more often in Ada, but at least in the Ada
test suite there was nothing triggering any of the sanitation assertions.

But time will tell.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.

Comments

Jeff Law Sept. 9, 2019, 6:48 p.m. UTC | #1
On 9/6/19 12:02 AM, Bernd Edlinger wrote:
> Hi,
> 
> 
> as discussed already I propose this little refactoring as a follow-up
> which is not supposed to be doing any change to the code generation.
> 
> I tried to get the description of ALT_RTL right, since it changed
> quite a lot recently what this weird parameter does, and nobody
> cared to update the comments :-/
> 
> I stared a while at the VCE expansion, and I kind of think that
> there is probably still something not quite right there,
> since we expand
> 
>            orig_op0
>               = expand_expr_real (tem,
>                                   (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
>                                    && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
>                                        != INTEGER_CST)
>                                    && modifier != EXPAND_STACK_PARM
>                                    ? target : NULL_RTX),
>                                   VOIDmode,
>                                   modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier,
>                                   NULL, true);
> 
> so inner_reference_p = true we want the memory address, maybe unaligned.
> But later op0 is used in a context where it needs to be aligned:
> 
>       else if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (treeop0)))
>         op0 = convert_modes (mode, GET_MODE (op0), op0,
>                              TYPE_UNSIGNED (TREE_TYPE (treeop0)));
> 
> and especially this:
> 
>           if (modifier != EXPAND_WRITE
>               && modifier != EXPAND_MEMORY
>               && !inner_reference_p
>               && mode != BLKmode
>               && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
>             {
>                   [...]
>                   if (GET_MODE (op0) == BLKmode)
>                     {
>                       rtx size_rtx = gen_int_mode (mode_size, Pmode);
>                       emit_block_move (new_with_op0_mode, op0, size_rtx,
>                                        (modifier == EXPAND_STACK_PARM
>                                         ? BLOCK_OP_CALL_PARM
>                                         : BLOCK_OP_NORMAL));
>                     }
>                   else
>                     emit_move_insn (new_with_op0_mode, op0);
> 
> ?
> 
> I think this kind of stuff happens more often in Ada, but at least in the Ada
> test suite there was nothing triggering any of the sanitation assertions.
> 
> But time will tell.
> 
> 
> Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
> Is it OK for trunk?
> 
> 
> Thanks
> Bernd.
> 
> 
> patch-expand-misalign.diff
> 
> 2019-09-04  Bernd Edlinger  <bernd.edlinger@hotmail.de>
> 
> 	* expmed.c (extract_bit_field): Update function comment
> 	regarding alt_rtl.
> 	* expr.c (expand_expr_real): Update function comment
> 	regarding alt_rtl.
> 	(expand_misaligned_mem_ref): New helper function.
> 	(expand_expr_real_2): Use expand_misaligned_mem_ref.
> 	Remove duplicate assignment to "base" at case MEM_REF.
> 	Remove a shadowed variable "unsignedp" at case VCE. 
> 
OK

jeff
diff mbox series

Patch

2019-09-04  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* expmed.c (extract_bit_field): Update function comment
	regarding alt_rtl.
	* expr.c (expand_expr_real): Update function comment
	regarding alt_rtl.
	(expand_misaligned_mem_ref): New helper function.
	(expand_expr_real_2): Use expand_misaligned_mem_ref.
	Remove duplicate assignment to "base" at case MEM_REF.
	Remove a shadowed variable "unsignedp" at case VCE. 

Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 275409)
+++ gcc/expmed.c	(working copy)
@@ -2046,8 +2046,11 @@  extract_integral_bit_field (rtx op0, opt_scalar_in
    If a TARGET is specified and we can store in it at no extra cost,
    we do so, and return TARGET.
    Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred
-   if they are equally easy.  */
+   if they are equally easy.
 
+   If the result can be stored at TARGET, and ALT_RTL is non-NULL,
+   then *ALT_RTL is set to TARGET (before legitimziation).  */
+
 rtx
 extract_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum,
 		   int unsignedp, rtx target, machine_mode mode,
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 275409)
+++ gcc/expr.c	(working copy)
@@ -8261,6 +8261,8 @@  expand_constructor (tree exp, rtx target, enum exp
    DECL_RTL of the VAR_DECL.  *ALT_RTL is also set if EXP is a
    COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on
    recursively.
+   If the result can be stored at TARGET, and ALT_RTL is non-NULL,
+   then *ALT_RTL is set to TARGET (before legitimziation).
 
    If INNER_REFERENCE_P is true, we are expanding an inner reference.
    In this case, we don't adjust a returned MEM rtx that wouldn't be
@@ -8398,6 +8400,40 @@  expand_cond_expr_using_cmove (tree treeop0 ATTRIBU
   return NULL_RTX;
 }
 
+/* A helper function for expand_expr_real_2 to be used with a
+   misaligned mem_ref TEMP.  Assume an unsigned type if UNSIGNEDP
+   is nonzero, with alignment ALIGN in bits.
+   Store the value at TARGET if possible (if TARGET is nonzero).
+   Regardless of TARGET, we return the rtx for where the value is placed.
+   If the result can be stored at TARGET, and ALT_RTL is non-NULL,
+   then *ALT_RTL is set to TARGET (before legitimziation).  */
+
+static rtx
+expand_misaligned_mem_ref (rtx temp, machine_mode mode, int unsignedp,
+			   unsigned int align, rtx target, rtx *alt_rtl)
+{
+  enum insn_code icode;
+
+  if ((icode = optab_handler (movmisalign_optab, mode))
+      != CODE_FOR_nothing)
+    {
+      class expand_operand ops[2];
+
+      /* We've already validated the memory, and we're creating a
+	 new pseudo destination.  The predicates really can't fail,
+	 nor can the generator.  */
+      create_output_operand (&ops[0], NULL_RTX, mode);
+      create_fixed_operand (&ops[1], temp);
+      expand_insn (icode, 2, ops);
+      temp = ops[0].value;
+    }
+  else if (targetm.slow_unaligned_access (mode, align))
+    temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
+			      0, unsignedp, target,
+			      mode, mode, false, alt_rtl);
+  return temp;
+}
+
 rtx
 expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 		    enum expand_modifier modifier)
@@ -10077,28 +10113,9 @@  expand_expr_real_1 (tree exp, rtx target, machine_
 	      && !inner_reference_p
 	      && mode != BLKmode
 	      && MEM_ALIGN (temp) < GET_MODE_ALIGNMENT (mode))
-	    {
-	      enum insn_code icode;
+	    temp = expand_misaligned_mem_ref (temp, mode, unsignedp,
+					      MEM_ALIGN (temp), NULL_RTX, NULL);
 
-	      if ((icode = optab_handler (movmisalign_optab, mode))
-		  != CODE_FOR_nothing)
-		{
-		  class expand_operand ops[2];
-
-		  /* We've already validated the memory, and we're creating a
-		     new pseudo destination.  The predicates really can't fail,
-		     nor can the generator.  */
-		  create_output_operand (&ops[0], NULL_RTX, mode);
-		  create_fixed_operand (&ops[1], temp);
-		  expand_insn (icode, 2, ops);
-		  temp = ops[0].value;
-		}
-	      else if (targetm.slow_unaligned_access (mode, MEM_ALIGN (temp)))
-		temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
-					  0, unsignedp, NULL_RTX,
-					  mode, mode, false, NULL);
-	    }
-
 	  return temp;
 	}
 
@@ -10325,27 +10342,8 @@  expand_expr_real_1 (tree exp, rtx target, machine_
 	    && modifier != EXPAND_MEMORY
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode))
-	  {
-	    enum insn_code icode;
-
-	    if ((icode = optab_handler (movmisalign_optab, mode))
-		!= CODE_FOR_nothing)
-	      {
-		class expand_operand ops[2];
-
-		/* We've already validated the memory, and we're creating a
-		   new pseudo destination.  The predicates really can't fail,
-		   nor can the generator.  */
-		create_output_operand (&ops[0], NULL_RTX, mode);
-		create_fixed_operand (&ops[1], temp);
-		expand_insn (icode, 2, ops);
-		temp = ops[0].value;
-	      }
-	    else if (targetm.slow_unaligned_access (mode, align))
-	      temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
-					0, unsignedp, NULL_RTX,
-					mode, mode, false, NULL);
-	  }
+	  temp = expand_misaligned_mem_ref (temp, mode, unsignedp,
+					    align, NULL_RTX, NULL);
 	return temp;
       }
 
@@ -10357,7 +10355,6 @@  expand_expr_real_1 (tree exp, rtx target, machine_
 	machine_mode address_mode;
 	tree base = TREE_OPERAND (exp, 0);
 	gimple *def_stmt;
-	enum insn_code icode;
 	unsigned align;
 	/* Handle expansion of non-aliased memory with non-BLKmode.  That
 	   might end up in a register.  */
@@ -10387,7 +10384,6 @@  expand_expr_real_1 (tree exp, rtx target, machine_
 	    return expand_expr (exp, target, tmode, modifier);
 	  }
 	address_mode = targetm.addr_space.address_mode (as);
-	base = TREE_OPERAND (exp, 0);
 	if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR)))
 	  {
 	    tree mask = gimple_assign_rhs2 (def_stmt);
@@ -10414,27 +10410,9 @@  expand_expr_real_1 (tree exp, rtx target, machine_
 	    && !inner_reference_p
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode))
-	  {
-	    if ((icode = optab_handler (movmisalign_optab, mode))
-		!= CODE_FOR_nothing)
-	      {
-		class expand_operand ops[2];
-
-		/* We've already validated the memory, and we're creating a
-		   new pseudo destination.  The predicates really can't fail,
-		   nor can the generator.  */
-		create_output_operand (&ops[0], NULL_RTX, mode);
-		create_fixed_operand (&ops[1], temp);
-		expand_insn (icode, 2, ops);
-		temp = ops[0].value;
-	      }
-	    else if (targetm.slow_unaligned_access (mode, align))
-	      temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
-					0, TYPE_UNSIGNED (TREE_TYPE (exp)),
-					(modifier == EXPAND_STACK_PARM
-					 ? NULL_RTX : target),
-					mode, mode, false, alt_rtl);
-	  }
+	  temp = expand_misaligned_mem_ref (temp, mode, unsignedp, align,
+					    modifier == EXPAND_STACK_PARM
+					    ? NULL_RTX : target, alt_rtl);
 	if (reverse
 	    && modifier != EXPAND_MEMORY
 	    && modifier != EXPAND_WRITE)
@@ -11109,11 +11087,10 @@  expand_expr_real_1 (tree exp, rtx target, machine_
 	machine_mode mode1;
 	poly_int64 bitsize, bitpos, bytepos;
 	tree offset;
-	int unsignedp, reversep, volatilep = 0;
+	int reversep, volatilep = 0;
 	tree tem
 	  = get_inner_reference (treeop0, &bitsize, &bitpos, &offset, &mode1,
 				 &unsignedp, &reversep, &volatilep);
-	rtx orig_op0;
 
 	/* ??? We should work harder and deal with non-zero offsets.  */
 	if (!offset
@@ -11123,7 +11100,7 @@  expand_expr_real_1 (tree exp, rtx target, machine_
 	    && known_eq (wi::to_poly_offset (TYPE_SIZE (type)), bitsize))
 	  {
 	    /* See the normal_inner_ref case for the rationale.  */
-	    orig_op0
+	    rtx orig_op0
 	      = expand_expr_real (tem,
 				  (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
 				   && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))