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: 1272 lines (+740/-140) (has conflicts)
20 files modified
ChangeLog.linaro (+129/-0)
gcc/config/arm/arm.md (+1/-1)
gcc/expr.c (+14/-15)
gcc/genopinit.c (+24/-20)
gcc/optabs.c (+78/-13)
gcc/optabs.h (+52/-0)
gcc/testsuite/gcc.target/arm/no-wmla-1.c (+11/-0)
gcc/testsuite/gcc.target/arm/wmul-10.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-11.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-12.c (+11/-0)
gcc/testsuite/gcc.target/arm/wmul-13.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-5.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-6.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-7.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-8.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-9.c (+10/-0)
gcc/testsuite/gcc.target/arm/wmul-bitfield-1.c (+17/-0)
gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c (+17/-0)
gcc/tree-cfg.c (+2/-2)
gcc/tree-ssa-math-opts.c (+304/-89)
Text conflict in ChangeLog.linaro
To merge this branch: bzr merge lp:~ams-codesourcery/gcc-linaro/widening-multiplies-4.6
Reviewer Review Type Date Requested Status
Michael Hope Pending
Review via email: mp+70577@code.launchpad.net

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

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

Description of the change

Widening multiplies optimizations.

The first commit is not approved yet, but the rest are reviewed upstream, and read to commit.

http://<email address hidden>/msg08720.html

UPDATE: Now with an extra bug-fix.

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

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

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

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

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

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

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

cbuild had trouble building this on <proposals.Build instance at 0x2b85680>.

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

The test suite results were not checked.

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

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

cbuild had trouble building this on <proposals.Build instance at 0x2141ea8>.

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

The test suite results were not checked.

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

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

cbuild had trouble building this on <proposals.Build instance at 0x7fe8f501a050>.

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

The test suite results were not checked.

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

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

cbuild had trouble building this on <proposals.Build instance at 0x7fe8f5028ab8>.

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

The test suite results were not checked.

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

review: Needs Fixing
Revision history for this message
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal

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

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

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

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

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

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

cbuild had trouble building this on <proposals.Build instance at 0x3fec710>.

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

The test suite results were not checked.

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

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

cbuild had trouble building this on <proposals.Build instance at 0x2b08c68>.

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

The test suite results were not checked.

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

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

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

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

The test suite results were not checked.

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

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

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

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

The test suite results were not checked.

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

review: Needs Fixing
Revision history for this message
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal

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

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

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

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

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

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

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

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

The test suite results were not checked.

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

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

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

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

The test suite results were not checked.

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

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

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

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

The test suite results were not checked.

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

review: Needs Fixing
Revision history for this message
Linaro Toolchain Builder (cbuild) wrote : Posted in a previous version of this proposal

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

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

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

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

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

Revision history for this message
Michael Hope (michaelh1) wrote : Posted in a previous version of this proposal
Download full text (4.0 KiB)

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

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

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

Read more...

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

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

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

The test suite results were not checked.

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

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

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

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

The test suite results were not checked.

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

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

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

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

The test suite results were not checked.

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

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

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

The snapshot is available at:
 http://ex.seabright.co.nz/snapshots/gcc-linaro-4.6+bzr106785~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+bzr106785~ams-codesourcery~widening-multiplies-4.6
cbuild-ancestor: lp:gcc-linaro/4.6+bzr106774
cbuild-state: check

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

cbuild successfully built this on armv7l-natty-cbuild159-ursa3-armv5r2.

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

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

Read more...

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

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

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

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

Read more...

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

cbuild successfully built this on i686-natty-cbuild159-oort6-i686r1.

The build results are available at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106785~ams-codesourcery~widening-multiplies-4.6/logs/i686-natty-cbuild159-oort6-i686r1

-PASS: gfortran.dg/integer_exponentiation_2.f90 -O2 (test for excess errors)
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O2 execution test
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O2 (internal compiler error)
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O2 (test for excess errors)
+UNRESOLVED: gfortran.dg/integer_exponentiation_2.f90 -O2 compilation failed to produce executable
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer (test for excess errors)
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer execution test
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer (internal compiler error)
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer (test for excess errors)
+UNRESOLVED: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer compilation failed to produce executable
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions (test for excess errors)
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions execution test
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions (internal compiler error)
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions (test for excess errors)
+UNRESOLVED: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions compilation failed to produce executable
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-loops (test for excess errors)
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-loops execution test
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-loops (internal compiler error)
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-loops (test for excess errors)
+UNRESOLVED: gfortran.dg/integer_exponentiation_2.f90 -O3 -fomit-frame-pointer -funroll-loops compilation failed to produce executable
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -g (test for excess errors)
-PASS: gfortran.dg/integer_exponentiation_2.f90 -O3 -g execution test
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -g (internal compiler error)
+FAIL: gfortran.dg/integer_exponentiation_2.f90 -O3 -g (test for excess errors)
+UNRESOLVED: gfortran.dg/integer_exponentiation_2.f90 -O3 -g compilation failed to produce executable

The full testsuite results are at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106785~ams-codesourcery~widening-multiplies-4.6/logs/i686-natty-cbuild159-oort6-i686r1/gcc-testsuite.txt

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

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

cbuild successfully built this on x86_64-natty-cbuild159-oort3-x86_64r1.

The build results are available at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106785~ams-codesourcery~widening-multiplies-4.6/logs/x86_64-natty-cbuild159-oort3-x86_64r1

The testsuite results are the same as the branch point lp:gcc-linaro/4.6+bzr106774

The full testsuite results are at:
 http://ex.seabright.co.nz/build/gcc-linaro-4.6+bzr106785~ams-codesourcery~widening-multiplies-4.6/logs/x86_64-natty-cbuild159-oort3-x86_64r1/gcc-testsuite.txt

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

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

Note that the tests pass on a 64 bit host but fail on all 32 bit hosts.

Preview Diff

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

Subscribers

People subscribed via source and target branches