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++; }