http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51681

--- Comment #5 from Uros Bizjak <ubizjak at gmail dot com> 2012-01-02 12:35:25 
UTC ---
Patch:

--cut here--
Index: ia64.c
===================================================================
--- ia64.c      (revision 182780)
+++ 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)
@@ -11101,6 +11101,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 +11118,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;
--cut here--

Just a bunch of mix-ups; where high/low part goes, shift value is not adjusted
after operand swap, and shift value is compared in *bits* to number of
elements.

Reply via email to