[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 Qi Feng changed: What|Removed |Added CC||ffengqi at gcc dot gnu.org --- Comment #2 from Qi Feng --- I tried some modifications in and_comparisons_1 and or_comparisons_1. It seems that `||' is transformed to `&&' somewhere. And that makes the changes in or_comparisons_1 noneffective. Should I find the place where the transformation happens and make changes before that?
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #3 from Qi Feng --- I have extended the transformations as following, the first five are the original ones: * unsigned Use UINT_MAX for demonstration, similar for UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, ULLONG_MAX x > y && x != 0 --> x > y x > y || x != 0 --> x != 0 x <= y || x != 0 --> true x <= y || x == 0 --> x <= y x > y && x == 0 --> false x < y && x != UINT_MAX--> x < y x < y || x != UINT_MAX--> x != UINT_MAX x >= y || x != UINT_MAX--> true x >= y || x == UINT_MAX--> x >= y x < y && x == UINT_MAX--> false * signed Use INT_MIN, INT_MAX for demonstration, similar for SCHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, SCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX x > y && x != INT_MIN --> x > y x > y || x != INT_MIN --> x != INT_MIN x <= y || x != INT_MIN --> true x <= y || x == INT_MIN --> x <= y x > y && x == INT_MIN --> false x < y && x != INT_MAX --> x < y x < y || x != INT_MAX --> x != UINT_MAX x >= y || x != INT_MAX --> true x >= y || x == INT_MAX --> x >= y x < y && x == INT_MAX --> false Want to know if I missed something.
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #4 from Qi Feng --- The fourth to the last should be: x < y || x != INT_MAX --> x != UINT_MAX sorry for the typo.
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #5 from Qi Feng --- (In reply to Qi Feng from comment #4) > The fourth to the last should be: > > x < y || x != INT_MAX --> x != UINT_MAX > > sorry for the typo. x < y || x != INT_MAX --> x != INT_MAX typo again...
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #7 from Qi Feng --- I add some patterns in match.pd which handles the original 5 transformations. But I don't the language used in match.pd well, the patterns I wrote are very similar. And I haven't found predicates for constant values other than zero (INT_MIN, LONG_MIN, LLONG_MIN etc.).
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #9 from Qi Feng --- And there's another problem. Take `x > y && x != 0 --> x > y' for example, I would also like to do x < y && y != 0 --> x < y x != 0 && x > y --> x > y y != 0 && x < y --> x < y If the constant always comes in as the second operand is incorrect, these would have to be doubled. I tried to add :c to truth_andif, but got the `operation is not commutative' error. I also tried to make truth_andif commutative by modifying genmatch.c, but again, I don't know it well, afraid that I would break something. The patterns I wrote looks like: /* x > y && x != 0 --> x > y Only for unsigned x and y. */ (simplify (truth_andif:c (gt@2 @0 @1) (ne @0 integer_zerop)) (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) && TYPE_UNSIGNED (TREE_TYPE(@1))) @2)) I have to wrote 4 of this with minor modification for a single transformation. If there's better way to do it, please do leave a comment.
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #11 from Qi Feng --- I tried 2 patterns for the following test /* 1. x > y && x != 0 --> x > y */ /* 2. y < x && x != 0 --> y < x */ /* 3. x != 0 && x > y --> x > y */ /* 4. x != 0 && y < x --> y < x */ _Bool f1 (unsigned x, unsigned y) { return x > y && x != 0; } _Bool f2 (unsigned x, unsigned y) { return y < x && x != 0; } _Bool f3 (unsigned x, unsigned y) { return x != 0 && x > y; } _Bool f4 (unsigned x, unsigned y) { return x != 0 && y < x; } The first one is (for and (truth_and bit_and) (simplify (and:c (gt:c@2 @0 @1) (ne @0 integer_zerop)) (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) && TYPE_UNSIGNED (TREE_TYPE(@1))) @2))) The transformations did not happen as I checked the dump files of -fdump-tree-{original,optimized}. And the second one is (simplify (truth_andif:C (gt:c@2 @0 @1) (ne @0 integer_zerop)) (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) && TYPE_UNSIGNED (TREE_TYPE(@1))) @2)) The transformations did happen for all the 4 functions. And the dump of -fdump-tree-original showes they already happened, so I guess the pattern is matched before the process get to GIMPLE.
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #14 from Qi Feng --- Checking .original and .optimized file is just a quick method I use to check whether an optimization happened (if not happen in first and last pass, probably it didn't happen). I didn't mean or think the transform should happen in these passes. Using the second pattern, the result of transform already showed in .original file, so I think it maybe happened earlier (like in GENERIC). And I tried the first pattern again using a totally clean debug build (bootstrap disabled), still didn't see the transformation happen. I don't know what went wrong. :( (I tested it on a ppc64le machine, don't know if that matters)
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #18 from Qi Feng --- I only learned gcc for about 2 months, and I have to say that I don't fully understand what you guys were saying. Is match.pd the right place to fix this issue? Am I in the wrong direction?
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #20 from Qi Feng --- I have tried to merge signed and unsigned together: /* x > y && x != ( 0 or XXX_MIN ) --> x > y */ (for and (truth_and bit_and) (simplify (and:c (gt:c@3 @0 @1) (ne @0 INTEGER_CST@2)) (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))) (if ((TYPE_UNSIGNED (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@1)) && integer_zerop (@2)) || (!TYPE_UNSIGNED (TREE_TYPE(@0)) && !TYPE_UNSIGNED (TREE_TYPE(@1)) && wi::eq_p (wi::to_wide (@2), wi::min_value (TYPE_PRECISION (TREE_TYPE (@2)), SIGNED @3 /* x > y || x != ( 0 or XXX_MIN ) --> x != ( 0 or XXX_MIN ) */ (for or (truth_or bit_ior) (simplify (or:c (gt:c @0 @1) (ne@3 @0 INTEGER_CST@2)) (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))) (if ((TYPE_UNSIGNED (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@1)) && integer_zerop (@2)) || (!TYPE_UNSIGNED (TREE_TYPE(@0)) && !TYPE_UNSIGNED (TREE_TYPE(@1)) && wi::eq_p (wi::to_wide (@2), wi::min_value (TYPE_PRECISION (TREE_TYPE (@2)), SIGNED @3 /* x < y && x != ( UXXX_MAX or XXX_MAX ) --> x < y */ (for and (truth_and bit_and) (simplify (and:c (lt:c@3 @0 @1) (ne @0 INTEGER_CST@2)) (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))) (if ((TYPE_UNSIGNED (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@1)) && wi::eq_p (wi::to_wide (@2), wi::max_value (TYPE_PRECISION (TREE_TYPE (@2)), UNSIGNED))) || (!TYPE_UNSIGNED (TREE_TYPE(@0)) && !TYPE_UNSIGNED (TREE_TYPE(@1)) && wi::eq_p (wi::to_wide (@2), wi::max_value (TYPE_PRECISION (TREE_TYPE (@2)), SIGNED @3 (That's not all of them, for that would be too long and I think it's not necessary.) I also tried it on a x86 laptop, seems it does work. But I got a bootstrap issue. I don't know if it's caused by my patch or the version of gcc I used to compile. Another problem is that I can't craft some c/c++ code to test truth_and. Maybe it's used by other languages? Is it necessary to use truth_and along side bit_and? I have to make this work on a ppc64le machine, could you give me some hints of where to look into? BTW, the following tests may be useful if you want test it on your machine: #include /* x > y && x != ( 0 or INT_MIN ) --> x > y */ _Bool f0 (unsigned x, unsigned y) { return x > y && x != 0; } _Bool f1 (unsigned x, unsigned y) { return y < x && x != 0; } _Bool f2 (unsigned x, unsigned y) { return x != 0 && x > y; } _Bool f3 (unsigned x, unsigned y) { return x != 0 && y < x; } _Bool f4 (int x, int y) { return x > y && x != INT_MIN; } _Bool f5 (int x, int y) { return y < x && x != INT_MIN; } _Bool f6 (int x, int y) { return x != INT_MIN && x > y; } _Bool f7 (int x, int y) { return x != INT_MIN && y < x; } _Bool f8 (unsigned char x, unsigned char y) { return x > y && x != 0; } /* x > y || x != ( 0 or XXX_MIN ) --> x != ( 0 or XXX_MIN ) */ _Bool f10 (unsigned x, unsigned y) { return x > y || x != 0; } _Bool f11 (int x, int y) { return x > y || x != INT_MIN; } _Bool f12 (unsigned char x, unsigned char y) { return x > y || x != 0; } _Bool f13 (signed char x, signed char y) { return x > y || x != SCHAR_MIN; } /* x < y && x != ( UXXX_MAX or XXX_MAX ) --> x < y */ _Bool f20 (unsigned x, unsigned y) { return x < y && x != UINT_MAX; } _Bool f21 (int x, int y) { return x < y && x != INT_MAX; } _Bool f22 (unsigned char x, unsigned char y) { return x < y && x != UCHAR_MAX; } _Bool f23 (signed char x, signed char y) { return x < y && x != SCHAR_MIN; }
[Bug middle-end/88784] Middle end is missing some optimizations about unsigned
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784 --- Comment #22 from Qi Feng --- Two more similar ones: x <= y && x == ( 0 or XXX_MIN ) --> x == ( 0 or XXX_MIN ) x >= y && x == ( UXXX_MAX or XXX_MAX ) --> x == ( UXXX_MAX or XXX_MAX )