mirror of git://gcc.gnu.org/git/gcc.git
powerpc: Handle DImode rotatert implemented with rlwinm (PR69946)
Some DImode rotate-right-and-mask can be implemented best with a rlwinm instruction: those that could be a lshiftrt instead of a rotatert, while the mask is not right-aligned. Why the rotate in the testcase is not optimised to a plain shift is another question, but we need to handle it here anyway. We compute the shift amount for a 64-bit rotate. This is 32 too high in this case; if we print using %h that is masked out (and this doesn't silently let through invalid instructions, everything is checked by rs6000_is_valid_shift_mask which is much more thorough). PR target/69946 * config/rs6000/rs6000.c (rs6000_insn_for_shift_mask): Print rlwinm shift amount using %h. Add comment. gcc/testsuite/ * gcc.target/powerpc/pr69946.c: New file. From-SVN: r233755
This commit is contained in:
parent
4a4f9d2bf8
commit
d1f2bea53f
|
|
@ -1,3 +1,9 @@
|
||||||
|
2016-02-26 Segher Boessenkool <segher@kernel.crashing.org>
|
||||||
|
|
||||||
|
PR target/69946
|
||||||
|
* config/rs6000/rs6000.c (rs6000_insn_for_shift_mask): Print rlwinm
|
||||||
|
shift amount using %h. Add comment.
|
||||||
|
|
||||||
2016-02-26 Richard Biener <rguenther@suse.de>
|
2016-02-26 Richard Biener <rguenther@suse.de>
|
||||||
Jeff Law <law@redhat.com>
|
Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17438,9 +17438,12 @@ rs6000_insn_for_shift_mask (machine_mode mode, rtx *operands, bool dot)
|
||||||
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
|
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
|
||||||
operands[3] = GEN_INT (31 - nb);
|
operands[3] = GEN_INT (31 - nb);
|
||||||
operands[4] = GEN_INT (31 - ne);
|
operands[4] = GEN_INT (31 - ne);
|
||||||
|
/* This insn can also be a 64-bit rotate with mask that really makes
|
||||||
|
it just a shift right (with mask); the %h below are to adjust for
|
||||||
|
that situation (shift count is >= 32 in that case). */
|
||||||
if (dot)
|
if (dot)
|
||||||
return "rlw%I2nm. %0,%1,%2,%3,%4";
|
return "rlw%I2nm. %0,%1,%h2,%3,%4";
|
||||||
return "rlw%I2nm %0,%1,%2,%3,%4";
|
return "rlw%I2nm %0,%1,%h2,%3,%4";
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2016-02-26 Segher Boessenkool <segher@kernel.crashing.org>
|
||||||
|
|
||||||
|
PR target/69946
|
||||||
|
* gcc.target/powerpc/pr69946.c: New file.
|
||||||
|
|
||||||
2016-02-26 Richard Biener <rguenther@suse.de>
|
2016-02-26 Richard Biener <rguenther@suse.de>
|
||||||
Jeff Law <law@redhat.com>
|
Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
|
||||||
|
/* { dg-skip-if "" { powerpc_elfv2 } } */
|
||||||
|
/* { dg-options "-O2" } */
|
||||||
|
|
||||||
|
/* This generates a rotate:DI by 44, with mask 0xf00, which is implemented
|
||||||
|
using a rlwinm instruction. We used to write 44 for the shift count
|
||||||
|
there; it should be 12. */
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
int a : 4;
|
||||||
|
int : 2;
|
||||||
|
int b : 2;
|
||||||
|
int : 2;
|
||||||
|
int c : 2;
|
||||||
|
int d : 1;
|
||||||
|
int e;
|
||||||
|
};
|
||||||
|
struct B
|
||||||
|
{
|
||||||
|
int a : 4;
|
||||||
|
} *a;
|
||||||
|
void bar (struct A);
|
||||||
|
|
||||||
|
void
|
||||||
|
foo (void)
|
||||||
|
{
|
||||||
|
struct B b = a[0];
|
||||||
|
struct A c;
|
||||||
|
c.a = b.a;
|
||||||
|
c.b = 1;
|
||||||
|
c.c = 1;
|
||||||
|
c.d = 0;
|
||||||
|
bar (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* { dg-final { scan-assembler-not {(?n)rlwinm.*,44,20,23} } } */
|
||||||
|
/* { dg-final { scan-assembler-times {(?n)rlwinm.*,12,20,23} 1 } } */
|
||||||
Loading…
Reference in New Issue