[Bug target/65317] New: [SH] Shifts used instead of and with const_int
olegendo at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Wed Mar 4 21:03:00 GMT 2015
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65317
Bug ID: 65317
Summary: [SH] Shifts used instead of and with const_int
Product: gcc
Version: 5.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: olegendo at gcc dot gnu.org
Target: sh*-*-*
int
test_01 (int a, int b)
{
int r = a < 0;
return r << 31;
}
compiled with -O2 -m4:
shll r4
movt r0
and #1,r0
rts
rotr r0
could be:
mov.l .Lconst,r0
rts
and r4,r0
.Lconst:
.long 0x80000000
combine says:
Failed to match this instruction:
(set (reg:SI 168 [ D.1470 ])
(and:SI (reg:SI 4 r4 [ a ])
(const_int -2147483648 [0xffffffff80000000])))
Notice that this
int
test_02 (int a)
{
return a & 0x80000000;
}
compiles as expected:
mov.l .L18,r0
rts
and r4,r0
.L19:
.align 2
.L18:
.long -2147483648
If code size is important, or constant loads should be avoided (because it's
not shared etc), a shorter (in code size) version would be:
shll r4
movt r0
rts
rotr r0
Another case:
int foo3(int *x)
{
int i,y;
int a[40];
int b[40] __attribute__ ((aligned(32)));
int c[40] __attribute__ ((aligned(128)));
for (i = 0; i < 40; i++)
a[i] = *x++;
for (i = 0; i < 40; i++)
b[i] = *x++;
for (i = 0; i < 40; i++)
c[i] = *x++;
y = -99;
for (i = 0; i < 40; i++)
y = y + a[i] + b[i] + c[i];
return y;
}
compiles to:
mov.l r14,@-r15
mov #-5,r3
add #-80,r15
mov.w .L11,r2
add #-80,r15
add r15,r2
mov r15,r14
mov r2,r15
mov r15,r7
add #31,r7
mov #5,r1
shld r3,r7 <<<<
shld r1,r7 <<<<
mov #0,r0
mov #40,r1
.align 2
.L2:
mov.l @(r0,r4),r2
....
The shifts used to mask out lower bits can be replaced with a much simpler and
with a constant.
Combine says:
Failed to match this instruction:
(set (reg/f:SI 217)
(and:SI (reg/f:SI 214)
(const_int -32 [0xffffffffffffffe0])))
It seems that it's better to allow any constant for the *andsi_compact pattern
and split out the constant load if it doesn't fit into K08. An and with
constant 0x80000000 could be treated as a special case to emit the shorter
sequence:
shll r4
movt r0
rts
rotr r0
If constant calculation optimization is done (PR 65069), it would automatically
be converted to:
mov #1,r0
rotr r0
rts
and r4,r0
which is equivalent and maybe even better because the input is not mutated.
More information about the Gcc-bugs
mailing list