This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

alpha block move fix


We would abort on something like

	struct foo { double a, b; };

	void bar(void *dest)
	{
	  struct foo reg;
	  memcpy(dest, ® sizeof(reg));
	}

because we did not handle TImode registers.


r~



        * alpha.c (alpha_expand_block_move): Handle TImode registers 
        used with ADDRESSOF.
        (alpha_expand_block_clear): Handle ADDRESSOF specially.

Index: alpha.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.85
diff -c -p -d -r1.85 alpha.c
*** alpha.c	1999/04/26 00:27:17	1.85
--- alpha.c	1999/05/12 03:45:09
*************** alpha_expand_block_move (operands)
*** 1961,1977 ****
        enum machine_mode mode;
        tmp = XEXP (XEXP (orig_src, 0), 0);
  
        mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
        if (mode != BLKmode
! 	  && GET_MODE_SIZE (GET_MODE (tmp)) <= bytes)
  	{
! 	  /* Whee!  Optimize the load to use the existing register.  */
! 	  data_regs[nregs++] = gen_lowpart (mode, tmp);
  	  goto src_done;
  	}
  
-       /* ??? We could potentially be copying 3 bytes or whatnot from
- 	 a wider reg.  Probably not worth worrying about.  */
        /* No appropriate mode; fall back on memory.  */
        orig_src = change_address (orig_src, GET_MODE (orig_src),
  				 copy_addr_to_reg (XEXP (orig_src, 0)));
--- 2075,2098 ----
        enum machine_mode mode;
        tmp = XEXP (XEXP (orig_src, 0), 0);
  
+       /* Don't use the existing register if we're reading more than
+ 	 is held in the register.  Nor if there is not a mode that
+ 	 handles the exact size.  */
        mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
        if (mode != BLKmode
! 	  && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes)
  	{
! 	  if (mode == TImode)
! 	    {
! 	      data_regs[nregs] = gen_lowpart (DImode, tmp);
! 	      data_regs[nregs+1] = gen_highpart (DImode, tmp);
! 	      nregs += 2;
! 	    }
! 	  else
! 	    data_regs[nregs++] = gen_lowpart (mode, tmp);
  	  goto src_done;
  	}
  
        /* No appropriate mode; fall back on memory.  */
        orig_src = change_address (orig_src, GET_MODE (orig_src),
  				 copy_addr_to_reg (XEXP (orig_src, 0)));
*************** alpha_expand_block_move (operands)
*** 1988,1996 ****
        for (i = 0; i < words; ++i)
  	{
  	  emit_move_insn (data_regs[nregs+i],
! 			  change_address(orig_src, DImode,
! 					 plus_constant (XEXP (orig_src, 0),
! 							ofs + i*8)));
  	}
  
        nregs += words;
--- 2109,2117 ----
        for (i = 0; i < words; ++i)
  	{
  	  emit_move_insn (data_regs[nregs+i],
! 			  change_address (orig_src, DImode,
! 					  plus_constant (XEXP (orig_src, 0),
! 							 ofs + i*8)));
  	}
  
        nregs += words;
*************** alpha_expand_block_move (operands)
*** 2007,2015 ****
        for (i = 0; i < words; ++i)
  	{
  	  emit_move_insn (data_regs[nregs+i],
! 			  change_address(orig_src, SImode,
! 					 plus_constant (XEXP (orig_src, 0),
! 							ofs + i*4)));
  	}
  
        nregs += words;
--- 2128,2136 ----
        for (i = 0; i < words; ++i)
  	{
  	  emit_move_insn (data_regs[nregs+i],
! 			  change_address (orig_src, SImode,
! 					  plus_constant (XEXP (orig_src, 0),
! 							 ofs + i*4)));
  	}
  
        nregs += words;
*************** alpha_expand_block_move (operands)
*** 2023,2029 ****
        for (i = 0; i < words+1; ++i)
  	data_regs[nregs+i] = gen_reg_rtx(DImode);
  
!       alpha_expand_unaligned_load_words(data_regs+nregs, orig_src, words, ofs);
  
        nregs += words;
        bytes -= words * 8;
--- 2144,2151 ----
        for (i = 0; i < words+1; ++i)
  	data_regs[nregs+i] = gen_reg_rtx(DImode);
  
!       alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
! 					 words, ofs);
  
        nregs += words;
        bytes -= words * 8;
*************** alpha_expand_block_move (operands)
*** 2092,2102 ****
        tmp = XEXP (XEXP (orig_dst, 0), 0);
  
        mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
!       if (GET_MODE (tmp) == mode && nregs == 1)
  	{
! 	  emit_move_insn (tmp, data_regs[0]);
! 	  i = 1;
! 	  goto dst_done;
  	}
  
        /* ??? If nregs > 1, consider reconstructing the word in regs.  */
