From e7ef91dc8eb398de7b6c780b00f1360dafd84798 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 18 Jan 2011 08:45:12 +0100 Subject: [PATCH] re PR rtl-optimization/47299 (Widening multiply optimization generates bad code) PR rtl-optimization/47299 * expr.c (expand_expr_real_2) : Don't use subtarget. Use normal multiplication if both operands are constants. * expmed.c (expand_widening_mult): Don't try to optimize constant multiplication if op0 has VOIDmode. Convert op1 constant to mode before using it. * gcc.c-torture/execute/pr47299.c: New test. From-SVN: r168944 --- gcc/ChangeLog | 10 ++++++++++ gcc/expmed.c | 12 +++++++++--- gcc/expr.c | 9 +++++---- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.c-torture/execute/pr47299.c | 17 +++++++++++++++++ 5 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr47299.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a8f3ad7aa7e..0ed4f018632 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2011-01-18 Jakub Jelinek + + PR rtl-optimization/47299 + * expr.c (expand_expr_real_2) : Don't use + subtarget. Use normal multiplication if both operands are + constants. + * expmed.c (expand_widening_mult): Don't try to optimize constant + multiplication if op0 has VOIDmode. Convert op1 constant to mode + before using it. + 2011-01-17 Ralf Wildenhues * doc/lto.texi (LTO): Ensure two spaces after period. Fix diff --git a/gcc/expmed.c b/gcc/expmed.c index 24aedccde9e..f17abb53568 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1,7 +1,8 @@ /* Medium-level subroutines: convert bit-field store and extract and shifts, multiplies and divides to rtl instructions. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -3188,12 +3189,17 @@ expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, int unsignedp, optab this_optab) { bool speed = optimize_insn_for_speed_p (); + rtx cop1; if (CONST_INT_P (op1) - && (INTVAL (op1) >= 0 + && GET_MODE (op0) != VOIDmode + && (cop1 = convert_modes (mode, GET_MODE (op0), op1, + this_optab == umul_widen_optab)) + && CONST_INT_P (cop1) + && (INTVAL (cop1) >= 0 || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)) { - HOST_WIDE_INT coeff = INTVAL (op1); + HOST_WIDE_INT coeff = INTVAL (cop1); int max_cost; enum mult_variant variant; struct algorithm algorithm; diff --git a/gcc/expr.c b/gcc/expr.c index dfcaefb4271..7441548884e 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1,6 +1,6 @@ /* Convert tree expression to rtl instructions, for GNU compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -7631,10 +7631,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, if (optab_handler (this_optab, mode) != CODE_FOR_nothing) { if (TYPE_UNSIGNED (TREE_TYPE (treeop0))) - expand_operands (treeop0, treeop1, subtarget, &op0, &op1, + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); else - expand_operands (treeop0, treeop1, subtarget, &op1, &op0, + expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0, EXPAND_NORMAL); goto binop3; } @@ -7652,7 +7652,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, 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_2XWIDER_MODE (innermode)) + if (mode == GET_MODE_2XWIDER_MODE (innermode) + && TREE_CODE (treeop0) != INTEGER_CST) { if (optab_handler (this_optab, mode) != CODE_FOR_nothing) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e12ba4c532d..19a6ab962ef 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-01-18 Jakub Jelinek + + PR rtl-optimization/47299 + * gcc.c-torture/execute/pr47299.c: New test. + 2011-01-17 Jason Merrill * g++.dg/cpp0x/constexpr-virtual.C: New. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr47299.c b/gcc/testsuite/gcc.c-torture/execute/pr47299.c new file mode 100644 index 00000000000..4f3d1f9cb12 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr47299.c @@ -0,0 +1,17 @@ +/* PR rtl-optimization/47299 */ + +extern void abort (void); + +__attribute__ ((noinline, noclone)) unsigned short +foo (unsigned char x) +{ + return x * 255; +} + +int +main () +{ + if (foo (0x40) != 0x3fc0) + abort (); + return 0; +}