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;