This patch tree-vrp handling and optimization for ZEXT_EXPR.
gcc/ChangeLog: 2015-09-07 Kugan Vivekanandarajah <kug...@linaro.org> * tree-vrp.c (extract_range_from_binary_expr_1): Handle SEXT_EXPR. (simplify_bit_ops_using_ranges): Likewise. (simplify_stmt_using_ranges): Likewise.
>From 7143e0575f309f70d838edf436b555fb93a6c4bb Mon Sep 17 00:00:00 2001 From: Kugan Vivekanandarajah <kugan.vivekanandara...@linaro.org> Date: Mon, 17 Aug 2015 13:45:52 +1000 Subject: [PATCH 3/8] Optimize ZEXT_EXPR with tree-vrp --- gcc/tree-vrp.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 21fbed0..d579b49 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2327,6 +2327,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, && code != LSHIFT_EXPR && code != MIN_EXPR && code != MAX_EXPR + && code != SEXT_EXPR && code != BIT_AND_EXPR && code != BIT_IOR_EXPR && code != BIT_XOR_EXPR) @@ -2887,6 +2888,55 @@ extract_range_from_binary_expr_1 (value_range_t *vr, extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1); return; } + else if (code == SEXT_EXPR) + { + gcc_assert (range_int_cst_p (&vr1)); + unsigned int prec = tree_to_uhwi (vr1.min); + type = vr0.type; + wide_int tmin, tmax; + wide_int type_min, type_max; + wide_int may_be_nonzero, must_be_nonzero; + + gcc_assert (!TYPE_UNSIGNED (expr_type)); + type_min = wi::shwi (1 << (prec - 1), + TYPE_PRECISION (TREE_TYPE (vr0.min))); + type_max = wi::shwi (((1 << (prec - 1)) - 1), + TYPE_PRECISION (TREE_TYPE (vr0.max))); + if (zero_nonzero_bits_from_vr (expr_type, &vr0, + &may_be_nonzero, + &must_be_nonzero)) + { + HOST_WIDE_INT int_may_be_nonzero = may_be_nonzero.to_uhwi (); + HOST_WIDE_INT int_must_be_nonzero = must_be_nonzero.to_uhwi (); + + if (int_must_be_nonzero & (1 << (prec - 1))) + { + /* If to-be-extended sign bit is one. */ + tmin = type_min; + tmax = may_be_nonzero; + } + else if ((int_may_be_nonzero & (1 << (prec - 1))) == 0) + { + /* If to-be-extended sign bit is zero. */ + tmin = must_be_nonzero; + tmax = may_be_nonzero; + } + else + { + tmin = type_min; + tmax = type_max; + } + } + else + { + tmin = type_min; + tmax = type_max; + } + tmin = wi::sext (tmin, prec - 1); + tmax = wi::sext (tmax, prec - 1); + min = wide_int_to_tree (expr_type, tmin); + max = wide_int_to_tree (expr_type, tmax); + } else if (code == RSHIFT_EXPR || code == LSHIFT_EXPR) { @@ -9254,6 +9304,30 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) break; } break; + case SEXT_EXPR: + { + gcc_assert (is_gimple_min_invariant (op1)); + unsigned int prec = tree_to_uhwi (op1); + wide_int mask; + HOST_WIDE_INT may_be_nonzero = may_be_nonzero0.to_uhwi (); + HOST_WIDE_INT must_be_nonzero = must_be_nonzero0.to_uhwi (); + mask = wi::shwi (((1 << (prec - 1)) - 1), + TYPE_PRECISION (TREE_TYPE (vr0.max))); + mask = wi::bit_not (mask); + if (must_be_nonzero & (1 << (prec - 1))) + { + /* If to-be-extended sign bit is one. */ + if (wi::bit_and (must_be_nonzero0, mask) == mask) + op = op0; + } + else if ((may_be_nonzero & (1 << (prec - 1))) == 0) + { + /* If to-be-extended sign bit is zero. */ + if (wi::bit_and (may_be_nonzero0, mask) == 0) + op = op0; + } + } + break; default: gcc_unreachable (); } @@ -9955,6 +10029,7 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) case BIT_AND_EXPR: case BIT_IOR_EXPR: + case SEXT_EXPR: /* Optimize away BIT_AND_EXPR and BIT_IOR_EXPR if all the bits being cleared are already cleared or all the bits being set are already set. */ -- 1.9.1