[PATCH v2 09/11] s390: Store SFrame CFA offset adjusted and scaled down

Jens Remus jremus@linux.ibm.com
Tue May 27 11:07:23 GMT 2025


In SFrame V2 the size of the offsets following an SFrame FRE can be
either signed 8-bit, 16-bit, or 32-bit integer, which the largest offset
determining their size:
  1. CFA offset from CFA base register
  2. RA (stack save slot) offset from CFA, usually -48 on s390x if saved
  3. FP (stack save slot) offset from CFA, usually -72 on s390x if saved
The FP and RA offsets from CFA, when FP/RA saved on the stack, usually
have fixed values that fit into signed 8-bit SFrame offsets.  Likewise
the DWARF register numbers on s390x of general registers (GR; 0-15) and
floating-point registers (FPR; 16-31), when FP/RA saved in registers.
With that the CFA offset from CFA base register has the greatest impact
on the signed SFrame offset size.

The s390x ELF ABI defines the stack pointer (SP) to be 8-byte aligned
[1] and the CFA as SP at call site + 160 [2].  The CFA offset from CFA
base register is therefore always a multiple of 8.

On s390x store the SFrame CFA offset from CFA base register scaled down
by the s390x-specific CFA alignment factor of 8, in addition to the
adjustment by the s390x-specific CFA adjustment of -160, to further
improve the use of signed 8-bit SFrame offsets.  This is similar to the
DWARF data alignment factor getting factored out from certain offsets
stored in DWARF CFI.

[1]: s390x ELF ABI, sections "Register Roles" and "Stack Frame
     Allocation", https://github.com/IBM/s390x-abi/releases
[2]: s390x ELF ABI, commit 4e38ad9c8a88 ("Document the CFA"),
     https://github.com/IBM/s390x-abi/commit/4e38ad9c8a88

include/
	* sframe.h (SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR): Define
	s390x-specific CFA offset alignment factor.
	(SFRAME_V2_FRE_S390X_CFA_OFFSET_ENCODE,
	SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE): Scale down/up by
	SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR.

libsframe/
	* doc/sframe-spec.texi (s390x,
	SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR): Document s390x-
	specific CFA offset alignment factor.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---

Notes (jremus):
    Changes in V2:
    - Reword commit message (s390 to s390x, offsets, FDE to FRE). (Indu)
    - Rename s390x-specific macros from *_S390_* to *_S390X_*. (Indu)
    - Use "s390x" instead of "S390" in comments and SFrame spec. (Indu)
    - Change order of CFA restore instructions in SFrame spec. (Indu)
    
    A test build of Glibc tag 2.41 on s390x libc.so shows an additional ~9%
    reduction in .sframe section size due to storing the SFrame CFA offsets
    scaled down by 8 in addition to the adjustment by -160.  In total
    adjusting and scaling down reduces the .sframe size by ~17%.  The
    overall number of offsets larger than 8-bit is effectively reduced down
    to ~2.4%.
    
    Statistics for libc.so - base (no CFA offset adjustment nor scaling):
    
      .sframe size:  169,749 bytes
    
      VALUE        TOTAL      MIN        MAX        AVG
      FDEs:        3652       -          -          -
      FREs/FDE:    15236      1          20         4
      Offsets/FDE: 29792      1          38         8
         8-bit:    0          0          0          0
        16-bit:    29792      1          38         8
        32-bit:    0          0          0          0
      Offsets/FRE: 29792      1          3          1
         8-bit:    -          0          0          0
        16-bit:    -          1          3          1
        32-bit:    -          0          0          0
      O_Padd/FDE:  342        -          -          0
         8-bit:    0
        16-bit:    342
        32-bit:    0
    
    Statistics for libc.so - CFA offset adjustment (no scaling):
    
      .sframe size: 154,757 bytes
    
      VALUE        TOTAL      MIN        MAX        AVG
      FDEs:        3654       -          -          -
      FREs/FDE:    15238      1          20         4
      Offsets/FDE: 29794      1          38         8
         8-bit:    14992      1          38         4
        16-bit:    14802      0          0          4
        32-bit:    0          0          0          0
      Offsets/FRE: 29794      2          6          1
         8-bit:    -          1          3          0
        16-bit:    -          1          3          0
        32-bit:    -          0          0          0
      O_Padd/FDE:  342        -          -          0
         8-bit:    283
        16-bit:    59
        32-bit:    0
    
    Statistics for libc.so - CFA offset adjustment and scaling:
    
      .sframe size: 140,657 bytes
    
      VALUE        TOTAL      MIN        MAX        AVG
      FDEs:        3654       -          -          -
      FREs/FDE:    15238      1          20         4
      Offsets/FDE: 29794      1          38         8
         8-bit:    29092      1          38         7
        16-bit:    702        0          0          0
        32-bit:    0          0          0          0
      Offsets/FRE: 29794      3          6          1
         8-bit:    -          1          3          1
        16-bit:    -          2          3          0
        32-bit:    -          0          0          0
      O_Padd/FDE:  342        -          -          0
         8-bit:    342
        16-bit:    0
        32-bit:    0

 include/sframe.h               | 11 ++++++++---
 libsframe/doc/sframe-spec.texi | 15 +++++++++------
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/include/sframe.h b/include/sframe.h
index 43cebc1b49cc..7fc592ab848e 100644
--- a/include/sframe.h
+++ b/include/sframe.h
@@ -365,12 +365,17 @@ typedef struct sframe_frame_row_entry_addr4
   (1ULL << ((SFRAME_FRE_TYPE_ADDR4 * 2) * 8))
 
 /* On s390x, the CFA offset from CFA base register is by definition a minimum
-   of 160.  Store it adjusted by -160 to enable use of 8-bit SFrame offsets.  */
+   of 160.  Store it adjusted by -160 to enable use of 8-bit SFrame offsets.
+   Additionally scale by an alignment factor of 8, as the SP and thus CFA
+   offset on s390x is always 8-byte aligned.  */
 #define SFRAME_S390X_CFA_OFFSET_ADJUSTMENT		SFRAME_S390X_SP_VAL_OFFSET
