public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Jinyang He <hejinyang@loongson.cn>
To: Chenghua Xu <xuchenghua@loongson.cn>,
	Zhensong Liu <liuzhensong@loongson.cn>,
	mengqinggang <mengqinggang@loongson.cn>,
	WANG Xuerui <i.swmail@xen0n.name>
Cc: binutils@sourceware.org, Xing Li <lixing@loongson.cn>,
	yala <zhaojunchao@loongson.cn>, Peng Fan <fanpeng@loongson.cn>
Subject: [PATCH 2/2] LoongArch: bfd: Add counter to get real relax region
Date: Tue, 11 Jul 2023 16:49:31 +0800	[thread overview]
Message-ID: <20230711084931.18978-2-hejinyang@loongson.cn> (raw)
In-Reply-To: <20230711084931.18978-1-hejinyang@loongson.cn>

The relax action, loongarch_relax_pcala_addi and loongarch_relax_align,
may reduce the pc value of later instructions. Add counter to count
the number of bytes or instructions deleted. And recalculate the relax
region in loongarch_relax_pcala_addi.

bfd/ChangeLog:

	* elfnn-loongarch.c (loongarch_elf_relax_section): Add vars
	to count the deleted instructions and the maximum number of
	instructions that may be deleted due to R_LARCH_ALIGN.
	(loongarch_relax_pcala_addi): Adjust the relax decision range.

ld/ChangeLog:

	* testsuite/ld-loongarch-elf/relax.exp: Add test.
	* testsuite/ld-loongarch-elf/relax-edge1.s: New test.
	* testsuite/ld-loongarch-elf/relax-edge2.s: New test.
	* testsuite/ld-loongarch-elf/relax-edge1.dd: New test.
	* testsuite/ld-loongarch-elf/relax-edge2.dd: New test.
---
 bfd/elfnn-loongarch.c                        | 31 +++++++++++++++-----
 ld/testsuite/ld-loongarch-elf/relax-edge1.dd |  6 ++++
 ld/testsuite/ld-loongarch-elf/relax-edge1.s  | 25 ++++++++++++++++
 ld/testsuite/ld-loongarch-elf/relax-edge2.dd |  8 +++++
 ld/testsuite/ld-loongarch-elf/relax-edge2.s  | 15 ++++++++++
 ld/testsuite/ld-loongarch-elf/relax.exp      | 20 +++++++++++++
 6 files changed, 98 insertions(+), 7 deletions(-)
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-edge1.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-edge1.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-edge2.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-edge2.s

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 01f349a24..52f8ab764 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -3700,16 +3700,19 @@ loongarch_relax_delete_bytes (bfd *abfd,
 /* Relax pcalau12i,addi.d => pcaddi.  */
 static bool
 loongarch_relax_pcala_addi (bfd *abfd, asection *sec,
-		       Elf_Internal_Rela *rel_hi, bfd_vma symval)
+		       Elf_Internal_Rela *rel_hi, bfd_vma symval,
+		       uint32_t align_max_deleted, uint32_t *pcnt_deleted)
 {
   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   Elf_Internal_Rela *rel_lo = rel_hi + 2;
   uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
   uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
   uint32_t rd = pca & 0x1f;
-  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
+  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset - *pcnt_deleted * 4;
   const uint32_t addi_d = 0x02c00000;
   const uint32_t pcaddi = 0x18000000;
+  bfd_signed_vma low = (bfd_signed_vma)(int32_t)0xffe00000;
+  bfd_signed_vma high = (bfd_signed_vma)(int32_t)0x1ffffc - align_max_deleted;
 
   /* Is pcalau12i + addi.d insns?  */
   if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_PCALA_LO12)
@@ -3722,8 +3725,8 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec,
       || (((add >> 5) & 0x1f) != rd)
       /* Can be relaxed to pcaddi?  */
       || (symval & 0x3) /* 4 bytes align.  */
-      || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xffe00000)
-      || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x1ffffc))
+      || ((bfd_signed_vma)(symval - pc) < low)
+      || ((bfd_signed_vma)(symval - pc) > high))
     return false;
 
   pca = pcaddi | rd;
@@ -3734,6 +3737,7 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec,
 				 R_LARCH_PCREL20_S2);
   rel_lo->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
 				 R_LARCH_DELETE);
+  (*pcnt_deleted) += 1;
 
   return true;
 }
@@ -3840,6 +3844,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
   struct bfd_elf_section_data *data = elf_section_data (sec);
   Elf_Internal_Rela *relocs;
   *again = false;
+  uint32_t cnt_deleted = 0, align_max_deleted = 0;
 
   if (bfd_link_relocatable (info)
       || sec->sec_flg0
@@ -3881,6 +3886,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
       bool local_got = false;
       char symtype;
       struct elf_link_hash_entry *h = NULL;
+      bool relaxed = false;
 
       if (r_symndx < symtab_hdr->sh_info)
 	{
@@ -3954,6 +3960,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 	case R_LARCH_ALIGN:
 	  if (2 == info->relax_pass)
 	    loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval);
+	  else if (0 == info->relax_pass)
+	    align_max_deleted += rel->r_addend;
 	  break;
 	case R_LARCH_DELETE:
 	  if (info->relax_pass == 1)
@@ -3961,23 +3969,32 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 	      loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, info);
 	      rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
 	    }
