Discovered when analyzing testresults for the v850. There's two bugs lurking in those patterns. The most serious is the divmodhi4 pattern. It takes a 32bit dividend and divides it by the low 16 bits of the divisor.
However, being a HImode pattern, we've assumed the upper 16 bits of the divisor don't affect the result. Consider -9216 as the divisor. We may have loaded that via a movhi from memory with zero extension resulting in 0x0000dc00 as the divisor which looks like 56320 since the dividend is actually 32 bits. Opps. The fix is to sign extend the dividend for divmodhi4 much like we were already zero extending it for udivmodhi4. Of course we need to fix the length while we're at it... Which brings us to the second bug. The udivmodhi4 pattern claimed to have a length of "4", but that's not right. The div instruction alone has a length of "4", but we're also emitting a zero-extension, so the total length is actually 6. Rather than use extend ; div In the output template, I'm now using extend\n\tdiv The latter gives better results when fed into the assembler with -al to verify lengths. This fixes a handful of execution failures on the v850e3v5 tests. Installing on the trunk. Jeff
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 754b5f10063..ceec833bb70 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-06-25 Jeff Law <l...@redhat.com> + + * config/v850/v850.md (divmodhi4): Make sure to sign extend the + dividend to 32 bits. Adjust length. + (udivmodhi4): Cleanup output template. Fix length. + 2018-06-25 Carl Love <c...@us.ibm.com> * config/rs6000/vsx.md: Change word selector to prefered location. diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md index 2656e90c90b..e01a3102c31 100644 --- a/gcc/config/v850/v850.md +++ b/gcc/config/v850/v850.md @@ -738,13 +738,13 @@ (match_dup 2))) (clobber (reg:CC CC_REGNUM))] "TARGET_V850E_UP" - "divh %2,%0,%3" - [(set_attr "length" "4") + "sxh %0\n\tdivh %2,%0,%3" + [(set_attr "length" "6") (set_attr "cc" "clobber") (set_attr "type" "div")]) -;; Half-words are sign-extended by default, so we must zero extend to a word -;; here before doing the divide. +;; The half word needs to be zero/sign extended to 32 bits before doing +;; the division/modulo operation. (define_insn "udivmodhi4" [(set (match_operand:HI 0 "register_operand" "=r") @@ -755,8 +755,8 @@ (match_dup 2))) (clobber (reg:CC CC_REGNUM))] "TARGET_V850E_UP" - "zxh %0 ; divhu %2,%0,%3" - [(set_attr "length" "4") + "zxh %0\n\tdivhu %2,%0,%3" + [(set_attr "length" "6") (set_attr "cc" "clobber") (set_attr "type" "div")])