From patchwork Tue May 3 09:07:36 2011
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [ARM] Fix 16-bit -> 64-bit multiply and accumulate
X-Patchwork-Submitter: Bernd Schmidt
X-Patchwork-Id: 93757
Message-Id: <4DBFC5D8.1090009@codesourcery.com>
To: Andrew Stubbs
Cc: Richard Earnshaw , gcc-patches@gcc.gnu.org
Date: Tue, 03 May 2011 11:07:36 +0200
From: Bernd Schmidt
List-Id:
On 04/15/2011 12:54 PM, Andrew Stubbs wrote:
> Ping.
Trying to unblock this...
I think the point is that both examples:
long long foolong (long long x, short *a, short *b)
{
return x + (long long)*a * (long long)*b;
}
and
long long foolong (long long x, short *a, short *b)
{
return x + *a * *b;
}
should produce the same code using the maddhidi pattern, and for that to
happen, simplify_rtx must produce a canonical form of the 16->64 bit
widening multiply. The form that already exists in arm.md looks better
so we should pick that.
I tried to fix it with the patch below, which unfortunately doesn't work
since during combine we don't see the SIGN_EXTEND operations inside the
MULT, but two shift operations instead. Maybe you can complete it from here?
Bernd
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c (revision 173242)
+++ gcc/simplify-rtx.c (working copy)
@@ -1000,6 +1000,23 @@ simplify_unary_operation_1 (enum rtx_cod
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF)
return XEXP (op, 0);
+ /* Extending a widening multiplication should be canonicalized to
+ a wider widening multiplication. */
+ if (GET_CODE (op) == MULT
+ && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND
+ && GET_CODE (XEXP (op, 1)) == SIGN_EXTEND)
+ {
+ rtx op0 = XEXP (XEXP (op, 0), 0);
+ rtx op1 = XEXP (XEXP (op, 1), 0);
+ enum machine_mode op0_mode = GET_MODE (op0);
+ enum machine_mode op1_mode = GET_MODE (op1);
+ return simplify_gen_binary (MULT, mode,
+ simplify_gen_unary (SIGN_EXTEND, mode,
+ op0, op0_mode),
+ simplify_gen_unary (SIGN_EXTEND, mode,
+ op1, op1_mode));
+ }
+
/* Check for a sign extension of a subreg of a promoted
variable, where the promotion is sign-extended, and the
target mode is the same as the variable's promotion. */
@@ -1071,6 +1088,23 @@ simplify_unary_operation_1 (enum rtx_cod
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
return rtl_hooks.gen_lowpart_no_emit (mode, op);
+ /* Extending a widening multiplication should be canonicalized to
+ a wider widening multiplication. */
+ if (GET_CODE (op) == MULT
+ && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND
+ && GET_CODE (XEXP (op, 1)) == ZERO_EXTEND)
+ {
+ rtx op0 = XEXP (XEXP (op, 0), 0);
+ rtx op1 = XEXP (XEXP (op, 1), 0);
+ enum machine_mode op0_mode = GET_MODE (op0);
+ enum machine_mode op1_mode = GET_MODE (op1);
+ return simplify_gen_binary (MULT, mode,
+ simplify_gen_unary (ZERO_EXTEND, mode,
+ op0, op0_mode),
+ simplify_gen_unary (ZERO_EXTEND, mode,
+ op1, op1_mode));
+ }
+
/* (zero_extend:M (zero_extend:N )) is (zero_extend:M ). */
if (GET_CODE (op) == ZERO_EXTEND)
return simplify_gen_unary (ZERO_EXTEND, mode, XEXP (op, 0),