toolchain: gcc: backport fixes for gcc bug 54295
authorJonas Gorski <jogo@openwrt.org>
Mon, 29 Apr 2013 15:40:21 +0000 (15:40 +0000)
committerJonas Gorski <jogo@openwrt.org>
Mon, 29 Apr 2013 15:40:21 +0000 (15:40 +0000)
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>
SVN-Revision: 36486

toolchain/gcc/patches/4.6-linaro/020-gcc_bug_54295.patch [new file with mode: 0644]
toolchain/gcc/patches/4.7-linaro/020-gcc_bug_54295.patch [new file with mode: 0644]
toolchain/gcc/patches/4.7.2/020-gcc_bug_54295.patch [new file with mode: 0644]

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 (file)
index 0000000..5bef9ea
--- /dev/null
@@ -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 (file)
index 0000000..7ceda06
--- /dev/null
@@ -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 (file)
index 0000000..0d51975
--- /dev/null
@@ -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
+           {