| /* { dg-do compile } */ |
| /* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */ |
| /* { dg-do run { target { s390_z14_hw } } } */ |
| #include <assert.h> |
| #include <stdint.h> |
| |
| __attribute__ ((noipa)) static long double |
| sqxbr (long double x) |
| { |
| register long double inout asm("f4") = x; |
| |
| asm("sqxbr\t%0,%0" : "+f"(inout)); |
| asm("# %0" : "+f"(inout)); |
| |
| return inout; |
| } |
| |
| /* Ideally there should be just one `vmrlg %v6,%v4,%v6`, but the compiler |
| * can't optimize it away, because the UNSPEC pattern operates on the whole |
| * register. Using the SUBREG pattern solves this problem, but it's fragile. |
| */ |
| /* { dg-final { scan-assembler-times {\n\tvmrlg\t%v6,%v4,%v6\n} 2 } } */ |
| /* { dg-final { scan-assembler-times {\n\tvmrhg\t%v4,%v4,%v6\n} 2 } } */ |
| |
| int |
| main (void) |
| { |
| long double x = 0x1.0000000000001p+0L, |
| exp = 1.00000000000000011102230246251564788e+0L; |
| assert (sqxbr (x) == exp); |
| } |