Bug 512030 - s390x: bfp-convert testcase fails
Summary: s390x: bfp-convert testcase fails
Status: RESOLVED FIXED
Alias: None
Product: valgrind
Classification: Developer tools
Component: vex (other bugs)
Version First Reported In: unspecified
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Julian Seward
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-11-13 11:41 UTC by Florian Krohm
Modified: 2025-11-19 10:03 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Florian Krohm 2025-11-13 11:41:47 UTC
The testcase fails on lfedora1.lf-dev.marist.edu with gcc 15.2.1 and binutils 2.44-6
Here is the reproducer:

int main(void)
{
  asm volatile ("csch");          // begin mark: do not remove

  asm volatile("clfxbr	%r9,3,%f0,0");  // 128-bit BFP --> 32-bit unsigned int
  asm volatile("ipm	%r1");

  asm volatile ("lghi %r1,1");    // __NR_exit
  asm volatile ("lghi %r2,0");    // return code = 0
  asm volatile ("svc 0");         // terminate process
  asm volatile ("csch");          // end mark: do not remove
  return 0;
}

$ auxprogs/s390-runone -b foo.c
$ ./vg-in-place --tool=none ./foo

==2533622== Process terminating with default action of signal 4 (SIGILL)
==2533622==  Illegal operand at address 0x80014127A

In the trace we see this:
if (always) s390_calculate_cc{0x8001406A0}(r2, r3, r4, r5)

with r2 == 38  (S390_CC_OP_BFP_128_TO_UINT_32)

In s390_calculate_cc:

   case S390_CC_OP_BFP_128_TO_UINT_32:
      return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1,
                                         cc_dep2, cc_ndep);

which expands for rounding_mode == 3 to:

   case S390_BFP_ROUND_PREPARE_SHORT:                                 \
      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,3); \
      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,3);            \
      break;                                                     

There is a dead assignment which is highly suspicious. As obvious when inspecting context,
 the 2nd one needs to go. And it is that macro which is responsible for the build failure.
It gets passed an opcode that wants to read 128 bit but only 64 are provided.

Removing that macro fixes the problem. However:

#define S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \
({ \
   union s390x_F128 op = { .i = { hi, lo } }; \
   ULong tmp; \
   __asm__ volatile ( \
        opcode ",%[tmp],%[op]," #rounding_mode ",0\n\t" \
        "ipm %[psw]\n\t"           : [psw] "=d"(psw), [tmp] "=d"(tmp) \
                                   : [op] "f"(op.f) \
                                   : "cc");\
   psw >> 28;   /* cc */ \
})

This also looks suspicious. How does the compiler know that op.f needs to be put in
a register that is valid to identify a floating point register pair ???
There is no gcc constraint for register pairs on s390 AFAICT.
Comment 1 Florian Krohm 2025-11-13 11:54:14 UTC
Fixed in 95cf5eed209f38b8d3e1bc61a68278be420c2778.

I'm leaving this open. Likely the .insn opcode specification needs to be replaced with
the mnemonic.
Comment 2 Andreas Arnez 2025-11-18 13:04:51 UTC
(In reply to Florian Krohm from comment #0)
[...]
> This also looks suspicious. How does the compiler know that op.f needs to be
> put in
> a register that is valid to identify a floating point register pair ???
> There is no gcc constraint for register pairs on s390 AFAICT.
No, that should be OK. The compiler knows that the data type of `op.f', Float128 (== long double) requires a register pair when storing it in floating-point registers.
Comment 3 Florian Krohm 2025-11-19 10:03:58 UTC
OK, good. Thanks for the explanation. Closing this now.