[This was actually pushed with the other v850 patch by accident... ]
So the LLM checker chewed on v850.md for a bit and spit out about 3
dozen issues. I took one that seemed likely to be a code generation
bug, the LLM claimed we were missing a condition code clobber on two of
the single bit manipulation instructions. It was trivial to review the
V8 docs and conclude yes, this is likely a real problem.
I made a cross compiler available to the LLM and asked it to spit out a
testcase which it did which it verified by looking at the .combine dumps
(to see the pattern being used), the sched2 dump to see it get reordered
in such a way as to expose the bug, then the final assembly code which
looked wrong by inspection. Then I told the LLM about the simulator and
it was able to see the undesirable behavior at runtime which it could
toggle on/off via -fno-schedule-insns2. Not bad.
This patch fixes the bug by adding the missing clobbers. It's possible
we could be more surgical here since those instructions just change the
Z bit, but full clobber is obviously safe. It's not likely worth the
effort to be more surgical.
Assisted-By: Claude for review of v850.md and testcase generation.
Regression tested on v850e-elf and pushed to the trunk.
Jeff
commit b31c358dd66fda84de3eb55e5d5924dfda8dc68a
Author: Jeff Law <[email protected]>
Date: Sun Oct 25 22:05:23 2026 -0600
[V850] Fix length computation for branches in V850 port
Here's another bug caught by the LLM.
In the E3V5 and newer V850 variants, the range of conditional branches
extended
from 8 to 17 bits. The conditional branch sequences were updated to account
for
that, except they mucked things up on the older targets.
Essentially the output C fragment selects the sequence based on the length
of
the insn
2 bytes -- short conditional
4 bytes -- E3V5 long conditional
6 bytes -- short inverted conditional around "jr"
But the length computation just assumed that the long conditional forms were
always available.
It looks like we're testing base, along with the E3V5 variants, so I can
only
assume that the assembler isn't strict enough and that it's likely using the
E3V5 instruction, even on base variants. Similarly for the simulator. If
either of those were not true, I would expect massive failures from the
testsuite.
Anyway, the fix is simple, verify we have the E3V5 variant or newer in the
length computation before returning "4".
Regression tested on v850e-elf with no regressions or improvements to
existing
tests. I'm still working through RISC-V bugs in that LLM based tester, but
I
wanted to see what it would do if I through another port's MD file at it.
Assisted by: Claude for review of v850.md and testcase generation.
gcc/
* config/v850/v850.md (conditional branch patterns): Fix length
computation for designs without long conditional branches.
gcc/testsuite
* gcc.target/v850/min_bit.c: New test.
diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md
index 304477629db..a64d5452e57 100644
--- a/gcc/config/v850/v850.md
+++ b/gcc/config/v850/v850.md
@@ -831,7 +831,8 @@
(define_insn "*v850_set1_2"
[(set (match_operand:HI 0 "indirect_operand" "=m")
(subreg:HI (ior:SI (subreg:SI (match_dup 0) 0)
- (match_operand 1 "power_of_two_operand" "")) 0))]
+ (match_operand 1 "power_of_two_operand" "")) 0))
+ (clobber (reg:CC CC_REGNUM))]
""
{
int log2 = exact_log2 (INTVAL (operands[1]));
@@ -930,7 +931,8 @@
(define_insn "*v850_not1_2"
[(set (match_operand:HI 0 "indirect_operand" "=m")
(subreg:HI (xor:SI (subreg:SI (match_dup 0) 0)
- (match_operand 1 "power_of_two_operand" "")) 0))]
+ (match_operand 1 "power_of_two_operand" "")) 0))
+ (clobber (reg:CC CC_REGNUM))]
""
{
int log2 = exact_log2 (INTVAL (operands[1]));
@@ -1533,8 +1535,9 @@
(if_then_else (lt (abs (minus (match_dup 0) (pc)))
(const_int 256))
(const_int 2)
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 65536))
+ (if_then_else (and (match_test "TARGET_V850E3V5_UP")
+ (lt (abs (minus (match_dup 0) (pc)))
+ (const_int 65536)))
(const_int 4)
(const_int 6))))])
@@ -1573,8 +1576,9 @@
(if_then_else (lt (abs (minus (match_dup 0) (pc)))
(const_int 256))
(const_int 2)
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 65536))
+ (if_then_else (and (match_test "TARGET_V850E3V5_UP")
+ (lt (abs (minus (match_dup 0) (pc)))
+ (const_int 65536)))
(const_int 4)
(const_int 6))))])
diff --git a/gcc/testsuite/gcc.target/v850/min_bit.c
b/gcc/testsuite/gcc.target/v850/min_bit.c
new file mode 100644
index 00000000000..c21c9797a2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/v850/min_bit.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int g1 = 1, g2 = 2;
+
+#define TEST(NAME, OP) \
+ __attribute__ ((noinline, noclone)) int \
+ NAME (short *p, int a, int b) \
+ { \
+ *p OP 0x10; \
+ if (a == b) \
+ return g1; \
+ return g2; \
+ }
+
+TEST (f_set1, |=)
+TEST (f_not1, ^=)
+
+int
+main (void)
+{
+ short x = 0;
+
+ if (f_set1 (&x, 1, 2) != 2)
+ __builtin_abort ();
+ x = 0;
+ if (f_not1 (&x, 1, 2) != 2)
+ __builtin_abort ();
+ __builtin_exit (0);
+}