This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/53087] New: Poor code for conversion from _Bool to int
- From: "steven at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Mon, 23 Apr 2012 16:36:26 +0000
- Subject: [Bug target/53087] New: Poor code for conversion from _Bool to int
- Auto-submitted: auto-generated
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53087
Bug #: 53087
Summary: Poor code for conversion from _Bool to int
Classification: Unclassified
Product: gcc
Version: 4.8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: steven@gcc.gnu.org
Consider this test case:
#define ONEUL (1UL)
int
foo (long unsigned int a)
{
_Bool b;
long unsigned int cst, csui;
if (a > 27) goto return_zero;
/*cst = 217579583UL;*/
cst = (ONEUL << 0) | (ONEUL << 1) | (ONEUL << 2) |
(ONEUL << 3) | (ONEUL << 4) | (ONEUL << 5) |
(ONEUL << 19) | (ONEUL << 20) | (ONEUL << 21) |
(ONEUL << 22) | (ONEUL << 23) | (ONEUL << 26) |
(ONEUL << 27);
csui = (ONEUL << a);
b = ((csui & cst) != 0);
if (b)
return 1;
else
return 0;
return_zero:
return 0;
}
On powerpc64, with GCC trunk r186580, the code generated for this example is:
foo:
.quad .L.foo,.TOC.@tocbase,0
.previous
.type foo, @function
.L.foo:
cmpldi 7,3,27
bgt 7,.L3
li 10,1
lis 9,0xcf8
sld 3,10,3
ori 9,9,63
and. 10,3,9
mfcr 9
rlwinm 9,9,3,1
xori 3,9,1
blr
.p2align 4,,15
.L3:
.L2:
li 3,0
blr
The poor code results from PHI-OPT which converts away the if() statement. The
.149t.optimized dump looks like this:
;; Function foo (foo, funcdef_no=0, decl_uid=1996, cgraph_uid=0)
foo (long unsigned int a)
{
_Bool D.2013;
long unsigned int csui;
int D.2008;
long unsigned int D.2005;
int D.2004;
<bb 2>:
if (a_2(D) > 27)
goto <bb 4> (return_zero);
else
goto <bb 3>;
<bb 3>:
D.2004_3 = (int) a_2(D);
csui_4 = 1 << D.2004_3;
D.2005_5 = csui_4 & 217579583;
D.2013_7 = D.2005_5 != 0;
D.2008_8 = (int) D.2013_7;
# D.2008_1 = PHI <D.2008_8(3), 0(2)>
return_zero:
return D.2008_1;
}
The last statement in <bb 3> and the PHI are expanded as follows (compiled with
-fno-tree-ter to make it easier to see as what RTL each statement expanded to):
;; D.2013_7 = D.2005_5 != 0;
(insn 15 14 16 (set (reg:CC 134)
(compare:CC (reg:DI 123 [ D.2005 ])
(const_int 0 [0]))) t.c:16 -1
(nil))
(insn 16 15 17 (set (reg:DI 135)
(eq:DI (reg:CC 134)
(const_int 0 [0]))) t.c:16 -1
(nil))
(insn 17 16 18 (set (reg:SI 133)
(subreg:SI (reg:DI 135) 4)) t.c:16 -1
(nil))
(insn 18 17 19 (set (reg:QI 132)
(subreg:QI (reg:SI 133) 3)) t.c:16 -1
(nil))
(insn 19 18 20 (set (reg:SI 136)
(xor:SI (subreg:SI (reg:QI 132) 0)
(const_int 1 [0x1]))) t.c:16 -1
(nil))
(insn 20 19 0 (set (reg:DI 124 [ D.2013+-7 ])
(zero_extend:DI (subreg:QI (reg:SI 136) 3))) t.c:16 -1
(nil))
;; D.2008_8 = (int) D.2013_7;
(insn 21 20 0 (set (reg:DI 120 [ D.2008+-4 ])
(sign_extend:DI (subreg/s/u:SI (reg:DI 124 [ D.2013+-7 ]) 4))) t.c:17
-1
(nil))
This is a target problem, because i686, x86_64, mips, and arm all generate much
better code for this example, for example:
MIPS:
foo:
.frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.set nomacro
sltu $2,$4,28
beq $2,$0,$L3
nop
li $2,1 # 0x1
sll $4,$2,$4
li $2,217579520 # 0xcf80000
addiu $2,$2,63
and $2,$4,$2
j $31
sltu $2,$0,$2
$L3:
$L2 = .
j $31
move $2,$0
ARM:
foo:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
cmp r0, #27
bhi .L3
mov r3, #1
mov r0, r3, asl r0
ldr r3, .L5
and r3, r0, r3
adds r0, r3, #0
movne r0, #1
bx lr
.L3:
.L2:
mov r0, #0
bx lr
.L6:
.align 2
.L5:
.word 217579583