On Fri, 20 Jul 2018, Richard Sandiford wrote:
--- gcc/match.pd 2018-07-18 18:44:22.565914281 +0100
+++ gcc/match.pd 2018-07-20 11:24:33.692045585 +0100
@@ -4924,3 +4924,37 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (inverse_conditions_p (@0, @2)
&& element_precision (type) == element_precision (op_type))
(view_convert (cond_op @2 @3 @4 @5 (view_convert:op_type @1)))))))
+
+/* For pointers @0 and @2 and unsigned constant offset @1, look for
+ expressions like:
+
+ A: (@0 + @1 < @2) | (@2 + @1 < @0)
+ B: (@0 + @1 <= @2) | (@2 + @1 <= @0)
+
+ If pointers are known not to wrap, B checks whether @1 bytes starting at
+ @0 and @2 do not overlap, while A tests the same thing for @1 + 1 bytes.
+ A is more efficiently tested as:
+
+ ((sizetype) @0 - (sizetype) @2 + @1) > (@1 * 2)
+
+ as long as @1 * 2 doesn't overflow. B is the same with @1 replaced
+ with @1 - 1. */
+(for ior (truth_orif truth_or bit_ior)
+ (for cmp (le lt)
+ (simplify
+ (ior (cmp (pointer_plus:s @0 INTEGER_CST@1) @2)
+ (cmp (pointer_plus:s @2 @1) @0))
Do you want :c on cmp, in case it appears as @2 > @0 + @1 ? (may need some
care with "cmp == LE_EXPR" below)
Do you want :s on cmp as well?
+ (if (!flag_trapv && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
Don't you want TYPE_OVERFLOW_UNDEFINED?
+ /* Convert the B form to the A form. */
+ (with { offset_int off = wi::to_offset (@1) - (cmp == LE_EXPR ? 1 : 0); }
+ /* Always fails for negative values. */
+ (if (wi::min_precision (off, UNSIGNED) * 2 <= TYPE_PRECISION (sizetype))
+ /* It doesn't matter whether we use @2 - @0 or @0 - @2, so let
+ tree_swap_operands_p pick a canonical order. */
+ (with { tree ptr1 = @0, ptr2 = @2;
+ if (tree_swap_operands_p (ptr1, ptr2))
+ std::swap (ptr1, ptr2); }
+ (gt (plus (minus (convert:sizetype { ptr1; })
+ (convert:sizetype { ptr2; }))
+ { wide_int_to_tree (sizetype, off); })
+ { wide_int_to_tree (sizetype, off * 2); }))))))))
--
Marc Glisse