[Bug middle-end/91687] New: Fused multiply subtract not generated when same operand appears in multiplication and subtraction.

2019-09-06 Thread barnaby.wilks at arm dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91687

Bug ID: 91687
   Summary: Fused multiply subtract not generated when same
operand appears in multiplication and subtraction.
   Product: gcc
   Version: 10.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: middle-end
  Assignee: unassigned at gcc dot gnu.org
  Reporter: barnaby.wilks at arm dot com
  Target Milestone: ---

Some architectures have instructions that allow the expressions of the form
"(x * y) - z" to be done in one instruction (for example the FNMSUB instruction
in AArch64).

For example

float f (float x, float y, float z) {
  return (y * x) - z;
}

Will generate

f:
  fnmsub  s0, s0, s1, s2
  ret

This is done with -O2/-O3 with GCC but if -funsafe-math-optimizations are
enabled
it will convert expressions of the form
  (x * y) - x
to
  (x - 1) * y

which then means that the FNMSUB instruction is not generated.

For example on AArch64 trunk (with -O2 -funsafe-math-optimizations)

float f (float x, float y) {
return (y * x) - y;
}

will generate

f:
  fmovs2, 1.0e+0
  fsubs0, s0, s2
  fmuls0, s0, s1
  ret

whereas if you just compile with (-funsafe-math-optimizations) then the correct
code will be generated.

f:
  fnmsub  s0, s1, s0, s1
  ret

This also happens on x86-64.

Godbolt demonstrating the problem.
https://godbolt.org/z/HuU5LO

[Bug middle-end/91687] Fused multiply subtract not generated when same operand appears in multiplication and subtraction.

2019-09-06 Thread barnaby.wilks at arm dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91687

--- Comment #1 from barnaby.wilks at arm dot com ---
(In reply to barnaby.wilks from comment #0)
> Some architectures have instructions that allow the expressions of the form
> "(x * y) - z" to be done in one instruction (for example the FNMSUB
> instruction in AArch64).
> 
> For example
> 
> float f (float x, float y, float z) {
>   return (y * x) - z;
> }
> 
> Will generate
> 
> f:
>   fnmsub  s0, s0, s1, s2
>   ret
> 
> This is done with -O2/-O3 with GCC but if -funsafe-math-optimizations are
> enabled
> it will convert expressions of the form
>   (x * y) - x
> to
>   (x - 1) * y
> 
> which then means that the FNMSUB instruction is not generated.
> 
> For example on AArch64 trunk (with -O2 -funsafe-math-optimizations)
> 
> float f (float x, float y) {
> return (y * x) - y;
> }
> 
> will generate
> 
> f:
>   fmovs2, 1.0e+0
>   fsubs0, s0, s2
>   fmuls0, s0, s1
>   ret
> 
> whereas if you just compile with (-funsafe-math-optimizations) then the
> correct
> code will be generated.

Ah, wrote the wrong thing :D
Here it should say

  > whereas if you just compile with -O2 then the
  > correct code will be generated.

The problem only occurs with -funsafe-math-optimizations.

> f:
>   fnmsub  s0, s1, s0, s1
>   ret
> 
> This also happens on x86-64.
> 
> Godbolt demonstrating the problem.
> https://godbolt.org/z/HuU5LO