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]
Other format: [Raw text]

[PATCH] PR target/9348: RTL expansion bug for widening multiply


The following patch is my proposed solution to PR target/9348 which is
a incorrect code bug on HPPA.  It turns out that the problem is actually
an RTL expansion issue in the middle-end.  Given a multiply of two
extensions, the fix-up in expand_mult_highpart_adjust needs to know
the signedness of the lowpart multiplication (i.e. whether we were
sign-extending or zero-extending the operands), not the signedness of
the result.  [The significant change is "unsignedp" -> "zextend_p" in
the call to expand_mult_highpart_adjust below].

Hence in

  long a, b;
  return (unsigned long long) a * (unsigned long long) b;

what is important is that both "a" and "b" are sign-extended, not
that the widened multiplication is unsigned.  The code in expr.c
worked fine if "a" and "b" are unsigned long, or if the type of
the multiplication is "long long", i.e. whenever the signedness
of the extensions matches the signedness of the multiplication.

I also took the opportunity to avoid generating the no-op move,
when expand_mult_highpart_adjust manages to return the result in
the requested target rtx.


The following patch has been tested with a full bootstrap on both
i686-pc-linux-gnu (except treelang) and hppa2.0w-hp-hpux11.0 (except
java, ada and treelang), both without any new failures from a top-level
"make -k check".  On PA-Risc, the new testcase fails without this
patch, but passes with it.


Ok for mainline?  The PR doesn't indicate if this bug is a regression
or not, but I believe this patch might also be suitable for the 3.4
branch once its been shown to be safe on mainline for a while?



2004-01-25  Roger Sayle  <roger@eyesopen.com>

	PR target/9348
	* expr.c (expand_expr_real) <MULT_EXPR>:  When performing widening
	multiplies with a multiplication of the wrong signedness, its the
	signedness of the multiplication that we've performed that needs to
	be passed to expand_mult_highpart_adjust.  Avoid emitting a nop-move
	if expand_mult_highpart_adjust places the result in target.

	* gcc.c-torture/execute/multdi-1.c: New test case.


Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.617
diff -c -3 -p -r1.617 expr.c
*** expr.c	21 Jan 2004 20:39:53 -0000	1.617
--- expr.c	25 Jan 2004 20:43:58 -0000
*************** expand_expr_real (tree exp, rtx target,
*** 7855,7866 ****
  		   ==
  		   TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
  	{
! 	  enum machine_mode innermode
! 	    = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
! 	  optab other_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
! 			? smul_widen_optab : umul_widen_optab);
! 	  this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
! 			? umul_widen_optab : smul_widen_optab);
  	  if (mode == GET_MODE_WIDER_MODE (innermode))
  	    {
  	      if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
--- 7855,7866 ----
  		   ==
  		   TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
  	{
! 	  tree op0type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
! 	  enum machine_mode innermode = TYPE_MODE (op0type);
! 	  bool zextend_p = TREE_UNSIGNED (op0type);
! 	  optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
! 	  this_optab = zextend_p ? umul_widen_optab : smul_widen_optab;
!
  	  if (mode == GET_MODE_WIDER_MODE (innermode))
  	    {
  	      if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
*************** expand_expr_real (tree exp, rtx target,
*** 7878,7884 ****
  	      else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
  		       && innermode == word_mode)
  		{
! 		  rtx htem;
  		  op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
  				     NULL_RTX, VOIDmode, 0);
  		  if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
--- 7878,7884 ----
  	      else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
  		       && innermode == word_mode)
  		{
! 		  rtx htem, hipart;
  		  op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
  				     NULL_RTX, VOIDmode, 0);
  		  if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
*************** expand_expr_real (tree exp, rtx target,
*** 7891,7902 ****
  				       NULL_RTX, VOIDmode, 0);
  		  temp = expand_binop (mode, other_optab, op0, op1, target,
  				       unsignedp, OPTAB_LIB_WIDEN);
! 		  htem = expand_mult_highpart_adjust (innermode,
! 						      gen_highpart (innermode, temp),
! 						      op0, op1,
! 						      gen_highpart (innermode, temp),
! 						      unsignedp);
! 		  emit_move_insn (gen_highpart (innermode, temp), htem);
  		  return temp;
  		}
  	    }
--- 7891,7902 ----
  				       NULL_RTX, VOIDmode, 0);
  		  temp = expand_binop (mode, other_optab, op0, op1, target,
  				       unsignedp, OPTAB_LIB_WIDEN);
! 		  hipart = gen_highpart (innermode, temp);
! 		  htem = expand_mult_highpart_adjust (innermode, hipart,
! 						      op0, op1, hipart,
! 						      zextend_p);
! 		  if (htem != hipart)
! 		    emit_move_insn (hipart, htem);
  		  return temp;
  		}
  	    }


/* PR target/9348 */

#define u_l_l unsigned long long
#define l_l long long

l_l mpy_res;

u_l_l mpy (long a, long b)
{
  return (u_l_l) a * (u_l_l) b;
}

int main(void)
{
  mpy_res = mpy(1,-1);
  if (mpy_res != -1LL)
    abort ();
  return 0;
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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