Bug 77407 - Optimize integer i / abs (i) into the sign of i
Summary: Optimize integer i / abs (i) into the sign of i
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 7.0
: P3 enhancement
Target Milestone: 7.0
Assignee: Richard Biener
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2016-08-29 20:04 UTC by Florian Weimer
Modified: 2021-08-10 21:35 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-08-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Florian Weimer 2016-08-29 20:04:26 UTC
I found this gem in some glibc test case:

  if (c != 0)
    c /= abs (c);

This could turn into:

  if (c < 0)
    c = -1;
  else if (c > 0)
    c = 1;

This would eliminate the division and also paper of the bug (the unexpected 1 result for INT_MIN).
Comment 1 Richard Biener 2016-08-30 09:49:58 UTC
Full testcase(?)

int foo (int c)
{
  if (c != 0)
    c /= __builtin_abs (c);
  return c;
}

Possible "fix":

(simplify
 (trunc_div @0 (abs @0))
 (if (! TYPE_UNSIGNED (type)
      && TYPE_OVERFLOW_UNDEFINED (type))
  (cond (lt @0 { build_zero_cst (type); }) { build_minus_one_cst (type); } { build_one_cst (type); })))

but eventually we should simply make __builtin_copysign also work on integers...

Not sure if desirable also for _Complex int and vector int (both handled above).

Need to double-check for non-truncating divisions.

Similar testcase would be

  if (c != 0)
    c /= -c;
Comment 2 Richard Biener 2016-09-29 12:28:39 UTC
Fixed.
Comment 3 Richard Biener 2016-09-29 12:28:51 UTC
Author: rguenth
Date: Thu Sep 29 12:28:19 2016
New Revision: 240616

URL: https://gcc.gnu.org/viewcvs?rev=240616&root=gcc&view=rev
Log:
2016-09-29  Richard Biener  <rguenther@suse.de>

	PR middle-end/77407
	* match.pd: Add X / abs (X) -> X < 0 ? -1 : 1 and
	X / -X -> -1 simplifications.

	* gcc.dg/pr77407.c: New testcase.

Added:
    trunk/gcc/testsuite/gcc.dg/pr77407.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/match.pd
    trunk/gcc/testsuite/ChangeLog
Comment 4 Richard Biener 2016-10-04 13:18:50 UTC
Author: rguenth
Date: Tue Oct  4 13:18:18 2016
New Revision: 240742

URL: https://gcc.gnu.org/viewcvs?rev=240742&root=gcc&view=rev
Log:
2016-10-04  Richard Biener  <rguenther@suse.de>

	PR middle-end/77407
	* match.pd (X / abs (X) -> X < 0 ? -1 : 1): Drop vector
	type support, mark with :C.
	(X / -X -> -1): Mark with :C.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/match.pd