@@ -740,19 +740,23 @@ static void relaxCall(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc,
740740 (r.expr == R_PLT_PC ? sym.getPltVA (ctx) : sym.getVA (ctx)) + r.addend ;
741741 const int64_t displace = dest - loc;
742742
743- if (rvc && isInt<12 >(displace) && rd == 0 ) {
743+ // When the caller specifies the old value of `remove`, disallow its
744+ // increment.
745+ if (remove >= 6 && rvc && isInt<12 >(displace) && rd == 0 ) {
744746 sec.relaxAux ->relocTypes [i] = R_RISCV_RVC_JUMP;
745747 sec.relaxAux ->writes .push_back (0xa001 ); // c.j
746748 remove = 6 ;
747- } else if (rvc && isInt<12 >(displace) && rd == X_RA &&
749+ } else if (remove >= 6 && rvc && isInt<12 >(displace) && rd == X_RA &&
748750 !ctx.arg .is64 ) { // RV32C only
749751 sec.relaxAux ->relocTypes [i] = R_RISCV_RVC_JUMP;
750752 sec.relaxAux ->writes .push_back (0x2001 ); // c.jal
751753 remove = 6 ;
752- } else if (isInt<21 >(displace)) {
754+ } else if (remove >= 4 && isInt<21 >(displace)) {
753755 sec.relaxAux ->relocTypes [i] = R_RISCV_JAL;
754756 sec.relaxAux ->writes .push_back (0x6f | rd << 7 ); // jal
755757 remove = 4 ;
758+ } else {
759+ remove = 0 ;
756760 }
757761}
758762
@@ -828,7 +832,7 @@ static void relaxHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
828832 }
829833}
830834
831- static bool relax (Ctx &ctx, InputSection &sec) {
835+ static bool relax (Ctx &ctx, int pass, InputSection &sec) {
832836 const uint64_t secAddr = sec.getVA ();
833837 const MutableArrayRef<Relocation> relocs = sec.relocs ();
834838 auto &aux = *sec.relaxAux ;
@@ -862,8 +866,13 @@ static bool relax(Ctx &ctx, InputSection &sec) {
862866 }
863867 case R_RISCV_CALL:
864868 case R_RISCV_CALL_PLT:
865- if (relaxable (relocs, i))
869+ // Prevent oscillation between states by disallowing the increment of
870+ // `remove` after a few passes. The previous `remove` value is
871+ // `cur-delta`.
872+ if (relaxable (relocs, i)) {
873+ remove = pass < 4 ? 6 : cur - delta;
866874 relaxCall (ctx, sec, i, loc, r, remove);
875+ }
867876 break ;
868877 case R_RISCV_TPREL_HI20:
869878 case R_RISCV_TPREL_ADD:
@@ -945,7 +954,7 @@ bool RISCV::relaxOnce(int pass) const {
945954 if (!(osec->flags & SHF_EXECINSTR))
946955 continue ;
947956 for (InputSection *sec : getInputSections (*osec, storage))
948- changed |= relax (ctx, *sec);
957+ changed |= relax (ctx, pass, *sec);
949958 }
950959 return changed;
951960}
0 commit comments