This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Implement one optimization from build_range_check in match.pd (PR tree-optimization/81346)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Biener <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org, Marc Glisse <marc dot glisse at inria dot fr>
- Date: Tue, 18 Jul 2017 15:47:30 +0200
- Subject: [PATCH] Implement one optimization from build_range_check in match.pd (PR tree-optimization/81346)
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jakub at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 5F7FF356F3
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 5F7FF356F3
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following patch implements the:
/* Optimize (c>=1) && (c<=127) into (signed char)c > 0. */
if (integer_onep (low) && TREE_CODE (high) == INTEGER_CST)
{
int prec = TYPE_PRECISION (etype);
if (wi::mask (prec - 1, false, prec) == high)
{
if (TYPE_UNSIGNED (etype))
{
tree signed_etype = signed_type_for (etype);
if (TYPE_PRECISION (signed_etype) != TYPE_PRECISION (etype))
etype
= build_nonstandard_integer_type (TYPE_PRECISION (etype), 0);
else
etype = signed_etype;
exp = fold_convert_loc (loc, etype, exp);
}
return fold_build2_loc (loc, GT_EXPR, type, exp,
build_int_cst (etype, 0));
}
}
optimization from build_range_check in match.pd if we already have the
less efficient x-1U <= 127U-1U. If somebody writes the range test
as x>=1 && x <= 127, then it is already optimized well, but if somebody
writes it as x-1U <= 126U, then it is not without this patch.
Bootstrapped/regtested on x86_64-linux and i686-linux.
In the PR Marc noted that the optimization might be useful even for
constants other than 1, by transforming
x+C1 <= C2 if unsigned and C2-C1==INT_MAX into (int)x > (int)(-1-C1).
Shall I do that immediately, or incrementally? Shall we also change
build_range_check to do that (i.e. drop the integer_onep above and use
right etype constant? Also, I think the build_nonstandard_integer_type
above is unnecessary, I think signed_type_for does already call that.
2017-07-18 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/81346
* match.pd: Optimize (X - 1U) <= INT_MAX-1U into (int) X > 0.
* gcc.dg/tree-ssa/pr81346-5.c: New test.
--- gcc/match.pd.jj 2017-07-17 16:25:20.000000000 +0200
+++ gcc/match.pd 2017-07-18 12:32:52.896924558 +0200
@@ -1125,6 +1125,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& wi::neg_p (@1, TYPE_SIGN (TREE_TYPE (@1))))
(cmp @2 @0))))))
+/* (X - 1U) <= INT_MAX-1U into (int) X > 0. */
+(for cmp (le gt)
+ icmp (gt le)
+ (simplify
+ (cmp (plus @0 integer_minus_onep@1) INTEGER_CST@2)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_UNSIGNED (TREE_TYPE (@0))
+ && TYPE_PRECISION (TREE_TYPE (@0)) > 1
+ && wi::eq_p (@2, wi::max_value (TYPE_PRECISION (TREE_TYPE (@0)),
+ SIGNED) - 1))
+ (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+ (icmp (convert:stype @0) { build_int_cst (stype, 0); })))))
+
/* X / 4 < Y / 4 iff X < Y when the division is known to be exact. */
(for cmp (simple_comparison)
(simplify
--- gcc/testsuite/gcc.dg/tree-ssa/pr81346-5.c.jj 2017-07-18 12:35:27.406063800 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/pr81346-5.c 2017-07-18 12:37:04.460894965 +0200
@@ -0,0 +1,17 @@
+/* PR tree-optimization/81346 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\\(signed int\\) x" 10 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " <= 0;" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " > 0;" 5 "optimized" } } */
+
+int f1 (unsigned x) { return x - 1 <= __INT_MAX__ - 1; }
+int f2 (unsigned x) { unsigned a = 1, b = __INT_MAX__ - 1; return x - a <= b; }
+int f3 (unsigned x) { return x - 1 < __INT_MAX__; }
+int f4 (unsigned x) { unsigned a = 1, b = __INT_MAX__; return x - a < b; }
+int f5 (unsigned x) { return x >= 1 && x <= __INT_MAX__; }
+int f6 (unsigned x) { return x - 1 > __INT_MAX__ - 1; }
+int f7 (unsigned x) { unsigned a = 1, b = __INT_MAX__ - 1; return x - a > b; }
+int f8 (unsigned x) { return x - 1 >= __INT_MAX__; }
+int f9 (unsigned x) { unsigned a = 1, b = __INT_MAX__; return x - a >= b; }
+int f10 (unsigned x) { return x < 1 || x > __INT_MAX__; }
Jakub