On Wed, 29 Apr 2015, Jeff Law wrote:
This is an incremental improvement to the type narrowing in match.pd. It's
largely based on the pattern I added to fix 47477.
Basically if we have
(bit_and (arith_op (convert A) (convert B)) mask)
Where the conversions are widening and the mask turns off all bits outside
the original types of A & B, then we can turn that into
(bit_and (arith_op A B) mask)
We may need to convert A & B to an unsigned type with the same
width/precision as their original type, but that's still better than a
widening conversion.
Bootstrapped and regression tested on x86_64-linux-gnu.
OK for the trunk?
+/* This is another case of narrowing, specifically when there's an outer
+ BIT_AND_EXPR which masks off bits outside the type of the innermost
+ operands. Like the previous case we have to convert the operands
+ to unsigned types to avoid introducing undefined behaviour for the
+ arithmetic operation. */
+(for op (minus plus)
No mult? or widen_mult with a different pattern? (maybe that's already
done elsewhere)
+ (simplify
+ (bit_and (op (convert@2 @0) (convert@3 @1)) INTEGER_CST@4)
Maybe op@5 and then test single_use on @5? If I compute something, and
before using it I test if the result is odd, I may not want to recompute
it.
+ (if (INTEGRAL_TYPE_P (type)
Can this be false, or is it for documentation?
+ /* We check for type compatibility between @0 and @1 below,
+ so there's no need to check that @1/@3 are integral types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ /* The precision of the type of each operand must match the
+ precision of the mode of each operand, similarly for the
+ result. */
A nicely named helper that does this test would be cool. Every time I
see it I have to think again why it is necessary, and if there was a
function, I could refer to the comment above its definition ;-)
+ && (TYPE_PRECISION (TREE_TYPE (@0))
+ == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@0))))
+ && (TYPE_PRECISION (TREE_TYPE (@1))
+ == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@1))))
+ && TYPE_PRECISION (type) == GET_MODE_PRECISION (TYPE_MODE (type))
+ /* The inner conversion must be a widening conversion. */
+ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+ && ((GENERIC
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (@0))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (@1))))
+ || (GIMPLE
+ && types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1))))
We don't need to be that strict, but this probably covers the most
common case.
+ && (tree_int_cst_min_precision (@4, UNSIGNED)
+ <= TYPE_PRECISION (TREE_TYPE (@0))))
+ (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+ (with { tree ntype = TREE_TYPE (@0); }
+ (convert (bit_and (op @0 @1) (convert:ntype @4)))))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (convert (bit_and (op (convert:utype @0) (convert:utype @1))
+ (convert:utype @4)))))))
--
Marc Glisse