------- 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

Reply via email to