[llvm] 7949709 - [JITLink][RISCV] Adjust offsets of non-relaxable edges

Job Noorman via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 26 00:44:56 PDT 2023


Author: Job Noorman
Date: 2023-06-26T09:41:20+02:00
New Revision: 794970988e9fd02fdb8ddc8479f4dcc7cdd93474

URL: https://github.com/llvm/llvm-project/commit/794970988e9fd02fdb8ddc8479f4dcc7cdd93474
DIFF: https://github.com/llvm/llvm-project/commit/794970988e9fd02fdb8ddc8479f4dcc7cdd93474.diff

LOG: [JITLink][RISCV] Adjust offsets of non-relaxable edges

The relaxation algorithm used to only update offsets of relaxable edges.
This caused non-relaxable edges that appear after a relaxed instruction
to have an incorrect offset and be applied at the wrong location. This
patch fixes this by updating the offsets of all edges.

Note that this bug was caused by an incorrect translation of LLD's
relaxation algorithm. LLD always uses all edges during relaxation while
I decided to filter-out relaxable edges to prevent having to iterate
non-relaxable edges at each step. However, this had the side-effect of
only updating offsets of relaxable edges. This patch leaves the
filtering of relaxable edges as-is but iterates all edges when updating
offsets.

Reviewed By: StephenFan

Differential Revision: https://reviews.llvm.org/D153515

Added: 
    llvm/test/ExecutionEngine/JITLink/RISCV/ELF_relax_nonrelaxable.s

Modified: 
    llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
index dbc10ac884286..7438666f3b479 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
@@ -728,13 +728,17 @@ static void finalizeBlockRelax(LinkGraph &G, Block &Block, BlockRelaxAux &Aux) {
 
   // Fixup edge offsets and kinds.
   Delta = 0;
-  for (auto [I, E] : llvm::enumerate(Aux.RelaxEdges)) {
-    E->setOffset(E->getOffset() - Delta);
+  size_t I = 0;
+  for (auto &E : Block.edges()) {
+    E.setOffset(E.getOffset() - Delta);
 
-    if (Aux.EdgeKinds[I] != Edge::Invalid)
-      E->setKind(Aux.EdgeKinds[I]);
+    if (I < Aux.RelaxEdges.size() && Aux.RelaxEdges[I] == &E) {
+      if (Aux.EdgeKinds[I] != Edge::Invalid)
+        E.setKind(Aux.EdgeKinds[I]);
 
-    Delta = Aux.RelocDeltas[I];
+      Delta = Aux.RelocDeltas[I];
+      ++I;
+    }
   }
 
   // Remove AlignRelaxable edges: all other relaxable edges got modified and

diff  --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_relax_nonrelaxable.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_relax_nonrelaxable.s
new file mode 100644
index 0000000000000..f22b07349fb41
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_relax_nonrelaxable.s
@@ -0,0 +1,35 @@
+## Test that non-relaxable edges have their offset adjusted by relaxation
+
+# RUN: rm -rf %t && mkdir %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax %s -o %t.rv32
+# RUN: llvm-jitlink -noexec \
+# RUN:     -slab-allocate 100Kb -slab-address 0x0 -slab-page-size 4096 \
+# RUN:     -check %s %t.rv32
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax %s -o %t.rv64
+# RUN: llvm-jitlink -noexec \
+# RUN:     -slab-allocate 100Kb -slab-address 0x0 -slab-page-size 4096 \
+# RUN:     -check %s %t.rv64
+
+    .globl main,nonrelaxable,nonrelaxable_target
+    .size nonrelaxable, 4
+    .size nonrelaxable_target, 4
+main:
+    call f
+nonrelaxable:
+    ## Non-relaxable R_RISCV_BRANCH edge after a relaxable R_RISCV_CALL edge.
+    ## Even though this edge isn't relaxable, its offset should still be
+    ## adjusted.
+    beq zero, zero, nonrelaxable_target
+nonrelaxable_target:
+    ret
+    .size main, .-main
+
+    .globl f
+f:
+    ret
+    .size f, .-f
+
+# jitlink-check: decode_operand(nonrelaxable, 2) = (nonrelaxable_target - nonrelaxable)
+


        


More information about the llvm-commits mailing list