llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.3k stars 11.68k forks source link

PowerPC Clang 16.0.6 emits fsqrt on unsupported CPUs #86415

Open retroman opened 6 months ago

retroman commented 6 months ago

machine: powerpc-unknown-freebsd14.0 -- Power Mac G4 MDD, which has a single PowerPC 7455

The test program below crashes with SIGILL due to encountering an fsqrt instruction when built with the command line: cc -ffast-math -mcpu=603 -lm fsqrt.c and executes normally when built with: cc -ffast-math -mcpu=602 -lm fsqrt.c It also executes normally when built with: cc -ffast-math -fno-finite-math-only -mcpu=603 -lm fsqrt.c

These mcpu types also generate the fsqrt with the test program: 603e, 603ev, 604, 604e, 620, 750, g3, 7400, g4, 7450, g4+. The test program executes normally without -ffast-math with all cpu types above.

This problem is unimportant, and it seems that FreeBSD 14 will be the final release with 32-bit PowerPC support, so this issue may only be useful for documentation.

test program fsqrt.c:

#include <stdio.h>
#include <math.h>

int main(void)
{
        double a = 2.;
        double b;

        b = sqrt(a);

        printf("a=%.1f b=%.1f\n", a, b);

        return 0;
}
brad0 commented 6 months ago

cc @kernigh

llvmbot commented 6 months ago

@llvm/issue-subscribers-backend-powerpc

Author: None (retroman)

machine: powerpc-unknown-freebsd14.0 -- Power Mac G4 MDD, which has a single PowerPC 7455 The test program below crashes with SIGILL due to encountering an fsqrt instruction when built with the command line: cc -ffast-math -mcpu=603 -lm fsqrt.c and executes normally when built with: cc -ffast-math -mcpu=602 -lm fsqrt.c It also executes normally when built with: cc -ffast-math -fno-finite-math-only -mcpu=603 -lm fsqrt.c These mcpu types also generate the fsqrt with the test program: 603e, 603ev, 604, 604e, 620, 750, g3, 7400, g4, 7450, g4+. The test program executes normally without -ffast-math with all cpu types above. This problem is unimportant, and it seems that FreeBSD 14 will be the final release with 32-bit PowerPC support, so this issue may only be useful for documentation. test program fsqrt.c: ``` #include <stdio.h> #include <math.h> int main(void) { double a = 2.; double b; b = sqrt(a); printf("a=%.1f b=%.1f\n", a, b); return 0; } ```
EugeneZelenko commented 6 months ago

Could you please try 18 or main branch?

DimitryAndric commented 6 months ago

Tried this here on FreeBSD 15.0-CURRENT with FreeBSD clang version 18.1.1 (https://github.com/llvm/llvm-project.git llvmorg-18.1.1-0-gdba2a75e9c7e), assuming the target is powerpc-freebsd:

$ ./repro.sh
+ cc -target powerpc-freebsd -ffast-math '-mcpu=603' -S fsqrt.c -o fsqrt-mcpu-603.s
+ cc -target powerpc-freebsd -ffast-math '-mcpu=602' -S fsqrt.c -o fsqrt-mcpu-602.s
+ cc -target powerpc-freebsd -ffast-math -fno-finite-math-only '-mcpu=603' -S fsqrt.c -o fsqrt-mcpu-603-no-finite-math.s

$ grep sqrt *.s
fsqrt-mcpu-602.s:       .file   "fsqrt.c"
fsqrt-mcpu-602.s:       bl sqrt
fsqrt-mcpu-603-no-finite-math.s:        .file   "fsqrt.c"
fsqrt-mcpu-603-no-finite-math.s:        bl sqrt
fsqrt-mcpu-603.s:       .file   "fsqrt.c"
fsqrt-mcpu-603.s:       frsqrte 0, 2
fsqrt-mcpu-603.s:       fsqrt 2, 2

So what seems to happen is that with -mcpu=603, the sqrt() call gets turned into a direct instruction, while with -mcpu=602 or -mcpu=603 -fno-finite-math-only it gets turned into a libcall. Presumably the libcall then has a software-only implementation.

I have no idea whether this behavior is correct or not. @chmeeedalf or @pkubaj are more knowledgeable out PowerPC than me, so maybe they can provide more information?

ecnelises commented 6 months ago

Current POWER ISA says fsqrt is available since 'P2' and fsqrts is available since 'PPC'. Could you check whether 603 supports fsqrts, fsub and fsubs?

From https://stuff.mit.edu/afs/sipb/contrib/doc/specs/ic/cpu/powerpc/mpc603e.pdf :

The following types of instructions are included in this class:

  • Implementation-specific instructions (for example, Load Data TLB Entry (tlbld) and Load Instruction TLB Entry (tlbli) instructions)
  • Optional instructions defined by the PowerPC architecture but not implemented by the 603e (for example, Floating Square Root (fsqrt) and Floating Square Root Single (fsqrts) instructions)
kernigh commented 5 months ago

In my experience, fsqrt and fsqrts are usually missing in 32-bit cpus, but present in 64-bit cpus.

PowerPC Programming Environments Rev. 1, "4.1.3.2.3 Optional Instructions", says,

A defined instruction may be optional. The optional instructions fall into the following categories:

  • General-purpose instructions­—fsqrt and fsqrts
  • Graphics instructions—fres, frsqrte, and fsel
  • ...

Note that the stfiwx instruction is defined as optional by the PowerPC architecture to ensure backwards compatibility with earlier processors; however, it will likely be required for subsequent PowerPC processors.

LLVM might emit fsqrt (square root of double float), fsqrts (square root of single float), fsel (select float by condition), and stfiwx (store float as 32-bit integer). LLVM should avoid fres (reciprocal estimate) and frsqrte (reciprocal square root estimate); many cpus have fsqrte but neither fsqrt nor fsqrts.

The oldest PowerPC models of Apple Macintosh have 601, 603, or 604 cpus, but I know little about them.

Mac G3 models have a 750 cpu, and G4 models have a 7400 or 7450 family cpu. Each has fsel, fres, frsqrte, stfiwx; but, "It does not support the optional fsqrt, fsqrts, and tlbia instructions" (quoting IBM PowerPC 750FX RISC Microprocessor User's Manual, "1.5.2 750FX Microprocessor Instruction Set" and "2.3.1.2 Defined Instruction Class"; similar words appear in the MPC750 and MPC7400 Family and MPC7450 Family manuals).

Mac G5 models have a 970 cpu, which is a 64-bit cpu. It supports fsqrt and fsqrts, along with fres, frsqrte, and fsel (IBM PowerPC 970FX manual, "2.2.1.2 Defined Instructions"). It also has stfiwx, as required by PowerPC 2.01.

I guess that the 603 might also have fsel and stfiwx, and the 601 might not, but I'm not sure. I guess that LLVM should stop using fsqrt or fsqrts on everything from the 603 to the 7450.

fsub (subtract double floats) and fsubs (subtract single floats) should exist on anything with classic floats, including all PowerPC Mac models. (Some other PowerPCs have no floats or SPE floats.)

OpenBSD runs on Mac G3, G4, and G5 models. I have not used clang options like -mcpu=750, so I have not yet encountered this issue.

chmeeedalf commented 3 months ago

This is odd, because FeatureFSqrt is not enabled for the 603 and 603e, not until 970/g5, and most other 64-bit processors (not e5500), see PPC.td. Maybe there's a bug in the codegen that needs an extra hasFSQRT()? I'll guess -ffast-math is ignoring it, but haven't yet reviewed that code.