Rather than always shift by 32, shift by the total number of zeros required. The improvement to also look to shift out ones comes from Kenner via alpha.
Cc: David Edelsohn <dje....@gmail.com> --- * config/rs6000/rs6000.c (genimm_ppc::exam_search): Use ctz to compute the shift. Also attempt to shift out ones. --- gcc/config/rs6000/rs6000.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 59c5014..b27e476 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -8145,6 +8145,7 @@ genimm_ppc::exam_search (HOST_WIDE_INT c, int budget) { const int sub_budget = budget - 1; HOST_WIDE_INT test; + int bits; /* Simple arithmetic on the low 32-bits. */ test = c & 0xffff; @@ -8181,11 +8182,23 @@ genimm_ppc::exam_search (HOST_WIDE_INT c, int budget) } /* Shift the constant left. */ - test = HOST_WIDE_INT_UC (0xffffffff00000000); - if ((c & test) == c && exam_sub (c >> 32, sub_budget)) + bits = ctz_hwi (c); + if (bits > 0) { - opN (ASHIFT, 32); /* SLDI */ - return true; + /* First try with zeros being shifted out. */ + HOST_WIDE_INT sub_c = (unsigned HOST_WIDE_INT)c >> bits; + bool ok = exam_sub (sub_c, sub_budget); + if (!ok) + { + /* If that failed, try with ones being shifted out. */ + sub_c |= ~(HOST_WIDE_INT_M1U >> bits); + ok = exam_sub (sub_c, sub_budget); + } + if (ok) + { + opN (ASHIFT, bits); /* SLDI */ + return true; + } } return false; -- 2.4.3