summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjogo <jogo@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-04-29 15:40:21 +0000
committerjogo <jogo@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-04-29 15:40:21 +0000
commit4492b366c42158e95e50877e624e0bf5b024dbfa (patch)
tree35b5f93a59cbfa513345bb8f3b58bcbaa62da7f0
parent715d08721cee7a944119eedbb0b41dddfb4e4a04 (diff)
toolchain: gcc: backport fixes for gcc bug 54295
Fix "Widening multiply-accumulate operation uses wrong value extension" for 4.7, 4.7-linaro and 4.6-linaro, which backported the broken code to 4.6. Vanilla 4.6 is unaffected. Fixes #13420. Signed-off-by: Jonas Gorski <jogo@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@36486 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--toolchain/gcc/patches/4.6-linaro/020-gcc_bug_54295.patch70
-rw-r--r--toolchain/gcc/patches/4.7-linaro/020-gcc_bug_54295.patch70
-rw-r--r--toolchain/gcc/patches/4.7.2/020-gcc_bug_54295.patch70
3 files changed, 210 insertions, 0 deletions
diff --git a/toolchain/gcc/patches/4.6-linaro/020-gcc_bug_54295.patch b/toolchain/gcc/patches/4.6-linaro/020-gcc_bug_54295.patch
new file mode 100644
index 000000000..5bef9eab0
--- /dev/null
+++ b/toolchain/gcc/patches/4.6-linaro/020-gcc_bug_54295.patch
@@ -0,0 +1,70 @@
+diff -urN a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
+--- a/gcc/tree-ssa-math-opts.c 2012-12-12 18:05:23.000000000 +0100
++++ b/gcc/tree-ssa-math-opts.c 2013-04-29 15:54:00.051998936 +0200
+@@ -1280,6 +1280,47 @@
+ return result;
+ }
+
++/* Return true if stmt is a type conversion operation that can be stripped
++ when used in a widening multiply operation. */
++static bool
++widening_mult_conversion_strippable_p (tree result_type, gimple stmt)
++{
++ enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
++
++ if (TREE_CODE (result_type) == INTEGER_TYPE)
++ {
++ tree op_type;
++ tree inner_op_type;
++
++ if (!CONVERT_EXPR_CODE_P (rhs_code))
++ return false;
++
++ op_type = TREE_TYPE (gimple_assign_lhs (stmt));
++
++ /* If the type of OP has the same precision as the result, then
++ we can strip this conversion. The multiply operation will be
++ selected to create the correct extension as a by-product. */
++ if (TYPE_PRECISION (result_type) == TYPE_PRECISION (op_type))
++ return true;
++
++ /* We can also strip a conversion if it preserves the signed-ness of
++ the operation and doesn't narrow the range. */
++ inner_op_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
++
++ /* If the inner-most type is unsigned, then we can strip any
++ intermediate widening operation. If it's signed, then the
++ intermediate widening operation must also be signed. */
++ if ((TYPE_UNSIGNED (inner_op_type)
++ || TYPE_UNSIGNED (op_type) == TYPE_UNSIGNED (inner_op_type))
++ && TYPE_PRECISION (op_type) > TYPE_PRECISION (inner_op_type))
++ return true;
++
++ return false;
++ }
++
++ return rhs_code == FIXED_CONVERT_EXPR;
++}
++
+ /* Return true if RHS is a suitable operand for a widening multiplication,
+ assuming a target type of TYPE.
+ There are two cases:
+@@ -1296,17 +1337,13 @@
+ {
+ gimple stmt;
+ tree type1, rhs1;
+- enum tree_code rhs_code;
+
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ stmt = SSA_NAME_DEF_STMT (rhs);
+ if (is_gimple_assign (stmt))
+ {
+- rhs_code = gimple_assign_rhs_code (stmt);
+- if (TREE_CODE (type) == INTEGER_TYPE
+- ? !CONVERT_EXPR_CODE_P (rhs_code)
+- : rhs_code != FIXED_CONVERT_EXPR)
++ if (! widening_mult_conversion_strippable_p (type, stmt))
+ rhs1 = rhs;
+ else
+ {
diff --git a/toolchain/gcc/patches/4.7-linaro/020-gcc_bug_54295.patch b/toolchain/gcc/patches/4.7-linaro/020-gcc_bug_54295.patch
new file mode 100644
index 000000000..7ceda06c3
--- /dev/null
+++ b/toolchain/gcc/patches/4.7-linaro/020-gcc_bug_54295.patch
@@ -0,0 +1,70 @@
+diff -urN a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
+--- a/gcc/tree-ssa-math-opts.c 2013-03-11 22:01:34.000000000 +0100
++++ b/gcc/tree-ssa-math-opts.c 2013-04-29 15:55:34.906809377 +0200
+@@ -2007,6 +2007,47 @@
+ }
+ };
+
++/* Return true if stmt is a type conversion operation that can be stripped
++ when used in a widening multiply operation. */
++static bool
++widening_mult_conversion_strippable_p (tree result_type, gimple stmt)
++{
++ enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
++
++ if (TREE_CODE (result_type) == INTEGER_TYPE)
++ {
++ tree op_type;
++ tree inner_op_type;
++
++ if (!CONVERT_EXPR_CODE_P (rhs_code))
++ return false;
++
++ op_type = TREE_TYPE (gimple_assign_lhs (stmt));
++
++ /* If the type of OP has the same precision as the result, then
++ we can strip this conversion. The multiply operation will be
++ selected to create the correct extension as a by-product. */
++ if (TYPE_PRECISION (result_type) == TYPE_PRECISION (op_type))
++ return true;
++
++ /* We can also strip a conversion if it preserves the signed-ness of
++ the operation and doesn't narrow the range. */
++ inner_op_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
++
++ /* If the inner-most type is unsigned, then we can strip any
++ intermediate widening operation. If it's signed, then the
++ intermediate widening operation must also be signed. */
++ if ((TYPE_UNSIGNED (inner_op_type)
++ || TYPE_UNSIGNED (op_type) == TYPE_UNSIGNED (inner_op_type))
++ && TYPE_PRECISION (op_type) > TYPE_PRECISION (inner_op_type))
++ return true;
++
++ return false;
++ }
++
++ return rhs_code == FIXED_CONVERT_EXPR;
++}
++
+ /* Return true if RHS is a suitable operand for a widening multiplication,
+ assuming a target type of TYPE.
+ There are two cases:
+@@ -2023,17 +2064,13 @@
+ {
+ gimple stmt;
+ tree type1, rhs1;
+- enum tree_code rhs_code;
+
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ stmt = SSA_NAME_DEF_STMT (rhs);
+ if (is_gimple_assign (stmt))
+ {
+- rhs_code = gimple_assign_rhs_code (stmt);
+- if (TREE_CODE (type) == INTEGER_TYPE
+- ? !CONVERT_EXPR_CODE_P (rhs_code)
+- : rhs_code != FIXED_CONVERT_EXPR)
++ if (! widening_mult_conversion_strippable_p (type, stmt))
+ rhs1 = rhs;
+ else
+ {
diff --git a/toolchain/gcc/patches/4.7.2/020-gcc_bug_54295.patch b/toolchain/gcc/patches/4.7.2/020-gcc_bug_54295.patch
new file mode 100644
index 000000000..0d519758a
--- /dev/null
+++ b/toolchain/gcc/patches/4.7.2/020-gcc_bug_54295.patch
@@ -0,0 +1,70 @@
+diff -urN a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
+--- a/gcc/tree-ssa-math-opts.c 2011-12-20 22:33:48.000000000 +0100
++++ b/gcc/tree-ssa-math-opts.c 2013-04-29 16:39:54.413585206 +0200
+@@ -1968,6 +1968,47 @@
+ }
+ };
+
++/* Return true if stmt is a type conversion operation that can be stripped
++ when used in a widening multiply operation. */
++static bool
++widening_mult_conversion_strippable_p (tree result_type, gimple stmt)
++{
++ enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
++
++ if (TREE_CODE (result_type) == INTEGER_TYPE)
++ {
++ tree op_type;
++ tree inner_op_type;
++
++ if (!CONVERT_EXPR_CODE_P (rhs_code))
++ return false;
++
++ op_type = TREE_TYPE (gimple_assign_lhs (stmt));
++
++ /* If the type of OP has the same precision as the result, then
++ we can strip this conversion. The multiply operation will be
++ selected to create the correct extension as a by-product. */
++ if (TYPE_PRECISION (result_type) == TYPE_PRECISION (op_type))
++ return true;
++
++ /* We can also strip a conversion if it preserves the signed-ness of
++ the operation and doesn't narrow the range. */
++ inner_op_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
++
++ /* If the inner-most type is unsigned, then we can strip any
++ intermediate widening operation. If it's signed, then the
++ intermediate widening operation must also be signed. */
++ if ((TYPE_UNSIGNED (inner_op_type)
++ || TYPE_UNSIGNED (op_type) == TYPE_UNSIGNED (inner_op_type))
++ && TYPE_PRECISION (op_type) > TYPE_PRECISION (inner_op_type))
++ return true;
++
++ return false;
++ }
++
++ return rhs_code == FIXED_CONVERT_EXPR;
++}
++
+ /* Return true if RHS is a suitable operand for a widening multiplication,
+ assuming a target type of TYPE.
+ There are two cases:
+@@ -1984,17 +2025,13 @@
+ {
+ gimple stmt;
+ tree type1, rhs1;
+- enum tree_code rhs_code;
+
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ stmt = SSA_NAME_DEF_STMT (rhs);
+ if (is_gimple_assign (stmt))
+ {
+- rhs_code = gimple_assign_rhs_code (stmt);
+- if (TREE_CODE (type) == INTEGER_TYPE
+- ? !CONVERT_EXPR_CODE_P (rhs_code)
+- : rhs_code != FIXED_CONVERT_EXPR)
++ if (! widening_mult_conversion_strippable_p (type, stmt))
+ rhs1 = rhs;
+ else
+ {