Merge lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6 into lp:gcc-linaro/4.6
- widening-multiplies-4.6
- Merge into 4.6
Status: | 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 |
Related bugs: |
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.
Commit message
Description of the change
Widening multiplies optimizations.
The first commit is not approved yet, but the rest are reviewed upstream, and read to commit.
http://<email address hidden>
UPDATE: Now with an extra bug-fix.
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x2b85680>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x2141ea8>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x7fe8f501a050>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x7fe8f5028ab8>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
cbuild has taken a snapshot of this branch at r106782 and queued it for build.
The snapshot is available at:
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x3fec710>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on <proposals.Build instance at 0x2b08c68>.
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on armv7l-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on armv7l-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal | # |
cbuild has taken a snapshot of this branch at r106783 and queued it for build.
The snapshot is available at:
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on x86_64-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on i686-natty-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal | # |
cbuild had trouble building this on armv7l-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: armv7l-
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://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at:
http://
cbuild-snapshot: gcc-linaro-
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check
Michael Hope (michaelh1) wrote : | # |
cbuild successfully built this on armv7l-
The build results are available at:
http://
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
+FAIL: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
-PASS: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
+UNRESOLVED: gcc.c-torture/
-PASS: gcc.dg/pr46499-1.c execution test
-PASS: gcc.dg/pr46499-1.c (test for excess errors)
+UNRESOLVED: gcc.dg/pr46499-1.c compilation failed to produce executable
+FAIL: gcc.dg/pr46499-1.c (test for excess errors)
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PASS: gcc.target/
+PAS...
Michael Hope (michaelh1) wrote : | # |
cbuild had trouble building this on i686-natty-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: i686-natty-
Michael Hope (michaelh1) wrote : | # |
cbuild had trouble building this on x86_64-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
Michael Hope (michaelh1) wrote : | # |
cbuild had trouble building this on x86_64-
See the *failed.txt logs under the build results at:
http://
The test suite results were not checked.
cbuild-checked: x86_64-
Preview Diff
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))) |
cbuild has taken a snapshot of this branch at r106781 and queued it for build.
The snapshot is available at: ex.seabright. co.nz/snapshots /gcc-linaro- 4.6+bzr106781~ ams-codesourcer y~widening- multiplies- 4.6.tar. xdelta3. xz
http://
and will be built on the following builders:
a9-builder armv5-builder i686 x86_64
You can track the build queue at: ex.seabright. co.nz/helpers/ scheduler
http://
cbuild-snapshot: gcc-linaro- 4.6+bzr106781~ ams-codesourcer y~widening- multiplies- 4.6
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check