[PATCH v1] LoongArch: Add relaxation for R_LARCH_CALL36

mengqinggang mengqinggang@loongson.cn
Fri Mar 8 09:28:25 GMT 2024


I'm sorry, this patch is for binutils.


在 2024/3/8 下午5:16, mengqinggang 写道:
> This relaxation is effective for both macro instructions (call36, tail36)
> and explicit relocation instructions (pcaddu18i + jirl).
>
> call36 f	  ->	bl f
>    R_LARCH_CALL36  ->	  R_LARCH_B26
>
> tail36 $t0, f	  ->	b f
>    R_LARCH_CALL36  ->	  R_LARCH_B26
> ---
>   bfd/elfnn-loongarch.c                         | 59 +++++++++++++++++++
>   gas/config/tc-loongarch.c                     | 19 +++++-
>   gas/testsuite/gas/loongarch/medium-call.d     |  7 ++-
>   .../relax-cfi-fde-DW_CFA_advance_loc.d        | 10 ++--
>   .../relax-cfi-fde-DW_CFA_advance_loc.s        |  4 ++
>   .../ld-loongarch-elf/ld-loongarch-elf.exp     |  2 +
>   .../ld-loongarch-elf/relax-medium-call-1.d    | 21 +++++++
>   .../ld-loongarch-elf/relax-medium-call-1.s    | 43 ++++++++++++++
>   .../ld-loongarch-elf/relax-medium-call.d      | 21 +++++++
>   .../ld-loongarch-elf/relax-medium-call.s      | 35 +++++++++++
>   10 files changed, 215 insertions(+), 6 deletions(-)
>   create mode 100644 ld/testsuite/ld-loongarch-elf/relax-medium-call-1.d
>   create mode 100644 ld/testsuite/ld-loongarch-elf/relax-medium-call-1.s
>   create mode 100644 ld/testsuite/ld-loongarch-elf/relax-medium-call.d
>   create mode 100644 ld/testsuite/ld-loongarch-elf/relax-medium-call.s
>
> diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
> index ee99fd7b2f8..c42052f9321 100644
> --- a/bfd/elfnn-loongarch.c
> +++ b/bfd/elfnn-loongarch.c
> @@ -4334,6 +4334,60 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
>     return true;
>   }
>   
> +/* call36 f -> bl f
> +   tail36 $t0, f -> b f.  */
> +static bool
> +loongarch_relax_call36 (bfd *abfd, asection *sec,
> +			    Elf_Internal_Rela *rel, bfd_vma symval,
> +			    struct bfd_link_info *info, bool *again,
> +			    bfd_vma max_alignment)
> +{
> +  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
> +  uint32_t jirl = bfd_get (32, abfd, contents + rel->r_offset + 4);
> +  uint32_t rd = jirl & 0x1f;
> +
> +  /* This section's output_offset need to subtract the bytes of instructions
> +     relaxed by the previous sections, so it needs to be updated beforehand.
> +     size_input_section already took care of updating it after relaxation,
> +     so we additionally update once here.  */
> +  sec->output_offset = sec->output_section->size;
> +  bfd_vma pc = sec_addr (sec) + rel->r_offset;
> +
> +  /* If pc and symbol not in the same segment, add/sub segment alignment.
> +     FIXME: if there are multiple readonly segments? How to determine if
> +     two sections are in the same segment.  */
> +  if (symval > pc)
> +    pc -= (max_alignment > 4 ? max_alignment : 0);
> +  else if (symval < pc)
> +    pc += (max_alignment > 4 ? max_alignment : 0);
> +
> +  const uint32_t jirl_opcode = 0x4c000000;
> +
> +  /* Is pcalau12i + addi.d insns?  */
> +  if ((ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX)
> +      || ((jirl & jirl_opcode) != jirl_opcode)
> +      || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xf8000000)
> +      || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x7fffffc))
> +    return false;
> +
> +  /* Continue next relax trip.  */
> +  *again = true;
> +
> +  const uint32_t bl = 0x54000000;
> +  const uint32_t b = 0x50000000;
> +
> +  if (rd)
> +    bfd_put (32, abfd, bl, contents + rel->r_offset);
> +  else
> +    bfd_put (32, abfd, b, contents + rel->r_offset);
> +
> +  /* Adjust relocations.  */
> +  rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_LARCH_B26);
> +  /* Delete jirl instruction.  */
> +  loongarch_relax_delete_bytes (abfd, sec, rel->r_offset + 4, 4, info);
> +  return true;
> +}
> +
>   /* Relax pcalau12i,ld.d => pcalau12i,addi.d.  */
>   static bool
>   loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
> @@ -4752,6 +4806,11 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>   	      rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
>   	    }
>   	  break;
> +	case R_LARCH_CALL36:
> +	  if (0 == info->relax_pass && (i + 2) <= sec->reloc_count)
> +	    loongarch_relax_call36 (abfd, sec, rel, symval, info, again,
> +				    max_alignment);
> +	  break;
>   
>   	case R_LARCH_TLS_LE_HI20_R:
>   	case R_LARCH_TLS_LE_LO12_R:
> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
> index 4ba547d7bdc..0294771c50f 100644
> --- a/gas/config/tc-loongarch.c
> +++ b/gas/config/tc-loongarch.c
> @@ -116,6 +116,8 @@ const char *md_shortopts = "O::g::G:";
>   
>   static const char default_arch[] = DEFAULT_ARCH;
>   
> +static bool call36 = 0;
> +
>   /* The lowest 4-bit is the bytes of instructions.  */
>   #define RELAX_BRANCH_16 0xc0000014
>   #define RELAX_BRANCH_21 0xc0000024
> @@ -720,7 +722,8 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>   			|| BFD_RELOC_LARCH_TLS_LE_HI20 == reloc_type
>   			|| BFD_RELOC_LARCH_TLS_LE_LO12 == reloc_type
>   			|| BFD_RELOC_LARCH_TLS_LE64_LO20 == reloc_type
> -			|| BFD_RELOC_LARCH_TLS_LE64_HI12 == reloc_type))
> +			|| BFD_RELOC_LARCH_TLS_LE64_HI12 == reloc_type
> +			|| BFD_RELOC_LARCH_CALL36 == reloc_type))
>   		{
>   		  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
>   		  ip->reloc_info[ip->reloc_num].value = const_0;
> @@ -1015,6 +1018,20 @@ append_fixed_insn (struct loongarch_cl_insn *insn)
>   
>     char *f = frag_more (insn->insn_length);
>     move_insn (insn, frag_now, f - frag_now->fr_literal);
> +
> +  if (call36)
> +    {
> +      if (strcmp (insn->name, "jirl") == 0)
> +	{
> +	  /* See comment at end of append_fixp_and_insn.  */
> +	  frag_wane (frag_now);
> +	  frag_new (0);
> +	}
> +      call36 = 0;
> +    }
> +
> +  if (BFD_RELOC_LARCH_CALL36 == insn->reloc_info[0].type)
> +    call36 = 1;
>   }
>   
>   /* Add instructions based on the worst-case scenario firstly.  */
> diff --git a/gas/testsuite/gas/loongarch/medium-call.d b/gas/testsuite/gas/loongarch/medium-call.d
> index 3491760b96a..79d74ba358c 100644
> --- a/gas/testsuite/gas/loongarch/medium-call.d
> +++ b/gas/testsuite/gas/loongarch/medium-call.d
> @@ -1,21 +1,26 @@
>   #as:
>   #objdump: -dr
> +#skip: loongarch32-*-*
>   
>   .*:[    ]+file format .*
>   
>   
>   Disassembly of section .text:
>   
> -.* <.text>:
> +[ 	]*0000000000000000 <.text>:
>   [ 	]+0:[ 	]+1e000001[ 	]+pcaddu18i[ 	]+\$ra, 0
>   [ 	]+0: R_LARCH_CALL36[ 	]+a
> +[ 	]+0: R_LARCH_RELAX[ 	]+\*ABS\*
>   [ 	]+4:[ 	]+4c000021[ 	]+jirl[ 	]+\$ra, \$ra, 0
>   [ 	]+8:[ 	]+1e000001[ 	]+pcaddu18i[ 	]+\$ra, 0
>   [ 	]+8: R_LARCH_CALL36[ 	]+a
> +[ 	]+8: R_LARCH_RELAX[ 	]+\*ABS\*
>   [ 	]+c:[ 	]+4c000021[ 	]+jirl[ 	]+\$ra, \$ra, 0
>   [ 	]+10:[ 	]+1e00000c[ 	]+pcaddu18i[ 	]+\$t0, 0
>   [ 	]+10: R_LARCH_CALL36[ 	]+a
> +[ 	]+10: R_LARCH_RELAX[ 	]+\*ABS\*
>   [ 	]+14:[ 	]+4c000180[ 	]+jr[ 	]+\$t0
>   [ 	]+18:[ 	]+1e00000c[ 	]+pcaddu18i[ 	]+\$t0, 0
>   [ 	]+18: R_LARCH_CALL36[ 	]+a
> +[ 	]+18: R_LARCH_RELAX[ 	]+\*ABS\*
>   [ 	]+1c:[ 	]+4c000180[ 	]+jr[ 	]+\$t0
> diff --git a/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.d b/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.d
> index 6b164cfbf61..d685bd86b51 100644
> --- a/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.d
> +++ b/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.d
> @@ -26,7 +26,7 @@ Disassembly of section .eh_frame:
>   [ 	]+2c:[ 	]+d6400016[ 	]+.word[ 	]+[ 	]+0xd6400016
>   [ 	]+2e: R_LARCH_ADD6[ 	]+L0\^A
>   [ 	]+2e: R_LARCH_SUB6[ 	]+L0\^A
> -[ 	]+30:[ 	]+4000160c[ 	]+beqz[ 	]+\$t4, 3145748[ 	]+# 300044 <L0\^A\+0x2ffffc>
> +[ 	]+30:[ 	]+4000160c[ 	]+beqz[ 	]+\$t4, 3145748[ 	]+# 300044 <L0\^A\+0x2ffff4>
>   [ 	]+33: R_LARCH_ADD6[ 	]+L0\^A
>   [ 	]+33: R_LARCH_SUB6[ 	]+L0\^A
>   [ 	]+34:[ 	]+00160cd6[ 	]+orn[ 	]+\$fp, \$a2, \$sp
> @@ -39,14 +39,16 @@ Disassembly of section .eh_frame:
>   [ 	]+40:[ 	]+d6400016[ 	]+.word[ 	]+[ 	]+0xd6400016
>   [ 	]+42: R_LARCH_ADD6[ 	]+L0\^A
>   [ 	]+42: R_LARCH_SUB6[ 	]+L0\^A
> -[ 	]+44:[ 	]+4000160c[ 	]+beqz[ 	]+\$t4, 3145748[ 	]+# 300058 <L0\^A\+0x300010>
> +[ 	]+44:[ 	]+4000160c[ 	]+beqz[ 	]+\$t4, 3145748[ 	]+# 300058 <L0\^A\+0x300008>
>   [ 	]+47: R_LARCH_ADD6[ 	]+L0\^A
>   [ 	]+47: R_LARCH_SUB6[ 	]+L0\^A
>   [ 	]+48:[ 	]+00160cd6[ 	]+orn[ 	]+\$fp, \$a2, \$sp
>   [ 	]+4c:[ 	]+160cd640[ 	]+lu32i.d[ 	]+\$zero, 26290
>   [ 	]+4c: R_LARCH_ADD6[ 	]+L0\^A
>   [ 	]+4c: R_LARCH_SUB6[ 	]+L0\^A
> -[ 	]+50:[ 	]+00d64000[ 	]+bstrpick.d[ 	]+\$zero, \$zero, 0x16, 0x10
> +[ 	]+50:[ 	]+0cd64000[ 	]+.word[ 	]+[ 	]+0x0cd64000
>   [ 	]+51: R_LARCH_ADD6[ 	]+L0\^A
>   [ 	]+51: R_LARCH_SUB6[ 	]+L0\^A
> -[ 	]+54:[ 	]+00000000[ 	]+.word[ 	]+[ 	]+0x00000000
> +[ 	]+54:[ 	]+d6400016[ 	]+.word[ 	]+[ 	]+0xd6400016
> +[ 	]+56: R_LARCH_ADD6[ 	]+L0\^A
> +[ 	]+56: R_LARCH_SUB6[ 	]+L0\^A
> diff --git a/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.s b/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.s
> index 2c67587b722..021d296a1fc 100644
> --- a/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.s
> +++ b/gas/testsuite/gas/loongarch/relax-cfi-fde-DW_CFA_advance_loc.s
> @@ -38,4 +38,8 @@ la.tls.ie $t0, a
>   la.tls.le $t0, a
>   .cfi_restore 22
>   
> +.cfi_def_cfa 22, 0
> +call36 f
> +.cfi_restore 22
> +
>   .cfi_endproc
> diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
> index 161cc1a4d10..c56bae91c32 100644
> --- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
> +++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
> @@ -52,6 +52,8 @@ if [istarget "loongarch64-*-*"] {
>       run_dump_test "underflow_s_5_20"
>       run_dump_test "tls-le-norelax"
>       run_dump_test "tls-le-relax"
> +    run_dump_test "relax-medium-call"
> +    run_dump_test "relax-medium-call-1"
>   }
>   
>   if [istarget "loongarch32-*-*"] {
> diff --git a/ld/testsuite/ld-loongarch-elf/relax-medium-call-1.d b/ld/testsuite/ld-loongarch-elf/relax-medium-call-1.d
> new file mode 100644
> index 00000000000..c8ee93337db
> --- /dev/null
> +++ b/ld/testsuite/ld-loongarch-elf/relax-medium-call-1.d
> @@ -0,0 +1,21 @@
> +#ld: -e0 -Ttext=0x120000000 --section-start=ta=0x118000000 --section-start=tb=0x127fffffc
> +#objdump: -d -j .text
> +
> +.*:[    ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +[ 	]*0000000120000000 <__bss_start-0x4030>:
> +[ 	]+120000000:[ 	]+54000200[ 	]+bl[ 	]+-134217728[ 	]+# 118000000 <a>
> +[ 	]+120000004:[ 	]+1fffc001[ 	]+pcaddu18i[ 	]+\$ra, -512
> +[ 	]+120000008:[ 	]+4ffffc21[ 	]+jirl[ 	]+\$ra, \$ra, -4
> +[ 	]+12000000c:[ 	]+50000200[ 	]+b[ 	]+-134217728[ 	]+# 11800000c <b>
> +[ 	]+120000010:[ 	]+1fffc00c[ 	]+pcaddu18i[ 	]+\$t0, -512
> +[ 	]+120000014:[ 	]+4ffffd80[ 	]+jirl[ 	]+\$zero, \$t0, -4
> +[ 	]+120000018:[ 	]+1e004001[ 	]+pcaddu18i[ 	]+\$ra, 512
> +[ 	]+12000001c:[ 	]+4c000421[ 	]+jirl[ 	]+\$ra, \$ra, 4
> +[ 	]+120000020:[ 	]+57fffdff[ 	]+bl[ 	]+134217724[ 	]+# 12800001c <c>
> +[ 	]+120000024:[ 	]+1e00400c[ 	]+pcaddu18i[ 	]+\$t0, 512
> +[ 	]+120000028:[ 	]+4c000580[ 	]+jirl[ 	]+\$zero, \$t0, 4
> +[ 	]+12000002c:[ 	]+53fffdff[ 	]+b[ 	]+134217724[ 	]+# 128000028 <d>
> diff --git a/ld/testsuite/ld-loongarch-elf/relax-medium-call-1.s b/ld/testsuite/ld-loongarch-elf/relax-medium-call-1.s
> new file mode 100644
> index 00000000000..5266fdaba7a
> --- /dev/null
> +++ b/ld/testsuite/ld-loongarch-elf/relax-medium-call-1.s
> @@ -0,0 +1,43 @@
> +.section "ta", "ax"
> +a:
> +  ret
> +  ret
> +  ret
> +b:
> +  ret
> +
> +.text
> +  pcaddu18i $ra, %call36(a) # min offset, can relax
> +  jirl	    $ra, $ra, 0
> +  pcaddu18i $ra, %call36(a) # overflow, not relax
> +  jirl	    $ra, $ra, 0
> +  pcaddu18i $t0, %call36(b) # min offset, can relax
> +  jirl	    $zero, $t0, 0
> +  pcaddu18i $t0, %call36(b) # overflow, not relax
> +  jirl	    $zero, $t0, 0
> +
> +  pcaddu18i $ra, %call36(c) # overflow, not relax
> +  jirl	    $ra, $ra, 0
> +  pcaddu18i $ra, %call36(c) # max offset, can relax
> +  jirl	    $ra, $ra, 0
> +  pcaddu18i $t0, %call36(d) # overflow, no relax
> +  jirl	    $zero, $t0, 0
> +  pcaddu18i $t0, %call36(d) # max offset, can relax
> +  jirl	    $zero, $t0, 0
> +
> +.section "tb", "ax"
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +c:
> +  ret
> +  ret
> +  ret
> +d:
> +  ret
> +
> diff --git a/ld/testsuite/ld-loongarch-elf/relax-medium-call.d b/ld/testsuite/ld-loongarch-elf/relax-medium-call.d
> new file mode 100644
> index 00000000000..c8ee93337db
> --- /dev/null
> +++ b/ld/testsuite/ld-loongarch-elf/relax-medium-call.d
> @@ -0,0 +1,21 @@
> +#ld: -e0 -Ttext=0x120000000 --section-start=ta=0x118000000 --section-start=tb=0x127fffffc
> +#objdump: -d -j .text
> +
> +.*:[    ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +[ 	]*0000000120000000 <__bss_start-0x4030>:
> +[ 	]+120000000:[ 	]+54000200[ 	]+bl[ 	]+-134217728[ 	]+# 118000000 <a>
> +[ 	]+120000004:[ 	]+1fffc001[ 	]+pcaddu18i[ 	]+\$ra, -512
> +[ 	]+120000008:[ 	]+4ffffc21[ 	]+jirl[ 	]+\$ra, \$ra, -4
> +[ 	]+12000000c:[ 	]+50000200[ 	]+b[ 	]+-134217728[ 	]+# 11800000c <b>
> +[ 	]+120000010:[ 	]+1fffc00c[ 	]+pcaddu18i[ 	]+\$t0, -512
> +[ 	]+120000014:[ 	]+4ffffd80[ 	]+jirl[ 	]+\$zero, \$t0, -4
> +[ 	]+120000018:[ 	]+1e004001[ 	]+pcaddu18i[ 	]+\$ra, 512
> +[ 	]+12000001c:[ 	]+4c000421[ 	]+jirl[ 	]+\$ra, \$ra, 4
> +[ 	]+120000020:[ 	]+57fffdff[ 	]+bl[ 	]+134217724[ 	]+# 12800001c <c>
> +[ 	]+120000024:[ 	]+1e00400c[ 	]+pcaddu18i[ 	]+\$t0, 512
> +[ 	]+120000028:[ 	]+4c000580[ 	]+jirl[ 	]+\$zero, \$t0, 4
> +[ 	]+12000002c:[ 	]+53fffdff[ 	]+b[ 	]+134217724[ 	]+# 128000028 <d>
> diff --git a/ld/testsuite/ld-loongarch-elf/relax-medium-call.s b/ld/testsuite/ld-loongarch-elf/relax-medium-call.s
> new file mode 100644
> index 00000000000..c0521b65732
> --- /dev/null
> +++ b/ld/testsuite/ld-loongarch-elf/relax-medium-call.s
> @@ -0,0 +1,35 @@
> +.section "ta", "ax"
> +a:
> +  ret
> +  ret
> +  ret
> +b:
> +  ret
> +
> +.text
> +  call36 a	# min offset, can relax
> +  call36 a	# overflow, not relax
> +  tail36 $t0, b	# min offset, can relax
> +  tail36 $t0, b	# overflow, not relax
> +
> +  call36 c	# overflow, not relax
> +  call36 c	# max offset, can relax
> +  tail36 $t0, d	# overflow, no relax
> +  tail36 $t0, d # max offset, can relax
> +
> +.section "tb", "ax"
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +  ret
> +c:
> +  ret
> +  ret
> +  ret
> +d:
> +  ret
> +



More information about the Libc-alpha mailing list