From: Richard Sandiford <rdsandiford@googlemail.com>
To: gcc-patches@gcc.gnu.org
Subject: Extend widening_mul pass to handle fixed-point types
Date: Sun, 18 Jul 2010 12:03:00 -0000 [thread overview]
Message-ID: <87fwzhro8i.fsf@firetop.home> (raw)
This patch makes the widening_mul pass handle fixed-point types,
thus fixing gcc.target/dpaq_sa_l_w.c. WIDEN_MULT_PLUS_EXPR and
WIDEN_MULT_MINUS_EXPR already handle the types correctly,
it's just that we never generate them.
The current multiply-accumulate code (quite reasonably) converts the
multiplication to a WIDEN_MULT first, then uses the operands of that
WIDEN_MULT in the WIDEN_MULT_PLUS_EXPR and WIDEN_MULT_MINUS_EXPR.
The main gotcha with fixed-point types is that WIDEN_MULT_EXPR _doesn't_
support fixed-point types. Indeed MIPS -- the only fixed-point target
AFAIK -- doesn't have a pure fixed-point widening multiplication
instruction, just a multiply-accumulate one[*]. So there isn't any
use for a fixed-point WIDEN_MULT_EXPR right now. Even if I tried to
implement it, it would just be dead code, and there's no easy way of
telling whether I got right.
This patch therefore separates out the processes of getting the
unwidened operands and of generating the WIDEN_MULT, so that we can
still use the operands in cases where converting to a WIDEN_MULT isn't
possible or worthwhile. I realise this is a bit of a strange case,
but it does mean that the generation of WIDEN_MULT_{PLUS,MINUS}_EXPR
depends only on whether the associated multiply-accumulate optab exists,
not on whether other optabs (like the pure multiplication ones) exist too.
Note that expand_debug_expr doesn't handle fixed-point types at
the moment. That goes for these codes and for much simpler ones.
I think adding that is a separate change.
Tested on mipsisa64-elfoabi, where it fixes the testsuite failure.
Also bootstrapped & regression-tested on x86_64-linux-gnu. OK to instal?
Richard
[*] It may well be that MIPS should use multiply-accumulate patterns
to implement plain multiplication, but I don't have appropriate
hardware to test that performance-wise.
gcc/
* tree-ssa-math-opts.c (convert_mult_to_widen): Add an RHS_OUT
parameter. Handle fixed-point types as well as integer ones,
but continue to only generate WIDEN_MULT_EXPR for the latter.
Use RHS_OUT to return the unwidened operands to the caller.
(convert_plusminus_to_widen): Handle fixed-point types as
well as integer ones. Update the call to convert_mult_to_widen.
(execute_optimize_widening_mul): Update the call to
convert_mult_to_widen.
Index: gcc/tree-ssa-math-opts.c
===================================================================
--- gcc/tree-ssa-math-opts.c 2010-07-18 08:36:48.000000000 +0100
+++ gcc/tree-ssa-math-opts.c 2010-07-18 12:35:42.000000000 +0100
@@ -1260,22 +1260,30 @@ struct gimple_opt_pass pass_optimize_bsw
}
};
-/* Process a single gimple statement STMT, which has a MULT_EXPR as
- its rhs, and try to convert it into a WIDEN_MULT_EXPR. The return
- value is true iff we converted the statement. */
+/* Process a single gimple statement STMT, which has a MULT_EXPR as its
+ rhs, and see if it is a widening multiplication. If so:
+
+ - store the two unextended operands in RHS_OUT[0] and RHS_OUT[1],
+ if RHS_OUT is nonnull; and
+ - try to convert the statement into a WIDEN_MULT_EXPR.
+
+ Return true if the statement could be converted or if operands
+ were stored in RHS_OUT. */
static bool
-convert_mult_to_widen (gimple stmt)
+convert_mult_to_widen (gimple stmt, tree *rhs_out)
{
gimple rhs1_stmt = NULL, rhs2_stmt = NULL;
tree type1 = NULL, type2 = NULL;
- tree rhs1, rhs2, rhs1_convop = NULL, rhs2_convop = NULL;
+ tree rhs1, rhs2, unwidened_rhs1 = NULL, unwidened_rhs2 = NULL;
enum tree_code rhs1_code, rhs2_code;
tree type;
+ bool use_widen_mult_p;
type = TREE_TYPE (gimple_assign_lhs (stmt));
- if (TREE_CODE (type) != INTEGER_TYPE)
+ if (TREE_CODE (type) != INTEGER_TYPE
+ && TREE_CODE (type) != FIXED_POINT_TYPE)
return false;
rhs1 = gimple_assign_rhs1 (stmt);
@@ -1287,14 +1295,17 @@ convert_mult_to_widen (gimple stmt)
if (!is_gimple_assign (rhs1_stmt))
return false;
rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
- if (!CONVERT_EXPR_CODE_P (rhs1_code))
+ if (TREE_CODE (type) == INTEGER_TYPE
+ ? !CONVERT_EXPR_CODE_P (rhs1_code)
+ : rhs1_code != FIXED_CONVERT_EXPR)
return false;
- rhs1_convop = gimple_assign_rhs1 (rhs1_stmt);
- type1 = TREE_TYPE (rhs1_convop);
+ unwidened_rhs1 = gimple_assign_rhs1 (rhs1_stmt);
+ type1 = TREE_TYPE (unwidened_rhs1);
if (TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type))
return false;
}
- else if (TREE_CODE (rhs1) != INTEGER_CST)
+ else if (TREE_CODE (rhs1) != INTEGER_CST
+ && TREE_CODE (rhs1) != FIXED_CST)
return false;
if (TREE_CODE (rhs2) == SSA_NAME)
@@ -1303,52 +1314,73 @@ convert_mult_to_widen (gimple stmt)
if (!is_gimple_assign (rhs2_stmt))
return false;
rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
- if (!CONVERT_EXPR_CODE_P (rhs2_code))
+ if (TREE_CODE (type) == INTEGER_TYPE
+ ? !CONVERT_EXPR_CODE_P (rhs2_code)
+ : rhs2_code != FIXED_CONVERT_EXPR)
return false;
- rhs2_convop = gimple_assign_rhs1 (rhs2_stmt);
- type2 = TREE_TYPE (rhs2_convop);
+ unwidened_rhs2 = gimple_assign_rhs1 (rhs2_stmt);
+ type2 = TREE_TYPE (unwidened_rhs2);
if (TYPE_PRECISION (type2) * 2 != TYPE_PRECISION (type))
return false;
}
- else if (TREE_CODE (rhs2) != INTEGER_CST)
+ else if (TREE_CODE (rhs2) != INTEGER_CST
+ && TREE_CODE (rhs2) != FIXED_CST)
return false;
if (rhs1_stmt == NULL && rhs2_stmt == NULL)
return false;
+ /* At present, WIDEN_MULT_EXPR only supports integer types,
+ not fixed-point ones. Processing fixed-point types is only
+ useful if the caller wants the unextended operands. */
+ if (TREE_CODE (type) == FIXED_POINT_TYPE)
+ use_widen_mult_p = false;
/* Verify that the machine can perform a widening multiply in this
mode/signedness combination, otherwise this transformation is
likely to pessimize code. */
- if ((rhs1_stmt == NULL || TYPE_UNSIGNED (type1))
- && (rhs2_stmt == NULL || TYPE_UNSIGNED (type2))
- && (optab_handler (umul_widen_optab, TYPE_MODE (type))
- == CODE_FOR_nothing))
- return false;
+ else if ((rhs1_stmt == NULL || TYPE_UNSIGNED (type1))
+ && (rhs2_stmt == NULL || TYPE_UNSIGNED (type2))
+ && (optab_handler (umul_widen_optab, TYPE_MODE (type))
+ == CODE_FOR_nothing))
+ use_widen_mult_p = false;
else if ((rhs1_stmt == NULL || !TYPE_UNSIGNED (type1))
&& (rhs2_stmt == NULL || !TYPE_UNSIGNED (type2))
&& (optab_handler (smul_widen_optab, TYPE_MODE (type))
== CODE_FOR_nothing))
- return false;
+ use_widen_mult_p = false;
else if (rhs1_stmt != NULL && rhs2_stmt != NULL
&& (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2))
&& (optab_handler (usmul_widen_optab, TYPE_MODE (type))
== CODE_FOR_nothing))
+ use_widen_mult_p = false;
+ else
+ use_widen_mult_p = true;
+
+ if (!use_widen_mult_p && rhs_out == NULL)
return false;
if ((rhs1_stmt == NULL && !int_fits_type_p (rhs1, type2))
|| (rhs2_stmt == NULL && !int_fits_type_p (rhs2, type1)))
return false;
- if (rhs1_stmt == NULL)
- gimple_assign_set_rhs1 (stmt, fold_convert (type2, rhs1));
- else
- gimple_assign_set_rhs1 (stmt, rhs1_convop);
- if (rhs2_stmt == NULL)
- gimple_assign_set_rhs2 (stmt, fold_convert (type1, rhs2));
- else
- gimple_assign_set_rhs2 (stmt, rhs2_convop);
- gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR);
- update_stmt (stmt);
+ if (unwidened_rhs1 == NULL)
+ unwidened_rhs1 = fold_convert (type2, rhs1);
+ if (unwidened_rhs2 == NULL)
+ unwidened_rhs2 = fold_convert (type1, rhs2);
+
+ if (rhs_out)
+ {
+ rhs_out[0] = unwidened_rhs1;
+ rhs_out[1] = unwidened_rhs2;
+ }
+
+ if (use_widen_mult_p)
+ {
+ gimple_assign_set_rhs1 (stmt, unwidened_rhs1);
+ gimple_assign_set_rhs2 (stmt, unwidened_rhs2);
+ gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR);
+ update_stmt (stmt);
+ }
return true;
}
@@ -1364,14 +1396,15 @@ convert_plusminus_to_widen (gimple_stmt_
{
gimple rhs1_stmt = NULL, rhs2_stmt = NULL;
tree type;
- tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs;
+ tree lhs, rhs1, rhs2, mult_rhs[2], add_rhs;
enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK;
optab this_optab;
enum tree_code wmult_code;
lhs = gimple_assign_lhs (stmt);
type = TREE_TYPE (lhs);
- if (TREE_CODE (type) != INTEGER_TYPE)
+ if (TREE_CODE (type) != INTEGER_TYPE
+ && TREE_CODE (type) != FIXED_POINT_TYPE)
return false;
if (code == MINUS_EXPR)
@@ -1407,29 +1440,28 @@ convert_plusminus_to_widen (gimple_stmt_
else
return false;
- if (rhs1_code == MULT_EXPR)
+ if (code == PLUS_EXPR && rhs1_code == MULT_EXPR)
{
- if (!convert_mult_to_widen (rhs1_stmt))
+ if (!convert_mult_to_widen (rhs1_stmt, mult_rhs))
return false;
- rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
+ add_rhs = rhs2;
}
- if (rhs2_code == MULT_EXPR)
+ else if (rhs2_code == MULT_EXPR)
{
- if (!convert_mult_to_widen (rhs2_stmt))
+ if (!convert_mult_to_widen (rhs2_stmt, mult_rhs))
return false;
- rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
+ add_rhs = rhs1;
}
-
- if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR)
+ else if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR)
{
- mult_rhs1 = gimple_assign_rhs1 (rhs1_stmt);
- mult_rhs2 = gimple_assign_rhs2 (rhs1_stmt);
+ mult_rhs[0] = gimple_assign_rhs1 (rhs1_stmt);
+ mult_rhs[1] = gimple_assign_rhs2 (rhs1_stmt);
add_rhs = rhs2;
}
else if (rhs2_code == WIDEN_MULT_EXPR)
{
- mult_rhs1 = gimple_assign_rhs1 (rhs2_stmt);
- mult_rhs2 = gimple_assign_rhs2 (rhs2_stmt);
+ mult_rhs[0] = gimple_assign_rhs1 (rhs2_stmt);
+ mult_rhs[1] = gimple_assign_rhs2 (rhs2_stmt);
add_rhs = rhs1;
}
else
@@ -1437,7 +1469,7 @@ convert_plusminus_to_widen (gimple_stmt_
/* ??? May need some type verification here? */
- gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs1, mult_rhs2,
+ gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs[0], mult_rhs[1],
add_rhs);
update_stmt (gsi_stmt (*gsi));
return true;
@@ -1467,7 +1499,7 @@ execute_optimize_widening_mul (void)
code = gimple_assign_rhs_code (stmt);
if (code == MULT_EXPR)
- changed |= convert_mult_to_widen (stmt);
+ changed |= convert_mult_to_widen (stmt, NULL);
else if (code == PLUS_EXPR || code == MINUS_EXPR)
changed |= convert_plusminus_to_widen (&gsi, stmt, code);
}
next reply other threads:[~2010-07-18 12:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-18 12:03 Richard Sandiford [this message]
2010-07-18 20:47 ` Bernd Schmidt
2010-07-19 18:35 ` Richard Sandiford
2010-07-19 21:53 ` Bernd Schmidt
2010-07-27 12:28 ` Ramana Radhakrishnan
2010-07-27 15:54 ` Bernd Schmidt
2010-07-27 17:10 ` Ramana Radhakrishnan
2010-07-28 15:43 ` Ramana Radhakrishnan
2010-07-28 21:20 ` Richard Sandiford
2010-07-29 10:39 ` Ramana Radhakrishnan
2010-07-31 9:45 ` Richard Sandiford
2010-07-31 9:45 ` Richard Sandiford
2010-07-31 13:03 ` Bernd Schmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87fwzhro8i.fsf@firetop.home \
--to=rdsandiford@googlemail.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).