Bug 67057 - [SH] Use negc to calculate 1-T+const_int
Summary: [SH] Use negc to calculate 1-T+const_int
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-07-29 14:30 UTC by Oleg Endo
Modified: 2015-07-29 14:53 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Oleg Endo 2015-07-29 14:30:31 UTC
The following

int foo (int a, int b)
{
 return ((a & (1 << 25)) ? 5 : 4);
}

compiled with -O2 results in:

	mov.l	.L4,r1
	mov	#-1,r0
	tst	r1,r4
	negc	r0,r0
	rts	
	add	#4,r0    // r0 = 1 - T + 4
	                 //    = 5 - T
.L5:
	.align 2
.L4:
	.long	33554432
	
The negc insn calculates 0 - reg - T, which can be used to calculate const_int + T.  In fact, it is already used to calculate 1 - T as a replacement for SH2A movrt.

The resulting code should look something like this:
	mov.l	.L4,r1
	mov	#-5,r0
	tst	r1,r4
	rts
	negc	r0,r0


Combine is looking for a pattern:

Failed to match this instruction:
(set (reg:SI 162 [ D.1652 ])
    (plus:SI (zero_extract:SI (reg:SI 4 r4 [ a ])
            (const_int 1 [0x1])
            (const_int 25 [0x19]))
        (const_int 4 [0x4])))

Which could be implemented with treg_set_expr.
Comment 1 Oleg Endo 2015-07-29 14:42:32 UTC
For some cases where T+const_int is calculated, like ...

int foo (int a, int b)
{
  return a == b ? 5 : 4;
}

comiled with -O2:
	cmp/eq	r5,r4
	movt	r0
	rts	
	add	#4,r0

.. the dependency of the comparison and the T bit store can be reduced:
	cmp/eq	r5,r4
	mov	#2,r0
	rts
	addc	r0,r0

This works only for even constants.
Comment 2 Oleg Endo 2015-07-29 14:53:06 UTC
(In reply to Oleg Endo from comment #0)
> Combine is looking for a pattern:
> 
> Failed to match this instruction:
> (set (reg:SI 162 [ D.1652 ])
>     (plus:SI (zero_extract:SI (reg:SI 4 r4 [ a ])
>             (const_int 1 [0x1])
>             (const_int 25 [0x19]))
>         (const_int 4 [0x4])))
> 
> Which could be implemented with treg_set_expr.

In this case, the treg_set_expr should be only matched if it will expand into a negating T bit store.  For that a new predicate "neg_treg_set_expr" should be added.  sh_recog_treg_set_expr should get an additional parameter whether it should match positive, negative or both forms.