So a followup to last week's bugfix. In last week's change we we stopped using define_insn_and_split to rewrite instructions. That change was done to avoid dropping a masking instruction out of the RTL.

As a result the pattern(s) were changed into simple define_insns, which is good. One of them uses the GPR iterator since it's supposed to work for both 32bit and 64bit shifts on rv64.

But we failed to emit the right opcode for a 32bit shift on rv64. Thankfully the fix is trivial. If the mode is anything but word_mode, then we must be doing a 32-bit shift on rv64, ie the various "w" shift instructions.

It's run through my tester. Just waiting on the upstream CI system to spin it.

Jeff


diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 7f6d0bbab3e..7e35d7877ed 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2938,7 +2938,14 @@ (define_insn "*<optab><GPR:mode>3_mask_1"
               (match_operand:GPR2 2 "register_operand"  "r")
               (match_operand 3 "<GPR:shiftm1>"))])))]
   ""
-  "<insn>\t%0,%1,%2"
+{
+  /* If the shift mode is not word mode, then it must be the
+     case that we're generating rv64 code, but this is a 32-bit
+     operation.  Thus we need to use the "w" variant.  */
+  if (E_<GPR:MODE>mode != word_mode)
+    return "<insn>w\t%0,%1,%2";
+  return "<insn>\t%0,%1,%2";
+}
   [(set_attr "type" "shift")
    (set_attr "mode" "<GPR:MODE>")])
 
diff --git a/gcc/testsuite/gcc.target/riscv/pr120368.c 
b/gcc/testsuite/gcc.target/riscv/pr120368.c
new file mode 100644
index 00000000000..4fea8e6fe7c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr120368.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+
+int g;
+
+int
+foo (int s, int v)
+{
+  __builtin_memset (&g, v >> (s & 31), sizeof(g));
+  return g;
+}
+
+int
+main ()
+{
+  int x = foo (-16, 0xdffff);
+  if (x != 0x0d0d0d0d)
+    __builtin_abort();
+  __builtin_exit (0);
+}

Reply via email to