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.
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));
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)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mbig-endian" } */
+
+_Atomic enum { E0 } e;
+void foo() { e++; }