[PATCH 8/8] s390: Store SFrame CFA offset adjusted and scaled down

Indu Bhagat indu.bhagat@oracle.com
Thu Apr 17 18:53:47 GMT 2025


On 4/2/25 9:12 AM, Jens Remus wrote:
> In SFrame V2 the size of the one to three offsets following a SFrame FDE

"following an SFrame FRE"

Also, I would avoid saying "of the one to three offsets".  The format by 
itself does not limit the number of offsets, though for all current 
practical usages, we see 1-3 offsets.  It is, of course, not recommended 
to use the format to encode large number of offsets.

So it can be confusing to see that in git logs.

> 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 S390 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_S390_CFA_OFFSET_ALIGNMENT_FACTOR): Define
> 	s390x-specific CFA offset alignment factor.
> 	(SFRAME_V2_FRE_S390_CFA_OFFSET_ENCODE,
> 	SFRAME_V2_FRE_S390_CFA_OFFSET_DECODE): Scale down/up by
> 	SFRAME_S390_CFA_OFFSET_ALIGNMENT_FACTOR.
> 
> libsframe/
> 	* doc/sframe-spec.texi (S390,
> 	SFRAME_S390_CFA_OFFSET_ALIGNMENT_FACTOR): Document S390-specific
> 	CFA offset alignment factor.
> 
> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
> ---
> 
> Notes (jremus):
>      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 | 13 ++++++++-----
>   2 files changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/include/sframe.h b/include/sframe.h
> index 325bc6b8b5dc..06474970ccc4 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 S390, 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 S390 is always 8-byte aligned.  */
>   #define SFRAME_S390_CFA_OFFSET_ADJUSTMENT	SFRAME_S390_SP_VAL_OFFSET
> +#define SFRAME_S390_CFA_OFFSET_ALIGNMENT_FACTOR	8
>   #define SFRAME_V2_FRE_S390_CFA_OFFSET_ENCODE(offset) \
> -  ((offset) + SFRAME_S390_CFA_OFFSET_ADJUSTMENT)
> +  (((offset) + SFRAME_S390_CFA_OFFSET_ADJUSTMENT) \
> +   / SFRAME_S390_CFA_OFFSET_ALIGNMENT_FACTOR)
>   #define SFRAME_V2_FRE_S390_CFA_OFFSET_DECODE(offset) \
> -  ((offset) - SFRAME_S390_CFA_OFFSET_ADJUSTMENT)
> +  (((offset) * SFRAME_S390_CFA_OFFSET_ALIGNMENT_FACTOR) \
> +   - SFRAME_S390_CFA_OFFSET_ADJUSTMENT)
>   
>   /* On S390, 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 f9a117d55cc8..d080f02e7bc5 100644
> --- a/libsframe/doc/sframe-spec.texi
> +++ b/libsframe/doc/sframe-spec.texi
> @@ -838,12 +838,15 @@ Hence, in summary:
>   
>   Irrespective of the ABI, the first stack offset is always used to locate the
>   CFA.  On S390 the value of the offset is stored adjusted by the S390-specific
> -@code{SFRAME_S390_CFA_OFFSET_ADJUSTMENT} to enable the use of signed 8-bit
> -offsets on S390.
> +@code{SFRAME_S390_CFA_OFFSET_ADJUSTMENT} and scaled down by the S390-specific
> +@code{SFRAME_S390_CFA_OFFSET_ALIGNMENT_FACTOR}, to enable and improve the use
> +of signed 8-bit offsets on S390.
>   S390-specific helpers @code{SFRAME_V2_FRE_S390_CFA_OFFSET_ENCODE} and
> -@code{SFRAME_V2_FRE_S390_CFA_OFFSET_DECODE} are provided to perform and undo the
> -adjustment.  The CFA offset can therefore be interpreted as:
> -CFA = @code{BASE_REG} + offset1 - @code{SFRAME_S390_CFA_OFFSET_ADJUSTMENT}
> +@code{SFRAME_V2_FRE_S390_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_S390_CFA_OFFSET_ALIGNMENT_FACTOR})
> +    - @code{SFRAME_S390_CFA_OFFSET_ADJUSTMENT}
>   or
>   CFA = @code{BASE_REG} + @code{SFRAME_V2_FRE_S390_CFA_OFFSET_DECODE(offset1)}.
>   The identification of the @code{BASE_REG} is done by using the

Was it considered to apply the scaling down for all stack offsets 
uniformly ?  It looks to me that the benefit of that will be simply 
uniformity, and not so much size benefits.  But I am curious to know 
your opinion (or any experimentation) on this.



More information about the Binutils mailing list