--- 2214,2253 ----
        tmp = XEXP (XEXP (orig_dst, 0), 0);
  
        mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
!       if (GET_MODE (tmp) == mode)
  	{
! 	  if (nregs == 1)
! 	    {
! 	      emit_move_insn (tmp, data_regs[0]);
! 	      i = 1;
! 	      goto dst_done;
! 	    }
! 	  else if (nregs == 2 && mode == TImode)
! 	    {
! 	      /* Undo the subregging done above when copying between
! 		 two TImode registers.  */
! 	      if (GET_CODE (data_regs[0]) == SUBREG
! 		  && GET_MODE (SUBREG_REG (data_regs[0])) == TImode)
! 		{
! 		  emit_move_insn (tmp, SUBREG_REG (data_regs[0]));
! 		}
! 	      else
! 		{
! 		  rtx seq;
! 
! 		  start_sequence ();
! 		  emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]);
! 		  emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]);
! 		  seq = gen_sequence ();
! 		  end_sequence ();
! 
! 		  emit_no_conflict_block (seq, tmp, data_regs[0],
! 					  data_regs[1], NULL_RTX);
! 		}
! 
! 	      i = 2;
! 	      goto dst_done;
! 	    }
  	}
  
        /* ??? If nregs > 1, consider reconstructing the word in regs.  */
*************** alpha_expand_block_move (operands)
*** 2114,2122 ****
      {
        while (i < nregs && GET_MODE (data_regs[i]) == DImode)
  	{
! 	  emit_move_insn (change_address(orig_dst, DImode,
! 					 plus_constant (XEXP (orig_dst, 0),
! 							ofs)),
  			  data_regs[i]);
  	  ofs += 8;
  	  i++;
--- 2265,2273 ----
      {
        while (i < nregs && GET_MODE (data_regs[i]) == DImode)
  	{
! 	  emit_move_insn (change_address (orig_dst, DImode,
! 					  plus_constant (XEXP (orig_dst, 0),
! 							 ofs)),
  			  data_regs[i]);
  	  ofs += 8;
  	  i++;
*************** alpha_expand_block_move (operands)
*** 2131,2143 ****
  	  tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
  			      NULL_RTX, 1, OPTAB_WIDEN);
  
! 	  emit_move_insn (change_address(orig_dst, SImode,
! 					 plus_constant (XEXP (orig_dst, 0),
! 							ofs)),
  			  gen_lowpart (SImode, data_regs[i]));
! 	  emit_move_insn (change_address(orig_dst, SImode,
! 					 plus_constant (XEXP (orig_dst, 0),
! 							ofs+4)),
  			  gen_lowpart (SImode, tmp));
  	  ofs += 8;
  	  i++;
--- 2282,2294 ----
  	  tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
  			      NULL_RTX, 1, OPTAB_WIDEN);
  
! 	  emit_move_insn (change_address (orig_dst, SImode,
! 					  plus_constant (XEXP (orig_dst, 0),
! 							 ofs)),
  			  gen_lowpart (SImode, data_regs[i]));
! 	  emit_move_insn (change_address (orig_dst, SImode,
! 					  plus_constant (XEXP (orig_dst, 0),
! 							 ofs+4)),
  			  gen_lowpart (SImode, tmp));
  	  ofs += 8;
  	  i++;
*************** alpha_expand_block_clear (operands)
*** 2256,2262 ****
--- 2407,2429 ----
  	    align = 2;
  	}
      }
+   else if (GET_CODE (tmp) == ADDRESSOF)
+     {
+       enum machine_mode mode;
  
+       mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
+       if (GET_MODE (XEXP (tmp, 0)) == mode)
+ 	{
+ 	  emit_move_insn (XEXP (tmp, 0), const0_rtx);
+ 	  return 1;
+ 	}
+ 
+       /* No appropriate mode; fall back on memory.  */
+       orig_dst = change_address (orig_dst, GET_MODE (orig_dst),
+ 				 copy_addr_to_reg (tmp));
+       align = GET_MODE_SIZE (GET_MODE (XEXP (tmp, 0)));
+     }
+ 
    /* Handle a block of contiguous words first.  */
  
    if (align >= 8 && bytes >= 8)
*************** alpha_expand_block_clear (operands)
*** 2280,2288 ****
  
        for (i = 0; i < words; ++i)
  	{
! 	  emit_move_insn (change_address(orig_dst, SImode,
! 					 plus_constant (XEXP (orig_dst, 0),
! 							ofs + i*4)),
  			  const0_rtx);
  	}
  
--- 2447,2455 ----
  
        for (i = 0; i < words; ++i)
  	{
! 	  emit_move_insn (change_address (orig_dst, SImode,
! 					  plus_constant (XEXP (orig_dst, 0),
! 							 ofs + i*4)),
  			  const0_rtx);
  	}
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]