------- Comment #1 from krebbel at gcc dot gnu dot org 2005-12-06 14:33 ------- Shorter testcase:
long long foo (long long x, int y) { return x << ((y + 1) & 63); } The count operand of a shift instruction is a somewhat weird thing on S/390. It is basically an address accepting the sum of an address register and a constant. To the resulting value an AND mask of 63 is applied. Looking for an easy way to get rid of pointless ANDs on a shift count operand we've defined an 'Y' address constraint and a predicate to accept these ANDs although our legitimize_address_p does not! We were aware that this could potentially cause trouble but we found it working because find_reloads_address strips ANDs before handling the address parts. Unfortunately find_reloads_address fails if there is actually a constant addend present. If legitimize_address_p said no to an address consisting of a register + constant it is assumed that the constant value is not valid as displacement and is reloaded into a register if the machine supports reg + reg addresses. So we end up with: r1 = c; r3 << (r1 + r2); not a valid shift count operand The only way to fix this seems to be making the 'Y' constraint and the shift_count_operand predicate to reject ANDs again and duplicating the shift patterns in order to have a variant including the AND in the insn pattern. I will come up with a patch as soon as possible. -- krebbel at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Ever Confirmed|0 |1 Last reconfirmed|0000-00-00 00:00:00 |2005-12-06 14:33:40 date| | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25268