+#define SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR	8
 #define SFRAME_V2_FRE_S390X_CFA_OFFSET_ENCODE(offset) \
-  ((offset) + SFRAME_S390X_CFA_OFFSET_ADJUSTMENT)
+  (((offset) + SFRAME_S390X_CFA_OFFSET_ADJUSTMENT) \
+   / SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR)
 #define SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE(offset) \
-  ((offset) - SFRAME_S390X_CFA_OFFSET_ADJUSTMENT)
+  (((offset) * SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR) \
+   - SFRAME_S390X_CFA_OFFSET_ADJUSTMENT)
 
 /* On s390x, the CFA is defined as SP at call site + 160.  Therefore the
    SP value offset from CFA is -160.  */
diff --git a/libsframe/doc/sframe-spec.texi b/libsframe/doc/sframe-spec.texi
index 8497619de427..650bd361c543 100644
--- a/libsframe/doc/sframe-spec.texi
+++ b/libsframe/doc/sframe-spec.texi
@@ -846,14 +846,17 @@ in any stack frame.
 
 Irrespective of the ABI, the first stack offset is always used to locate the
 CFA.  On s390x the value of the offset is stored adjusted by the s390x-specific
-@code{SFRAME_S390X_CFA_OFFSET_ADJUSTMENT} to enable the use of signed 8-bit
-offsets on s390x.
+@code{SFRAME_S390X_CFA_OFFSET_ADJUSTMENT} and scaled down by the s390x-specific
+@code{SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR}, to enable and improve the use
+of signed 8-bit offsets on s390x.
 s390x-specific helpers @code{SFRAME_V2_FRE_S390X_CFA_OFFSET_ENCODE} and
-@code{SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE} are provided to perform and undo
-the adjustment.  The CFA offset can therefore be interpreted as:
-CFA = @code{BASE_REG} + @code{SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE(offset1)}
+@code{SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE} are provided to perform or undo
+the adjustment and scaling.  The CFA offset can therefore be interpreted as:
+CFA = @code{BASE_REG} + offset1 - @code{SFRAME_S390X_CFA_OFFSET_ADJUSTMENT}
 or
-CFA = @code{BASE_REG} + offset1 - @code{SFRAME_S390X_CFA_OFFSET_ADJUSTMENT}.
+CFA = @code{BASE_REG}
+    + (offset1 * @code{SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR})
+    - @code{SFRAME_S390X_CFA_OFFSET_ADJUSTMENT}.
 The identification of the @code{BASE_REG} is done by using the
 @code{fre_cfa_base_reg_id} field in the SFrame FRE info word.
 
-- 
2.45.2



More information about the Binutils mailing list