https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110136

            Bug ID: 110136
           Summary: After optimization, the $r1 register will be broken
                    when jumping to the jump table, resulting in a
                    significant increase in the false prediction rate of
                    branch prediction.
           Product: gcc
           Version: 12.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: lto
          Assignee: unassigned at gcc dot gnu.org
          Reporter: chenglulu at loongson dot cn
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---
            Target: loongarch64-*-linux

Created attachment 55267
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55267&action=edit
perlbench.ltrans15.ltrans.args.0

tag: releases/gcc-12.2.0
The code here replicates the problem.

$ ./libexec/gcc/loongarch64-linux-gnu/12.2.0/lto1 -quiet -dumpbase
./perlbench.ltrans15.ltrans -mabi=lp64d -march=loongarch64 -mfpu=64
-mcmodel=normal -mtune=loongarch64 -g -g -Ofast -Ofast -version -fno-openmp
-fno-openacc -fcf-protection=none -fno-omit-frame-pointer -funroll-all-loops 
-fltrans @./perlbench.ltrans15.ltrans.args.0 -fdump-rtl-all -o
./perlbench.ltrans15.ltrans.s -fpie

Perl_sv_upgrade:
...
 5908         addi.w  $r18,$r0,15                     # 0xf
 5909         bgtu    $r23,$r18,.L502
 5910         la.local        $r16,.L504
 5911         slli.d  $r19,$r23,3
 5912         ldx.d   $r20,$r16,$r19
 5913         add.d   $r1,$r16,$r20
 5914         jr      $r1
...

In the regrename passover optimization, replace the registers of lines 5193 and
5194 with $r1.

I tried debugging and found that the problem would be solved if hook
HARD_REGNO_RENAME_OK was defined, but found that this was just an accident and
there is no guarantee that this register will not be replaced with $r1 when
jumping to the jump table.

The patch that defines the HARD_REGNO_RENAME_OK is as follows:
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index 5c9a33c14f7..0df0ae15c3e 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -5782,6 +5782,19 @@ loongarch_starting_frame_offset (void)
   return crtl->outgoing_args_size;
 }

+/* Return nonzero if register FROM_REGNO can be renamed to register
+   TO_REGNO.  */
+
+bool
+loongarch_hard_regno_rename_ok (unsigned from_regno ATTRIBUTE_UNUSED,
+                           unsigned to_regno)
+{
+  return df_regs_ever_live_p (to_regno);
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
diff --git a/gcc/config/loongarch/loongarch.h
b/gcc/config/loongarch/loongarch.h
index f9de9a6e4fb..b22b439eaac 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -563,6 +563,8 @@ enum reg_class
 #define IMM_BITS 12
 #define IMM_REACH (1LL << IMM_BITS)

+#define HARD_REGNO_RENAME_OK(FROM, TO) loongarch_hard_regno_rename_ok (FROM,
TO)
+
 /* True if VALUE is an unsigned 6-bit number.  */


Is there a way to make sure that the $r1 register is not corrupted when jumping
to the table?

Reply via email to