diff options
author | Kugan <kugan@kugan-desktop> | 2015-03-16 09:18:37 +1100 |
---|---|---|
committer | Kugan <kugan@kugan-desktop> | 2015-03-16 09:18:37 +1100 |
commit | 68aa04ef160c37b9d50ec02a51ace096417e645d (patch) | |
tree | adec2eb61a17e4c00424acfb2cde03f9f7fba016 /gcc/tree-vrp.c | |
parent | ddf06852be2f12dc49f5fd610df3aefb8ff203fb (diff) |
2015-03-16 Kugan Vivekanandarajah <kuganv@linaro.org>linaro-dev/type-promotion-pass
* Makefile.in: Add gimple-ssa-type-promote.o.
* cfgexpand.c (expand_debug_expr): Handle SEXT_EXPR.
* common.opt: New option -ftree-type-promote.
* expr.c (expand_expr_real_2): Handle SEXT_EXPR.
* fold-const.c (int_const_binop_1):
* gimple-ssa-type-promote.c: New file.
* passes.def: Define new pass_type_promote.
* timevar.def: Define new TV_TREE_TYPE_PROMOTE.
* tree-cfg.c (verify_gimple_assign_binary): Handle SEXT_EXPR.
* tree-inline.c (estimate_operator_cost):
* tree-pass.h (make_pass_type_promote): New.
* tree-pretty-print.c (dump_generic_node): Handle SEXT_EXPR.
(op_symbol_code): Likewise.
* tree-vrp.c (extract_range_from_binary_expr_1): Likewise.
* tree.def: Define new SEXT_EXPR.
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 9556ede6247..7119aa9d1a5 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2354,6 +2354,7 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr, set_value_range (vr, type, min, max, NULL); } +void debug_value_range (value_range_t *); /* Extract range information from a binary operation CODE based on the ranges of each of its operands *VR0 and *VR1 with resulting type EXPR_TYPE. The resulting range is stored in *VR. */ @@ -2392,6 +2393,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) @@ -2968,6 +2970,49 @@ 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 _may_be_nonzero = may_be_nonzero.to_uhwi (); + + if (_may_be_nonzero & (1 << (prec - 1))) + { + /* If to-be-extended sign bit can be one. */ + tmin = type_min; + tmax = may_be_nonzero & type_max; + } + else + { + /* If to-be-extended sign bit is zero. */ + tmin = must_be_nonzero; + tmax = may_be_nonzero; + } + } + else + { + tmin = type_min; + tmax = type_max; + } + tmin = wi::sext (tmin, prec); + tmax = wi::sext (tmax, prec); + min = wide_int_to_tree (expr_type, tmin); + max = wide_int_to_tree (expr_type, tmax); + } else if (code == RSHIFT_EXPR || code == LSHIFT_EXPR) { |