Merge lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6 into lp:gcc-linaro/4.6
- widening-multiplies-4.6
- Merge into 4.6
Status: | Merged |
---|---|
Approved by: | Richard Sandiford |
Approved revision: | no longer in the source branch. |
Merged at revision: | 106796 |
Proposed branch: | lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6 |
Merge into: | lp:gcc-linaro/4.6 |
Diff against target: |
1272 lines (+740/-140) (has conflicts) 20 files modified
ChangeLog.linaro (+129/-0) gcc/config/arm/arm.md (+1/-1) gcc/expr.c (+14/-15) gcc/genopinit.c (+24/-20) gcc/optabs.c (+78/-13) gcc/optabs.h (+52/-0) gcc/testsuite/gcc.target/arm/no-wmla-1.c (+11/-0) gcc/testsuite/gcc.target/arm/wmul-10.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-11.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-12.c (+11/-0) gcc/testsuite/gcc.target/arm/wmul-13.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-5.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-6.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-7.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-8.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-9.c (+10/-0) gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c (+17/-0) gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c (+17/-0) gcc/tree-cfg.c (+2/-2) gcc/tree-ssa-math-opts.c (+304/-89) Text conflict in ChangeLog.linaro |
To merge this branch: | bzr merge lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Richard Sandiford | Approve | ||
Michael Hope | Pending | ||
Review via email:
|
This proposal supersedes a proposal from 2011-08-05.
Commit message
Description of the change
Widening multiplies optimizations.
The first commit is not approved yet, but the rest are reviewed upstream, and read to commit.
http://<email address hidden>
UPDATE: Now with an extra bug-fix.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x2b85680>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x2141ea8>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x7fe8f501a050>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x7fe8f5028ab8>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
cbuild has taken a snapshot of this branch at r106782 and queued it for build.
The snapshot is available at:
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x3fec710>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x2b08c68>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on armv7l-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on armv7l-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
cbuild has taken a snapshot of this branch at r106783 and queued it for build.
The snapshot is available at:
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on x86_64-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on i686-natty-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on armv7l-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
cbuild has taken a snapshot of this branch at r106784 and queued it for build.
The snapshot is available at:
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild successfully built this on armv7l-
The build results are available at:
http://
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
-PASS: gcc.dg/pr46499-1.c execution test
-PASS: gcc.dg/pr46499-1.c (test for excess errors)
+UNRESOLVED: gcc.dg/pr46499-1.c compilation failed to produce executable
+FAIL: gcc.dg/pr46499-1.c (test for excess errors)
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PAS...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on i686-natty-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on x86_64-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on x86_64-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
cbuild has taken a snapshot of this branch at r106785 and queued it for build.
The snapshot is available at:
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild successfully built this on armv7l-
The build results are available at:
http://
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
-PASS: gfortran.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild successfully built this on armv7l-
The build results are available at:
http://
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
-PASS: gfortran.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild successfully built this on i686-natty-
The build results are available at:
http://
-PASS: gfortran.
-PASS: gfortran.
+FAIL: gfortran.
+FAIL: gfortran.
+UNRESOLVED: gfortran.
-PASS: gfortran.
-PASS: gfortran.
+FAIL: gfortran.
+FAIL: gfortran.
+UNRESOLVED: gfortran.
-PASS: gfortran.
-PASS: gfortran.
+FAIL: gfortran.
+FAIL: gfortran.
+UNRESOLVED: gfortran.
-PASS: gfortran.
-PASS: gfortran.
+FAIL: gfortran.
+FAIL: gfortran.
+UNRESOLVED: gfortran.
-PASS: gfortran.
-PASS: gfortran.
+FAIL: gfortran.
+FAIL: gfortran.
+UNRESOLVED: gfortran.
The full testsuite results are at:
http://
cbuild-checked: i686-natty-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild successfully built this on x86_64-
The build results are available at:
http://
The testsuite results are the same as the branch point lp:gcc-linaro/4.6+bzr106774
The full testsuite results are at:
http://
cbuild-checked: x86_64-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
Note that the tests pass on a 64 bit host but fail on all 32 bit hosts.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Linaro Toolchain Builder (cbuild) wrote : | # |
cbuild has taken a snapshot of this branch at r106787 and queued it for build.
The snapshot is available at:
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : | # |
cbuild successfully built this on x86_64-
The build results are available at:
http://
The testsuite results are the same as the branch point lp:gcc-linaro/4.6+bzr106774
The full testsuite results are at:
http://
cbuild-checked: x86_64-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : | # |
cbuild successfully built this on i686-natty-
The build results are available at:
http://
The testsuite results are the same as the branch point lp:gcc-linaro/4.6+bzr106774
The full testsuite results are at:
http://
cbuild-checked: i686-natty-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : | # |
cbuild successfully built this on armv7l-
The build results are available at:
http://
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
The full testsuite results are at:
http://
cbuild-checked: armv7l-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Hope (michaelh1) wrote : | # |
cbuild successfully built this on armv7l-
The build results are available at:
http://
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
The full testsuite results are at:
http://
cbuild-checked: armv7l-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ramana Radhakrishnan (ramana) wrote : | # |
Could you point me at the one set of patches that were finally accepted upstream ?
Also, is that one extra bug fix that you say at the top in FSF trunk upstream ?
Ramana
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrew Stubbs (ams-codesourcery) wrote : | # |
The patches are not yet committed upstream. The accepted versions of the patches are in the thread on the gcc-patches@ list, but I have not yet posted the bug-fixed versions.
Here are the originals:
http://
http://
http://
http://
http://
http://
http://
http://
http://
I do not expect them to require further approval. I plan to do some tests on the 4.7 baseline, and then commit the patches and post the new versions with updated context and bug fixes, where they have changed.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ramana Radhakrishnan (ramana) wrote : | # |
I had a quick look through them - the patches that have been committed upstream have been committed slightly different to the revisions here which makes a complete review a bit harder. Also given that there is a bit of churn because of backport conflicts doing a full review is harder in this case.
The testresults look OK. Given I'm not on review duty this week I don't have more time to spend on this.
Ramana
Preview Diff
1 | === modified file 'ChangeLog.linaro' |
2 | --- ChangeLog.linaro 2011-08-10 23:03:03 +0000 |
3 | +++ ChangeLog.linaro 2011-08-11 16:16:07 +0000 |
4 | @@ -1,3 +1,4 @@ |
5 | +<<<<<<< TREE |
6 | 2011-08-11 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> |
7 | |
8 | gcc/ |
9 | @@ -185,6 +186,134 @@ |
10 | |
11 | * gcc.c-torture/compile/20110401-1.c: New test. |
12 | |
13 | +======= |
14 | +2011-08-05 Andrew Stubbs <ams@codesourcery.com> |
15 | + |
16 | + Backport from patches proposed for 4.7: |
17 | + |
18 | + 2011-07-22 Andrew Stubbs <ams@codesourcery.com> |
19 | + |
20 | + gcc/ |
21 | + * tree-ssa-math-opts.c (is_widening_mult_rhs_p): Handle constants |
22 | + beyond conversions. |
23 | + (convert_mult_to_widen): Convert constant inputs to the right type. |
24 | + (convert_plusminus_to_widen): Don't automatically reject inputs that |
25 | + are not an SSA_NAME. |
26 | + Convert constant inputs to the right type. |
27 | + |
28 | + gcc/testsuite/ |
29 | + * gcc.target/arm/wmul-11.c: New file. |
30 | + * gcc.target/arm/wmul-12.c: New file. |
31 | + * gcc.target/arm/wmul-13.c: New file. |
32 | + |
33 | + 2011-07-21 Andrew Stubbs <ams@codesourcery.com> |
34 | + |
35 | + gcc/ |
36 | + * tree-ssa-math-opts.c (convert_plusminus_to_widen): Convert add_rhs |
37 | + to the correct type. |
38 | + |
39 | + gcc/testsuite/ |
40 | + * gcc.target/arm/wmul-10.c: New file. |
41 | + |
42 | + 2011-06-24 Andrew Stubbs <ams@codesourcery.com> |
43 | + |
44 | + gcc/ |
45 | + * tree-ssa-math-opts.c (convert_mult_to_widen): Better handle |
46 | + unsigned inputs of different modes. |
47 | + (convert_plusminus_to_widen): Likewise. |
48 | + |
49 | + gcc/testsuite/ |
50 | + * gcc.target/arm/wmul-9.c: New file. |
51 | + * gcc.target/arm/wmul-bitfield-2.c: New file. |
52 | + |
53 | + 2011-07-14 Andrew Stubbs <ams@codesourcery.com> |
54 | + |
55 | + gcc/ |
56 | + * tree-ssa-math-opts.c (is_widening_mult_rhs_p): Add new argument |
57 | + 'type'. |
58 | + Use 'type' from caller, not inferred from 'rhs'. |
59 | + Don't reject non-conversion statements. Do return lhs in this case. |
60 | + (is_widening_mult_p): Add new argument 'type'. |
61 | + Use 'type' from caller, not inferred from 'stmt'. |
62 | + Pass type to is_widening_mult_rhs_p. |
63 | + (convert_mult_to_widen): Pass type to is_widening_mult_p. |
64 | + (convert_plusminus_to_widen): Likewise. |
65 | + |
66 | + gcc/testsuite/ |
67 | + * gcc.target/arm/wmul-8.c: New file. |
68 | + |
69 | + 2011-07-14 Andrew Stubbs <ams@codesourcery.com> |
70 | + |
71 | + gcc/ |
72 | + * tree-ssa-math-opts.c (is_widening_mult_p): Remove FIXME. |
73 | + Ensure the the larger type is the first operand. |
74 | + |
75 | + gcc/testsuite/ |
76 | + * gcc.target/arm/wmul-7.c: New file. |
77 | + |
78 | + 2011-07-14 Andrew Stubbs <ams@codesourcery.com> |
79 | + |
80 | + gcc/ |
81 | + * tree-ssa-math-opts.c (convert_mult_to_widen): Convert |
82 | + unsupported unsigned multiplies to signed. |
83 | + (convert_plusminus_to_widen): Likewise. |
84 | + |
85 | + gcc/testsuite/ |
86 | + * gcc.target/arm/wmul-6.c: New file. |
87 | + |
88 | + 2011-07-14 Andrew Stubbs <ams@codesourcery.com> |
89 | + |
90 | + gcc/ |
91 | + * tree-ssa-math-opts.c (convert_plusminus_to_widen): Permit a single |
92 | + conversion statement separating multiply-and-accumulate. |
93 | + |
94 | + gcc/testsuite/ |
95 | + * gcc.target/arm/wmul-5.c: New file. |
96 | + * gcc.target/arm/no-wmla-1.c: New file. |
97 | + |
98 | + 2011-07-27 Andrew Stubbs <ams@codesourcery.com> |
99 | + |
100 | + gcc/ |
101 | + * config/arm/arm.md (maddhidi4): Remove '*' from name. |
102 | + * expr.c (expand_expr_real_2): Use find_widening_optab_handler. |
103 | + * optabs.c (find_widening_optab_handler_and_mode): New function. |
104 | + (expand_widen_pattern_expr): Use find_widening_optab_handler. |
105 | + (expand_binop_directly): Likewise. |
106 | + (expand_binop): Likewise. |
107 | + * optabs.h (find_widening_optab_handler): New macro define. |
108 | + (find_widening_optab_handler_and_mode): New prototype. |
109 | + * tree-cfg.c (verify_gimple_assign_binary): Adjust WIDEN_MULT_EXPR |
110 | + type precision rules. |
111 | + (verify_gimple_assign_ternary): Likewise for WIDEN_MULT_PLUS_EXPR. |
112 | + * tree-ssa-math-opts.c (build_and_insert_cast): New function. |
113 | + (is_widening_mult_rhs_p): Allow widening by more than one mode. |
114 | + Explicitly disallow mis-matched input types. |
115 | + (convert_mult_to_widen): Use find_widening_optab_handler, and cast |
116 | + input types to fit the new handler. |
117 | + (convert_plusminus_to_widen): Likewise. |
118 | + |
119 | + gcc/testsuite/ |
120 | + * gcc.target/arm/wmul-bitfield-1.c: New file. |
121 | + |
122 | + 2011-07-27 Andrew Stubbs <ams@codesourcery.com> |
123 | + |
124 | + gcc/ |
125 | + * expr.c (expand_expr_real_2): Use widening_optab_handler. |
126 | + * genopinit.c (optabs): Use set_widening_optab_handler for $N. |
127 | + (gen_insn): $N now means $a must be wider than $b, not consecutive. |
128 | + * optabs.c (widened_mode): New function. |
129 | + (expand_widen_pattern_expr): Use widening_optab_handler. |
130 | + (expand_binop_directly): Likewise. |
131 | + (expand_binop): Likewise. |
132 | + * optabs.h (widening_optab_handlers): New struct. |
133 | + (optab_d): New member, 'widening'. |
134 | + (widening_optab_handler): New function. |
135 | + (set_widening_optab_handler): New function. |
136 | + * tree-ssa-math-opts.c (convert_mult_to_widen): Use |
137 | + widening_optab_handler. |
138 | + (convert_plusminus_to_widen): Likewise. |
139 | + |
140 | +>>>>>>> MERGE-SOURCE |
141 | 2011-07-13 Richard Sandiford <richard.sandiford@linaro.org> |
142 | |
143 | Backport from mainline: |
144 | |
145 | === modified file 'gcc/config/arm/arm.md' |
146 | --- gcc/config/arm/arm.md 2011-06-28 12:02:27 +0000 |
147 | +++ gcc/config/arm/arm.md 2011-08-11 16:16:07 +0000 |
148 | @@ -1839,7 +1839,7 @@ |
149 | (set_attr "predicable" "yes")] |
150 | ) |
151 | |
152 | -(define_insn "*maddhidi4" |
153 | +(define_insn "maddhidi4" |
154 | [(set (match_operand:DI 0 "s_register_operand" "=r") |
155 | (plus:DI |
156 | (mult:DI (sign_extend:DI |
157 | |
158 | === modified file 'gcc/expr.c' |
159 | --- gcc/expr.c 2011-07-14 11:52:32 +0000 |
160 | +++ gcc/expr.c 2011-08-11 16:16:07 +0000 |
161 | @@ -7680,18 +7680,16 @@ |
162 | { |
163 | enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0)); |
164 | this_optab = usmul_widen_optab; |
165 | - if (mode == GET_MODE_2XWIDER_MODE (innermode)) |
166 | + if (find_widening_optab_handler (this_optab, mode, innermode, 0) |
167 | + != CODE_FOR_nothing) |
168 | { |
169 | - if (optab_handler (this_optab, mode) != CODE_FOR_nothing) |
170 | - { |
171 | - if (TYPE_UNSIGNED (TREE_TYPE (treeop0))) |
172 | - expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, |
173 | - EXPAND_NORMAL); |
174 | - else |
175 | - expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0, |
176 | - EXPAND_NORMAL); |
177 | - goto binop3; |
178 | - } |
179 | + if (TYPE_UNSIGNED (TREE_TYPE (treeop0))) |
180 | + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, |
181 | + EXPAND_NORMAL); |
182 | + else |
183 | + expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0, |
184 | + EXPAND_NORMAL); |
185 | + goto binop3; |
186 | } |
187 | } |
188 | /* Check for a multiplication with matching signedness. */ |
189 | @@ -7706,10 +7704,10 @@ |
190 | optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab; |
191 | this_optab = zextend_p ? umul_widen_optab : smul_widen_optab; |
192 | |
193 | - if (mode == GET_MODE_2XWIDER_MODE (innermode) |
194 | - && TREE_CODE (treeop0) != INTEGER_CST) |
195 | + if (TREE_CODE (treeop0) != INTEGER_CST) |
196 | { |
197 | - if (optab_handler (this_optab, mode) != CODE_FOR_nothing) |
198 | + if (find_widening_optab_handler (this_optab, mode, innermode, 0) |
199 | + != CODE_FOR_nothing) |
200 | { |
201 | expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, |
202 | EXPAND_NORMAL); |
203 | @@ -7717,7 +7715,8 @@ |
204 | unsignedp, this_optab); |
205 | return REDUCE_BIT_FIELD (temp); |
206 | } |
207 | - if (optab_handler (other_optab, mode) != CODE_FOR_nothing |
208 | + if (find_widening_optab_handler (other_optab, mode, innermode, 0) |
209 | + != CODE_FOR_nothing |
210 | && innermode == word_mode) |
211 | { |
212 | rtx htem, hipart; |
213 | |
214 | === modified file 'gcc/genopinit.c' |
215 | --- gcc/genopinit.c 2011-05-05 15:43:06 +0000 |
216 | +++ gcc/genopinit.c 2011-08-11 16:16:07 +0000 |
217 | @@ -46,10 +46,12 @@ |
218 | used. $A and $B are replaced with the full name of the mode; $a and $b |
219 | are replaced with the short form of the name, as above. |
220 | |
221 | - If $N is present in the pattern, it means the two modes must be consecutive |
222 | - widths in the same mode class (e.g, QImode and HImode). $I means that |
223 | - only full integer modes should be considered for the next mode, and $F |
224 | - means that only float modes should be considered. |
225 | + If $N is present in the pattern, it means the two modes must be in |
226 | + the same mode class, and $b must be greater than $a (e.g, QImode |
227 | + and HImode). |
228 | + |
229 | + $I means that only full integer modes should be considered for the |
230 | + next mode, and $F means that only float modes should be considered. |
231 | $P means that both full and partial integer modes should be considered. |
232 | $Q means that only fixed-point modes should be considered. |
233 | |
234 | @@ -99,17 +101,17 @@ |
235 | "set_optab_handler (smulv_optab, $A, CODE_FOR_$(mulv$I$a3$))", |
236 | "set_optab_handler (umul_highpart_optab, $A, CODE_FOR_$(umul$a3_highpart$))", |
237 | "set_optab_handler (smul_highpart_optab, $A, CODE_FOR_$(smul$a3_highpart$))", |
238 | - "set_optab_handler (smul_widen_optab, $B, CODE_FOR_$(mul$a$b3$)$N)", |
239 | - "set_optab_handler (umul_widen_optab, $B, CODE_FOR_$(umul$a$b3$)$N)", |
240 | - "set_optab_handler (usmul_widen_optab, $B, CODE_FOR_$(usmul$a$b3$)$N)", |
241 | - "set_optab_handler (smadd_widen_optab, $B, CODE_FOR_$(madd$a$b4$)$N)", |
242 | - "set_optab_handler (umadd_widen_optab, $B, CODE_FOR_$(umadd$a$b4$)$N)", |
243 | - "set_optab_handler (ssmadd_widen_optab, $B, CODE_FOR_$(ssmadd$a$b4$)$N)", |
244 | - "set_optab_handler (usmadd_widen_optab, $B, CODE_FOR_$(usmadd$a$b4$)$N)", |
245 | - "set_optab_handler (smsub_widen_optab, $B, CODE_FOR_$(msub$a$b4$)$N)", |
246 | - "set_optab_handler (umsub_widen_optab, $B, CODE_FOR_$(umsub$a$b4$)$N)", |
247 | - "set_optab_handler (ssmsub_widen_optab, $B, CODE_FOR_$(ssmsub$a$b4$)$N)", |
248 | - "set_optab_handler (usmsub_widen_optab, $B, CODE_FOR_$(usmsub$a$b4$)$N)", |
249 | + "set_widening_optab_handler (smul_widen_optab, $B, $A, CODE_FOR_$(mul$a$b3$)$N)", |
250 | + "set_widening_optab_handler (umul_widen_optab, $B, $A, CODE_FOR_$(umul$a$b3$)$N)", |
251 | + "set_widening_optab_handler (usmul_widen_optab, $B, $A, CODE_FOR_$(usmul$a$b3$)$N)", |
252 | + "set_widening_optab_handler (smadd_widen_optab, $B, $A, CODE_FOR_$(madd$a$b4$)$N)", |
253 | + "set_widening_optab_handler (umadd_widen_optab, $B, $A, CODE_FOR_$(umadd$a$b4$)$N)", |
254 | + "set_widening_optab_handler (ssmadd_widen_optab, $B, $A, CODE_FOR_$(ssmadd$a$b4$)$N)", |
255 | + "set_widening_optab_handler (usmadd_widen_optab, $B, $A, CODE_FOR_$(usmadd$a$b4$)$N)", |
256 | + "set_widening_optab_handler (smsub_widen_optab, $B, $A, CODE_FOR_$(msub$a$b4$)$N)", |
257 | + "set_widening_optab_handler (umsub_widen_optab, $B, $A, CODE_FOR_$(umsub$a$b4$)$N)", |
258 | + "set_widening_optab_handler (ssmsub_widen_optab, $B, $A, CODE_FOR_$(ssmsub$a$b4$)$N)", |
259 | + "set_widening_optab_handler (usmsub_widen_optab, $B, $A, CODE_FOR_$(usmsub$a$b4$)$N)", |
260 | "set_optab_handler (sdiv_optab, $A, CODE_FOR_$(div$a3$))", |
261 | "set_optab_handler (ssdiv_optab, $A, CODE_FOR_$(ssdiv$Q$a3$))", |
262 | "set_optab_handler (sdivv_optab, $A, CODE_FOR_$(div$V$I$a3$))", |
263 | @@ -304,7 +306,7 @@ |
264 | { |
265 | int force_float = 0, force_int = 0, force_partial_int = 0; |
266 | int force_fixed = 0; |
267 | - int force_consec = 0; |
268 | + int force_wider = 0; |
269 | int matches = 1; |
270 | |
271 | for (pp = optabs[pindex]; pp[0] != '$' || pp[1] != '('; pp++) |
272 | @@ -322,7 +324,7 @@ |
273 | switch (*++pp) |
274 | { |
275 | case 'N': |
276 | - force_consec = 1; |
277 | + force_wider = 1; |
278 | break; |
279 | case 'I': |
280 | force_int = 1; |
281 | @@ -391,7 +393,10 @@ |
282 | || mode_class[i] == MODE_VECTOR_FRACT |
283 | || mode_class[i] == MODE_VECTOR_UFRACT |
284 | || mode_class[i] == MODE_VECTOR_ACCUM |
285 | - || mode_class[i] == MODE_VECTOR_UACCUM)) |
286 | + || mode_class[i] == MODE_VECTOR_UACCUM) |
287 | + && (! force_wider |
288 | + || *pp == 'a' |
289 | + || m1 < i)) |
290 | break; |
291 | } |
292 | |
293 | @@ -411,8 +416,7 @@ |
294 | } |
295 | |
296 | if (matches && pp[0] == '$' && pp[1] == ')' |
297 | - && *np == 0 |
298 | - && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2)) |
299 | + && *np == 0) |
300 | break; |
301 | } |
302 | |
303 | |
304 | === modified file 'gcc/optabs.c' |
305 | --- gcc/optabs.c 2011-07-04 14:03:49 +0000 |
306 | +++ gcc/optabs.c 2011-08-11 16:16:07 +0000 |
307 | @@ -225,6 +225,61 @@ |
308 | return 1; |
309 | } |
310 | |
311 | |
312 | +/* Given two input operands, OP0 and OP1, determine what the correct from_mode |
313 | + for a widening operation would be. In most cases this would be OP0, but if |
314 | + that's a constant it'll be VOIDmode, which isn't useful. */ |
315 | + |
316 | +static enum machine_mode |
317 | +widened_mode (enum machine_mode to_mode, rtx op0, rtx op1) |
318 | +{ |
319 | + enum machine_mode m0 = GET_MODE (op0); |
320 | + enum machine_mode m1 = GET_MODE (op1); |
321 | + enum machine_mode result; |
322 | + |
323 | + if (m0 == VOIDmode && m1 == VOIDmode) |
324 | + return to_mode; |
325 | + else if (m0 == VOIDmode || GET_MODE_SIZE (m0) < GET_MODE_SIZE (m1)) |
326 | + result = m1; |
327 | + else |
328 | + result = m0; |
329 | + |
330 | + if (GET_MODE_SIZE (result) > GET_MODE_SIZE (to_mode)) |
331 | + return to_mode; |
332 | + |
333 | + return result; |
334 | +} |
335 | + |
336 | |
337 | +/* Find a widening optab even if it doesn't widen as much as we want. |
338 | + E.g. if from_mode is HImode, and to_mode is DImode, and there is no |
339 | + direct HI->SI insn, then return SI->DI, if that exists. |
340 | + If PERMIT_NON_WIDENING is non-zero then this can be used with |
341 | + non-widening optabs also. */ |
342 | + |
343 | +enum insn_code |
344 | +find_widening_optab_handler_and_mode (optab op, enum machine_mode to_mode, |
345 | + enum machine_mode from_mode, |
346 | + int permit_non_widening, |
347 | + enum machine_mode *found_mode) |
348 | +{ |
349 | + for (; (permit_non_widening || from_mode != to_mode) |
350 | + && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode) |
351 | + && from_mode != VOIDmode; |
352 | + from_mode = GET_MODE_WIDER_MODE (from_mode)) |
353 | + { |
354 | + enum insn_code handler = widening_optab_handler (op, to_mode, |
355 | + from_mode); |
356 | + |
357 | + if (handler != CODE_FOR_nothing) |
358 | + { |
359 | + if (found_mode) |
360 | + *found_mode = from_mode; |
361 | + return handler; |
362 | + } |
363 | + } |
364 | + |
365 | + return CODE_FOR_nothing; |
366 | +} |
367 | + |
368 | |
369 | /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP |
370 | says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need |
371 | not actually do a sign-extend or zero-extend, but can leave the |
372 | @@ -517,8 +572,9 @@ |
373 | optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default); |
374 | if (ops->code == WIDEN_MULT_PLUS_EXPR |
375 | || ops->code == WIDEN_MULT_MINUS_EXPR) |
376 | - icode = (int) optab_handler (widen_pattern_optab, |
377 | - TYPE_MODE (TREE_TYPE (ops->op2))); |
378 | + icode = (int) find_widening_optab_handler (widen_pattern_optab, |
379 | + TYPE_MODE (TREE_TYPE (ops->op2)), |
380 | + tmode0, 0); |
381 | else |
382 | icode = (int) optab_handler (widen_pattern_optab, tmode0); |
383 | gcc_assert (icode != CODE_FOR_nothing); |
384 | @@ -1389,7 +1445,9 @@ |
385 | rtx target, int unsignedp, enum optab_methods methods, |
386 | rtx last) |
387 | { |
388 | - int icode = (int) optab_handler (binoptab, mode); |
389 | + enum machine_mode from_mode = widened_mode (mode, op0, op1); |
390 | + int icode = (int) find_widening_optab_handler (binoptab, mode, |
391 | + from_mode, 1); |
392 | enum machine_mode mode0 = insn_data[icode].operand[1].mode; |
393 | enum machine_mode mode1 = insn_data[icode].operand[2].mode; |
394 | enum machine_mode tmp_mode; |
395 | @@ -1546,7 +1604,9 @@ |
396 | /* If we can do it with a three-operand insn, do so. */ |
397 | |
398 | if (methods != OPTAB_MUST_WIDEN |
399 | - && optab_handler (binoptab, mode) != CODE_FOR_nothing) |
400 | + && find_widening_optab_handler (binoptab, mode, |
401 | + widened_mode (mode, op0, op1), 1) |
402 | + != CODE_FOR_nothing) |
403 | { |
404 | temp = expand_binop_directly (mode, binoptab, op0, op1, target, |
405 | unsignedp, methods, last); |
406 | @@ -1586,8 +1646,9 @@ |
407 | |
408 | if (binoptab == smul_optab |
409 | && GET_MODE_WIDER_MODE (mode) != VOIDmode |
410 | - && (optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab), |
411 | - GET_MODE_WIDER_MODE (mode)) |
412 | + && (widening_optab_handler ((unsignedp ? umul_widen_optab |
413 | + : smul_widen_optab), |
414 | + GET_MODE_WIDER_MODE (mode), mode) |
415 | != CODE_FOR_nothing)) |
416 | { |
417 | temp = expand_binop (GET_MODE_WIDER_MODE (mode), |
418 | @@ -1618,9 +1679,11 @@ |
419 | if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing |
420 | || (binoptab == smul_optab |
421 | && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode |
422 | - && (optab_handler ((unsignedp ? umul_widen_optab |
423 | - : smul_widen_optab), |
424 | - GET_MODE_WIDER_MODE (wider_mode)) |
425 | + && (find_widening_optab_handler ((unsignedp |
426 | + ? umul_widen_optab |
427 | + : smul_widen_optab), |
428 | + GET_MODE_WIDER_MODE (wider_mode), |
429 | + mode, 0) |
430 | != CODE_FOR_nothing))) |
431 | { |
432 | rtx xop0 = op0, xop1 = op1; |
433 | @@ -2043,8 +2106,8 @@ |
434 | && optab_handler (add_optab, word_mode) != CODE_FOR_nothing) |
435 | { |
436 | rtx product = NULL_RTX; |
437 | - |
438 | - if (optab_handler (umul_widen_optab, mode) != CODE_FOR_nothing) |
439 | + if (widening_optab_handler (umul_widen_optab, mode, word_mode) |
440 | + != CODE_FOR_nothing) |
441 | { |
442 | product = expand_doubleword_mult (mode, op0, op1, target, |
443 | true, methods); |
444 | @@ -2053,7 +2116,8 @@ |
445 | } |
446 | |
447 | if (product == NULL_RTX |
448 | - && optab_handler (smul_widen_optab, mode) != CODE_FOR_nothing) |
449 | + && widening_optab_handler (smul_widen_optab, mode, word_mode) |
450 | + != CODE_FOR_nothing) |
451 | { |
452 | product = expand_doubleword_mult (mode, op0, op1, target, |
453 | false, methods); |
454 | @@ -2144,7 +2208,8 @@ |
455 | wider_mode != VOIDmode; |
456 | wider_mode = GET_MODE_WIDER_MODE (wider_mode)) |
457 | { |
458 | - if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing |
459 | + if (find_widening_optab_handler (binoptab, wider_mode, mode, 1) |
460 | + != CODE_FOR_nothing |
461 | || (methods == OPTAB_LIB |
462 | && optab_libfunc (binoptab, wider_mode))) |
463 | { |
464 | |
465 | === modified file 'gcc/optabs.h' |
466 | --- gcc/optabs.h 2011-05-05 15:43:06 +0000 |
467 | +++ gcc/optabs.h 2011-08-11 16:16:07 +0000 |
468 | @@ -42,6 +42,11 @@ |
469 | int insn_code; |
470 | }; |
471 | |
472 | +struct widening_optab_handlers |
473 | +{ |
474 | + struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES]; |
475 | +}; |
476 | + |
477 | struct optab_d |
478 | { |
479 | enum rtx_code code; |
480 | @@ -50,6 +55,7 @@ |
481 | void (*libcall_gen)(struct optab_d *, const char *name, char suffix, |
482 | enum machine_mode); |
483 | struct optab_handlers handlers[NUM_MACHINE_MODES]; |
484 | + struct widening_optab_handlers *widening; |
485 | }; |
486 | typedef struct optab_d * optab; |
487 | |
488 | @@ -799,6 +805,15 @@ |
489 | extern void emit_unop_insn (int, rtx, rtx, enum rtx_code); |
490 | extern bool maybe_emit_unop_insn (int, rtx, rtx, enum rtx_code); |
491 | |
492 | +/* Find a widening optab even if it doesn't widen as much as we want. */ |
493 | +#define find_widening_optab_handler(A,B,C,D) \ |
494 | + find_widening_optab_handler_and_mode (A, B, C, D, NULL) |
495 | +extern enum insn_code find_widening_optab_handler_and_mode (optab, |
496 | + enum machine_mode, |
497 | + enum machine_mode, |
498 | + int, |
499 | + enum machine_mode *); |
500 | + |
501 | /* An extra flag to control optab_for_tree_code's behavior. This is needed to |
502 | distinguish between machines with a vector shift that takes a scalar for the |
503 | shift amount vs. machines that take a vector for the shift amount. */ |
504 | @@ -874,6 +889,23 @@ |
505 | + (int) CODE_FOR_nothing); |
506 | } |
507 | |
508 | +/* Like optab_handler, but for widening_operations that have a TO_MODE and |
509 | + a FROM_MODE. */ |
510 | + |
511 | +static inline enum insn_code |
512 | +widening_optab_handler (optab op, enum machine_mode to_mode, |
513 | + enum machine_mode from_mode) |
514 | +{ |
515 | + if (to_mode == from_mode || from_mode == VOIDmode) |
516 | + return optab_handler (op, to_mode); |
517 | + |
518 | + if (op->widening) |
519 | + return (enum insn_code) (op->widening->handlers[(int) to_mode][(int) from_mode].insn_code |
520 | + + (int) CODE_FOR_nothing); |
521 | + |
522 | + return CODE_FOR_nothing; |
523 | +} |
524 | + |
525 | /* Record that insn CODE should be used to implement mode MODE of OP. */ |
526 | |
527 | static inline void |
528 | @@ -882,6 +914,26 @@ |
529 | op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing; |
530 | } |
531 | |
532 | +/* Like set_optab_handler, but for widening operations that have a TO_MODE |
533 | + and a FROM_MODE. */ |
534 | + |
535 | +static inline void |
536 | +set_widening_optab_handler (optab op, enum machine_mode to_mode, |
537 | + enum machine_mode from_mode, enum insn_code code) |
538 | +{ |
539 | + if (to_mode == from_mode) |
540 | + set_optab_handler (op, to_mode, code); |
541 | + else |
542 | + { |
543 | + if (op->widening == NULL) |
544 | + op->widening = (struct widening_optab_handlers *) |
545 | + xcalloc (1, sizeof (struct widening_optab_handlers)); |
546 | + |
547 | + op->widening->handlers[(int) to_mode][(int) from_mode].insn_code |
548 | + = (int) code - (int) CODE_FOR_nothing; |
549 | + } |
550 | +} |
551 | + |
552 | /* Return the insn used to perform conversion OP from mode FROM_MODE |
553 | to mode TO_MODE; return CODE_FOR_nothing if the target does not have |
554 | such an insn. */ |
555 | |
556 | === added file 'gcc/testsuite/gcc.target/arm/no-wmla-1.c' |
557 | --- gcc/testsuite/gcc.target/arm/no-wmla-1.c 1970-01-01 00:00:00 +0000 |
558 | +++ gcc/testsuite/gcc.target/arm/no-wmla-1.c 2011-08-11 16:16:07 +0000 |
559 | @@ -0,0 +1,11 @@ |
560 | +/* { dg-do compile } */ |
561 | +/* { dg-options "-O2 -march=armv7-a" } */ |
562 | + |
563 | +int |
564 | +foo (int a, short b, short c) |
565 | +{ |
566 | + int bc = b * c; |
567 | + return a + (short)bc; |
568 | +} |
569 | + |
570 | +/* { dg-final { scan-assembler "mul" } } */ |
571 | |
572 | === added file 'gcc/testsuite/gcc.target/arm/wmul-10.c' |
573 | --- gcc/testsuite/gcc.target/arm/wmul-10.c 1970-01-01 00:00:00 +0000 |
574 | +++ gcc/testsuite/gcc.target/arm/wmul-10.c 2011-08-11 16:16:07 +0000 |
575 | @@ -0,0 +1,10 @@ |
576 | +/* { dg-do compile } */ |
577 | +/* { dg-options "-O2 -march=armv7-a" } */ |
578 | + |
579 | +unsigned long long |
580 | +foo (unsigned short a, unsigned short *b, unsigned short *c) |
581 | +{ |
582 | + return (unsigned)a + (unsigned long long)*b * (unsigned long long)*c; |
583 | +} |
584 | + |
585 | +/* { dg-final { scan-assembler "umlal" } } */ |
586 | |
587 | === added file 'gcc/testsuite/gcc.target/arm/wmul-11.c' |
588 | --- gcc/testsuite/gcc.target/arm/wmul-11.c 1970-01-01 00:00:00 +0000 |
589 | +++ gcc/testsuite/gcc.target/arm/wmul-11.c 2011-08-11 16:16:07 +0000 |
590 | @@ -0,0 +1,10 @@ |
591 | +/* { dg-do compile } */ |
592 | +/* { dg-options "-O2 -march=armv7-a" } */ |
593 | + |
594 | +long long |
595 | +foo (int *b) |
596 | +{ |
597 | + return 10 * (long long)*b; |
598 | +} |
599 | + |
600 | +/* { dg-final { scan-assembler "smull" } } */ |
601 | |
602 | === added file 'gcc/testsuite/gcc.target/arm/wmul-12.c' |
603 | --- gcc/testsuite/gcc.target/arm/wmul-12.c 1970-01-01 00:00:00 +0000 |
604 | +++ gcc/testsuite/gcc.target/arm/wmul-12.c 2011-08-11 16:16:07 +0000 |
605 | @@ -0,0 +1,11 @@ |
606 | +/* { dg-do compile } */ |
607 | +/* { dg-options "-O2 -march=armv7-a" } */ |
608 | + |
609 | +long long |
610 | +foo (int *b, int *c) |
611 | +{ |
612 | + int tmp = *b * *c; |
613 | + return 10 + (long long)tmp; |
614 | +} |
615 | + |
616 | +/* { dg-final { scan-assembler "smlal" } } */ |
617 | |
618 | === added file 'gcc/testsuite/gcc.target/arm/wmul-13.c' |
619 | --- gcc/testsuite/gcc.target/arm/wmul-13.c 1970-01-01 00:00:00 +0000 |
620 | +++ gcc/testsuite/gcc.target/arm/wmul-13.c 2011-08-11 16:16:07 +0000 |
621 | @@ -0,0 +1,10 @@ |
622 | +/* { dg-do compile } */ |
623 | +/* { dg-options "-O2 -march=armv7-a" } */ |
624 | + |
625 | +long long |
626 | +foo (int *a, int *b) |
627 | +{ |
628 | + return *a + (long long)*b * 10; |
629 | +} |
630 | + |
631 | +/* { dg-final { scan-assembler "smlal" } } */ |
632 | |
633 | === added file 'gcc/testsuite/gcc.target/arm/wmul-5.c' |
634 | --- gcc/testsuite/gcc.target/arm/wmul-5.c 1970-01-01 00:00:00 +0000 |
635 | +++ gcc/testsuite/gcc.target/arm/wmul-5.c 2011-08-11 16:16:07 +0000 |
636 | @@ -0,0 +1,10 @@ |
637 | +/* { dg-do compile } */ |
638 | +/* { dg-options "-O2 -march=armv7-a" } */ |
639 | + |
640 | +long long |
641 | +foo (long long a, char *b, char *c) |
642 | +{ |
643 | + return a + *b * *c; |
644 | +} |
645 | + |
646 | +/* { dg-final { scan-assembler "umlal" } } */ |
647 | |
648 | === added file 'gcc/testsuite/gcc.target/arm/wmul-6.c' |
649 | --- gcc/testsuite/gcc.target/arm/wmul-6.c 1970-01-01 00:00:00 +0000 |
650 | +++ gcc/testsuite/gcc.target/arm/wmul-6.c 2011-08-11 16:16:07 +0000 |
651 | @@ -0,0 +1,10 @@ |
652 | +/* { dg-do compile } */ |
653 | +/* { dg-options "-O2 -march=armv7-a" } */ |
654 | + |
655 | +long long |
656 | +foo (long long a, unsigned char *b, signed char *c) |
657 | +{ |
658 | + return a + (long long)*b * (long long)*c; |
659 | +} |
660 | + |
661 | +/* { dg-final { scan-assembler "smlal" } } */ |
662 | |
663 | === added file 'gcc/testsuite/gcc.target/arm/wmul-7.c' |
664 | --- gcc/testsuite/gcc.target/arm/wmul-7.c 1970-01-01 00:00:00 +0000 |
665 | +++ gcc/testsuite/gcc.target/arm/wmul-7.c 2011-08-11 16:16:07 +0000 |
666 | @@ -0,0 +1,10 @@ |
667 | +/* { dg-do compile } */ |
668 | +/* { dg-options "-O2 -march=armv7-a" } */ |
669 | + |
670 | +unsigned long long |
671 | +foo (unsigned long long a, unsigned char *b, unsigned short *c) |
672 | +{ |
673 | + return a + *b * *c; |
674 | +} |
675 | + |
676 | +/* { dg-final { scan-assembler "umlal" } } */ |
677 | |
678 | === added file 'gcc/testsuite/gcc.target/arm/wmul-8.c' |
679 | --- gcc/testsuite/gcc.target/arm/wmul-8.c 1970-01-01 00:00:00 +0000 |
680 | +++ gcc/testsuite/gcc.target/arm/wmul-8.c 2011-08-11 16:16:07 +0000 |
681 | @@ -0,0 +1,10 @@ |
682 | +/* { dg-do compile } */ |
683 | +/* { dg-options "-O2 -march=armv7-a" } */ |
684 | + |
685 | +long long |
686 | +foo (long long a, int *b, int *c) |
687 | +{ |
688 | + return a + *b * *c; |
689 | +} |
690 | + |
691 | +/* { dg-final { scan-assembler "smlal" } } */ |
692 | |
693 | === added file 'gcc/testsuite/gcc.target/arm/wmul-9.c' |
694 | --- gcc/testsuite/gcc.target/arm/wmul-9.c 1970-01-01 00:00:00 +0000 |
695 | +++ gcc/testsuite/gcc.target/arm/wmul-9.c 2011-08-11 16:16:07 +0000 |
696 | @@ -0,0 +1,10 @@ |
697 | +/* { dg-do compile } */ |
698 | +/* { dg-options "-O2 -march=armv7-a" } */ |
699 | + |
700 | +long long |
701 | +foo (long long a, short *b, char *c) |
702 | +{ |
703 | + return a + *b * *c; |
704 | +} |
705 | + |
706 | +/* { dg-final { scan-assembler "smlalbb" } } */ |
707 | |
708 | === added file 'gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c' |
709 | --- gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c 1970-01-01 00:00:00 +0000 |
710 | +++ gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c 2011-08-11 16:16:07 +0000 |
711 | @@ -0,0 +1,17 @@ |
712 | +/* { dg-do compile } */ |
713 | +/* { dg-options "-O2 -march=armv7-a" } */ |
714 | + |
715 | +struct bf |
716 | +{ |
717 | + int a : 3; |
718 | + int b : 15; |
719 | + int c : 3; |
720 | +}; |
721 | + |
722 | +long long |
723 | +foo (long long a, struct bf b, struct bf c) |
724 | +{ |
725 | + return a + b.b * c.b; |
726 | +} |
727 | + |
728 | +/* { dg-final { scan-assembler "smlalbb" } } */ |
729 | |
730 | === added file 'gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c' |
731 | --- gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c 1970-01-01 00:00:00 +0000 |
732 | +++ gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c 2011-08-11 16:16:07 +0000 |
733 | @@ -0,0 +1,17 @@ |
734 | +/* { dg-do compile } */ |
735 | +/* { dg-options "-O2 -march=armv7-a" } */ |
736 | + |
737 | +struct bf |
738 | +{ |
739 | + int a : 3; |
740 | + unsigned int b : 15; |
741 | + int c : 3; |
742 | +}; |
743 | + |
744 | +long long |
745 | +foo (long long a, struct bf b, struct bf c) |
746 | +{ |
747 | + return a + b.b * c.c; |
748 | +} |
749 | + |
750 | +/* { dg-final { scan-assembler "smlalbb" } } */ |
751 | |
752 | === modified file 'gcc/tree-cfg.c' |
753 | --- gcc/tree-cfg.c 2011-07-01 09:19:21 +0000 |
754 | +++ gcc/tree-cfg.c 2011-08-11 16:16:07 +0000 |
755 | @@ -3574,7 +3574,7 @@ |
756 | case WIDEN_MULT_EXPR: |
757 | if (TREE_CODE (lhs_type) != INTEGER_TYPE) |
758 | return true; |
759 | - return ((2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type)) |
760 | + return ((2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)) |
761 | || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))); |
762 | |
763 | case WIDEN_SUM_EXPR: |
764 | @@ -3667,7 +3667,7 @@ |
765 | && !FIXED_POINT_TYPE_P (rhs1_type)) |
766 | || !useless_type_conversion_p (rhs1_type, rhs2_type) |
767 | || !useless_type_conversion_p (lhs_type, rhs3_type) |
768 | - || 2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type) |
769 | + || 2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type) |
770 | || TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)) |
771 | { |
772 | error ("type mismatch in widening multiply-accumulate expression"); |
773 | |
774 | === modified file 'gcc/tree-ssa-math-opts.c' |
775 | --- gcc/tree-ssa-math-opts.c 2011-03-11 16:36:16 +0000 |
776 | +++ gcc/tree-ssa-math-opts.c 2011-08-11 16:16:07 +0000 |
777 | @@ -1266,39 +1266,67 @@ |
778 | } |
779 | }; |
780 | |
781 | -/* Return true if RHS is a suitable operand for a widening multiplication. |
782 | +/* Build a gimple assignment to cast VAL to TARGET. Insert the statement |
783 | + prior to GSI's current position, and return the fresh SSA name. */ |
784 | + |
785 | +static tree |
786 | +build_and_insert_cast (gimple_stmt_iterator *gsi, location_t loc, |
787 | + tree target, tree val) |
788 | +{ |
789 | + tree result = make_ssa_name (target, NULL); |
790 | + gimple stmt = gimple_build_assign_with_ops (CONVERT_EXPR, result, val, NULL); |
791 | + gimple_set_location (stmt, loc); |
792 | + gsi_insert_before (gsi, stmt, GSI_SAME_STMT); |
793 | + return result; |
794 | +} |
795 | + |
796 | +/* Return true if RHS is a suitable operand for a widening multiplication, |
797 | + assuming a target type of TYPE. |
798 | There are two cases: |
799 | |
800 | - - RHS makes some value twice as wide. Store that value in *NEW_RHS_OUT |
801 | - if so, and store its type in *TYPE_OUT. |
802 | + - RHS makes some value at least twice as wide. Store that value |
803 | + in *NEW_RHS_OUT if so, and store its type in *TYPE_OUT. |
804 | |
805 | - RHS is an integer constant. Store that value in *NEW_RHS_OUT if so, |
806 | but leave *TYPE_OUT untouched. */ |
807 | |
808 | static bool |
809 | -is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out) |
810 | +is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out, |
811 | + tree *new_rhs_out) |
812 | { |
813 | gimple stmt; |
814 | - tree type, type1, rhs1; |
815 | + tree type1, rhs1; |
816 | enum tree_code rhs_code; |
817 | |
818 | if (TREE_CODE (rhs) == SSA_NAME) |
819 | { |
820 | - type = TREE_TYPE (rhs); |
821 | stmt = SSA_NAME_DEF_STMT (rhs); |
822 | - if (!is_gimple_assign (stmt)) |
823 | - return false; |
824 | - |
825 | - rhs_code = gimple_assign_rhs_code (stmt); |
826 | - if (TREE_CODE (type) == INTEGER_TYPE |
827 | - ? !CONVERT_EXPR_CODE_P (rhs_code) |
828 | - : rhs_code != FIXED_CONVERT_EXPR) |
829 | - return false; |
830 | - |
831 | - rhs1 = gimple_assign_rhs1 (stmt); |
832 | + if (is_gimple_assign (stmt)) |
833 | + { |
834 | + rhs_code = gimple_assign_rhs_code (stmt); |
835 | + if (TREE_CODE (type) == INTEGER_TYPE |
836 | + ? !CONVERT_EXPR_CODE_P (rhs_code) |
837 | + : rhs_code != FIXED_CONVERT_EXPR) |
838 | + rhs1 = rhs; |
839 | + else |
840 | + { |
841 | + rhs1 = gimple_assign_rhs1 (stmt); |
842 | + |
843 | + if (TREE_CODE (rhs1) == INTEGER_CST) |
844 | + { |
845 | + *new_rhs_out = rhs1; |
846 | + *type_out = NULL; |
847 | + return true; |
848 | + } |
849 | + } |
850 | + } |
851 | + else |
852 | + rhs1 = rhs; |
853 | + |
854 | type1 = TREE_TYPE (rhs1); |
855 | + |
856 | if (TREE_CODE (type1) != TREE_CODE (type) |
857 | - || TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) |
858 | + || TYPE_PRECISION (type1) * 2 > TYPE_PRECISION (type)) |
859 | return false; |
860 | |
861 | *new_rhs_out = rhs1; |
862 | @@ -1316,28 +1344,27 @@ |
863 | return false; |
864 | } |
865 | |
866 | -/* Return true if STMT performs a widening multiplication. If so, |
867 | - store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT |
868 | - respectively. Also fill *RHS1_OUT and *RHS2_OUT such that converting |
869 | - those operands to types *TYPE1_OUT and *TYPE2_OUT would give the |
870 | - operands of the multiplication. */ |
871 | +/* Return true if STMT performs a widening multiplication, assuming the |
872 | + output type is TYPE. If so, store the unwidened types of the operands |
873 | + in *TYPE1_OUT and *TYPE2_OUT respectively. Also fill *RHS1_OUT and |
874 | + *RHS2_OUT such that converting those operands to types *TYPE1_OUT |
875 | + and *TYPE2_OUT would give the operands of the multiplication. */ |
876 | |
877 | static bool |
878 | -is_widening_mult_p (gimple stmt, |
879 | +is_widening_mult_p (tree type, gimple stmt, |
880 | tree *type1_out, tree *rhs1_out, |
881 | tree *type2_out, tree *rhs2_out) |
882 | { |
883 | - tree type; |
884 | - |
885 | - type = TREE_TYPE (gimple_assign_lhs (stmt)); |
886 | if (TREE_CODE (type) != INTEGER_TYPE |
887 | && TREE_CODE (type) != FIXED_POINT_TYPE) |
888 | return false; |
889 | |
890 | - if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out)) |
891 | + if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out, |
892 | + rhs1_out)) |
893 | return false; |
894 | |
895 | - if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out)) |
896 | + if (!is_widening_mult_rhs_p (type, gimple_assign_rhs2 (stmt), type2_out, |
897 | + rhs2_out)) |
898 | return false; |
899 | |
900 | if (*type1_out == NULL) |
901 | @@ -1354,6 +1381,18 @@ |
902 | *type2_out = *type1_out; |
903 | } |
904 | |
905 | + /* Ensure that the larger of the two operands comes first. */ |
906 | + if (TYPE_PRECISION (*type1_out) < TYPE_PRECISION (*type2_out)) |
907 | + { |
908 | + tree tmp; |
909 | + tmp = *type1_out; |
910 | + *type1_out = *type2_out; |
911 | + *type2_out = tmp; |
912 | + tmp = *rhs1_out; |
913 | + *rhs1_out = *rhs2_out; |
914 | + *rhs2_out = tmp; |
915 | + } |
916 | + |
917 | return true; |
918 | } |
919 | |
920 | @@ -1362,31 +1401,100 @@ |
921 | value is true iff we converted the statement. */ |
922 | |
923 | static bool |
924 | -convert_mult_to_widen (gimple stmt) |
925 | +convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) |
926 | { |
927 | - tree lhs, rhs1, rhs2, type, type1, type2; |
928 | + tree lhs, rhs1, rhs2, type, type1, type2, tmp = NULL; |
929 | enum insn_code handler; |
930 | + enum machine_mode to_mode, from_mode, actual_mode; |
931 | + optab op; |
932 | + int actual_precision; |
933 | + location_t loc = gimple_location (stmt); |
934 | + bool from_unsigned1, from_unsigned2; |
935 | |
936 | lhs = gimple_assign_lhs (stmt); |
937 | type = TREE_TYPE (lhs); |
938 | if (TREE_CODE (type) != INTEGER_TYPE) |
939 | return false; |
940 | |
941 | - if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2)) |
942 | + if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2)) |
943 | return false; |
944 | |
945 | - if (TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2)) |
946 | - handler = optab_handler (umul_widen_optab, TYPE_MODE (type)); |
947 | - else if (!TYPE_UNSIGNED (type1) && !TYPE_UNSIGNED (type2)) |
948 | - handler = optab_handler (smul_widen_optab, TYPE_MODE (type)); |
949 | + to_mode = TYPE_MODE (type); |
950 | + from_mode = TYPE_MODE (type1); |
951 | + from_unsigned1 = TYPE_UNSIGNED (type1); |
952 | + from_unsigned2 = TYPE_UNSIGNED (type2); |
953 | + |
954 | + if (from_unsigned1 && from_unsigned2) |
955 | + op = umul_widen_optab; |
956 | + else if (!from_unsigned1 && !from_unsigned2) |
957 | + op = smul_widen_optab; |
958 | else |
959 | - handler = optab_handler (usmul_widen_optab, TYPE_MODE (type)); |
960 | + op = usmul_widen_optab; |
961 | + |
962 | + handler = find_widening_optab_handler_and_mode (op, to_mode, from_mode, |
963 | + 0, &actual_mode); |
964 | |
965 | if (handler == CODE_FOR_nothing) |
966 | - return false; |
967 | - |
968 | - gimple_assign_set_rhs1 (stmt, fold_convert (type1, rhs1)); |
969 | - gimple_assign_set_rhs2 (stmt, fold_convert (type2, rhs2)); |
970 | + { |
971 | + if (op != smul_widen_optab) |
972 | + { |
973 | + /* We can use a signed multiply with unsigned types as long as |
974 | + there is a wider mode to use, or it is the smaller of the two |
975 | + types that is unsigned. Note that type1 >= type2, always. */ |
976 | + if ((TYPE_UNSIGNED (type1) |
977 | + && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode)) |
978 | + || (TYPE_UNSIGNED (type2) |
979 | + && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) |
980 | + { |
981 | + from_mode = GET_MODE_WIDER_MODE (from_mode); |
982 | + if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode)) |
983 | + return false; |
984 | + } |
985 | + |
986 | + op = smul_widen_optab; |
987 | + handler = find_widening_optab_handler_and_mode (op, to_mode, |
988 | + from_mode, 0, |
989 | + &actual_mode); |
990 | + |
991 | + if (handler == CODE_FOR_nothing) |
992 | + return false; |
993 | + |
994 | + from_unsigned1 = from_unsigned2 = false; |
995 | + } |
996 | + else |
997 | + return false; |
998 | + } |
999 | + |
1000 | + /* Ensure that the inputs to the handler are in the correct precison |
1001 | + for the opcode. This will be the full mode size. */ |
1002 | + actual_precision = GET_MODE_PRECISION (actual_mode); |
1003 | + if (actual_precision != TYPE_PRECISION (type1) |
1004 | + || from_unsigned1 != TYPE_UNSIGNED (type1)) |
1005 | + { |
1006 | + tmp = create_tmp_var (build_nonstandard_integer_type |
1007 | + (actual_precision, from_unsigned1), |
1008 | + NULL); |
1009 | + rhs1 = build_and_insert_cast (gsi, loc, tmp, rhs1); |
1010 | + } |
1011 | + if (actual_precision != TYPE_PRECISION (type2) |
1012 | + || from_unsigned2 != TYPE_UNSIGNED (type2)) |
1013 | + { |
1014 | + /* Reuse the same type info, if possible. */ |
1015 | + if (!tmp || from_unsigned1 != from_unsigned2) |
1016 | + tmp = create_tmp_var (build_nonstandard_integer_type |
1017 | + (actual_precision, from_unsigned2), |
1018 | + NULL); |
1019 | + rhs2 = build_and_insert_cast (gsi, loc, tmp, rhs2); |
1020 | + } |
1021 | + |
1022 | + /* Handle constants. */ |
1023 | + if (TREE_CODE (rhs1) == INTEGER_CST) |
1024 | + rhs1 = fold_convert (type1, rhs1); |
1025 | + if (TREE_CODE (rhs2) == INTEGER_CST) |
1026 | + rhs2 = fold_convert (type2, rhs2); |
1027 | + |
1028 | + gimple_assign_set_rhs1 (stmt, rhs1); |
1029 | + gimple_assign_set_rhs2 (stmt, rhs2); |
1030 | gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); |
1031 | update_stmt (stmt); |
1032 | return true; |
1033 | @@ -1403,11 +1511,17 @@ |
1034 | enum tree_code code) |
1035 | { |
1036 | gimple rhs1_stmt = NULL, rhs2_stmt = NULL; |
1037 | - tree type, type1, type2; |
1038 | + gimple conv1_stmt = NULL, conv2_stmt = NULL, conv_stmt; |
1039 | + tree type, type1, type2, optype, tmp = NULL; |
1040 | tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs; |
1041 | enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK; |
1042 | optab this_optab; |
1043 | enum tree_code wmult_code; |
1044 | + enum insn_code handler; |
1045 | + enum machine_mode to_mode, from_mode, actual_mode; |
1046 | + location_t loc = gimple_location (stmt); |
1047 | + int actual_precision; |
1048 | + bool from_unsigned1, from_unsigned2; |
1049 | |
1050 | lhs = gimple_assign_lhs (stmt); |
1051 | type = TREE_TYPE (lhs); |
1052 | @@ -1429,8 +1543,6 @@ |
1053 | if (is_gimple_assign (rhs1_stmt)) |
1054 | rhs1_code = gimple_assign_rhs_code (rhs1_stmt); |
1055 | } |
1056 | - else |
1057 | - return false; |
1058 | |
1059 | if (TREE_CODE (rhs2) == SSA_NAME) |
1060 | { |
1061 | @@ -1438,57 +1550,160 @@ |
1062 | if (is_gimple_assign (rhs2_stmt)) |
1063 | rhs2_code = gimple_assign_rhs_code (rhs2_stmt); |
1064 | } |
1065 | - else |
1066 | - return false; |
1067 | - |
1068 | - if (code == PLUS_EXPR && rhs1_code == MULT_EXPR) |
1069 | - { |
1070 | - if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, |
1071 | - &type2, &mult_rhs2)) |
1072 | - return false; |
1073 | - add_rhs = rhs2; |
1074 | - } |
1075 | - else if (rhs2_code == MULT_EXPR) |
1076 | - { |
1077 | - if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1, |
1078 | - &type2, &mult_rhs2)) |
1079 | - return false; |
1080 | - add_rhs = rhs1; |
1081 | - } |
1082 | - else if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR) |
1083 | - { |
1084 | - mult_rhs1 = gimple_assign_rhs1 (rhs1_stmt); |
1085 | - mult_rhs2 = gimple_assign_rhs2 (rhs1_stmt); |
1086 | - type1 = TREE_TYPE (mult_rhs1); |
1087 | - type2 = TREE_TYPE (mult_rhs2); |
1088 | - add_rhs = rhs2; |
1089 | - } |
1090 | - else if (rhs2_code == WIDEN_MULT_EXPR) |
1091 | - { |
1092 | - mult_rhs1 = gimple_assign_rhs1 (rhs2_stmt); |
1093 | - mult_rhs2 = gimple_assign_rhs2 (rhs2_stmt); |
1094 | - type1 = TREE_TYPE (mult_rhs1); |
1095 | - type2 = TREE_TYPE (mult_rhs2); |
1096 | - add_rhs = rhs1; |
1097 | - } |
1098 | - else |
1099 | - return false; |
1100 | - |
1101 | - if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) |
1102 | - return false; |
1103 | + |
1104 | + /* Allow for one conversion statement between the multiply |
1105 | + and addition/subtraction statement. If there are more than |
1106 | + one conversions then we assume they would invalidate this |
1107 | + transformation. If that's not the case then they should have |
1108 | + been folded before now. */ |
1109 | + if (CONVERT_EXPR_CODE_P (rhs1_code)) |
1110 | + { |
1111 | + conv1_stmt = rhs1_stmt; |
1112 | + rhs1 = gimple_assign_rhs1 (rhs1_stmt); |
1113 | + if (TREE_CODE (rhs1) == SSA_NAME) |
1114 | + { |
1115 | + rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); |
1116 | + if (is_gimple_assign (rhs1_stmt)) |
1117 | + rhs1_code = gimple_assign_rhs_code (rhs1_stmt); |
1118 | + } |
1119 | + else |
1120 | + return false; |
1121 | + } |
1122 | + if (CONVERT_EXPR_CODE_P (rhs2_code)) |
1123 | + { |
1124 | + conv2_stmt = rhs2_stmt; |
1125 | + rhs2 = gimple_assign_rhs1 (rhs2_stmt); |
1126 | + if (TREE_CODE (rhs2) == SSA_NAME) |
1127 | + { |
1128 | + rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); |
1129 | + if (is_gimple_assign (rhs2_stmt)) |
1130 | + rhs2_code = gimple_assign_rhs_code (rhs2_stmt); |
1131 | + } |
1132 | + else |
1133 | + return false; |
1134 | + } |
1135 | + |
1136 | + /* If code is WIDEN_MULT_EXPR then it would seem unnecessary to call |
1137 | + is_widening_mult_p, but we still need the rhs returns. |
1138 | + |
1139 | + It might also appear that it would be sufficient to use the existing |
1140 | + operands of the widening multiply, but that would limit the choice of |
1141 | + multiply-and-accumulate instructions. */ |
1142 | + if (code == PLUS_EXPR |
1143 | + && (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR)) |
1144 | + { |
1145 | + if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1, |
1146 | + &type2, &mult_rhs2)) |
1147 | + return false; |
1148 | + add_rhs = rhs2; |
1149 | + conv_stmt = conv1_stmt; |
1150 | + } |
1151 | + else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR) |
1152 | + { |
1153 | + if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1, |
1154 | + &type2, &mult_rhs2)) |
1155 | + return false; |
1156 | + add_rhs = rhs1; |
1157 | + conv_stmt = conv2_stmt; |
1158 | + } |
1159 | + else |
1160 | + return false; |
1161 | + |
1162 | + to_mode = TYPE_MODE (type); |
1163 | + from_mode = TYPE_MODE (type1); |
1164 | + from_unsigned1 = TYPE_UNSIGNED (type1); |
1165 | + from_unsigned2 = TYPE_UNSIGNED (type2); |
1166 | + |
1167 | + /* There's no such thing as a mixed sign madd yet, so use a wider mode. */ |
1168 | + if (from_unsigned1 != from_unsigned2) |
1169 | + { |
1170 | + /* We can use a signed multiply with unsigned types as long as |
1171 | + there is a wider mode to use, or it is the smaller of the two |
1172 | + types that is unsigned. Note that type1 >= type2, always. */ |
1173 | + if ((from_unsigned1 |
1174 | + && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode)) |
1175 | + || (from_unsigned2 |
1176 | + && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) |
1177 | + { |
1178 | + from_mode = GET_MODE_WIDER_MODE (from_mode); |
1179 | + if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode)) |
1180 | + return false; |
1181 | + } |
1182 | + |
1183 | + from_unsigned1 = from_unsigned2 = false; |
1184 | + } |
1185 | + |
1186 | + /* If there was a conversion between the multiply and addition |
1187 | + then we need to make sure it fits a multiply-and-accumulate. |
1188 | + The should be a single mode change which does not change the |
1189 | + value. */ |
1190 | + if (conv_stmt) |
1191 | + { |
1192 | + /* We use the original, unmodified data types for this. */ |
1193 | + tree from_type = TREE_TYPE (gimple_assign_rhs1 (conv_stmt)); |
1194 | + tree to_type = TREE_TYPE (gimple_assign_lhs (conv_stmt)); |
1195 | + int data_size = TYPE_PRECISION (type1) + TYPE_PRECISION (type2); |
1196 | + bool is_unsigned = TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2); |
1197 | + |
1198 | + if (TYPE_PRECISION (from_type) > TYPE_PRECISION (to_type)) |
1199 | + { |
1200 | + /* Conversion is a truncate. */ |
1201 | + if (TYPE_PRECISION (to_type) < data_size) |
1202 | + return false; |
1203 | + } |
1204 | + else if (TYPE_PRECISION (from_type) < TYPE_PRECISION (to_type)) |
1205 | + { |
1206 | + /* Conversion is an extend. Check it's the right sort. */ |
1207 | + if (TYPE_UNSIGNED (from_type) != is_unsigned |
1208 | + && !(is_unsigned && TYPE_PRECISION (from_type) > data_size)) |
1209 | + return false; |
1210 | + } |
1211 | + /* else convert is a no-op for our purposes. */ |
1212 | + } |
1213 | |
1214 | /* Verify that the machine can perform a widening multiply |
1215 | accumulate in this mode/signedness combination, otherwise |
1216 | this transformation is likely to pessimize code. */ |
1217 | - this_optab = optab_for_tree_code (wmult_code, type1, optab_default); |
1218 | - if (optab_handler (this_optab, TYPE_MODE (type)) == CODE_FOR_nothing) |
1219 | + optype = build_nonstandard_integer_type (from_mode, from_unsigned1); |
1220 | + this_optab = optab_for_tree_code (wmult_code, optype, optab_default); |
1221 | + handler = find_widening_optab_handler_and_mode (this_optab, to_mode, |
1222 | + from_mode, 0, &actual_mode); |
1223 | + |
1224 | + if (handler == CODE_FOR_nothing) |
1225 | return false; |
1226 | |
1227 | - /* ??? May need some type verification here? */ |
1228 | - |
1229 | - gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, |
1230 | - fold_convert (type1, mult_rhs1), |
1231 | - fold_convert (type2, mult_rhs2), |
1232 | + /* Ensure that the inputs to the handler are in the correct precison |
1233 | + for the opcode. This will be the full mode size. */ |
1234 | + actual_precision = GET_MODE_PRECISION (actual_mode); |
1235 | + if (actual_precision != TYPE_PRECISION (type1) |
1236 | + || from_unsigned1 != TYPE_UNSIGNED (type1)) |
1237 | + { |
1238 | + tmp = create_tmp_var (build_nonstandard_integer_type |
1239 | + (actual_precision, from_unsigned1), |
1240 | + NULL); |
1241 | + mult_rhs1 = build_and_insert_cast (gsi, loc, tmp, mult_rhs1); |
1242 | + } |
1243 | + if (actual_precision != TYPE_PRECISION (type2) |
1244 | + || from_unsigned2 != TYPE_UNSIGNED (type2)) |
1245 | + { |
1246 | + if (!tmp || from_unsigned1 != from_unsigned2) |
1247 | + tmp = create_tmp_var (build_nonstandard_integer_type |
1248 | + (actual_precision, from_unsigned2), |
1249 | + NULL); |
1250 | + mult_rhs2 = build_and_insert_cast (gsi, loc, tmp, mult_rhs2); |
1251 | + } |
1252 | + |
1253 | + if (!useless_type_conversion_p (type, TREE_TYPE (add_rhs))) |
1254 | + add_rhs = build_and_insert_cast (gsi, loc, create_tmp_var (type, NULL), |
1255 | + add_rhs); |
1256 | + |
1257 | + /* Handle constants. */ |
1258 | + if (TREE_CODE (mult_rhs1) == INTEGER_CST) |
1259 | + rhs1 = fold_convert (type1, mult_rhs1); |
1260 | + if (TREE_CODE (mult_rhs2) == INTEGER_CST) |
1261 | + rhs2 = fold_convert (type2, mult_rhs2); |
1262 | + |
1263 | + gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs1, mult_rhs2, |
1264 | add_rhs); |
1265 | update_stmt (gsi_stmt (*gsi)); |
1266 | return true; |
1267 | @@ -1696,7 +1911,7 @@ |
1268 | switch (code) |
1269 | { |
1270 | case MULT_EXPR: |
1271 | - if (!convert_mult_to_widen (stmt) |
1272 | + if (!convert_mult_to_widen (stmt, &gsi) |
1273 | && convert_mult_to_fma (stmt, |
1274 | gimple_assign_rhs1 (stmt), |
1275 | gimple_assign_rhs2 (stmt))) |
cbuild has taken a snapshot of this branch at r106781 and queued it for build.
The snapshot is available at: ex.seabright. co.nz/snapshots /gcc-linaro- 4.6+bzr106781~ ams-codesourcer y~widening- multiplies- 4.6.tar. xdelta3. xz
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at: ex.seabright. co.nz/helpers/ scheduler
http://
cbuild-snapshot: gcc-linaro- 4.6+bzr106781~ ams-codesourcer y~widening- multiplies- 4.6
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check