Merge lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6 into lp:gcc-linaro/4.6

Proposed by Andrew Stubbs
Status: Superseded
Proposed branch: lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6
Merge into: lp:gcc-linaro/4.6
Diff against target: 1274 lines (+739/-141) (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 (+71/-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 (+310/-90)
Text conflict in ChangeLog.linaro
To merge this branch: bzr merge lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6
Reviewer Review Type Date Requested Status
Michael Hope Needs Fixing
Review via email: mp+69475@code.launchpad.net

This proposal supersedes a proposal from 2011-07-22.

This proposal has been superseded by a proposal from 2011-08-05.

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>/msg08720.html

UPDATE: Now with an extra bug-fix.

To post a comment you must log in.
Revision history for this message
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal

cbuild has taken a snapshot of this branch at r106781 and queued it for build.

The snapshot is available at:
 http://ex.seabright.co.nz/snapshots/gcc-linaro-4.6+bzr106781~ams-codesourcery~widening-multiplies-4.6.tar.xdelta3.xz

and will be built on the following builders:
 a9-builder armv5-builder i686 x86_64

You can track the build queue at:
 http://ex.seabright.co.nz/helpers/scheduler

cbuild-snapshot: gcc-linaro-4.6+bzr106781~ams-codesourcery~widening-multiplies-4.6
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check

Revision history for this message
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://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106781~ams-codesourcery~widening-multiplies-4.6/logs/armv7l-natty-cbuild158-ursa3-armv5r2

The test suite results were not checked.

cbuild-checked: armv7l-natty-cbuild158-ursa3-armv5r2

review: Needs Fixing
Revision history for this message
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://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106781~ams-codesourcery~widening-multiplies-4.6/logs/armv7l-natty-cbuild158-ursa4-cortexa9r1

The test suite results were not checked.

cbuild-checked: armv7l-natty-cbuild158-ursa4-cortexa9r1

review: Needs Fixing
Revision history for this message
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://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106781~ams-codesourcery~widening-multiplies-4.6/logs/i686-natty-cbuild158-oort2-i686r1

The test suite results were not checked.

cbuild-checked: i686-natty-cbuild158-oort2-i686r1

review: Needs Fixing
Revision history for this message
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://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106781~ams-codesourcery~widening-multiplies-4.6/logs/x86_64-natty-cbuild158-oort1-x86_64r1

The test suite results were not checked.

cbuild-checked: x86_64-natty-cbuild158-oort1-x86_64r1

review: Needs Fixing
Revision history for this message
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://ex.seabright.co.nz/snapshots/gcc-linaro-4.6+bzr106782~ams-codesourcery~widening-multiplies-4.6.tar.xdelta3.xz

and will be built on the following builders:
 a9-builder armv5-builder i686 x86_64

You can track the build queue at:
 http://ex.seabright.co.nz/helpers/scheduler

cbuild-snapshot: gcc-linaro-4.6+bzr106782~ams-codesourcery~widening-multiplies-4.6
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check

Revision history for this message
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://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106782~ams-codesourcery~widening-multiplies-4.6/logs/i686-natty-cbuild158-oort6-i686r1

The test suite results were not checked.

cbuild-checked: i686-natty-cbuild158-oort6-i686r1

review: Needs Fixing
Revision history for this message
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://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106782~ams-codesourcery~widening-multiplies-4.6/logs/x86_64-natty-cbuild158-oort3-x86_64r1

The test suite results were not checked.

cbuild-checked: x86_64-natty-cbuild158-oort3-x86_64r1

review: Needs Fixing
Revision history for this message
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal

cbuild had trouble building this on armv7l-natty-cbuild158-ursa3-cortexa9r1.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106782~ams-codesourcery~widening-multiplies-4.6/logs/armv7l-natty-cbuild158-ursa3-cortexa9r1

The test suite results were not checked.

cbuild-checked: armv7l-natty-cbuild158-ursa3-cortexa9r1

review: Needs Fixing
Revision history for this message
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal

cbuild had trouble building this on armv7l-natty-cbuild158-ursa1-armv5r2.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106782~ams-codesourcery~widening-multiplies-4.6/logs/armv7l-natty-cbuild158-ursa1-armv5r2

The test suite results were not checked.

cbuild-checked: armv7l-natty-cbuild158-ursa1-armv5r2

review: Needs Fixing
Revision history for this message
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://ex.seabright.co.nz/snapshots/gcc-linaro-4.6+bzr106783~ams-codesourcery~widening-multiplies-4.6.tar.xdelta3.xz

and will be built on the following builders:
 a9-builder armv5-builder i686 x86_64

You can track the build queue at:
 http://ex.seabright.co.nz/helpers/scheduler

cbuild-snapshot: gcc-linaro-4.6+bzr106783~ams-codesourcery~widening-multiplies-4.6
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check

Revision history for this message
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal

cbuild had trouble building this on x86_64-natty-cbuild159-oort1-x86_64r1.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106783~ams-codesourcery~widening-multiplies-4.6/logs/x86_64-natty-cbuild159-oort1-x86_64r1

The test suite results were not checked.

cbuild-checked: x86_64-natty-cbuild159-oort1-x86_64r1

review: Needs Fixing
Revision history for this message
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal

cbuild had trouble building this on i686-natty-cbuild159-oort6-i686r1.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106783~ams-codesourcery~widening-multiplies-4.6/logs/i686-natty-cbuild159-oort6-i686r1

The test suite results were not checked.

cbuild-checked: i686-natty-cbuild159-oort6-i686r1

review: Needs Fixing
Revision history for this message
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal

cbuild had trouble building this on armv7l-natty-cbuild159-ursa2-cortexa9r1.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106783~ams-codesourcery~widening-multiplies-4.6/logs/armv7l-natty-cbuild159-ursa2-cortexa9r1

The test suite results were not checked.

cbuild-checked: armv7l-natty-cbuild159-ursa2-cortexa9r1

review: Needs Fixing
Revision history for this message
Linaro Toolchain Builder (cbuild) wrote :

cbuild has taken a snapshot of this branch at r106784 and queued it for build.

The snapshot is available at:
 http://ex.seabright.co.nz/snapshots/gcc-linaro-4.6+bzr106784~ams-codesourcery~widening-multiplies-4.6.tar.xdelta3.xz

and will be built on the following builders:
 a9-builder armv5-builder i686 x86_64

You can track the build queue at:
 http://ex.seabright.co.nz/helpers/scheduler

cbuild-snapshot: gcc-linaro-4.6+bzr106784~ams-codesourcery~widening-multiplies-4.6
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check

Revision history for this message
Michael Hope (michaelh1) wrote :
Download full text (4.0 KiB)

cbuild successfully built this on armv7l-natty-cbuild159-ursa2-cortexa9r1.

The build results are available at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106784~ams-codesourcery~widening-multiplies-4.6/logs/armv7l-natty-cbuild159-ursa2-cortexa9r1

-PASS: gcc.c-torture/execute/961213-1.c compilation, -O3 -fomit-frame-pointer
-PASS: gcc.c-torture/execute/961213-1.c compilation, -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions
-PASS: gcc.c-torture/execute/961213-1.c compilation, -O3 -fomit-frame-pointer -funroll-loops
-PASS: gcc.c-torture/execute/961213-1.c compilation, -O3 -g
+FAIL: gcc.c-torture/execute/961213-1.c compilation, -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions (internal compiler error)
+FAIL: gcc.c-torture/execute/961213-1.c compilation, -O3 -fomit-frame-pointer -funroll-loops (internal compiler error)
+FAIL: gcc.c-torture/execute/961213-1.c compilation, -O3 -fomit-frame-pointer (internal compiler error)
+FAIL: gcc.c-torture/execute/961213-1.c compilation, -O3 -g (internal compiler error)
-PASS: gcc.c-torture/execute/961213-1.c execution, -O3 -fomit-frame-pointer
-PASS: gcc.c-torture/execute/961213-1.c execution, -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions
-PASS: gcc.c-torture/execute/961213-1.c execution, -O3 -fomit-frame-pointer -funroll-loops
-PASS: gcc.c-torture/execute/961213-1.c execution, -O3 -g
+UNRESOLVED: gcc.c-torture/execute/961213-1.c execution, -O3 -fomit-frame-pointer
+UNRESOLVED: gcc.c-torture/execute/961213-1.c execution, -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions
+UNRESOLVED: gcc.c-torture/execute/961213-1.c execution, -O3 -fomit-frame-pointer -funroll-loops
+UNRESOLVED: gcc.c-torture/execute/961213-1.c execution, -O3 -g
-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/arm/no-wmla-1.c scan-assembler mul
+PASS: gcc.target/arm/no-wmla-1.c (test for excess errors)
+PASS: gcc.target/arm/wmul-10.c scan-assembler umlal
+PASS: gcc.target/arm/wmul-10.c (test for excess errors)
+PASS: gcc.target/arm/wmul-11.c scan-assembler smull
+PASS: gcc.target/arm/wmul-11.c (test for excess errors)
+PASS: gcc.target/arm/wmul-12.c scan-assembler smlal
+PASS: gcc.target/arm/wmul-12.c (test for excess errors)
+PASS: gcc.target/arm/wmul-13.c scan-assembler smlal
+PASS: gcc.target/arm/wmul-13.c (test for excess errors)
+PASS: gcc.target/arm/wmul-5.c scan-assembler umlal
+PASS: gcc.target/arm/wmul-5.c (test for excess errors)
+PASS: gcc.target/arm/wmul-6.c scan-assembler smlal
+PASS: gcc.target/arm/wmul-6.c (test for excess errors)
+PASS: gcc.target/arm/wmul-7.c scan-assembler umlal
+PASS: gcc.target/arm/wmul-7.c (test for excess errors)
+PASS: gcc.target/arm/wmul-8.c scan-assembler smlal
+PASS: gcc.target/arm/wmul-8.c (test for excess errors)
+PASS: gcc.target/arm/wmul-9.c scan-assembler smlalbb
+PASS: gcc.target/arm/wmul-9.c (test for excess errors)
+PASS: gcc.target/arm/wmul-bitfield-1.c scan-assembler smlalbb
+PAS...

Read more...

Revision history for this message
Michael Hope (michaelh1) wrote :

cbuild had trouble building this on i686-natty-cbuild159-oort8-i686r1.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106784~ams-codesourcery~widening-multiplies-4.6/logs/i686-natty-cbuild159-oort8-i686r1

The test suite results were not checked.

cbuild-checked: i686-natty-cbuild159-oort8-i686r1

review: Needs Fixing
Revision history for this message
Michael Hope (michaelh1) wrote :

cbuild had trouble building this on x86_64-natty-cbuild159-oort3-x86_64r1.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106784~ams-codesourcery~widening-multiplies-4.6/logs/x86_64-natty-cbuild159-oort3-x86_64r1

The test suite results were not checked.

cbuild-checked: x86_64-natty-cbuild159-oort3-x86_64r1

review: Needs Fixing
Revision history for this message
Michael Hope (michaelh1) wrote :

cbuild had trouble building this on x86_64-natty-cbuild159-oort3-x86_64r1.

See the *failed.txt logs under the build results at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106784~ams-codesourcery~widening-multiplies-4.6/logs/x86_64-natty-cbuild159-oort3-x86_64r1

The test suite results were not checked.

cbuild-checked: x86_64-natty-cbuild159-oort3-x86_64r1

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog.linaro'
2--- ChangeLog.linaro 2011-07-21 11:30:53 +0000
3+++ ChangeLog.linaro 2011-08-05 14:18:27 +0000
4@@ -1,3 +1,4 @@
5+<<<<<<< TREE
6 2011-07-21 Richard Sandiford <rdsandiford@googlemail.com>
7
8 gcc/
9@@ -137,6 +138,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-05 14:18:27 +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-05 14:18:27 +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-05 14:18:27 +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-05 14:18:27 +0000
307@@ -225,6 +225,54 @@
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+ if (m0 == VOIDmode && m1 == VOIDmode)
322+ return to_mode;
323+ else if (GET_MODE_SIZE (m0) < GET_MODE_SIZE (m1))
324+ return m1;
325+ else
326+ return m0;
327+}
328+
329
330+/* Find a widening optab even if it doesn't widen as much as we want.
331+ E.g. if from_mode is HImode, and to_mode is DImode, and there is no
332+ direct HI->SI insn, then return SI->DI, if that exists.
333+ If PERMIT_NON_WIDENING is non-zero then this can be used with
334+ non-widening optabs also. */
335+
336+enum insn_code
337+find_widening_optab_handler_and_mode (optab op, enum machine_mode to_mode,
338+ enum machine_mode from_mode,
339+ int permit_non_widening,
340+ enum machine_mode *found_mode)
341+{
342+ for (; (permit_non_widening || from_mode != to_mode)
343+ && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
344+ && from_mode != VOIDmode;
345+ from_mode = GET_MODE_WIDER_MODE (from_mode))
346+ {
347+ enum insn_code handler = widening_optab_handler (op, to_mode,
348+ from_mode);
349+
350+ if (handler != CODE_FOR_nothing)
351+ {
352+ if (found_mode)
353+ *found_mode = from_mode;
354+ return handler;
355+ }
356+ }
357+
358+ return CODE_FOR_nothing;
359+}
360+
361
362 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
363 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
364 not actually do a sign-extend or zero-extend, but can leave the
365@@ -517,8 +565,9 @@
366 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
367 if (ops->code == WIDEN_MULT_PLUS_EXPR
368 || ops->code == WIDEN_MULT_MINUS_EXPR)
369- icode = (int) optab_handler (widen_pattern_optab,
370- TYPE_MODE (TREE_TYPE (ops->op2)));
371+ icode = (int) find_widening_optab_handler (widen_pattern_optab,
372+ TYPE_MODE (TREE_TYPE (ops->op2)),
373+ tmode0, 0);
374 else
375 icode = (int) optab_handler (widen_pattern_optab, tmode0);
376 gcc_assert (icode != CODE_FOR_nothing);
377@@ -1389,7 +1438,9 @@
378 rtx target, int unsignedp, enum optab_methods methods,
379 rtx last)
380 {
381- int icode = (int) optab_handler (binoptab, mode);
382+ enum machine_mode from_mode = widened_mode (mode, op0, op1);
383+ int icode = (int) find_widening_optab_handler (binoptab, mode,
384+ from_mode, 1);
385 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
386 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
387 enum machine_mode tmp_mode;
388@@ -1546,7 +1597,9 @@
389 /* If we can do it with a three-operand insn, do so. */
390
391 if (methods != OPTAB_MUST_WIDEN
392- && optab_handler (binoptab, mode) != CODE_FOR_nothing)
393+ && find_widening_optab_handler (binoptab, mode,
394+ widened_mode (mode, op0, op1), 1)
395+ != CODE_FOR_nothing)
396 {
397 temp = expand_binop_directly (mode, binoptab, op0, op1, target,
398 unsignedp, methods, last);
399@@ -1586,8 +1639,9 @@
400
401 if (binoptab == smul_optab
402 && GET_MODE_WIDER_MODE (mode) != VOIDmode
403- && (optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab),
404- GET_MODE_WIDER_MODE (mode))
405+ && (widening_optab_handler ((unsignedp ? umul_widen_optab
406+ : smul_widen_optab),
407+ GET_MODE_WIDER_MODE (mode), mode)
408 != CODE_FOR_nothing))
409 {
410 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
411@@ -1618,9 +1672,11 @@
412 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
413 || (binoptab == smul_optab
414 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
415- && (optab_handler ((unsignedp ? umul_widen_optab
416- : smul_widen_optab),
417- GET_MODE_WIDER_MODE (wider_mode))
418+ && (find_widening_optab_handler ((unsignedp
419+ ? umul_widen_optab
420+ : smul_widen_optab),
421+ GET_MODE_WIDER_MODE (wider_mode),
422+ mode, 0)
423 != CODE_FOR_nothing)))
424 {
425 rtx xop0 = op0, xop1 = op1;
426@@ -2043,8 +2099,8 @@
427 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)
428 {
429 rtx product = NULL_RTX;
430-
431- if (optab_handler (umul_widen_optab, mode) != CODE_FOR_nothing)
432+ if (widening_optab_handler (umul_widen_optab, mode, word_mode)
433+ != CODE_FOR_nothing)
434 {
435 product = expand_doubleword_mult (mode, op0, op1, target,
436 true, methods);
437@@ -2053,7 +2109,8 @@
438 }
439
440 if (product == NULL_RTX
441- && optab_handler (smul_widen_optab, mode) != CODE_FOR_nothing)
442+ && widening_optab_handler (smul_widen_optab, mode, word_mode)
443+ != CODE_FOR_nothing)
444 {
445 product = expand_doubleword_mult (mode, op0, op1, target,
446 false, methods);
447@@ -2144,7 +2201,8 @@
448 wider_mode != VOIDmode;
449 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
450 {
451- if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
452+ if (find_widening_optab_handler (binoptab, wider_mode, mode, 1)
453+ != CODE_FOR_nothing
454 || (methods == OPTAB_LIB
455 && optab_libfunc (binoptab, wider_mode)))
456 {
457
458=== modified file 'gcc/optabs.h'
459--- gcc/optabs.h 2011-05-05 15:43:06 +0000
460+++ gcc/optabs.h 2011-08-05 14:18:27 +0000
461@@ -42,6 +42,11 @@
462 int insn_code;
463 };
464
465+struct widening_optab_handlers
466+{
467+ struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
468+};
469+
470 struct optab_d
471 {
472 enum rtx_code code;
473@@ -50,6 +55,7 @@
474 void (*libcall_gen)(struct optab_d *, const char *name, char suffix,
475 enum machine_mode);
476 struct optab_handlers handlers[NUM_MACHINE_MODES];
477+ struct widening_optab_handlers *widening;
478 };
479 typedef struct optab_d * optab;
480
481@@ -799,6 +805,15 @@
482 extern void emit_unop_insn (int, rtx, rtx, enum rtx_code);
483 extern bool maybe_emit_unop_insn (int, rtx, rtx, enum rtx_code);
484
485+/* Find a widening optab even if it doesn't widen as much as we want. */
486+#define find_widening_optab_handler(A,B,C,D) \
487+ find_widening_optab_handler_and_mode (A, B, C, D, NULL)
488+extern enum insn_code find_widening_optab_handler_and_mode (optab,
489+ enum machine_mode,
490+ enum machine_mode,
491+ int,
492+ enum machine_mode *);
493+
494 /* An extra flag to control optab_for_tree_code's behavior. This is needed to
495 distinguish between machines with a vector shift that takes a scalar for the
496 shift amount vs. machines that take a vector for the shift amount. */
497@@ -874,6 +889,23 @@
498 + (int) CODE_FOR_nothing);
499 }
500
501+/* Like optab_handler, but for widening_operations that have a TO_MODE and
502+ a FROM_MODE. */
503+
504+static inline enum insn_code
505+widening_optab_handler (optab op, enum machine_mode to_mode,
506+ enum machine_mode from_mode)
507+{
508+ if (to_mode == from_mode || from_mode == VOIDmode)
509+ return optab_handler (op, to_mode);
510+
511+ if (op->widening)
512+ return (enum insn_code) (op->widening->handlers[(int) to_mode][(int) from_mode].insn_code
513+ + (int) CODE_FOR_nothing);
514+
515+ return CODE_FOR_nothing;
516+}
517+
518 /* Record that insn CODE should be used to implement mode MODE of OP. */
519
520 static inline void
521@@ -882,6 +914,26 @@
522 op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing;
523 }
524
525+/* Like set_optab_handler, but for widening operations that have a TO_MODE
526+ and a FROM_MODE. */
527+
528+static inline void
529+set_widening_optab_handler (optab op, enum machine_mode to_mode,
530+ enum machine_mode from_mode, enum insn_code code)
531+{
532+ if (to_mode == from_mode)
533+ set_optab_handler (op, to_mode, code);
534+ else
535+ {
536+ if (op->widening == NULL)
537+ op->widening = (struct widening_optab_handlers *)
538+ xcalloc (1, sizeof (struct widening_optab_handlers));
539+
540+ op->widening->handlers[(int) to_mode][(int) from_mode].insn_code
541+ = (int) code - (int) CODE_FOR_nothing;
542+ }
543+}
544+
545 /* Return the insn used to perform conversion OP from mode FROM_MODE
546 to mode TO_MODE; return CODE_FOR_nothing if the target does not have
547 such an insn. */
548
549=== added file 'gcc/testsuite/gcc.target/arm/no-wmla-1.c'
550--- gcc/testsuite/gcc.target/arm/no-wmla-1.c 1970-01-01 00:00:00 +0000
551+++ gcc/testsuite/gcc.target/arm/no-wmla-1.c 2011-08-05 14:18:27 +0000
552@@ -0,0 +1,11 @@
553+/* { dg-do compile } */
554+/* { dg-options "-O2 -march=armv7-a" } */
555+
556+int
557+foo (int a, short b, short c)
558+{
559+ int bc = b * c;
560+ return a + (short)bc;
561+}
562+
563+/* { dg-final { scan-assembler "mul" } } */
564
565=== added file 'gcc/testsuite/gcc.target/arm/wmul-10.c'
566--- gcc/testsuite/gcc.target/arm/wmul-10.c 1970-01-01 00:00:00 +0000
567+++ gcc/testsuite/gcc.target/arm/wmul-10.c 2011-08-05 14:18:27 +0000
568@@ -0,0 +1,10 @@
569+/* { dg-do compile } */
570+/* { dg-options "-O2 -march=armv7-a" } */
571+
572+unsigned long long
573+foo (unsigned short a, unsigned short *b, unsigned short *c)
574+{
575+ return (unsigned)a + (unsigned long long)*b * (unsigned long long)*c;
576+}
577+
578+/* { dg-final { scan-assembler "umlal" } } */
579
580=== added file 'gcc/testsuite/gcc.target/arm/wmul-11.c'
581--- gcc/testsuite/gcc.target/arm/wmul-11.c 1970-01-01 00:00:00 +0000
582+++ gcc/testsuite/gcc.target/arm/wmul-11.c 2011-08-05 14:18:27 +0000
583@@ -0,0 +1,10 @@
584+/* { dg-do compile } */
585+/* { dg-options "-O2 -march=armv7-a" } */
586+
587+long long
588+foo (int *b)
589+{
590+ return 10 * (long long)*b;
591+}
592+
593+/* { dg-final { scan-assembler "smull" } } */
594
595=== added file 'gcc/testsuite/gcc.target/arm/wmul-12.c'
596--- gcc/testsuite/gcc.target/arm/wmul-12.c 1970-01-01 00:00:00 +0000
597+++ gcc/testsuite/gcc.target/arm/wmul-12.c 2011-08-05 14:18:27 +0000
598@@ -0,0 +1,11 @@
599+/* { dg-do compile } */
600+/* { dg-options "-O2 -march=armv7-a" } */
601+
602+long long
603+foo (int *b, int *c)
604+{
605+ int tmp = *b * *c;
606+ return 10 + (long long)tmp;
607+}
608+
609+/* { dg-final { scan-assembler "smlal" } } */
610
611=== added file 'gcc/testsuite/gcc.target/arm/wmul-13.c'
612--- gcc/testsuite/gcc.target/arm/wmul-13.c 1970-01-01 00:00:00 +0000
613+++ gcc/testsuite/gcc.target/arm/wmul-13.c 2011-08-05 14:18:27 +0000
614@@ -0,0 +1,10 @@
615+/* { dg-do compile } */
616+/* { dg-options "-O2 -march=armv7-a" } */
617+
618+long long
619+foo (int *a, int *b)
620+{
621+ return *a + (long long)*b * 10;
622+}
623+
624+/* { dg-final { scan-assembler "smlal" } } */
625
626=== added file 'gcc/testsuite/gcc.target/arm/wmul-5.c'
627--- gcc/testsuite/gcc.target/arm/wmul-5.c 1970-01-01 00:00:00 +0000
628+++ gcc/testsuite/gcc.target/arm/wmul-5.c 2011-08-05 14:18:27 +0000
629@@ -0,0 +1,10 @@
630+/* { dg-do compile } */
631+/* { dg-options "-O2 -march=armv7-a" } */
632+
633+long long
634+foo (long long a, char *b, char *c)
635+{
636+ return a + *b * *c;
637+}
638+
639+/* { dg-final { scan-assembler "umlal" } } */
640
641=== added file 'gcc/testsuite/gcc.target/arm/wmul-6.c'
642--- gcc/testsuite/gcc.target/arm/wmul-6.c 1970-01-01 00:00:00 +0000
643+++ gcc/testsuite/gcc.target/arm/wmul-6.c 2011-08-05 14:18:27 +0000
644@@ -0,0 +1,10 @@
645+/* { dg-do compile } */
646+/* { dg-options "-O2 -march=armv7-a" } */
647+
648+long long
649+foo (long long a, unsigned char *b, signed char *c)
650+{
651+ return a + (long long)*b * (long long)*c;
652+}
653+
654+/* { dg-final { scan-assembler "smlal" } } */
655
656=== added file 'gcc/testsuite/gcc.target/arm/wmul-7.c'
657--- gcc/testsuite/gcc.target/arm/wmul-7.c 1970-01-01 00:00:00 +0000
658+++ gcc/testsuite/gcc.target/arm/wmul-7.c 2011-08-05 14:18:27 +0000
659@@ -0,0 +1,10 @@
660+/* { dg-do compile } */
661+/* { dg-options "-O2 -march=armv7-a" } */
662+
663+unsigned long long
664+foo (unsigned long long a, unsigned char *b, unsigned short *c)
665+{
666+ return a + *b * *c;
667+}
668+
669+/* { dg-final { scan-assembler "umlal" } } */
670
671=== added file 'gcc/testsuite/gcc.target/arm/wmul-8.c'
672--- gcc/testsuite/gcc.target/arm/wmul-8.c 1970-01-01 00:00:00 +0000
673+++ gcc/testsuite/gcc.target/arm/wmul-8.c 2011-08-05 14:18:27 +0000
674@@ -0,0 +1,10 @@
675+/* { dg-do compile } */
676+/* { dg-options "-O2 -march=armv7-a" } */
677+
678+long long
679+foo (long long a, int *b, int *c)
680+{
681+ return a + *b * *c;
682+}
683+
684+/* { dg-final { scan-assembler "smlal" } } */
685
686=== added file 'gcc/testsuite/gcc.target/arm/wmul-9.c'
687--- gcc/testsuite/gcc.target/arm/wmul-9.c 1970-01-01 00:00:00 +0000
688+++ gcc/testsuite/gcc.target/arm/wmul-9.c 2011-08-05 14:18:27 +0000
689@@ -0,0 +1,10 @@
690+/* { dg-do compile } */
691+/* { dg-options "-O2 -march=armv7-a" } */
692+
693+long long
694+foo (long long a, short *b, char *c)
695+{
696+ return a + *b * *c;
697+}
698+
699+/* { dg-final { scan-assembler "smlalbb" } } */
700
701=== added file 'gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c'
702--- gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c 1970-01-01 00:00:00 +0000
703+++ gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c 2011-08-05 14:18:27 +0000
704@@ -0,0 +1,17 @@
705+/* { dg-do compile } */
706+/* { dg-options "-O2 -march=armv7-a" } */
707+
708+struct bf
709+{
710+ int a : 3;
711+ int b : 15;
712+ int c : 3;
713+};
714+
715+long long
716+foo (long long a, struct bf b, struct bf c)
717+{
718+ return a + b.b * c.b;
719+}
720+
721+/* { dg-final { scan-assembler "smlalbb" } } */
722
723=== added file 'gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c'
724--- gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c 1970-01-01 00:00:00 +0000
725+++ gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c 2011-08-05 14:18:27 +0000
726@@ -0,0 +1,17 @@
727+/* { dg-do compile } */
728+/* { dg-options "-O2 -march=armv7-a" } */
729+
730+struct bf
731+{
732+ int a : 3;
733+ unsigned int b : 15;
734+ int c : 3;
735+};
736+
737+long long
738+foo (long long a, struct bf b, struct bf c)
739+{
740+ return a + b.b * c.c;
741+}
742+
743+/* { dg-final { scan-assembler "smlalbb" } } */
744
745=== modified file 'gcc/tree-cfg.c'
746--- gcc/tree-cfg.c 2011-07-01 09:19:21 +0000
747+++ gcc/tree-cfg.c 2011-08-05 14:18:27 +0000
748@@ -3574,7 +3574,7 @@
749 case WIDEN_MULT_EXPR:
750 if (TREE_CODE (lhs_type) != INTEGER_TYPE)
751 return true;
752- return ((2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type))
753+ return ((2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type))
754 || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)));
755
756 case WIDEN_SUM_EXPR:
757@@ -3667,7 +3667,7 @@
758 && !FIXED_POINT_TYPE_P (rhs1_type))
759 || !useless_type_conversion_p (rhs1_type, rhs2_type)
760 || !useless_type_conversion_p (lhs_type, rhs3_type)
761- || 2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type)
762+ || 2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)
763 || TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))
764 {
765 error ("type mismatch in widening multiply-accumulate expression");
766
767=== modified file 'gcc/tree-ssa-math-opts.c'
768--- gcc/tree-ssa-math-opts.c 2011-03-11 16:36:16 +0000
769+++ gcc/tree-ssa-math-opts.c 2011-08-05 14:18:27 +0000
770@@ -1266,42 +1266,75 @@
771 }
772 };
773
774-/* Return true if RHS is a suitable operand for a widening multiplication.
775+/* Build a gimple assignment to cast VAL to TARGET. Insert the statement
776+ prior to GSI's current position, and return the fresh SSA name. */
777+
778+static tree
779+build_and_insert_cast (gimple_stmt_iterator *gsi, location_t loc,
780+ tree target, tree val)
781+{
782+ tree result = make_ssa_name (target, NULL);
783+ gimple stmt = gimple_build_assign_with_ops (CONVERT_EXPR, result, val, NULL);
784+ gimple_set_location (stmt, loc);
785+ gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
786+ return result;
787+}
788+
789+/* Return true if RHS is a suitable operand for a widening multiplication,
790+ assuming a target type of TYPE.
791 There are two cases:
792
793- - RHS makes some value twice as wide. Store that value in *NEW_RHS_OUT
794- if so, and store its type in *TYPE_OUT.
795+ - RHS makes some value at least twice as wide. Store that value
796+ in *NEW_RHS_OUT if so, and store its type in *TYPE_OUT.
797
798 - RHS is an integer constant. Store that value in *NEW_RHS_OUT if so,
799 but leave *TYPE_OUT untouched. */
800
801 static bool
802-is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out)
803+is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
804+ tree *new_rhs_out)
805 {
806 gimple stmt;
807- tree type, type1, rhs1;
808+ tree type1, rhs1;
809 enum tree_code rhs_code;
810
811 if (TREE_CODE (rhs) == SSA_NAME)
812 {
813- type = TREE_TYPE (rhs);
814 stmt = SSA_NAME_DEF_STMT (rhs);
815 if (!is_gimple_assign (stmt))
816- return false;
817-
818- rhs_code = gimple_assign_rhs_code (stmt);
819- if (TREE_CODE (type) == INTEGER_TYPE
820- ? !CONVERT_EXPR_CODE_P (rhs_code)
821- : rhs_code != FIXED_CONVERT_EXPR)
822- return false;
823-
824- rhs1 = gimple_assign_rhs1 (stmt);
825- type1 = TREE_TYPE (rhs1);
826+ {
827+ rhs1 = NULL;
828+ type1 = TREE_TYPE (rhs);
829+ }
830+ else
831+ {
832+ rhs1 = gimple_assign_rhs1 (stmt);
833+ type1 = TREE_TYPE (rhs1);
834+ }
835+
836+ if (rhs1 && TREE_CODE (rhs1) == INTEGER_CST)
837+ {
838+ *new_rhs_out = rhs1;
839+ *type_out = NULL;
840+ return true;
841+ }
842+
843 if (TREE_CODE (type1) != TREE_CODE (type)
844- || TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type))
845+ || TYPE_PRECISION (type1) * 2 > TYPE_PRECISION (type))
846 return false;
847
848- *new_rhs_out = rhs1;
849+ if (rhs1)
850+ {
851+ rhs_code = gimple_assign_rhs_code (stmt);
852+ if (TREE_CODE (type) == INTEGER_TYPE
853+ ? !CONVERT_EXPR_CODE_P (rhs_code)
854+ : rhs_code != FIXED_CONVERT_EXPR)
855+ *new_rhs_out = rhs;
856+ else
857+ *new_rhs_out = rhs1;
858+ }
859+ else
860+ *new_rhs_out = rhs;
861 *type_out = type1;
862 return true;
863 }
864@@ -1316,28 +1349,27 @@
865 return false;
866 }
867
868-/* Return true if STMT performs a widening multiplication. If so,
869- store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT
870- respectively. Also fill *RHS1_OUT and *RHS2_OUT such that converting
871- those operands to types *TYPE1_OUT and *TYPE2_OUT would give the
872- operands of the multiplication. */
873+/* Return true if STMT performs a widening multiplication, assuming the
874+ output type is TYPE. If so, store the unwidened types of the operands
875+ in *TYPE1_OUT and *TYPE2_OUT respectively. Also fill *RHS1_OUT and
876+ *RHS2_OUT such that converting those operands to types *TYPE1_OUT
877+ and *TYPE2_OUT would give the operands of the multiplication. */
878
879 static bool
880-is_widening_mult_p (gimple stmt,
881+is_widening_mult_p (tree type, gimple stmt,
882 tree *type1_out, tree *rhs1_out,
883 tree *type2_out, tree *rhs2_out)
884 {
885- tree type;
886-
887- type = TREE_TYPE (gimple_assign_lhs (stmt));
888 if (TREE_CODE (type) != INTEGER_TYPE
889 && TREE_CODE (type) != FIXED_POINT_TYPE)
890 return false;
891
892- if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out))
893+ if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out,
894+ rhs1_out))
895 return false;
896
897- if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out))
898+ if (!is_widening_mult_rhs_p (type, gimple_assign_rhs2 (stmt), type2_out,
899+ rhs2_out))
900 return false;
901
902 if (*type1_out == NULL)
903@@ -1354,6 +1386,18 @@
904 *type2_out = *type1_out;
905 }
906
907+ /* Ensure that the larger of the two operands comes first. */
908+ if (TYPE_PRECISION (*type1_out) < TYPE_PRECISION (*type2_out))
909+ {
910+ tree tmp;
911+ tmp = *type1_out;
912+ *type1_out = *type2_out;
913+ *type2_out = tmp;
914+ tmp = *rhs1_out;
915+ *rhs1_out = *rhs2_out;
916+ *rhs2_out = tmp;
917+ }
918+
919 return true;
920 }
921
922@@ -1362,31 +1406,100 @@
923 value is true iff we converted the statement. */
924
925 static bool
926-convert_mult_to_widen (gimple stmt)
927+convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
928 {
929- tree lhs, rhs1, rhs2, type, type1, type2;
930+ tree lhs, rhs1, rhs2, type, type1, type2, tmp = NULL;
931 enum insn_code handler;
932+ enum machine_mode to_mode, from_mode, actual_mode;
933+ optab op;
934+ int actual_precision;
935+ location_t loc = gimple_location (stmt);
936+ bool from_unsigned1, from_unsigned2;
937
938 lhs = gimple_assign_lhs (stmt);
939 type = TREE_TYPE (lhs);
940 if (TREE_CODE (type) != INTEGER_TYPE)
941 return false;
942
943- if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
944+ if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2))
945 return false;
946
947- if (TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2))
948- handler = optab_handler (umul_widen_optab, TYPE_MODE (type));
949- else if (!TYPE_UNSIGNED (type1) && !TYPE_UNSIGNED (type2))
950- handler = optab_handler (smul_widen_optab, TYPE_MODE (type));
951+ to_mode = TYPE_MODE (type);
952+ from_mode = TYPE_MODE (type1);
953+ from_unsigned1 = TYPE_UNSIGNED (type1);
954+ from_unsigned2 = TYPE_UNSIGNED (type2);
955+
956+ if (from_unsigned1 && from_unsigned2)
957+ op = umul_widen_optab;
958+ else if (!from_unsigned1 && !from_unsigned2)
959+ op = smul_widen_optab;
960 else
961- handler = optab_handler (usmul_widen_optab, TYPE_MODE (type));
962+ op = usmul_widen_optab;
963+
964+ handler = find_widening_optab_handler_and_mode (op, to_mode, from_mode,
965+ 0, &actual_mode);
966
967 if (handler == CODE_FOR_nothing)
968- return false;
969-
970- gimple_assign_set_rhs1 (stmt, fold_convert (type1, rhs1));
971- gimple_assign_set_rhs2 (stmt, fold_convert (type2, rhs2));
972+ {
973+ if (op != smul_widen_optab)
974+ {
975+ /* We can use a signed multiply with unsigned types as long as
976+ there is a wider mode to use, or it is the smaller of the two
977+ types that is unsigned. Note that type1 >= type2, always. */
978+ if ((TYPE_UNSIGNED (type1)
979+ && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode))
980+ || (TYPE_UNSIGNED (type2)
981+ && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
982+ {
983+ from_mode = GET_MODE_WIDER_MODE (from_mode);
984+ if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
985+ return false;
986+ }
987+
988+ op = smul_widen_optab;
989+ handler = find_widening_optab_handler_and_mode (op, to_mode,
990+ from_mode, 0,
991+ &actual_mode);
992+
993+ if (handler == CODE_FOR_nothing)
994+ return false;
995+
996+ from_unsigned1 = from_unsigned2 = false;
997+ }
998+ else
999+ return false;
1000+ }
1001+
1002+ /* Ensure that the inputs to the handler are in the correct precison
1003+ for the opcode. This will be the full mode size. */
1004+ actual_precision = GET_MODE_PRECISION (actual_mode);
1005+ if (actual_precision != TYPE_PRECISION (type1)
1006+ || from_unsigned1 != TYPE_UNSIGNED (type1))
1007+ {
1008+ tmp = create_tmp_var (build_nonstandard_integer_type
1009+ (actual_precision, from_unsigned1),
1010+ NULL);
1011+ rhs1 = build_and_insert_cast (gsi, loc, tmp, rhs1);
1012+ }
1013+ if (actual_precision != TYPE_PRECISION (type2)
1014+ || from_unsigned2 != TYPE_UNSIGNED (type2))
1015+ {
1016+ /* Reuse the same type info, if possible. */
1017+ if (!tmp || from_unsigned1 != from_unsigned2)
1018+ tmp = create_tmp_var (build_nonstandard_integer_type
1019+ (actual_precision, from_unsigned2),
1020+ NULL);
1021+ rhs2 = build_and_insert_cast (gsi, loc, tmp, rhs2);
1022+ }
1023+
1024+ /* Handle constants. */
1025+ if (TREE_CODE (rhs1) == INTEGER_CST)
1026+ rhs1 = fold_convert (type1, rhs1);
1027+ if (TREE_CODE (rhs2) == INTEGER_CST)
1028+ rhs2 = fold_convert (type2, rhs2);
1029+
1030+ gimple_assign_set_rhs1 (stmt, rhs1);
1031+ gimple_assign_set_rhs2 (stmt, rhs2);
1032 gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR);
1033 update_stmt (stmt);
1034 return true;
1035@@ -1403,11 +1516,17 @@
1036 enum tree_code code)
1037 {
1038 gimple rhs1_stmt = NULL, rhs2_stmt = NULL;
1039- tree type, type1, type2;
1040+ gimple conv1_stmt = NULL, conv2_stmt = NULL, conv_stmt;
1041+ tree type, type1, type2, optype, tmp = NULL;
1042 tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs;
1043 enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK;
1044 optab this_optab;
1045 enum tree_code wmult_code;
1046+ enum insn_code handler;
1047+ enum machine_mode to_mode, from_mode, actual_mode;
1048+ location_t loc = gimple_location (stmt);
1049+ int actual_precision;
1050+ bool from_unsigned1, from_unsigned2;
1051
1052 lhs = gimple_assign_lhs (stmt);
1053 type = TREE_TYPE (lhs);
1054@@ -1429,8 +1548,6 @@
1055 if (is_gimple_assign (rhs1_stmt))
1056 rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
1057 }
1058- else
1059- return false;
1060
1061 if (TREE_CODE (rhs2) == SSA_NAME)
1062 {
1063@@ -1438,57 +1555,160 @@
1064 if (is_gimple_assign (rhs2_stmt))
1065 rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
1066 }
1067- else
1068- return false;
1069-
1070- if (code == PLUS_EXPR && rhs1_code == MULT_EXPR)
1071- {
1072- if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
1073- &type2, &mult_rhs2))
1074- return false;
1075- add_rhs = rhs2;
1076- }
1077- else if (rhs2_code == MULT_EXPR)
1078- {
1079- if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
1080- &type2, &mult_rhs2))
1081- return false;
1082- add_rhs = rhs1;
1083- }
1084- else if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR)
1085- {
1086- mult_rhs1 = gimple_assign_rhs1 (rhs1_stmt);
1087- mult_rhs2 = gimple_assign_rhs2 (rhs1_stmt);
1088- type1 = TREE_TYPE (mult_rhs1);
1089- type2 = TREE_TYPE (mult_rhs2);
1090- add_rhs = rhs2;
1091- }
1092- else if (rhs2_code == WIDEN_MULT_EXPR)
1093- {
1094- mult_rhs1 = gimple_assign_rhs1 (rhs2_stmt);
1095- mult_rhs2 = gimple_assign_rhs2 (rhs2_stmt);
1096- type1 = TREE_TYPE (mult_rhs1);
1097- type2 = TREE_TYPE (mult_rhs2);
1098- add_rhs = rhs1;
1099- }
1100- else
1101- return false;
1102-
1103- if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2))
1104- return false;
1105+
1106+ /* Allow for one conversion statement between the multiply
1107+ and addition/subtraction statement. If there are more than
1108+ one conversions then we assume they would invalidate this
1109+ transformation. If that's not the case then they should have
1110+ been folded before now. */
1111+ if (CONVERT_EXPR_CODE_P (rhs1_code))
1112+ {
1113+ conv1_stmt = rhs1_stmt;
1114+ rhs1 = gimple_assign_rhs1 (rhs1_stmt);
1115+ if (TREE_CODE (rhs1) == SSA_NAME)
1116+ {
1117+ rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
1118+ if (is_gimple_assign (rhs1_stmt))
1119+ rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
1120+ }
1121+ else
1122+ return false;
1123+ }
1124+ if (CONVERT_EXPR_CODE_P (rhs2_code))
1125+ {
1126+ conv2_stmt = rhs2_stmt;
1127+ rhs2 = gimple_assign_rhs1 (rhs2_stmt);
1128+ if (TREE_CODE (rhs2) == SSA_NAME)
1129+ {
1130+ rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
1131+ if (is_gimple_assign (rhs2_stmt))
1132+ rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
1133+ }
1134+ else
1135+ return false;
1136+ }
1137+
1138+ /* If code is WIDEN_MULT_EXPR then it would seem unnecessary to call
1139+ is_widening_mult_p, but we still need the rhs returns.
1140+
1141+ It might also appear that it would be sufficient to use the existing
1142+ operands of the widening multiply, but that would limit the choice of
1143+ multiply-and-accumulate instructions. */
1144+ if (code == PLUS_EXPR
1145+ && (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
1146+ {
1147+ if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1,
1148+ &type2, &mult_rhs2))
1149+ return false;
1150+ add_rhs = rhs2;
1151+ conv_stmt = conv1_stmt;
1152+ }
1153+ else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
1154+ {
1155+ if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1,
1156+ &type2, &mult_rhs2))
1157+ return false;
1158+ add_rhs = rhs1;
1159+ conv_stmt = conv2_stmt;
1160+ }
1161+ else
1162+ return false;
1163+
1164+ to_mode = TYPE_MODE (type);
1165+ from_mode = TYPE_MODE (type1);
1166+ from_unsigned1 = TYPE_UNSIGNED (type1);
1167+ from_unsigned2 = TYPE_UNSIGNED (type2);
1168+
1169+ /* There's no such thing as a mixed sign madd yet, so use a wider mode. */
1170+ if (from_unsigned1 != from_unsigned2)
1171+ {
1172+ /* We can use a signed multiply with unsigned types as long as
1173+ there is a wider mode to use, or it is the smaller of the two
1174+ types that is unsigned. Note that type1 >= type2, always. */
1175+ if ((from_unsigned1
1176+ && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode))
1177+ || (from_unsigned2
1178+ && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
1179+ {
1180+ from_mode = GET_MODE_WIDER_MODE (from_mode);
1181+ if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode))
1182+ return false;
1183+ }
1184+
1185+ from_unsigned1 = from_unsigned2 = false;
1186+ }
1187+
1188+ /* If there was a conversion between the multiply and addition
1189+ then we need to make sure it fits a multiply-and-accumulate.
1190+ The should be a single mode change which does not change the
1191+ value. */
1192+ if (conv_stmt)
1193+ {
1194+ /* We use the original, unmodified data types for this. */
1195+ tree from_type = TREE_TYPE (gimple_assign_rhs1 (conv_stmt));
1196+ tree to_type = TREE_TYPE (gimple_assign_lhs (conv_stmt));
1197+ int data_size = TYPE_PRECISION (type1) + TYPE_PRECISION (type2);
1198+ bool is_unsigned = TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2);
1199+
1200+ if (TYPE_PRECISION (from_type) > TYPE_PRECISION (to_type))
1201+ {
1202+ /* Conversion is a truncate. */
1203+ if (TYPE_PRECISION (to_type) < data_size)
1204+ return false;
1205+ }
1206+ else if (TYPE_PRECISION (from_type) < TYPE_PRECISION (to_type))
1207+ {
1208+ /* Conversion is an extend. Check it's the right sort. */
1209+ if (TYPE_UNSIGNED (from_type) != is_unsigned
1210+ && !(is_unsigned && TYPE_PRECISION (from_type) > data_size))
1211+ return false;
1212+ }
1213+ /* else convert is a no-op for our purposes. */
1214+ }
1215
1216 /* Verify that the machine can perform a widening multiply
1217 accumulate in this mode/signedness combination, otherwise
1218 this transformation is likely to pessimize code. */
1219- this_optab = optab_for_tree_code (wmult_code, type1, optab_default);
1220- if (optab_handler (this_optab, TYPE_MODE (type)) == CODE_FOR_nothing)
1221+ optype = build_nonstandard_integer_type (from_mode, from_unsigned1);
1222+ this_optab = optab_for_tree_code (wmult_code, optype, optab_default);
1223+ handler = find_widening_optab_handler_and_mode (this_optab, to_mode,
1224+ from_mode, 0, &actual_mode);
1225+
1226+ if (handler == CODE_FOR_nothing)
1227 return false;
1228
1229- /* ??? May need some type verification here? */
1230-
1231- gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code,
1232- fold_convert (type1, mult_rhs1),
1233- fold_convert (type2, mult_rhs2),
1234+ /* Ensure that the inputs to the handler are in the correct precison
1235+ for the opcode. This will be the full mode size. */
1236+ actual_precision = GET_MODE_PRECISION (actual_mode);
1237+ if (actual_precision != TYPE_PRECISION (type1)
1238+ || from_unsigned1 != TYPE_UNSIGNED (type1))
1239+ {
1240+ tmp = create_tmp_var (build_nonstandard_integer_type
1241+ (actual_precision, from_unsigned1),
1242+ NULL);
1243+ mult_rhs1 = build_and_insert_cast (gsi, loc, tmp, mult_rhs1);
1244+ }
1245+ if (actual_precision != TYPE_PRECISION (type2)
1246+ || from_unsigned2 != TYPE_UNSIGNED (type2))
1247+ {
1248+ if (!tmp || from_unsigned1 != from_unsigned2)
1249+ tmp = create_tmp_var (build_nonstandard_integer_type
1250+ (actual_precision, from_unsigned2),
1251+ NULL);
1252+ mult_rhs2 = build_and_insert_cast (gsi, loc, tmp, mult_rhs2);
1253+ }
1254+
1255+ if (!useless_type_conversion_p (type, TREE_TYPE (add_rhs)))
1256+ add_rhs = build_and_insert_cast (gsi, loc, create_tmp_var (type, NULL),
1257+ add_rhs);
1258+
1259+ /* Handle constants. */
1260+ if (TREE_CODE (mult_rhs1) == INTEGER_CST)
1261+ rhs1 = fold_convert (type1, mult_rhs1);
1262+ if (TREE_CODE (mult_rhs2) == INTEGER_CST)
1263+ rhs2 = fold_convert (type2, mult_rhs2);
1264+
1265+ gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs1, mult_rhs2,
1266 add_rhs);
1267 update_stmt (gsi_stmt (*gsi));
1268 return true;
1269@@ -1696,7 +1916,7 @@
1270 switch (code)
1271 {
1272 case MULT_EXPR:
1273- if (!convert_mult_to_widen (stmt)
1274+ if (!convert_mult_to_widen (stmt, &gsi)
1275 && convert_mult_to_fma (stmt,
1276 gimple_assign_rhs1 (stmt),
1277 gimple_assign_rhs2 (stmt)))

Subscribers

People subscribed via source and target branches