https://gcc.gnu.org/g:f5ceca96278b2ffaff838216aa6644fedb603573
commit r15-5412-gf5ceca96278b2ffaff838216aa6644fedb603573 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: --- gcc/config/riscv/riscv.cc | 2 +- gcc/config/riscv/sync.md | 2 +- gcc/testsuite/gcc.target/riscv/pr117595.c | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 7694954c4c5c..03271d893b60 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 aa0c20446f42..23c0859e0856 100644 --- a/gcc/config/riscv/sync.md +++ b/gcc/config/riscv/sync.md @@ -580,7 +580,7 @@ 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 000000000000..a870df08ee4b --- /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++; }