--- gcc-4.1.1/gcc/tree-vrp.c.orig 2006-08-06 16:07:03.000000000 +0200 +++ gcc-4.1.1/gcc/tree-vrp.c 2006-08-06 21:44:24.000000000 +0200 @@ -1086,7 +1086,7 @@ extract_range_from_ssa_name (value_range are not using wrapping arithmetic, then adjust the result to be -INF or +INF depending on CODE, VAL1 and VAL2. */ -static inline tree +static tree vrp_int_const_binop (enum tree_code code, tree val1, tree val2) { tree res; @@ -1182,6 +1182,63 @@ vrp_int_const_binop (enum tree_code code } +/* Example: let's say operand has: +max = 01010010101001010010 +min = 01010010100000010010 +We can infer that these bits will be set +in any possible value of the operand: + 01010010100000000000 +*/ +static tree +find_bits1 (tree min, tree max) +{ + tree xored, shift, always1; + int xor_hi; + + always1 = vrp_int_const_binop(BIT_AND_EXPR, min, max); + xored = vrp_int_const_binop(BIT_XOR_EXPR, min, max); + xor_hi = tree_floor_log2(xored); + if(xor_hi >= 0) /* if min!=max */ + { + shift = build_int_cst (NULL_TREE, xor_hi+1); + always1 = vrp_int_const_binop(RSHIFT_EXPR, always1, shift); + always1 = vrp_int_const_binop(LSHIFT_EXPR, always1, shift); + } + return always1; +} +/* Example: let's say operand has: +max = 01010010101001010010 +min = 01010010100000010010 +We can infer that these bits will be unset +in any possible value of the operand: + 01010010101111111111 +*/ +static tree +find_bits0 (tree min, tree max) +{ + tree xored, always0, tmp; + int xor_hi; + + always0 = vrp_int_const_binop(BIT_IOR_EXPR, min, max); + xored = vrp_int_const_binop(BIT_XOR_EXPR, min, max); + xor_hi = tree_floor_log2(xored); + if(xor_hi > 0) /* if min!=max and difference is not in lowest bit only */ + { + tmp = build_int_cst (NULL_TREE, xor_hi); + always0 = vrp_int_const_binop(RSHIFT_EXPR, always0, tmp); + /* Too ugly for words */ + tmp = build_int_cst (NULL_TREE, 1); + do + { + always0 = vrp_int_const_binop(LSHIFT_EXPR, always0, tmp); + always0 = vrp_int_const_binop(PLUS_EXPR, always0, tmp); + xor_hi--; + } + while(xor_hi); + } + return always0; +} + /* Extract range information from a binary expression EXPR based on the ranges of each of its operands and the expression code. */ @@ -1206,6 +1263,8 @@ extract_range_from_binary_expr (value_ra && code != ROUND_DIV_EXPR && code != MIN_EXPR && code != MAX_EXPR + && code != BIT_AND_EXPR + && code != BIT_IOR_EXPR && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR && code != TRUTH_AND_EXPR @@ -1234,6 +1293,72 @@ extract_range_from_binary_expr (value_ra else set_value_range_to_varying (&vr1); + /* Bitwise ops */ + if (code == BIT_AND_EXPR) + { + if (vr0.type == VR_RANGE || vr1.type == VR_RANGE) + { + if(vr0.type == VR_RANGE) + { + if(vr1.type == VR_RANGE) + { + tree always1_0, always1_1; + always1_0 = find_bits1(vr0.min, vr0.max); + always1_1 = find_bits1(vr1.min, vr1.max); + min = vrp_int_const_binop(BIT_AND_EXPR, always1_0, always1_1); + max = vrp_int_const_binop(MIN_EXPR, vr0.max, vr1.max); + } + else + { + min = build_int_cst(TREE_TYPE(vr0.min), 0); + max = vr0.max; + } + set_value_range (vr, vr0.type, min, max, NULL); + } + else + { + min = build_int_cst(TREE_TYPE(vr1.min), 0); + max = vr1.max; + set_value_range (vr, vr1.type, min, max, NULL); + } + return; + } + set_value_range_to_varying (vr); + return; + } + if (code == BIT_IOR_EXPR) + { + if (vr0.type == VR_RANGE || vr1.type == VR_RANGE) + { + if(vr0.type == VR_RANGE) + { + if(vr1.type == VR_RANGE) + { + tree always0_0, always0_1; + always0_0 = find_bits0(vr0.min, vr0.max); + always0_1 = find_bits0(vr1.min, vr1.max); + min = vrp_int_const_binop(MAX_EXPR, vr0.min, vr1.min); + max = vrp_int_const_binop(BIT_IOR_EXPR, always0_0, always0_1); + } + else + { + min = vr0.min; + max = TYPE_MAX_VALUE(TREE_TYPE(vr0.max)); + } + set_value_range (vr, vr0.type, min, max, NULL); + } + else + { + min = vr1.min; + max = TYPE_MAX_VALUE(TREE_TYPE(vr1.max)); + set_value_range (vr, vr1.type, min, max, NULL); + } + return; + } + set_value_range_to_varying (vr); + return; + } + /* If either range is UNDEFINED, so is the result. */ if (vr0.type == VR_UNDEFINED || vr1.type == VR_UNDEFINED) { @@ -1244,9 +1369,8 @@ extract_range_from_binary_expr (value_ra /* Refuse to operate on VARYING ranges, ranges of different kinds and symbolic ranges. TODO, we may be able to derive anti-ranges in some cases. */ - if (vr0.type == VR_VARYING - || vr1.type == VR_VARYING - || vr0.type != vr1.type + if (vr0.type != vr1.type + || vr0.type == VR_VARYING || symbolic_range_p (&vr0) || symbolic_range_p (&vr1)) {