diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-09-26 15:58:11 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-09-26 15:58:11 +0200 |
commit | caab37632257b7b002da791d6372ab9136e0d54f (patch) | |
tree | 1a330899c3f451ef600431b3536b3ee28f914a59 /gcc/tree-ssa-reassoc.c | |
parent | 18b10d78d4344427e269e20f07117029daa52a97 (diff) | |
download | gcc-caab37632257b7b002da791d6372ab9136e0d54f.zip gcc-caab37632257b7b002da791d6372ab9136e0d54f.tar.gz gcc-caab37632257b7b002da791d6372ab9136e0d54f.tar.bz2 |
re PR middle-end/35691 (Missed (a == 0) && (b == 0) into (a|(typeof(a)(b)) == 0 when the types don't match)
PR middle-end/35691
* tree-ssa-reassoc.c (update_range_test): Dump r->exp each time
if it is different SSA_NAME.
(optimize_range_tests_cmp_bitwise): New function.
(optimize_range_tests): Call it.
* gcc.dg/pr35691-5.c: New test.
* gcc.dg/pr35691-6.c: New test.
From-SVN: r253201
Diffstat (limited to 'gcc/tree-ssa-reassoc.c')
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 141 |
1 files changed, 140 insertions, 1 deletions
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 2fb6aef..b2d0f57 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -2379,7 +2379,16 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, r = otherrange + i; else r = otherrangep[i]; - fprintf (dump_file, " and %c[", r->in_p ? '+' : '-'); + if (r->exp + && r->exp != range->exp + && TREE_CODE (r->exp) == SSA_NAME) + { + fprintf (dump_file, " and "); + print_generic_expr (dump_file, r->exp); + } + else + fprintf (dump_file, " and"); + fprintf (dump_file, " %c[", r->in_p ? '+' : '-'); print_generic_expr (dump_file, r->low); fprintf (dump_file, ", "); print_generic_expr (dump_file, r->high); @@ -2880,6 +2889,134 @@ optimize_range_tests_to_bit_test (enum tree_code opcode, int first, int length, return any_changes; } +/* Optimize x != 0 && y != 0 && z != 0 into (x | y | z) != 0 + and similarly x != -1 && y != -1 && y != -1 into (x & y & z) != -1. */ + +static bool +optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length, + vec<operand_entry *> *ops, + struct range_entry *ranges) +{ + int i; + unsigned int b; + bool any_changes = false; + auto_vec<int, 128> buckets; + auto_vec<int, 32> chains; + auto_vec<struct range_entry *, 32> candidates; + + for (i = first; i < length; i++) + { + if (ranges[i].exp == NULL_TREE + || TREE_CODE (ranges[i].exp) != SSA_NAME + || !ranges[i].in_p + || TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) <= 1 + || TREE_CODE (TREE_TYPE (ranges[i].exp)) == BOOLEAN_TYPE + || ranges[i].low == NULL_TREE + || ranges[i].low != ranges[i].high) + continue; + + bool zero_p = integer_zerop (ranges[i].low); + if (!zero_p && !integer_all_onesp (ranges[i].low)) + continue; + + b = TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) * 2 + !zero_p; + if (buckets.length () <= b) + buckets.safe_grow_cleared (b + 1); + if (chains.length () <= (unsigned) i) + chains.safe_grow (i + 1); + chains[i] = buckets[b]; + buckets[b] = i + 1; + } + + FOR_EACH_VEC_ELT (buckets, b, i) + if (i && chains[i - 1]) + { + int j, k = i; + for (j = chains[i - 1]; j; j = chains[j - 1]) + { + gimple *gk = SSA_NAME_DEF_STMT (ranges[k - 1].exp); + gimple *gj = SSA_NAME_DEF_STMT (ranges[j - 1].exp); + if (reassoc_stmt_dominates_stmt_p (gk, gj)) + k = j; + } + tree type1 = TREE_TYPE (ranges[k - 1].exp); + tree type2 = NULL_TREE; + bool strict_overflow_p = false; + candidates.truncate (0); + for (j = i; j; j = chains[j - 1]) + { + tree type = TREE_TYPE (ranges[j - 1].exp); + strict_overflow_p |= ranges[j - 1].strict_overflow_p; + if (j == k + || useless_type_conversion_p (type1, type)) + ; + else if (type2 == NULL_TREE + || useless_type_conversion_p (type2, type)) + { + if (type2 == NULL_TREE) + type2 = type; + candidates.safe_push (&ranges[j - 1]); + } + } + unsigned l = candidates.length (); + for (j = i; j; j = chains[j - 1]) + { + tree type = TREE_TYPE (ranges[j - 1].exp); + if (j == k) + continue; + if (useless_type_conversion_p (type1, type)) + ; + else if (type2 == NULL_TREE + || useless_type_conversion_p (type2, type)) + continue; + candidates.safe_push (&ranges[j - 1]); + } + gimple_seq seq = NULL; + tree op = NULL_TREE; + unsigned int id; + struct range_entry *r; + candidates.safe_push (&ranges[k - 1]); + FOR_EACH_VEC_ELT (candidates, id, r) + { + gimple *g; + if (id == 0) + { + op = r->exp; + continue; + } + if (id == l) + { + g = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, op); + gimple_seq_add_stmt_without_update (&seq, g); + op = gimple_assign_lhs (g); + } + tree type = TREE_TYPE (r->exp); + tree exp = r->exp; + if (id >= l && !useless_type_conversion_p (type1, type)) + { + g = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, exp); + gimple_seq_add_stmt_without_update (&seq, g); + exp = gimple_assign_lhs (g); + } + g = gimple_build_assign (make_ssa_name (id >= l ? type1 : type2), + (b & 1) ? BIT_AND_EXPR : BIT_IOR_EXPR, + op, exp); + gimple_seq_add_stmt_without_update (&seq, g); + op = gimple_assign_lhs (g); + } + candidates.pop (); + if (update_range_test (&ranges[k - 1], NULL, candidates.address (), + candidates.length (), opcode, ops, op, + seq, true, ranges[k - 1].low, + ranges[k - 1].low, strict_overflow_p)) + any_changes = true; + else + gimple_seq_discard (seq); + } + + return any_changes; +} + /* Attempt to optimize for signed a and b where b is known to be >= 0: a >= 0 && a < b into (unsigned) a < (unsigned) b a >= 0 && a <= b into (unsigned) a <= (unsigned) b */ @@ -3202,6 +3339,8 @@ optimize_range_tests (enum tree_code opcode, if (lshift_cheap_p (optimize_function_for_speed_p (cfun))) any_changes |= optimize_range_tests_to_bit_test (opcode, first, length, ops, ranges); + any_changes |= optimize_range_tests_cmp_bitwise (opcode, first, length, + ops, ranges); any_changes |= optimize_range_tests_var_bound (opcode, first, length, ops, ranges); |