public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch, tree-ssa] PR54295 Incorrect value extension in widening multiply-accumulate
@ 2012-08-17 14:04 Richard Earnshaw
  2012-08-17 14:22 ` Andrew Stubbs
  0 siblings, 1 reply; 15+ messages in thread
From: Richard Earnshaw @ 2012-08-17 14:04 UTC (permalink / raw)
  To: gcc-patches, Richard Sandiford, Andrew Stubbs

[-- Attachment #1: Type: text/plain, Size: 2073 bytes --]

PR54295 shows that widening multiply-accumulate operations can end up
with incorrect code.  The path to the failure is as follows

1) Compiler detects a widening multiply operation and generates the
correct widening-multiply operation.  This involves stripping off the
widening cast to leave the underlying operands.

That is

	X = (c1) a * (c2) b
=>
	X = a w* b

the type of w is picked based on the types of a and b; if both are
signed a signed multiply-extend operation is used; if both are unsigned
an unsigned multiply-extend is used.  If they differ a signed/unsigned
multiply is used, if it exists.  If either a or b is a positive constant
it is coerced, if possible, into the type of the other operand.

2) The compiler then notices that the result, X is used in an addition
operation

	Y = X + d

As X is a widening multiply, the compiler then looks inside it to try
and generate a widening-multiply-accumulate operation.  However, it
passes the rewritten expression (X = a w* b) to is_widening_mult_p and
that routine does not correctly check what type of multiply is being
done: the code blindly tries to strip of an conversion operations.

The failure happens when a is also the result of a cast operation, for
example, being cast from an unsigned to an int.  The compiler then
re-formulates a signed multiply-extend into an unsigned multiply-extend.
 That is, if
	a = (int) e	// typeof(e) == unsigned

Then instead of
	Y = WIDEN_MULT_PLUS (a, b, d)
we end up with
	Y = WIDEN_MULT_PLUS (e, b, d)

The fix is to make is_widening_mult_p note that it has been called with
a WIDEN_MULT_EXPR and rather than decompose the operands again, to
simply extract the existing operands, which have already been formulated
correctly for a widening multiply operation.

	PR tree-ssa/54295
	* tree-ssa-math-opts.c (is_widening_mult_p): Short-circuit when
	the stmt is already a widening multiply.

Testsuite

	PR tree-ssa/54295
	* gcc.c-torture/execute/20120817-1.c: New test.

OK to commit once testing has completed?


[-- Attachment #2: wmult.patch --]
[-- Type: text/plain, Size: 1315 bytes --]

--- tree-ssa-math-opts.c	(revision 190462)
+++ tree-ssa-math-opts.c	(local)
@@ -2039,6 +2039,25 @@ is_widening_mult_p (gimple stmt,
       && TREE_CODE (type) != FIXED_POINT_TYPE)
     return false;
 
+  /* If we already have a widening multiply expression, simply extract the
+     operands.  */
+  if (gimple_assign_rhs_code (stmt) == WIDEN_MULT_EXPR)
+    {
+      *rhs1_out = gimple_assign_rhs1 (stmt);
+      *rhs2_out = gimple_assign_rhs2 (stmt);
+      if (TREE_CODE (*rhs1_out) == INTEGER_CST)
+	*type1_out = TREE_TYPE (*rhs2_out);
+      else
+	*type1_out = TREE_TYPE (*rhs1_out);
+
+      if (TREE_CODE (*rhs2_out) == INTEGER_CST)
+	*type2_out = TREE_TYPE (*rhs1_out);
+      else
+	*type2_out = TREE_TYPE (*rhs2_out);
+
+      return true;
+    }
+
   if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out,
 			       rhs1_out))
     return false;
Index: 20120817-1.c
===================================================================
--- 20120817-1.c	(revision 0)
+++ 20120817-1.c	(revision 0)
@@ -0,0 +1,14 @@
+typedef unsigned long long u64;
+unsigned long foo = 0;
+u64 f() __attribute__((noinline));
+
+u64 f() {
+  return ((u64)40) + ((u64) 24) * (int)(foo - 1);
+}
+
+int main ()
+{
+  if (f () != 16)
+    abort ();
+  exit (0);
+}

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2012-09-07  9:20 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-17 14:04 [patch, tree-ssa] PR54295 Incorrect value extension in widening multiply-accumulate Richard Earnshaw
2012-08-17 14:22 ` Andrew Stubbs
2012-08-17 14:31   ` Richard Earnshaw
2012-08-17 14:40     ` Andrew Stubbs
2012-08-17 14:48       ` Richard Earnshaw
2012-08-17 15:06         ` Andrew Stubbs
2012-08-17 15:20           ` Richard Earnshaw
2012-08-17 17:05             ` Richard Earnshaw
2012-08-17 19:21               ` Andrew Stubbs
2012-08-20 11:36               ` Richard Guenther
2012-09-07  8:36                 ` Richard Earnshaw
2012-09-07  9:20                   ` Richard Guenther
2012-08-20 14:02               ` Tobias Burnus
2012-08-20 14:14                 ` Richard Earnshaw
2012-08-17 18:57             ` Andrew Stubbs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).