diff --git a/gcc/ChangeLog b/gcc/ChangeLog index daf843df80f..2ee6a143587 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-02-03 Roger Sayle + + PR target/9348 + * expr.c (expand_expr_real) : 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. + 2004-02-03 Richard Henderson * varasm.c (const_desc_rtx_sym_eq): Compare symbol strings. diff --git a/gcc/expr.c b/gcc/expr.c index ba27b04d115..55e5f0690fe 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7859,12 +7859,12 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, == 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); + 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) @@ -7882,7 +7882,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing && innermode == word_mode) { - rtx htem; + 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) @@ -7895,12 +7895,12 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, 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); + 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; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f31c5c53007..ca134857b2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-02-03 Roger Sayle + + PR target/9348 + * gcc.c-torture/execute/multdi-1.c: New test case. + 2004-02-03 Mark Mitchell PR c++/13925 diff --git a/gcc/testsuite/gcc.c-torture/execute/multdi-1.c b/gcc/testsuite/gcc.c-torture/execute/multdi-1.c new file mode 100644 index 00000000000..1ffcc578e51 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/multdi-1.c @@ -0,0 +1,20 @@ +/* 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; +} +