diff options
author | Richard Biener <rguenther@suse.de> | 2021-01-13 09:43:52 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2021-01-13 11:13:33 +0100 |
commit | ffd28c265e6d611983cd27e9332dc799039a3f04 (patch) | |
tree | c4cc185c351fc1a6805b62c9ea3740ce1835b876 /gcc | |
parent | 5d057bfeff70e5b8d00e521844c476f62d51e22c (diff) | |
download | gcc-ffd28c265e6d611983cd27e9332dc799039a3f04.zip gcc-ffd28c265e6d611983cd27e9332dc799039a3f04.tar.gz gcc-ffd28c265e6d611983cd27e9332dc799039a3f04.tar.bz2 |
tree-optimization/98640 - fix bogus sign-extension with VN
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr98640.c | 22 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 15 |
2 files changed, 31 insertions, 6 deletions
diff --git a/gcc/testsuite/gcc.dg/torture/pr98640.c b/gcc/testsuite/gcc.dg/torture/pr98640.c new file mode 100644 index 0000000..b187781 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr98640.c @@ -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; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 0ba846f..588f1b8 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -4681,7 +4681,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); @@ -4695,7 +4695,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) @@ -4760,12 +4760,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 |