Helps for constants like 0x3300000000000033ul and 0xf5555ffffffffffful. Cc: David Edelsohn <dje....@gmail.com> --- * config/rs6000/rs6000.c (genimm_ppc::exam_rotl): New. (genimm_ppc::exam_search): Use it. (genimm_ppc::generate): Handle ROTATE. --- gcc/config/rs6000/rs6000.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 40b29b0..f5d6fdf 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -8059,6 +8059,7 @@ struct genimm_ppc : genimm_base <rtx_code, 5> bool exam_simple (HOST_WIDE_INT c, machine_mode, int budget); bool exam_sub (HOST_WIDE_INT c, int budget); bool exam_mask (HOST_WIDE_INT c, HOST_WIDE_INT mask, int sub_budget); + bool exam_rotl (HOST_WIDE_INT c, int bits); bool exam_search (HOST_WIDE_INT c, int budget); void exam_full (HOST_WIDE_INT c); void generate (rtx dest, machine_mode mode) const; @@ -8137,6 +8138,24 @@ genimm_ppc::exam_mask (HOST_WIDE_INT c, HOST_WIDE_INT mask, int sub_budget) return false; } +/* If we're able to rotate a 16-bit signed constant to form C, + return true and fill in the recipe. */ + +bool +genimm_ppc::exam_rotl (HOST_WIDE_INT c, int bits) +{ + HOST_WIDE_INT sub_c = (unsigned HOST_WIDE_INT)c >> bits; + sub_c |= (unsigned HOST_WIDE_INT)c << (64 - bits); + + if ((unsigned HOST_WIDE_INT)sub_c + 0x8000 < 0x10000) + { + set0 (sub_c); + opN (ROTATE, bits); + return true; + } + return false; +} + /* The body of the recursive search for C within BUDGET. We've already failed exam_simple. */ @@ -8212,6 +8231,35 @@ genimm_ppc::exam_search (HOST_WIDE_INT c, int budget) } } + /* Rotate the constant left. Because of combinatorial complexity, + only consider this with a 16-bit base, which means there's no + point in considering this high in the search tree. */ + if (sub_budget == 1) + { + /* The 16-bit signed constant upon which we are going to base + the rotate can have no more than 15 bits set as a positive + or no less than 49 bits set as a negative. */ + bits = popcount_hwi (c); + if (bits <= 15) + { + /* The constant must be positive, and it must have failed + the simpler shift test above. Therefore, any success + will be with a rotate of more than 48. */ + bits = ctz_hwi (c & ~ HOST_WIDE_INT_UC (0x7fff)); + if (bits > 48 && exam_rotl (c, bits)) + return true; + } + else if (bits > 48) + { + /* The constant must be negative, and it must have rotated + copies of the sign bit around into the low order bits. + Those copies must be the number of rotations. */ + bits = ctz_hwi (~c); + if (exam_rotl (c, bits)) + return true; + } + } + return false; } @@ -8255,6 +8303,9 @@ genimm_ppc::generate (rtx dest, machine_mode mode) const case SET: x = op2; break; + case ROTATE: + gcc_assert (mode == DImode); + /* FALLTHRU */ case PLUS: case AND: case IOR: -- 2.4.3