]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/98640 - fix bogus sign-extension with VN
authorRichard Biener <rguenther@suse.de>
Wed, 13 Jan 2021 08:43:52 +0000 (09:43 +0100)
committerRichard Biener <rguenther@suse.de>
Wed, 3 Mar 2021 09:49:38 +0000 (10:49 +0100)
VN tried to express a sign extension from int to long of
a trucated quantity with a plain conversion but that loses the
truncation.  Since there's no single operand doing truncate plus
sign extend (there was a proposed SEXT_EXPR to do that at some
point mapping to RTL sign_extract) don't bother to appropriately
model this with two ops (which the VN insert machinery doesn't
handle and which is unlikely to CSE fully).

2021-01-13  Richard Biener  <rguenther@suse.de>

PR tree-optimization/98640
* tree-ssa-sccvn.c (visit_nary_op): Do not try to
handle plus or minus from a truncated operand to be
sign-extended.

* gcc.dg/torture/pr98640.c: New testcase.

(cherry picked from commit ffd28c265e6d611983cd27e9332dc799039a3f04)

gcc/testsuite/gcc.dg/torture/pr98640.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr98640.c b/gcc/testsuite/gcc.dg/torture/pr98640.c
new file mode 100644 (file)
index 0000000..b187781
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-require-effective-target stdint_types } */
+
+#include <stdint.h>
+
+uint64_t var_0 = 18128133247277979402ULL;
+int64_t var_14 = 6557021550272328915LL;
+uint64_t var_83 = 10966786425750692026ULL;
+
+void test()
+{
+  var_14 = var_0 + (_Bool)7;
+  var_83 = 1 + (int)var_0; // 1 + 888395530
+}
+
+int main()
+{
+  test();
+  if (var_83 != 888395531)
+    __builtin_abort ();
+  return 0;
+}
index 2c2696ebb2af93475b29c499ac4ac97a4d38260a..a55516b5d3a30c60ea190095965831c62351e9bb 100644 (file)
@@ -4650,7 +4650,7 @@ visit_copy (tree lhs, tree rhs)
    is the same.  */
 
 static tree
-valueized_wider_op (tree wide_type, tree op)
+valueized_wider_op (tree wide_type, tree op, bool allow_truncate)
 {
   if (TREE_CODE (op) == SSA_NAME)
     op = vn_valueize (op);
@@ -4664,7 +4664,7 @@ valueized_wider_op (tree wide_type, tree op)
     return tem;
 
   /* Or the op is truncated from some existing value.  */
-  if (TREE_CODE (op) == SSA_NAME)
+  if (allow_truncate && TREE_CODE (op) == SSA_NAME)
     {
       gimple *def = SSA_NAME_DEF_STMT (op);
       if (is_gimple_assign (def)
@@ -4729,12 +4729,15 @@ visit_nary_op (tree lhs, gassign *stmt)
                  || gimple_assign_rhs_code (def) == MULT_EXPR))
            {
              tree ops[3] = {};
+             /* When requiring a sign-extension we cannot model a
+                previous truncation with a single op so don't bother.  */
+             bool allow_truncate = TYPE_UNSIGNED (TREE_TYPE (rhs1));
              /* Either we have the op widened available.  */
-             ops[0] = valueized_wider_op (type,
-                                          gimple_assign_rhs1 (def));
+             ops[0] = valueized_wider_op (type, gimple_assign_rhs1 (def),
+                                          allow_truncate);
              if (ops[0])
-               ops[1] = valueized_wider_op (type,
-                                            gimple_assign_rhs2 (def));
+               ops[1] = valueized_wider_op (type, gimple_assign_rhs2 (def),
+                                            allow_truncate);
              if (ops[0] && ops[1])
                {
                  ops[0] = vn_nary_op_lookup_pieces