Bug 14617 - [tree-ssa] suboptimal code ('0' <= c && c <= '9') ? c - '0' : 0
Summary: [tree-ssa] suboptimal code ('0' <= c && c <= '9') ? c - '0' : 0
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: tree-ssa
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on: 52157
Blocks: 65964
  Show dependency treegraph
 
Reported: 2004-03-17 09:03 UTC by Kazu Hirata
Modified: 2015-05-01 21:23 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-02-07 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kazu Hirata 2004-03-17 09:03:16 UTC
Here is what I get with the current tree-ssa:

int
foo (char c)
{
  return ('0' <= c && c <= '9') ? c - '0' : 0;
}
/*
	movzbl	4(%esp), %ecx
	xorl	%eax, %eax
	movb	%cl, %dl
	subb	$48, %dl
	cmpb	$9, %dl
	ja	.L4
	movsbl	%cl,%eax      ; extending again (but this time sign-ext)?
	subl	$48, %eax     ; again subtracting 48 (but in different mode)?
.L4:
	ret
*/

int
bar (char c)
{
  c -= '0';
  return ((unsigned char) c <= 9) ? c : 0;
}
/*
	movzbl	4(%esp), %ecx
	xorl	%eax, %eax
	subb	$48, %cl
	movsbl	%cl,%edx      ; extending again (but this time sign-ext)?
	cmpb	$10, %cl
	cmovb	%edx, %eax
*/

int
baz (char c)
{
  int tem = c;
  tem -= '0';
  return ((unsigned char) tem <= 9) ? tem : 0;
}
/*
	movsbl	4(%esp), %edx
	xorl	%eax, %eax
	subl	$48, %edx
	cmpb	$10, %dl
	cmovb	%edx, %eax
*/

For "foo", here is what I get right before TER:

foo (c)
{
  unsigned int tem;
  unsigned char T.6;
  int iftmp.5;
  unsigned char c.4;
  int T.3;
  unsigned char T.2;
  char T.1;
  int iftmp.0;

<bb 0>:
  T.1_3 = c_2 - 48;
  T.2_4 = (unsigned char)T.1_3;
  if (T.2_4 <= 9) goto <L0>; else goto <L2>;

<L0>:;
  T.3_7 = (int)c_2;
  iftmp.0_8 = T.3_7 - 48;

  # iftmp.0_1 = PHI <0(0), iftmp.0_8(1)>;
<L2>:;
  return iftmp.0_1;

}

Note that if we extended c_2 earlier and did all the computation in int
wherever possible, it would be pretty easy to avoid subtracting of 48 twice.
The idea of extending everything first comes from a paper

Effective Sign Extension Elimination
Kawahito, Komatsu, and Nakatani
http://www.trl.ibm.com/projects/jit/paper/sxt.pdf
Comment 1 Andrew Pinski 2004-03-17 16:03:22 UTC
Confirmed, the issue here is a little more complated than the other PR, the problem is fold converts ('0' 
<= c && c <= '9') into "(c - '0') <= 9u"  but it converts the types to unsigned int as it wants to do an 
unsigned comparision.  The other issue since the subtracts is done in two different types it is not 
recognized by either DOM or PRE.
Comment 2 Andrew Pinski 2012-02-07 20:18:59 UTC
I have a patch which improves this to:
<bb 2>:
  D.1957_3 = (unsigned int) c_2(D);
  D.1958_4 = D.1957_3 + 4294967248;
  if (D.1958_4 <= 9)
    goto <bb 3>;
  else
    goto <bb 4>;

<bb 3>:
  D.1961_5 = (int) c_2(D);
  D.1955_6 = D.1961_5 + -48;

<bb 4>:
  # D.1955_1 = PHI <D.1955_6(3), 0(2)>

--- CUT ---
Note the addition is found via PRE on the RTL level though and then we convert it to the an ifconversion but we should able to find that on TREE Level.