This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix A < 0 ? <sign bit of A> : 0 optimization (PR middle-end/58564)
- 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
- Date: Mon, 30 Sep 2013 15:29:08 +0200
- Subject: [PATCH] Fix A < 0 ? <sign bit of A> : 0 optimization (PR middle-end/58564)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Apparently sign_bit_p looks through both sign and zero extensions.
That is just fine for the single bit test optimization, where we know the
constant is a power of two, and it is (A & power_of_two) == 0 (or != 0)
test. sign_bit_p is also used to check for minimum value of some integral
type, because it is called with the same argument twice, it must be
INTEGER_CST if non-NULL is returned and thus there is no zero extensions.
But in the last spot where sign_bit_p is used, sign extensions would be
fine, ((int) x) < 0 for say signed char or signed short x iff x < 0,
but if there is a zero extension, it is just a possible missed optimization
on the comparison.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk/4.8?
2013-09-30 Jakub Jelinek <jakub@redhat.com>
PR middle-end/58564
* fold-const.c (fold_ternary_loc): For A < 0 : <sign bit of A> : 0
optimization, punt if sign_bit_p looked through any zero extension.
* gcc.c-torture/execute/pr58564.c: New test.
--- gcc/fold-const.c.jj 2013-09-27 15:42:37.000000000 +0200
+++ gcc/fold-const.c 2013-09-30 11:19:06.333978484 +0200
@@ -14196,14 +14196,29 @@ fold_ternary_loc (location_t loc, enum t
&& integer_zerop (op2)
&& (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
{
+ /* sign_bit_p looks through both zero and sign extensions,
+ but for this optimization only sign extensions are
+ usable. */
+ tree tem2 = TREE_OPERAND (arg0, 0);
+ while (tem != tem2)
+ {
+ if (TREE_CODE (tem2) != NOP_EXPR
+ || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (tem2, 0))))
+ {
+ tem = NULL_TREE;
+ break;
+ }
+ tem2 = TREE_OPERAND (tem2, 0);
+ }
/* sign_bit_p only checks ARG1 bits within A's precision.
If <sign bit of A> has wider type than A, bits outside
of A's precision in <sign bit of A> need to be checked.
If they are all 0, this optimization needs to be done
in unsigned A's type, if they are all 1 in signed A's type,
otherwise this can't be done. */
- if (TYPE_PRECISION (TREE_TYPE (tem))
- < TYPE_PRECISION (TREE_TYPE (arg1))
+ if (tem
+ && TYPE_PRECISION (TREE_TYPE (tem))
+ < TYPE_PRECISION (TREE_TYPE (arg1))
&& TYPE_PRECISION (TREE_TYPE (tem))
< TYPE_PRECISION (type))
{
--- gcc/testsuite/gcc.c-torture/execute/pr58564.c.jj 2013-09-30 11:09:38.691122488 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr58564.c 2013-09-30 11:09:14.000000000 +0200
@@ -0,0 +1,14 @@
+/* PR middle-end/58564 */
+
+extern void abort (void);
+int a, b;
+short *c, **d = &c;
+
+int
+main ()
+{
+ b = (0, 0 > ((&c == d) & (1 && (a ^ 1)))) | 0U;
+ if (b != 0)
+ abort ();
+ return 0;
+}
Jakub