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: 1276 lines (+737/-143) (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 (+69/-15)
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+68866@code.launchpad.net

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

This proposal has been superseded by a proposal from 2011-07-27.

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 :

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 :

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 :

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 :

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ChangeLog.linaro'
--- ChangeLog.linaro 2011-07-21 11:30:53 +0000
+++ ChangeLog.linaro 2011-07-27 14:18:25 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
12011-07-21 Richard Sandiford <rdsandiford@googlemail.com>22011-07-21 Richard Sandiford <rdsandiford@googlemail.com>
23
3 gcc/4 gcc/
@@ -137,6 +138,134 @@
137138
138 * gcc.c-torture/compile/20110401-1.c: New test.139 * gcc.c-torture/compile/20110401-1.c: New test.
139140
141=======
1422011-07-22 Andrew Stubbs <ams@codesourcery.com>
143
144 Backport from patches proposed for 4.7:
145
146 2011-07-22 Andrew Stubbs <ams@codesourcery.com>
147
148 gcc/
149 * tree-ssa-math-opts.c (is_widening_mult_rhs_p): Handle constants
150 beyond conversions.
151 (convert_mult_to_widen): Convert constant inputs to the right type.
152 (convert_plusminus_to_widen): Don't automatically reject inputs that
153 are not an SSA_NAME.
154 Convert constant inputs to the right type.
155
156 gcc/testsuite/
157 * gcc.target/arm/wmul-11.c: New file.
158 * gcc.target/arm/wmul-12.c: New file.
159 * gcc.target/arm/wmul-13.c: New file.
160
161 2011-07-21 Andrew Stubbs <ams@codesourcery.com>
162
163 gcc/
164 * tree-ssa-math-opts.c (convert_plusminus_to_widen): Convert add_rhs
165 to the correct type.
166
167 gcc/testsuite/
168 * gcc.target/arm/wmul-10.c: New file.
169
170 2011-06-24 Andrew Stubbs <ams@codesourcery.com>
171
172 gcc/
173 * tree-ssa-math-opts.c (convert_mult_to_widen): Better handle
174 unsigned inputs of different modes.
175 (convert_plusminus_to_widen): Likewise.
176
177 gcc/testsuite/
178 * gcc.target/arm/wmul-9.c: New file.
179 * gcc.target/arm/wmul-bitfield-2.c: New file.
180
181 2011-07-14 Andrew Stubbs <ams@codesourcery.com>
182
183 gcc/
184 * tree-ssa-math-opts.c (is_widening_mult_rhs_p): Add new argument
185 'type'.
186 Use 'type' from caller, not inferred from 'rhs'.
187 Don't reject non-conversion statements. Do return lhs in this case.
188 (is_widening_mult_p): Add new argument 'type'.
189 Use 'type' from caller, not inferred from 'stmt'.
190 Pass type to is_widening_mult_rhs_p.
191 (convert_mult_to_widen): Pass type to is_widening_mult_p.
192 (convert_plusminus_to_widen): Likewise.
193
194 gcc/testsuite/
195 * gcc.target/arm/wmul-8.c: New file.
196
197 2011-07-14 Andrew Stubbs <ams@codesourcery.com>
198
199 gcc/
200 * tree-ssa-math-opts.c (is_widening_mult_p): Remove FIXME.
201 Ensure the the larger type is the first operand.
202
203 gcc/testsuite/
204 * gcc.target/arm/wmul-7.c: New file.
205
206 2011-07-14 Andrew Stubbs <ams@codesourcery.com>
207
208 gcc/
209 * tree-ssa-math-opts.c (convert_mult_to_widen): Convert
210 unsupported unsigned multiplies to signed.
211 (convert_plusminus_to_widen): Likewise.
212
213 gcc/testsuite/
214 * gcc.target/arm/wmul-6.c: New file.
215
216 2011-07-14 Andrew Stubbs <ams@codesourcery.com>
217
218 gcc/
219 * tree-ssa-math-opts.c (convert_plusminus_to_widen): Permit a single
220 conversion statement separating multiply-and-accumulate.
221
222 gcc/testsuite/
223 * gcc.target/arm/wmul-5.c: New file.
224 * gcc.target/arm/no-wmla-1.c: New file.
225
226 2011-07-14 Andrew Stubbs <ams@codesourcery.com>
227
228 gcc/
229 * config/arm/arm.md (maddhidi4): Remove '*' from name.
230 * expr.c (expand_expr_real_2): Use find_widening_optab_handler.
231 * optabs.c (find_widening_optab_handler_and_mode): New function.
232 (expand_widen_pattern_expr): Use find_widening_optab_handler.
233 (expand_binop_directly): Likewise.
234 (expand_binop): Likewise.
235 * optabs.h (find_widening_optab_handler): New macro define.
236 (find_widening_optab_handler_and_mode): New prototype.
237 * tree-cfg.c (verify_gimple_assign_binary): Adjust WIDEN_MULT_EXPR
238 type precision rules.
239 (verify_gimple_assign_ternary): Likewise for WIDEN_MULT_PLUS_EXPR.
240 * tree-ssa-math-opts.c (build_and_insert_cast): New function.
241 (is_widening_mult_rhs_p): Allow widening by more than one mode.
242 Explicitly disallow mis-matched input types.
243 (convert_mult_to_widen): Use find_widening_optab_handler, and cast
244 input types to fit the new handler.
245 (convert_plusminus_to_widen): Likewise.
246
247 gcc/testsuite/
248 * gcc.target/arm/wmul-bitfield-1.c: New file.
249
250
251 2011-07-09 Andrew Stubbs <ams@codesourcery.com>
252
253 gcc/
254 * expr.c (expand_expr_real_2): Use widening_optab_handler.
255 * genopinit.c (optabs): Use set_widening_optab_handler for $N.
256 (gen_insn): $N now means $a must be wider than $b, not consecutive.
257 * optabs.c (expand_widen_pattern_expr): Use widening_optab_handler.
258 (expand_binop_directly): Likewise.
259 (expand_binop): Likewise.
260 * optabs.h (widening_optab_handlers): New struct.
261 (optab_d): New member, 'widening'.
262 (widening_optab_handler): New function.
263 (set_widening_optab_handler): New function.
264 * tree-ssa-math-opts.c (convert_mult_to_widen): Use
265 widening_optab_handler.
266 (convert_plusminus_to_widen): Likewise.
267
268>>>>>>> MERGE-SOURCE
1402011-07-13 Richard Sandiford <richard.sandiford@linaro.org>2692011-07-13 Richard Sandiford <richard.sandiford@linaro.org>
141270
142 Backport from mainline:271 Backport from mainline:
143272
=== modified file 'gcc/config/arm/arm.md'
--- gcc/config/arm/arm.md 2011-06-28 12:02:27 +0000
+++ gcc/config/arm/arm.md 2011-07-27 14:18:25 +0000
@@ -1839,7 +1839,7 @@
1839 (set_attr "predicable" "yes")]1839 (set_attr "predicable" "yes")]
1840)1840)
18411841
1842(define_insn "*maddhidi4"1842(define_insn "maddhidi4"
1843 [(set (match_operand:DI 0 "s_register_operand" "=r")1843 [(set (match_operand:DI 0 "s_register_operand" "=r")
1844 (plus:DI1844 (plus:DI
1845 (mult:DI (sign_extend:DI1845 (mult:DI (sign_extend:DI
18461846
=== modified file 'gcc/expr.c'
--- gcc/expr.c 2011-07-14 11:52:32 +0000
+++ gcc/expr.c 2011-07-27 14:18:25 +0000
@@ -7680,18 +7680,16 @@
7680 {7680 {
7681 enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0));7681 enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0));
7682 this_optab = usmul_widen_optab;7682 this_optab = usmul_widen_optab;
7683 if (mode == GET_MODE_2XWIDER_MODE (innermode))7683 if (find_widening_optab_handler (this_optab, mode, innermode, 0)
7684 != CODE_FOR_nothing)
7684 {7685 {
7685 if (optab_handler (this_optab, mode) != CODE_FOR_nothing)7686 if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
7686 {7687 expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
7687 if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))7688 EXPAND_NORMAL);
7688 expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,7689 else
7689 EXPAND_NORMAL);7690 expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0,
7690 else7691 EXPAND_NORMAL);
7691 expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0,7692 goto binop3;
7692 EXPAND_NORMAL);
7693 goto binop3;
7694 }
7695 }7693 }
7696 }7694 }
7697 /* Check for a multiplication with matching signedness. */7695 /* Check for a multiplication with matching signedness. */
@@ -7706,10 +7704,10 @@
7706 optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;7704 optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
7707 this_optab = zextend_p ? umul_widen_optab : smul_widen_optab;7705 this_optab = zextend_p ? umul_widen_optab : smul_widen_optab;
77087706
7709 if (mode == GET_MODE_2XWIDER_MODE (innermode)7707 if (TREE_CODE (treeop0) != INTEGER_CST)
7710 && TREE_CODE (treeop0) != INTEGER_CST)
7711 {7708 {
7712 if (optab_handler (this_optab, mode) != CODE_FOR_nothing)7709 if (find_widening_optab_handler (this_optab, mode, innermode, 0)
7710 != CODE_FOR_nothing)
7713 {7711 {
7714 expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,7712 expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
7715 EXPAND_NORMAL);7713 EXPAND_NORMAL);
@@ -7717,7 +7715,8 @@
7717 unsignedp, this_optab);7715 unsignedp, this_optab);
7718 return REDUCE_BIT_FIELD (temp);7716 return REDUCE_BIT_FIELD (temp);
7719 }7717 }
7720 if (optab_handler (other_optab, mode) != CODE_FOR_nothing7718 if (find_widening_optab_handler (other_optab, mode, innermode, 0)
7719 != CODE_FOR_nothing
7721 && innermode == word_mode)7720 && innermode == word_mode)
7722 {7721 {
7723 rtx htem, hipart;7722 rtx htem, hipart;
77247723
=== modified file 'gcc/genopinit.c'
--- gcc/genopinit.c 2011-05-05 15:43:06 +0000
+++ gcc/genopinit.c 2011-07-27 14:18:25 +0000
@@ -46,10 +46,12 @@
46 used. $A and $B are replaced with the full name of the mode; $a and $b46 used. $A and $B are replaced with the full name of the mode; $a and $b
47 are replaced with the short form of the name, as above.47 are replaced with the short form of the name, as above.
4848
49 If $N is present in the pattern, it means the two modes must be consecutive49 If $N is present in the pattern, it means the two modes must be in
50 widths in the same mode class (e.g, QImode and HImode). $I means that50 the same mode class, and $b must be greater than $a (e.g, QImode
51 only full integer modes should be considered for the next mode, and $F51 and HImode).
52 means that only float modes should be considered.52
53 $I means that only full integer modes should be considered for the
54 next mode, and $F means that only float modes should be considered.
53 $P means that both full and partial integer modes should be considered.55 $P means that both full and partial integer modes should be considered.
54 $Q means that only fixed-point modes should be considered.56 $Q means that only fixed-point modes should be considered.
5557
@@ -99,17 +101,17 @@
99 "set_optab_handler (smulv_optab, $A, CODE_FOR_$(mulv$I$a3$))",101 "set_optab_handler (smulv_optab, $A, CODE_FOR_$(mulv$I$a3$))",
100 "set_optab_handler (umul_highpart_optab, $A, CODE_FOR_$(umul$a3_highpart$))",102 "set_optab_handler (umul_highpart_optab, $A, CODE_FOR_$(umul$a3_highpart$))",
101 "set_optab_handler (smul_highpart_optab, $A, CODE_FOR_$(smul$a3_highpart$))",103 "set_optab_handler (smul_highpart_optab, $A, CODE_FOR_$(smul$a3_highpart$))",
102 "set_optab_handler (smul_widen_optab, $B, CODE_FOR_$(mul$a$b3$)$N)",104 "set_widening_optab_handler (smul_widen_optab, $B, $A, CODE_FOR_$(mul$a$b3$)$N)",
103 "set_optab_handler (umul_widen_optab, $B, CODE_FOR_$(umul$a$b3$)$N)",105 "set_widening_optab_handler (umul_widen_optab, $B, $A, CODE_FOR_$(umul$a$b3$)$N)",
104 "set_optab_handler (usmul_widen_optab, $B, CODE_FOR_$(usmul$a$b3$)$N)",106 "set_widening_optab_handler (usmul_widen_optab, $B, $A, CODE_FOR_$(usmul$a$b3$)$N)",
105 "set_optab_handler (smadd_widen_optab, $B, CODE_FOR_$(madd$a$b4$)$N)",107 "set_widening_optab_handler (smadd_widen_optab, $B, $A, CODE_FOR_$(madd$a$b4$)$N)",
106 "set_optab_handler (umadd_widen_optab, $B, CODE_FOR_$(umadd$a$b4$)$N)",108 "set_widening_optab_handler (umadd_widen_optab, $B, $A, CODE_FOR_$(umadd$a$b4$)$N)",
107 "set_optab_handler (ssmadd_widen_optab, $B, CODE_FOR_$(ssmadd$a$b4$)$N)",109 "set_widening_optab_handler (ssmadd_widen_optab, $B, $A, CODE_FOR_$(ssmadd$a$b4$)$N)",
108 "set_optab_handler (usmadd_widen_optab, $B, CODE_FOR_$(usmadd$a$b4$)$N)",110 "set_widening_optab_handler (usmadd_widen_optab, $B, $A, CODE_FOR_$(usmadd$a$b4$)$N)",
109 "set_optab_handler (smsub_widen_optab, $B, CODE_FOR_$(msub$a$b4$)$N)",111 "set_widening_optab_handler (smsub_widen_optab, $B, $A, CODE_FOR_$(msub$a$b4$)$N)",
110 "set_optab_handler (umsub_widen_optab, $B, CODE_FOR_$(umsub$a$b4$)$N)",112 "set_widening_optab_handler (umsub_widen_optab, $B, $A, CODE_FOR_$(umsub$a$b4$)$N)",
111 "set_optab_handler (ssmsub_widen_optab, $B, CODE_FOR_$(ssmsub$a$b4$)$N)",113 "set_widening_optab_handler (ssmsub_widen_optab, $B, $A, CODE_FOR_$(ssmsub$a$b4$)$N)",
112 "set_optab_handler (usmsub_widen_optab, $B, CODE_FOR_$(usmsub$a$b4$)$N)",114 "set_widening_optab_handler (usmsub_widen_optab, $B, $A, CODE_FOR_$(usmsub$a$b4$)$N)",
113 "set_optab_handler (sdiv_optab, $A, CODE_FOR_$(div$a3$))",115 "set_optab_handler (sdiv_optab, $A, CODE_FOR_$(div$a3$))",
114 "set_optab_handler (ssdiv_optab, $A, CODE_FOR_$(ssdiv$Q$a3$))",116 "set_optab_handler (ssdiv_optab, $A, CODE_FOR_$(ssdiv$Q$a3$))",
115 "set_optab_handler (sdivv_optab, $A, CODE_FOR_$(div$V$I$a3$))",117 "set_optab_handler (sdivv_optab, $A, CODE_FOR_$(div$V$I$a3$))",
@@ -304,7 +306,7 @@
304 {306 {
305 int force_float = 0, force_int = 0, force_partial_int = 0;307 int force_float = 0, force_int = 0, force_partial_int = 0;
306 int force_fixed = 0;308 int force_fixed = 0;
307 int force_consec = 0;309 int force_wider = 0;
308 int matches = 1;310 int matches = 1;
309311
310 for (pp = optabs[pindex]; pp[0] != '$' || pp[1] != '('; pp++)312 for (pp = optabs[pindex]; pp[0] != '$' || pp[1] != '('; pp++)
@@ -322,7 +324,7 @@
322 switch (*++pp)324 switch (*++pp)
323 {325 {
324 case 'N':326 case 'N':
325 force_consec = 1;327 force_wider = 1;
326 break;328 break;
327 case 'I':329 case 'I':
328 force_int = 1;330 force_int = 1;
@@ -391,7 +393,10 @@
391 || mode_class[i] == MODE_VECTOR_FRACT393 || mode_class[i] == MODE_VECTOR_FRACT
392 || mode_class[i] == MODE_VECTOR_UFRACT394 || mode_class[i] == MODE_VECTOR_UFRACT
393 || mode_class[i] == MODE_VECTOR_ACCUM395 || mode_class[i] == MODE_VECTOR_ACCUM
394 || mode_class[i] == MODE_VECTOR_UACCUM))396 || mode_class[i] == MODE_VECTOR_UACCUM)
397 && (! force_wider
398 || *pp == 'a'
399 || m1 < i))
395 break;400 break;
396 }401 }
397402
@@ -411,8 +416,7 @@
411 }416 }
412417
413 if (matches && pp[0] == '$' && pp[1] == ')'418 if (matches && pp[0] == '$' && pp[1] == ')'
414 && *np == 0419 && *np == 0)
415 && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))
416 break;420 break;
417 }421 }
418422
419423
=== modified file 'gcc/optabs.c'
--- gcc/optabs.c 2011-07-04 14:03:49 +0000
+++ gcc/optabs.c 2011-07-27 14:18:25 +0000
@@ -225,6 +225,49 @@
225 return 1;225 return 1;
226}226}
227227
228228
229/* Given two input operands, OP0 and OP1, determine what the correct from_mode
230 for a widening operation would be. In most cases this would be OP0, but if
231 that's a constant it'll be VOIDmode, which isn't useful. */
232
233static enum machine_mode
234widened_mode (rtx op0, rtx op1)
235{
236 enum machine_mode m0 = GET_MODE (op0);
237 enum machine_mode m1 = GET_MODE (op1);
238 return (GET_MODE_SIZE (m0) < GET_MODE_SIZE (m1)) ? m1 : m0;
239}
240
229241
242/* Find a widening optab even if it doesn't widen as much as we want.
243 E.g. if from_mode is HImode, and to_mode is DImode, and there is no
244 direct HI->SI insn, then return SI->DI, if that exists.
245 If PERMIT_NON_WIDENING is non-zero then this can be used with
246 non-widening optabs also. */
247
248enum insn_code
249find_widening_optab_handler_and_mode (optab op, enum machine_mode to_mode,
250 enum machine_mode from_mode,
251 int permit_non_widening,
252 enum machine_mode *found_mode)
253{
254 for (; (permit_non_widening || from_mode != to_mode)
255 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
256 && from_mode != VOIDmode;
257 from_mode = GET_MODE_WIDER_MODE (from_mode))
258 {
259 enum insn_code handler = widening_optab_handler (op, to_mode,
260 from_mode);
261
262 if (handler != CODE_FOR_nothing)
263 {
264 if (found_mode)
265 *found_mode = from_mode;
266 return handler;
267 }
268 }
269
270 return CODE_FOR_nothing;
271}
272
230273
231/* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP274/* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
232 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need275 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
233 not actually do a sign-extend or zero-extend, but can leave the276 not actually do a sign-extend or zero-extend, but can leave the
@@ -517,8 +560,9 @@
517 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);560 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
518 if (ops->code == WIDEN_MULT_PLUS_EXPR561 if (ops->code == WIDEN_MULT_PLUS_EXPR
519 || ops->code == WIDEN_MULT_MINUS_EXPR)562 || ops->code == WIDEN_MULT_MINUS_EXPR)
520 icode = (int) optab_handler (widen_pattern_optab,563 icode = (int) find_widening_optab_handler (widen_pattern_optab,
521 TYPE_MODE (TREE_TYPE (ops->op2)));564 TYPE_MODE (TREE_TYPE (ops->op2)),
565 tmode0, 0);
522 else566 else
523 icode = (int) optab_handler (widen_pattern_optab, tmode0);567 icode = (int) optab_handler (widen_pattern_optab, tmode0);
524 gcc_assert (icode != CODE_FOR_nothing);568 gcc_assert (icode != CODE_FOR_nothing);
@@ -1389,7 +1433,9 @@
1389 rtx target, int unsignedp, enum optab_methods methods,1433 rtx target, int unsignedp, enum optab_methods methods,
1390 rtx last)1434 rtx last)
1391{1435{
1392 int icode = (int) optab_handler (binoptab, mode);1436 enum machine_mode from_mode = widened_mode (op0, op1);
1437 int icode = (int) find_widening_optab_handler (binoptab, mode,
1438 from_mode, 1);
1393 enum machine_mode mode0 = insn_data[icode].operand[1].mode;1439 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
1394 enum machine_mode mode1 = insn_data[icode].operand[2].mode;1440 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
1395 enum machine_mode tmp_mode;1441 enum machine_mode tmp_mode;
@@ -1546,7 +1592,9 @@
1546 /* If we can do it with a three-operand insn, do so. */1592 /* If we can do it with a three-operand insn, do so. */
15471593
1548 if (methods != OPTAB_MUST_WIDEN1594 if (methods != OPTAB_MUST_WIDEN
1549 && optab_handler (binoptab, mode) != CODE_FOR_nothing)1595 && find_widening_optab_handler (binoptab, mode,
1596 widened_mode (op0, op1), 1)
1597 != CODE_FOR_nothing)
1550 {1598 {
1551 temp = expand_binop_directly (mode, binoptab, op0, op1, target,1599 temp = expand_binop_directly (mode, binoptab, op0, op1, target,
1552 unsignedp, methods, last);1600 unsignedp, methods, last);
@@ -1585,9 +1633,10 @@
1585 takes operands of this mode and makes a wider mode. */1633 takes operands of this mode and makes a wider mode. */
15861634
1587 if (binoptab == smul_optab1635 if (binoptab == smul_optab
1588 && GET_MODE_WIDER_MODE (mode) != VOIDmode1636 && GET_MODE_2XWIDER_MODE (mode) != VOIDmode
1589 && (optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab),1637 && (widening_optab_handler ((unsignedp ? umul_widen_optab
1590 GET_MODE_WIDER_MODE (mode))1638 : smul_widen_optab),
1639 GET_MODE_2XWIDER_MODE (mode), mode)
1591 != CODE_FOR_nothing))1640 != CODE_FOR_nothing))
1592 {1641 {
1593 temp = expand_binop (GET_MODE_WIDER_MODE (mode),1642 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
@@ -1615,12 +1664,15 @@
1615 wider_mode != VOIDmode;1664 wider_mode != VOIDmode;
1616 wider_mode = GET_MODE_WIDER_MODE (wider_mode))1665 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1617 {1666 {
1618 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing1667 if (optab_handler (binoptab, wider_mode)
1668 != CODE_FOR_nothing
1619 || (binoptab == smul_optab1669 || (binoptab == smul_optab
1620 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode1670 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
1621 && (optab_handler ((unsignedp ? umul_widen_optab1671 && (find_widening_optab_handler ((unsignedp
1622 : smul_widen_optab),1672 ? umul_widen_optab
1623 GET_MODE_WIDER_MODE (wider_mode))1673 : smul_widen_optab),
1674 GET_MODE_WIDER_MODE (wider_mode),
1675 mode, 0)
1624 != CODE_FOR_nothing)))1676 != CODE_FOR_nothing)))
1625 {1677 {
1626 rtx xop0 = op0, xop1 = op1;1678 rtx xop0 = op0, xop1 = op1;
@@ -2043,8 +2095,8 @@
2043 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)2095 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)
2044 {2096 {
2045 rtx product = NULL_RTX;2097 rtx product = NULL_RTX;
20462098 if (widening_optab_handler (umul_widen_optab, mode, word_mode)
2047 if (optab_handler (umul_widen_optab, mode) != CODE_FOR_nothing)2099 != CODE_FOR_nothing)
2048 {2100 {
2049 product = expand_doubleword_mult (mode, op0, op1, target,2101 product = expand_doubleword_mult (mode, op0, op1, target,
2050 true, methods);2102 true, methods);
@@ -2053,7 +2105,8 @@
2053 }2105 }
20542106
2055 if (product == NULL_RTX2107 if (product == NULL_RTX
2056 && optab_handler (smul_widen_optab, mode) != CODE_FOR_nothing)2108 && widening_optab_handler (smul_widen_optab, mode, word_mode)
2109 != CODE_FOR_nothing)
2057 {2110 {
2058 product = expand_doubleword_mult (mode, op0, op1, target,2111 product = expand_doubleword_mult (mode, op0, op1, target,
2059 false, methods);2112 false, methods);
@@ -2144,7 +2197,8 @@
2144 wider_mode != VOIDmode;2197 wider_mode != VOIDmode;
2145 wider_mode = GET_MODE_WIDER_MODE (wider_mode))2198 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2146 {2199 {
2147 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing2200 if (find_widening_optab_handler (binoptab, wider_mode, mode, 1)
2201 != CODE_FOR_nothing
2148 || (methods == OPTAB_LIB2202 || (methods == OPTAB_LIB
2149 && optab_libfunc (binoptab, wider_mode)))2203 && optab_libfunc (binoptab, wider_mode)))
2150 {2204 {
21512205
=== modified file 'gcc/optabs.h'
--- gcc/optabs.h 2011-05-05 15:43:06 +0000
+++ gcc/optabs.h 2011-07-27 14:18:25 +0000
@@ -42,6 +42,11 @@
42 int insn_code;42 int insn_code;
43};43};
4444
45struct widening_optab_handlers
46{
47 struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
48};
49
45struct optab_d50struct optab_d
46{51{
47 enum rtx_code code;52 enum rtx_code code;
@@ -50,6 +55,7 @@
50 void (*libcall_gen)(struct optab_d *, const char *name, char suffix,55 void (*libcall_gen)(struct optab_d *, const char *name, char suffix,
51 enum machine_mode);56 enum machine_mode);
52 struct optab_handlers handlers[NUM_MACHINE_MODES];57 struct optab_handlers handlers[NUM_MACHINE_MODES];
58 struct widening_optab_handlers *widening;
53};59};
54typedef struct optab_d * optab;60typedef struct optab_d * optab;
5561
@@ -799,6 +805,15 @@
799extern void emit_unop_insn (int, rtx, rtx, enum rtx_code);805extern void emit_unop_insn (int, rtx, rtx, enum rtx_code);
800extern bool maybe_emit_unop_insn (int, rtx, rtx, enum rtx_code);806extern bool maybe_emit_unop_insn (int, rtx, rtx, enum rtx_code);
801807
808/* Find a widening optab even if it doesn't widen as much as we want. */
809#define find_widening_optab_handler(A,B,C,D) \
810 find_widening_optab_handler_and_mode (A, B, C, D, NULL)
811extern enum insn_code find_widening_optab_handler_and_mode (optab,
812 enum machine_mode,
813 enum machine_mode,
814 int,
815 enum machine_mode *);
816
802/* An extra flag to control optab_for_tree_code's behavior. This is needed to817/* An extra flag to control optab_for_tree_code's behavior. This is needed to
803 distinguish between machines with a vector shift that takes a scalar for the818 distinguish between machines with a vector shift that takes a scalar for the
804 shift amount vs. machines that take a vector for the shift amount. */819 shift amount vs. machines that take a vector for the shift amount. */
@@ -874,6 +889,23 @@
874 + (int) CODE_FOR_nothing);889 + (int) CODE_FOR_nothing);
875}890}
876891
892/* Like optab_handler, but for widening_operations that have a TO_MODE and
893 a FROM_MODE. */
894
895static inline enum insn_code
896widening_optab_handler (optab op, enum machine_mode to_mode,
897 enum machine_mode from_mode)
898{
899 if (to_mode == from_mode || from_mode == VOIDmode)
900 return optab_handler (op, to_mode);
901
902 if (op->widening)
903 return (enum insn_code) (op->widening->handlers[(int) to_mode][(int) from_mode].insn_code
904 + (int) CODE_FOR_nothing);
905
906 return CODE_FOR_nothing;
907}
908
877/* Record that insn CODE should be used to implement mode MODE of OP. */909/* Record that insn CODE should be used to implement mode MODE of OP. */
878910
879static inline void911static inline void
@@ -882,6 +914,26 @@
882 op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing;914 op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing;
883}915}
884916
917/* Like set_optab_handler, but for widening operations that have a TO_MODE
918 and a FROM_MODE. */
919
920static inline void
921set_widening_optab_handler (optab op, enum machine_mode to_mode,
922 enum machine_mode from_mode, enum insn_code code)
923{
924 if (to_mode == from_mode)
925 set_optab_handler (op, to_mode, code);
926 else
927 {
928 if (op->widening == NULL)
929 op->widening = (struct widening_optab_handlers *)
930 xcalloc (1, sizeof (struct widening_optab_handlers));
931
932 op->widening->handlers[(int) to_mode][(int) from_mode].insn_code
933 = (int) code - (int) CODE_FOR_nothing;
934 }
935}
936
885/* Return the insn used to perform conversion OP from mode FROM_MODE937/* Return the insn used to perform conversion OP from mode FROM_MODE
886 to mode TO_MODE; return CODE_FOR_nothing if the target does not have938 to mode TO_MODE; return CODE_FOR_nothing if the target does not have
887 such an insn. */939 such an insn. */
888940
=== added file 'gcc/testsuite/gcc.target/arm/no-wmla-1.c'
--- gcc/testsuite/gcc.target/arm/no-wmla-1.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/no-wmla-1.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,11 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4int
5foo (int a, short b, short c)
6{
7 int bc = b * c;
8 return a + (short)bc;
9}
10
11/* { dg-final { scan-assembler "mul" } } */
012
=== added file 'gcc/testsuite/gcc.target/arm/wmul-10.c'
--- gcc/testsuite/gcc.target/arm/wmul-10.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-10.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4unsigned long long
5foo (unsigned short a, unsigned short *b, unsigned short *c)
6{
7 return (unsigned)a + (unsigned long long)*b * (unsigned long long)*c;
8}
9
10/* { dg-final { scan-assembler "umlal" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-11.c'
--- gcc/testsuite/gcc.target/arm/wmul-11.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-11.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4long long
5foo (int *b)
6{
7 return 10 * (long long)*b;
8}
9
10/* { dg-final { scan-assembler "smull" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-12.c'
--- gcc/testsuite/gcc.target/arm/wmul-12.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-12.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,11 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4long long
5foo (int *b, int *c)
6{
7 int tmp = *b * *c;
8 return 10 + (long long)tmp;
9}
10
11/* { dg-final { scan-assembler "smlal" } } */
012
=== added file 'gcc/testsuite/gcc.target/arm/wmul-13.c'
--- gcc/testsuite/gcc.target/arm/wmul-13.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-13.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4long long
5foo (int *a, int *b)
6{
7 return *a + (long long)*b * 10;
8}
9
10/* { dg-final { scan-assembler "smlal" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-5.c'
--- gcc/testsuite/gcc.target/arm/wmul-5.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-5.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4long long
5foo (long long a, char *b, char *c)
6{
7 return a + *b * *c;
8}
9
10/* { dg-final { scan-assembler "umlal" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-6.c'
--- gcc/testsuite/gcc.target/arm/wmul-6.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-6.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4long long
5foo (long long a, unsigned char *b, signed char *c)
6{
7 return a + (long long)*b * (long long)*c;
8}
9
10/* { dg-final { scan-assembler "smlal" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-7.c'
--- gcc/testsuite/gcc.target/arm/wmul-7.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-7.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4unsigned long long
5foo (unsigned long long a, unsigned char *b, unsigned short *c)
6{
7 return a + *b * *c;
8}
9
10/* { dg-final { scan-assembler "umlal" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-8.c'
--- gcc/testsuite/gcc.target/arm/wmul-8.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-8.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4long long
5foo (long long a, int *b, int *c)
6{
7 return a + *b * *c;
8}
9
10/* { dg-final { scan-assembler "smlal" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-9.c'
--- gcc/testsuite/gcc.target/arm/wmul-9.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-9.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,10 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4long long
5foo (long long a, short *b, char *c)
6{
7 return a + *b * *c;
8}
9
10/* { dg-final { scan-assembler "smlalbb" } } */
011
=== added file 'gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c'
--- gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,17 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4struct bf
5{
6 int a : 3;
7 int b : 15;
8 int c : 3;
9};
10
11long long
12foo (long long a, struct bf b, struct bf c)
13{
14 return a + b.b * c.b;
15}
16
17/* { dg-final { scan-assembler "smlalbb" } } */
018
=== added file 'gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c'
--- gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c 1970-01-01 00:00:00 +0000
+++ gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c 2011-07-27 14:18:25 +0000
@@ -0,0 +1,17 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -march=armv7-a" } */
3
4struct bf
5{
6 int a : 3;
7 unsigned int b : 15;
8 int c : 3;
9};
10
11long long
12foo (long long a, struct bf b, struct bf c)
13{
14 return a + b.b * c.c;
15}
16
17/* { dg-final { scan-assembler "smlalbb" } } */
018
=== modified file 'gcc/tree-cfg.c'
--- gcc/tree-cfg.c 2011-07-01 09:19:21 +0000
+++ gcc/tree-cfg.c 2011-07-27 14:18:25 +0000
@@ -3574,7 +3574,7 @@
3574 case WIDEN_MULT_EXPR:3574 case WIDEN_MULT_EXPR:
3575 if (TREE_CODE (lhs_type) != INTEGER_TYPE)3575 if (TREE_CODE (lhs_type) != INTEGER_TYPE)
3576 return true;3576 return true;
3577 return ((2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type))3577 return ((2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type))
3578 || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)));3578 || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)));
35793579
3580 case WIDEN_SUM_EXPR:3580 case WIDEN_SUM_EXPR:
@@ -3667,7 +3667,7 @@
3667 && !FIXED_POINT_TYPE_P (rhs1_type))3667 && !FIXED_POINT_TYPE_P (rhs1_type))
3668 || !useless_type_conversion_p (rhs1_type, rhs2_type)3668 || !useless_type_conversion_p (rhs1_type, rhs2_type)
3669 || !useless_type_conversion_p (lhs_type, rhs3_type)3669 || !useless_type_conversion_p (lhs_type, rhs3_type)
3670 || 2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type)3670 || 2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)
3671 || TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))3671 || TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))
3672 {3672 {
3673 error ("type mismatch in widening multiply-accumulate expression");3673 error ("type mismatch in widening multiply-accumulate expression");
36743674
=== modified file 'gcc/tree-ssa-math-opts.c'
--- gcc/tree-ssa-math-opts.c 2011-03-11 16:36:16 +0000
+++ gcc/tree-ssa-math-opts.c 2011-07-27 14:18:25 +0000
@@ -1266,42 +1266,75 @@
1266 }1266 }
1267};1267};
12681268
1269/* Return true if RHS is a suitable operand for a widening multiplication.1269/* Build a gimple assignment to cast VAL to TARGET. Insert the statement
1270 prior to GSI's current position, and return the fresh SSA name. */
1271
1272static tree
1273build_and_insert_cast (gimple_stmt_iterator *gsi, location_t loc,
1274 tree target, tree val)
1275{
1276 tree result = make_ssa_name (target, NULL);
1277 gimple stmt = gimple_build_assign_with_ops (CONVERT_EXPR, result, val, NULL);
1278 gimple_set_location (stmt, loc);
1279 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1280 return result;
1281}
1282
1283/* Return true if RHS is a suitable operand for a widening multiplication,
1284 assuming a target type of TYPE.
1270 There are two cases:1285 There are two cases:
12711286
1272 - RHS makes some value twice as wide. Store that value in *NEW_RHS_OUT1287 - RHS makes some value at least twice as wide. Store that value
1273 if so, and store its type in *TYPE_OUT.1288 in *NEW_RHS_OUT if so, and store its type in *TYPE_OUT.
12741289
1275 - RHS is an integer constant. Store that value in *NEW_RHS_OUT if so,1290 - RHS is an integer constant. Store that value in *NEW_RHS_OUT if so,
1276 but leave *TYPE_OUT untouched. */1291 but leave *TYPE_OUT untouched. */
12771292
1278static bool1293static bool
1279is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out)1294is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
1295 tree *new_rhs_out)
1280{1296{
1281 gimple stmt;1297 gimple stmt;
1282 tree type, type1, rhs1;1298 tree type1, rhs1;
1283 enum tree_code rhs_code;1299 enum tree_code rhs_code;
12841300
1285 if (TREE_CODE (rhs) == SSA_NAME)1301 if (TREE_CODE (rhs) == SSA_NAME)
1286 {1302 {
1287 type = TREE_TYPE (rhs);
1288 stmt = SSA_NAME_DEF_STMT (rhs);1303 stmt = SSA_NAME_DEF_STMT (rhs);
1289 if (!is_gimple_assign (stmt))1304 if (!is_gimple_assign (stmt))
1290 return false;1305 {
12911306 rhs1 = NULL;
1292 rhs_code = gimple_assign_rhs_code (stmt);1307 type1 = TREE_TYPE (rhs);
1293 if (TREE_CODE (type) == INTEGER_TYPE1308 }
1294 ? !CONVERT_EXPR_CODE_P (rhs_code)1309 else
1295 : rhs_code != FIXED_CONVERT_EXPR)1310 {
1296 return false;1311 rhs1 = gimple_assign_rhs1 (stmt);
12971312 type1 = TREE_TYPE (rhs1);
1298 rhs1 = gimple_assign_rhs1 (stmt);1313 }
1299 type1 = TREE_TYPE (rhs1);1314
1315 if (rhs1 && TREE_CODE (rhs1) == INTEGER_CST)
1316 {
1317 *new_rhs_out = rhs1;
1318 *type_out = NULL;
1319 return true;
1320 }
1321
1300 if (TREE_CODE (type1) != TREE_CODE (type)1322 if (TREE_CODE (type1) != TREE_CODE (type)
1301 || TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type))1323 || TYPE_PRECISION (type1) * 2 > TYPE_PRECISION (type))
1302 return false;1324 return false;
13031325
1304 *new_rhs_out = rhs1;1326 if (rhs1)
1327 {
1328 rhs_code = gimple_assign_rhs_code (stmt);
1329 if (TREE_CODE (type) == INTEGER_TYPE
1330 ? !CONVERT_EXPR_CODE_P (rhs_code)
1331 : rhs_code != FIXED_CONVERT_EXPR)
1332 *new_rhs_out = rhs;
1333 else
1334 *new_rhs_out = rhs1;
1335 }
1336 else
1337 *new_rhs_out = rhs;
1305 *type_out = type1;1338 *type_out = type1;
1306 return true;1339 return true;
1307 }1340 }
@@ -1316,28 +1349,27 @@
1316 return false;1349 return false;
1317}1350}
13181351
1319/* Return true if STMT performs a widening multiplication. If so,1352/* Return true if STMT performs a widening multiplication, assuming the
1320 store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT1353 output type is TYPE. If so, store the unwidened types of the operands
1321 respectively. Also fill *RHS1_OUT and *RHS2_OUT such that converting1354 in *TYPE1_OUT and *TYPE2_OUT respectively. Also fill *RHS1_OUT and
1322 those operands to types *TYPE1_OUT and *TYPE2_OUT would give the1355 *RHS2_OUT such that converting those operands to types *TYPE1_OUT
1323 operands of the multiplication. */1356 and *TYPE2_OUT would give the operands of the multiplication. */
13241357
1325static bool1358static bool
1326is_widening_mult_p (gimple stmt,1359is_widening_mult_p (tree type, gimple stmt,
1327 tree *type1_out, tree *rhs1_out,1360 tree *type1_out, tree *rhs1_out,
1328 tree *type2_out, tree *rhs2_out)1361 tree *type2_out, tree *rhs2_out)
1329{1362{
1330 tree type;
1331
1332 type = TREE_TYPE (gimple_assign_lhs (stmt));
1333 if (TREE_CODE (type) != INTEGER_TYPE1363 if (TREE_CODE (type) != INTEGER_TYPE
1334 && TREE_CODE (type) != FIXED_POINT_TYPE)1364 && TREE_CODE (type) != FIXED_POINT_TYPE)
1335 return false;1365 return false;
13361366
1337 if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out))1367 if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out,
1368 rhs1_out))
1338 return false;1369 return false;
13391370
1340 if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out))1371 if (!is_widening_mult_rhs_p (type, gimple_assign_rhs2 (stmt), type2_out,
1372 rhs2_out))
1341 return false;1373 return false;
13421374
1343 if (*type1_out == NULL)1375 if (*type1_out == NULL)
@@ -1354,6 +1386,18 @@
1354 *type2_out = *type1_out;1386 *type2_out = *type1_out;
1355 }1387 }
13561388
1389 /* Ensure that the larger of the two operands comes first. */
1390 if (TYPE_PRECISION (*type1_out) < TYPE_PRECISION (*type2_out))
1391 {
1392 tree tmp;
1393 tmp = *type1_out;
1394 *type1_out = *type2_out;
1395 *type2_out = tmp;
1396 tmp = *rhs1_out;
1397 *rhs1_out = *rhs2_out;
1398 *rhs2_out = tmp;
1399 }
1400
1357 return true;1401 return true;
1358}1402}
13591403
@@ -1362,31 +1406,100 @@
1362 value is true iff we converted the statement. */1406 value is true iff we converted the statement. */
13631407
1364static bool1408static bool
1365convert_mult_to_widen (gimple stmt)1409convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
1366{1410{
1367 tree lhs, rhs1, rhs2, type, type1, type2;1411 tree lhs, rhs1, rhs2, type, type1, type2, tmp = NULL;
1368 enum insn_code handler;1412 enum insn_code handler;
1413 enum machine_mode to_mode, from_mode, actual_mode;
1414 optab op;
1415 int actual_precision;
1416 location_t loc = gimple_location (stmt);
1417 bool from_unsigned1, from_unsigned2;
13691418
1370 lhs = gimple_assign_lhs (stmt);1419 lhs = gimple_assign_lhs (stmt);
1371 type = TREE_TYPE (lhs);1420 type = TREE_TYPE (lhs);
1372 if (TREE_CODE (type) != INTEGER_TYPE)1421 if (TREE_CODE (type) != INTEGER_TYPE)
1373 return false;1422 return false;
13741423
1375 if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))1424 if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2))
1376 return false;1425 return false;
13771426
1378 if (TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2))1427 to_mode = TYPE_MODE (type);
1379 handler = optab_handler (umul_widen_optab, TYPE_MODE (type));1428 from_mode = TYPE_MODE (type1);
1380 else if (!TYPE_UNSIGNED (type1) && !TYPE_UNSIGNED (type2))1429 from_unsigned1 = TYPE_UNSIGNED (type1);
1381 handler = optab_handler (smul_widen_optab, TYPE_MODE (type));1430 from_unsigned2 = TYPE_UNSIGNED (type2);
1431
1432 if (from_unsigned1 && from_unsigned2)
1433 op = umul_widen_optab;
1434 else if (!from_unsigned1 && !from_unsigned2)
1435 op = smul_widen_optab;
1382 else1436 else
1383 handler = optab_handler (usmul_widen_optab, TYPE_MODE (type));1437 op = usmul_widen_optab;
1438
1439 handler = find_widening_optab_handler_and_mode (op, to_mode, from_mode,
1440 0, &actual_mode);
13841441
1385 if (handler == CODE_FOR_nothing)1442 if (handler == CODE_FOR_nothing)
1386 return false;1443 {
13871444 if (op != smul_widen_optab)
1388 gimple_assign_set_rhs1 (stmt, fold_convert (type1, rhs1));1445 {
1389 gimple_assign_set_rhs2 (stmt, fold_convert (type2, rhs2));1446 /* We can use a signed multiply with unsigned types as long as
1447 there is a wider mode to use, or it is the smaller of the two
1448 types that is unsigned. Note that type1 >= type2, always. */
1449 if ((TYPE_UNSIGNED (type1)
1450 && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode))
1451 || (TYPE_UNSIGNED (type2)
1452 && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
1453 {
1454 from_mode = GET_MODE_WIDER_MODE (from_mode);
1455 if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
1456 return false;
1457 }
1458
1459 op = smul_widen_optab;
1460 handler = find_widening_optab_handler_and_mode (op, to_mode,
1461 from_mode, 0,
1462 &actual_mode);
1463
1464 if (handler == CODE_FOR_nothing)
1465 return false;
1466
1467 from_unsigned1 = from_unsigned2 = false;
1468 }
1469 else
1470 return false;
1471 }
1472
1473 /* Ensure that the inputs to the handler are in the correct precison
1474 for the opcode. This will be the full mode size. */
1475 actual_precision = GET_MODE_PRECISION (actual_mode);
1476 if (actual_precision != TYPE_PRECISION (type1)
1477 || from_unsigned1 != TYPE_UNSIGNED (type1))
1478 {
1479 tmp = create_tmp_var (build_nonstandard_integer_type
1480 (actual_precision, from_unsigned1),
1481 NULL);
1482 rhs1 = build_and_insert_cast (gsi, loc, tmp, rhs1);
1483 }
1484 if (actual_precision != TYPE_PRECISION (type2)
1485 || from_unsigned2 != TYPE_UNSIGNED (type2))
1486 {
1487 /* Reuse the same type info, if possible. */
1488 if (!tmp || from_unsigned1 != from_unsigned2)
1489 tmp = create_tmp_var (build_nonstandard_integer_type
1490 (actual_precision, from_unsigned2),
1491 NULL);
1492 rhs2 = build_and_insert_cast (gsi, loc, tmp, rhs2);
1493 }
1494
1495 /* Handle constants. */
1496 if (TREE_CODE (rhs1) == INTEGER_CST)
1497 rhs1 = fold_convert (type1, rhs1);
1498 if (TREE_CODE (rhs2) == INTEGER_CST)
1499 rhs2 = fold_convert (type2, rhs2);
1500
1501 gimple_assign_set_rhs1 (stmt, rhs1);
1502 gimple_assign_set_rhs2 (stmt, rhs2);
1390 gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR);1503 gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR);
1391 update_stmt (stmt);1504 update_stmt (stmt);
1392 return true;1505 return true;
@@ -1403,11 +1516,17 @@
1403 enum tree_code code)1516 enum tree_code code)
1404{1517{
1405 gimple rhs1_stmt = NULL, rhs2_stmt = NULL;1518 gimple rhs1_stmt = NULL, rhs2_stmt = NULL;
1406 tree type, type1, type2;1519 gimple conv1_stmt = NULL, conv2_stmt = NULL, conv_stmt;
1520 tree type, type1, type2, optype, tmp = NULL;
1407 tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs;1521 tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs;
1408 enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK;1522 enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK;
1409 optab this_optab;1523 optab this_optab;
1410 enum tree_code wmult_code;1524 enum tree_code wmult_code;
1525 enum insn_code handler;
1526 enum machine_mode to_mode, from_mode, actual_mode;
1527 location_t loc = gimple_location (stmt);
1528 int actual_precision;
1529 bool from_unsigned1, from_unsigned2;
14111530
1412 lhs = gimple_assign_lhs (stmt);1531 lhs = gimple_assign_lhs (stmt);
1413 type = TREE_TYPE (lhs);1532 type = TREE_TYPE (lhs);
@@ -1429,8 +1548,6 @@
1429 if (is_gimple_assign (rhs1_stmt))1548 if (is_gimple_assign (rhs1_stmt))
1430 rhs1_code = gimple_assign_rhs_code (rhs1_stmt);1549 rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
1431 }1550 }
1432 else
1433 return false;
14341551
1435 if (TREE_CODE (rhs2) == SSA_NAME)1552 if (TREE_CODE (rhs2) == SSA_NAME)
1436 {1553 {
@@ -1438,57 +1555,160 @@
1438 if (is_gimple_assign (rhs2_stmt))1555 if (is_gimple_assign (rhs2_stmt))
1439 rhs2_code = gimple_assign_rhs_code (rhs2_stmt);1556 rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
1440 }1557 }
1441 else1558
1442 return false;1559 /* Allow for one conversion statement between the multiply
14431560 and addition/subtraction statement. If there are more than
1444 if (code == PLUS_EXPR && rhs1_code == MULT_EXPR)1561 one conversions then we assume they would invalidate this
1445 {1562 transformation. If that's not the case then they should have
1446 if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,1563 been folded before now. */
1447 &type2, &mult_rhs2))1564 if (CONVERT_EXPR_CODE_P (rhs1_code))
1448 return false;1565 {
1449 add_rhs = rhs2;1566 conv1_stmt = rhs1_stmt;
1450 }1567 rhs1 = gimple_assign_rhs1 (rhs1_stmt);
1451 else if (rhs2_code == MULT_EXPR)1568 if (TREE_CODE (rhs1) == SSA_NAME)
1452 {1569 {
1453 if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,1570 rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
1454 &type2, &mult_rhs2))1571 if (is_gimple_assign (rhs1_stmt))
1455 return false;1572 rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
1456 add_rhs = rhs1;1573 }
1457 }1574 else
1458 else if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR)1575 return false;
1459 {1576 }
1460 mult_rhs1 = gimple_assign_rhs1 (rhs1_stmt);1577 if (CONVERT_EXPR_CODE_P (rhs2_code))
1461 mult_rhs2 = gimple_assign_rhs2 (rhs1_stmt);1578 {
1462 type1 = TREE_TYPE (mult_rhs1);1579 conv2_stmt = rhs2_stmt;
1463 type2 = TREE_TYPE (mult_rhs2);1580 rhs2 = gimple_assign_rhs1 (rhs2_stmt);
1464 add_rhs = rhs2;1581 if (TREE_CODE (rhs2) == SSA_NAME)
1465 }1582 {
1466 else if (rhs2_code == WIDEN_MULT_EXPR)1583 rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
1467 {1584 if (is_gimple_assign (rhs2_stmt))
1468 mult_rhs1 = gimple_assign_rhs1 (rhs2_stmt);1585 rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
1469 mult_rhs2 = gimple_assign_rhs2 (rhs2_stmt);1586 }
1470 type1 = TREE_TYPE (mult_rhs1);1587 else
1471 type2 = TREE_TYPE (mult_rhs2);1588 return false;
1472 add_rhs = rhs1;1589 }
1473 }1590
1474 else1591 /* If code is WIDEN_MULT_EXPR then it would seem unnecessary to call
1475 return false;1592 is_widening_mult_p, but we still need the rhs returns.
14761593
1477 if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2))1594 It might also appear that it would be sufficient to use the existing
1478 return false;1595 operands of the widening multiply, but that would limit the choice of
1596 multiply-and-accumulate instructions. */
1597 if (code == PLUS_EXPR
1598 && (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
1599 {
1600 if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1,
1601 &type2, &mult_rhs2))
1602 return false;
1603 add_rhs = rhs2;
1604 conv_stmt = conv1_stmt;
1605 }
1606 else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
1607 {
1608 if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1,
1609 &type2, &mult_rhs2))
1610 return false;
1611 add_rhs = rhs1;
1612 conv_stmt = conv2_stmt;
1613 }
1614 else
1615 return false;
1616
1617 to_mode = TYPE_MODE (type);
1618 from_mode = TYPE_MODE (type1);
1619 from_unsigned1 = TYPE_UNSIGNED (type1);
1620 from_unsigned2 = TYPE_UNSIGNED (type2);
1621
1622 /* There's no such thing as a mixed sign madd yet, so use a wider mode. */
1623 if (from_unsigned1 != from_unsigned2)
1624 {
1625 /* We can use a signed multiply with unsigned types as long as
1626 there is a wider mode to use, or it is the smaller of the two
1627 types that is unsigned. Note that type1 >= type2, always. */
1628 if ((from_unsigned1
1629 && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode))
1630 || (from_unsigned2
1631 && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
1632 {
1633 from_mode = GET_MODE_WIDER_MODE (from_mode);
1634 if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode))
1635 return false;
1636 }
1637
1638 from_unsigned1 = from_unsigned2 = false;
1639 }
1640
1641 /* If there was a conversion between the multiply and addition
1642 then we need to make sure it fits a multiply-and-accumulate.
1643 The should be a single mode change which does not change the
1644 value. */
1645 if (conv_stmt)
1646 {
1647 /* We use the original, unmodified data types for this. */
1648 tree from_type = TREE_TYPE (gimple_assign_rhs1 (conv_stmt));
1649 tree to_type = TREE_TYPE (gimple_assign_lhs (conv_stmt));
1650 int data_size = TYPE_PRECISION (type1) + TYPE_PRECISION (type2);
1651 bool is_unsigned = TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2);
1652
1653 if (TYPE_PRECISION (from_type) > TYPE_PRECISION (to_type))
1654 {
1655 /* Conversion is a truncate. */
1656 if (TYPE_PRECISION (to_type) < data_size)
1657 return false;
1658 }
1659 else if (TYPE_PRECISION (from_type) < TYPE_PRECISION (to_type))
1660 {
1661 /* Conversion is an extend. Check it's the right sort. */
1662 if (TYPE_UNSIGNED (from_type) != is_unsigned
1663 && !(is_unsigned && TYPE_PRECISION (from_type) > data_size))
1664 return false;
1665 }
1666 /* else convert is a no-op for our purposes. */
1667 }
14791668
1480 /* Verify that the machine can perform a widening multiply1669 /* Verify that the machine can perform a widening multiply
1481 accumulate in this mode/signedness combination, otherwise1670 accumulate in this mode/signedness combination, otherwise
1482 this transformation is likely to pessimize code. */1671 this transformation is likely to pessimize code. */
1483 this_optab = optab_for_tree_code (wmult_code, type1, optab_default);1672 optype = build_nonstandard_integer_type (from_mode, from_unsigned1);
1484 if (optab_handler (this_optab, TYPE_MODE (type)) == CODE_FOR_nothing)1673 this_optab = optab_for_tree_code (wmult_code, optype, optab_default);
1674 handler = find_widening_optab_handler_and_mode (this_optab, to_mode,
1675 from_mode, 0, &actual_mode);
1676
1677 if (handler == CODE_FOR_nothing)
1485 return false;1678 return false;
14861679
1487 /* ??? May need some type verification here? */1680 /* Ensure that the inputs to the handler are in the correct precison
14881681 for the opcode. This will be the full mode size. */
1489 gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code,1682 actual_precision = GET_MODE_PRECISION (actual_mode);
1490 fold_convert (type1, mult_rhs1),1683 if (actual_precision != TYPE_PRECISION (type1)
1491 fold_convert (type2, mult_rhs2),1684 || from_unsigned1 != TYPE_UNSIGNED (type1))
1685 {
1686 tmp = create_tmp_var (build_nonstandard_integer_type
1687 (actual_precision, from_unsigned1),
1688 NULL);
1689 mult_rhs1 = build_and_insert_cast (gsi, loc, tmp, mult_rhs1);
1690 }
1691 if (actual_precision != TYPE_PRECISION (type2)
1692 || from_unsigned2 != TYPE_UNSIGNED (type2))
1693 {
1694 if (!tmp || from_unsigned1 != from_unsigned2)
1695 tmp = create_tmp_var (build_nonstandard_integer_type
1696 (actual_precision, from_unsigned2),
1697 NULL);
1698 mult_rhs2 = build_and_insert_cast (gsi, loc, tmp, mult_rhs2);
1699 }
1700
1701 if (TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (add_rhs)))
1702 add_rhs = build_and_insert_cast (gsi, loc, create_tmp_var (type, NULL),
1703 add_rhs);
1704
1705 /* Handle constants. */
1706 if (TREE_CODE (mult_rhs1) == INTEGER_CST)
1707 rhs1 = fold_convert (type1, mult_rhs1);
1708 if (TREE_CODE (mult_rhs2) == INTEGER_CST)
1709 rhs2 = fold_convert (type2, mult_rhs2);
1710
1711 gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs1, mult_rhs2,
1492 add_rhs);1712 add_rhs);
1493 update_stmt (gsi_stmt (*gsi));1713 update_stmt (gsi_stmt (*gsi));
1494 return true;1714 return true;
@@ -1696,7 +1916,7 @@
1696 switch (code)1916 switch (code)
1697 {1917 {
1698 case MULT_EXPR:1918 case MULT_EXPR:
1699 if (!convert_mult_to_widen (stmt)1919 if (!convert_mult_to_widen (stmt, &gsi)
1700 && convert_mult_to_fma (stmt,1920 && convert_mult_to_fma (stmt,
1701 gimple_assign_rhs1 (stmt),1921 gimple_assign_rhs1 (stmt),
1702 gimple_assign_rhs2 (stmt)))1922 gimple_assign_rhs2 (stmt)))

Subscribers

People subscribed via source and target branches