1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
2011-01-18 Ulrich Weigand <uweigand@de.ibm.com>
LP: #685352
Backport from mainline:
2011-01-18 Jakub Jelinek <jakub@redhat.com>
gcc/
PR rtl-optimization/47299
* expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: 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/testsuite/
PR rtl-optimization/47299
* gcc.c-torture/execute/pr47299.c: New test.
=== modified file 'gcc/expmed.c'
Index: gcc-4_5-branch/gcc/expmed.c
===================================================================
--- gcc-4_5-branch.orig/gcc/expmed.c
+++ gcc-4_5-branch/gcc/expmed.c
@@ -3355,12 +3355,17 @@ expand_widening_mult (enum machine_mode
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;
Index: gcc-4_5-branch/gcc/expr.c
===================================================================
--- gcc-4_5-branch.orig/gcc/expr.c
+++ gcc-4_5-branch/gcc/expr.c
@@ -7624,10 +7624,10 @@ expand_expr_real_2 (sepops ops, rtx targ
if (optab_handler (this_optab, mode)->insn_code != 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;
}
@@ -7645,7 +7645,8 @@ expand_expr_real_2 (sepops ops, rtx targ
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)->insn_code != CODE_FOR_nothing)
{
Index: gcc-4_5-branch/gcc/testsuite/gcc.c-torture/execute/pr47299.c
===================================================================
--- /dev/null
+++ gcc-4_5-branch/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;
+}
|