On Tue, Jan 3, 2012 at 9:36 PM, Richard Henderson <r...@redhat.com> wrote:
> On 01/03/2012 09:50 PM, Uros Bizjak wrote:
>> I tried to investigate -mbig-endian a bit, but unfortunately almost
>> all gcc.dg/torture/vshuf-*.c tests FAIL with -O2 on unpatched gcc.
>> Tests pass with -O0, though.
>
> Tests without -O don't actually test this code.
>
> And -mbig-endian doesn't get big-endian execution on linux, so it's
> only useful for manually examining assembly and checking for ICEs.

Attached patch adds early exit for BYTES_BIG_ENDIAN, as suggested by rth.

2012-01-05  Uros Bizjak  <ubiz...@gmail.com>

        PR target/51681
        * config/ia64/ia64.c (expand_vec_perm_shrp): Use correct operands
        for shrp pattern.  Correctly handle and fixup shift variable.
        Return false when shift > nelt for BYTES_BIG_ENDIAN target.

Patch was bootstrapped and regression tested on
ia64-unknown-linux-gnu.  Additionally, the patch was tested on
gcc.dg/torture/vshuf*.c with -mbig-endian, where it didn't caused any
ICEs.

OK for mainline?

Uros.
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c  (revision 182917)
+++ config/ia64/ia64.c  (working copy)
@@ -11085,7 +11085,7 @@ static bool
 expand_vec_perm_shrp (struct expand_vec_perm_d *d)
 {
   unsigned i, nelt = d->nelt, shift, mask;
-  rtx tmp, op0, op1;;
+  rtx tmp, hi, lo;
 
   /* ??? Don't force V2SFmode into the integer registers.  */
   if (d->vmode == V2SFmode)
@@ -11094,6 +11094,9 @@ expand_vec_perm_shrp (struct expand_vec_perm_d *d)
   mask = (d->one_operand_p ? nelt - 1 : 2 * nelt - 1);
 
   shift = d->perm[0];
+  if (BYTES_BIG_ENDIAN && shift > nelt)
+    return false;
+
   for (i = 1; i < nelt; ++i)
     if (d->perm[i] != ((shift + i) & mask))
       return false;
@@ -11101,6 +11104,11 @@ expand_vec_perm_shrp (struct expand_vec_perm_d *d)
   if (d->testing_p)
     return true;
 
+  hi = shift < nelt ? d->op1 : d->op0;
+  lo = shift < nelt ? d->op0 : d->op1;
+
+  shift %= nelt;
+
   shift *= GET_MODE_UNIT_SIZE (d->vmode) * BITS_PER_UNIT;
 
   /* We've eliminated the shift 0 case via expand_vec_perm_identity.  */
@@ -11113,11 +11121,9 @@ expand_vec_perm_shrp (struct expand_vec_perm_d *d)
     shift = 64 - shift;
 
   tmp = gen_reg_rtx (DImode);
-  op0 = (shift < nelt ? d->op0 : d->op1);
-  op1 = (shift < nelt ? d->op1 : d->op0);
-  op0 = gen_lowpart (DImode, op0);
-  op1 = gen_lowpart (DImode, op1);
-  emit_insn (gen_shrp (tmp, op0, op1, GEN_INT (shift)));
+  hi = gen_lowpart (DImode, hi);
+  lo = gen_lowpart (DImode, lo);
+  emit_insn (gen_shrp (tmp, hi, lo, GEN_INT (shift)));
 
   emit_move_insn (d->target, gen_lowpart (d->vmode, tmp));
   return true;

Reply via email to