+	  else if (0 == info->relax_pass)
+	    cnt_deleted += 1;
 	  break;
 	case R_LARCH_PCALA_HI20:
 	  if (info->relax_pass == 0)
 	    {
 	      if (i + 4 > sec->reloc_count)
 		break;
-	      loongarch_relax_pcala_addi (abfd, sec, rel, symval);
+	      relaxed = loongarch_relax_pcala_addi (abfd, sec, rel, symval,
+						    align_max_deleted, &cnt_deleted);
+	      /* Skip the next R_LARCH_{RELAX, PCALA_LO12, RELAX} relocs. */
+	      if (relaxed)
+		i += 3;
 	    }
 	  break;
 	case R_LARCH_GOT_PC_HI20:
-	  if (local_got)
+	  if (info->relax_pass == 0 && local_got)
 	    {
 	      if (i + 4 > sec->reloc_count)
 		break;
 	      if (loongarch_relax_pcala_ld (abfd, sec, rel))
 		{
-		  loongarch_relax_pcala_addi (abfd, sec, rel, symval);
+		  relaxed = loongarch_relax_pcala_addi (abfd, sec, rel, symval,
+							align_max_deleted, &cnt_deleted);
+		  if (relaxed)
+		    i += 3;
 		}
 	    }
 	  break;
diff --git a/ld/testsuite/ld-loongarch-elf/relax-edge1.dd b/ld/testsuite/ld-loongarch-elf/relax-edge1.dd
new file mode 100644
index 000000000..92836e679
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-edge1.dd
@@ -0,0 +1,6 @@
+#...
+.*pcaddi.*
+.*pcalau12i.*
+.*addi.*
+.*pcaddi.*
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/relax-edge1.s b/ld/testsuite/ld-loongarch-elf/relax-edge1.s
new file mode 100644
index 000000000..df16c1384
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-edge1.s
@@ -0,0 +1,25 @@
+  .data
+  .type obj1, @object
+obj1:
+  .word 0
+  .size obj1, .-obj1
+
+  .space 8
+
+  .type obj2, @object
+obj2:
+  .word 0
+  .size obj2, .-obj2
+
+  .text
+main:
+  la.local $a0, obj1
+  la.local $a0, obj3
+  la.local $a0, obj2
+
+  .bss
+  .space 0x4
+  .type obj3, @object
+obj3:
+  .word 0
+  .size obj3, .-obj3
diff --git a/ld/testsuite/ld-loongarch-elf/relax-edge2.dd b/ld/testsuite/ld-loongarch-elf/relax-edge2.dd
new file mode 100644
index 000000000..5610cc8ed
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-edge2.dd
@@ -0,0 +1,8 @@
+#...
+.*nop.*
+.*nop.*
+.*nop.*
+.*nop.*
+.*pcalau12i.*
+.*addi.*
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/relax-edge2.s b/ld/testsuite/ld-loongarch-elf/relax-edge2.s
new file mode 100644
index 000000000..c2a42e705
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-edge2.s
@@ -0,0 +1,15 @@
+  .text
+main:
+  nop
+  nop
+  nop
+  nop
+  .align 4
+  la.local $a0, obj1
+
+  .data
+  .space 0x10
+  .type obj1, @object
+obj1:
+  .word 0
+  .size obj1, .-obj1
diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp
index d2bb967c6..19ade4970 100644
--- a/ld/testsuite/ld-loongarch-elf/relax.exp
+++ b/ld/testsuite/ld-loongarch-elf/relax.exp
@@ -43,6 +43,26 @@ if [istarget loongarch64-*-*] {
 	      ] \
 	      "relax" \
 	  ] \
+	  [list \
+	      "relax-edge1" \
+	      "-e 0 -Ttext 0x400000 -Tdata 0x200000 -Tbss 0x600000" "" \
+	      "" \
+	      {relax-edge1.s} \
+	      [list \
+		  [list objdump -d relax-edge1.dd] \
+	      ] \
+	      "relax-edge1" \
+	  ] \
+	  [list \
+	      "relax-edge2" \
+	      "-e 0 -Ttext 0x400000 -Tdata 0x600000" "" \
+	      "" \
+	      {relax-edge2.s} \
+	      [list \
+		  [list objdump -d relax-edge2.dd] \
+	      ] \
+	      "relax-edge2" \
+	  ] \
       ]
 
   set objdump_flags "-s -j .data"
-- 
2.33.0


  reply	other threads:[~2023-07-11  8:49 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-11  8:49 [PATCH 1/2] LoongArch: bfd: Remove elf_seg_map condition in loongarch_elf_relax_section Jinyang He
2023-07-11  8:49 ` Jinyang He [this message]
2023-07-12  6:35 ` mengqinggang
2023-07-12  8:08   ` Jinyang He
2023-07-13  3:13     ` mengqinggang
2023-07-13  7:19       ` Jinyang He
2023-07-13  8:18         ` Jinyang He
2023-10-05 10:09           ` Xi Ruoyao
2023-10-05 11:19             ` Xi Ruoyao
2023-10-07  1:23               ` mengqinggang
2023-10-10 13:13                 ` Xi Ruoyao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230711084931.18978-2-hejinyang@loongson.cn \
    --to=hejinyang@loongson.cn \
    --cc=binutils@sourceware.org \
    --cc=fanpeng@loongson.cn \
    --cc=i.swmail@xen0n.name \
    --cc=liuzhensong@loongson.cn \
    --cc=lixing@loongson.cn \
    --cc=mengqinggang@loongson.cn \
    --cc=xuchenghua@loongson.cn \
    --cc=zhaojunchao@loongson.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).