And stage3 begins...

Zdenek's fuzzer caught this one. Essentially using simplify_gen_subreg directly with an offset of 0 when we just needed a lowpart.

The offset of 0 works for little endian, but for big endian it's simply wrong. simplify_gen_subreg will return NULL_RTX because the case isn't representable. We then embed that NULL_RTX into an insn that's later scanned during mark_jump_label.

Scanning the port I see a couple more instances of this incorrect idiom. One is pretty obvious to fix. The others look a bit goofy and I'll probably need to sync with Patrick on them.

Anyway tested on riscv64-elf and riscv32-elf with no regressions. Pushing to the trunk.

jeff

commit f5ceca96278b2ffaff838216aa6644fedb603573
Author: Jeff Law <j...@ventanamicro.com>
Date:   Mon Nov 18 10:55:09 2024 -0700

    [committed][RISC-V][PR target/117595] Fix bogus use of simplify_gen_subreg
    
    And stage3 begins...
    
    Zdenek's fuzzer caught this one.  Essentially using simplify_gen_subreg
    directly with an offset of 0 when we just needed a lowpart.
    
    The offset of 0 works for little endian, but for big endian it's simply 
wrong.
    simplify_gen_subreg will return NULL_RTX because the case isn't 
representable.
    We then embed that NULL_RTX into an insn that's later scanned during
    mark_jump_label.
    
    Scanning the port I see a couple more instances of this incorrect idiom.   
One
    is pretty obvious to fix.  The others look a bit goofy and I'll probably 
need
    to sync with Patrick on them.
    
    Anyway tested on riscv64-elf and riscv32-elf with no regressions.  Pushing 
to
    the trunk.
    
            PR target/117595
    gcc/
            * config/riscv/sync.md (atomic_compare_and_swap<mode>): Use 
gen_lowpart
            rather than simplify_gen_subreg.
            * config/riscv/riscv.cc (riscv_legitimize_move): Similarly.
    
    gcc/testsuite/
            * gcc.target/riscv/pr117595.c: New test.

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7694954c4c5..03271d893b6 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3646,7 +3646,7 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx 
src)
       rtx mask = force_reg (word_mode, gen_int_mode (-65536, word_mode));
       rtx temp = gen_reg_rtx (word_mode);
       emit_insn (gen_extend_insn (temp,
-                                 simplify_gen_subreg (HImode, src, mode, 0),
+                                 gen_lowpart (HImode, src),
                                  word_mode, HImode, 1));
       if (word_mode == SImode)
        emit_insn (gen_iorsi3 (temp, mask, temp));
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index aa0c20446f4..23c0859e085 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -580,7 +580,7 @@ (define_expand "atomic_compare_and_swap<mode>"
         value is sign-extended.  */
       rtx tmp0 = gen_reg_rtx (word_mode);
       emit_insn (gen_extend_insn (tmp0, operands[3], word_mode, <MODE>mode, 
0));
-      operands[3] = simplify_gen_subreg (<MODE>mode, tmp0, word_mode, 0);
+      operands[3] = gen_lowpart (<MODE>mode, tmp0);
     }
 
   if (TARGET_ZACAS)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117595.c 
b/gcc/testsuite/gcc.target/riscv/pr117595.c
new file mode 100644
index 00000000000..a870df08ee4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117595.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-mbig-endian" } */
+
+_Atomic enum { E0 } e;
+void foo() { e++; }

Reply via email to