https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69403
Bug ID: 69403 Summary: Wrong thumb2_ior_scc_strict_it insn pattern. Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: shenhan at google dot com Target Milestone: --- Created attachment 37415 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37415&action=edit Test case For the attached case.c, "armv7a-cros-linux-gnueabi-gcc -march=armv8-a -O2 case.c -S -mthumb" results in the following wrong assembly: bug: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 1, uses_anonymous_args = 0 push {r3, r4, r5, r6, r7, lr} cmp r0, r2 add r7, sp, #0 bcc .L8 mvn r0, #-2147483648 pop {r3, r4, r5, r6, r7, pc} .L8: mov r6, r2 mov r4, r1 mov r5, r0 bl FT_MSB(PLT) rsb r3, r0, #31 adds r2, r0, #1 lsls r5, r5, r3 lsr r1, r4, r2 orrs r5, r5, r1 lsl r1, r4, r3 udiv r0, r5, r6 mls r3, r6, r0, r5 .L3: lsrs r4, r1, #31 lsls r0, r0, #1 orr r3, r4, r3, lsl #1 lsls r1, r1, #1 cmp r6, r3 sub r5, r3, r6 >>> it ls >>> movls r0, #1 >>> it ls >>> orrls r0, r0 it ls movls r3, r5 subs r2, r2, #1 bne .L3 pop {r3, r4, r5, r6, r7, pc} .size bug, .-bug .ident "GCC: (4.9.2_cos_gg_b6125c7_4.9.2-r115) .section .note.GNU-stack,"",%progbits The ">>>" lines (corresponding to line 27 in case.c) effectively set r0 to 1. By examing the source code : (define_insn "*thumb2_ior_scc_strict_it" [(set (match_operand:SI 0 "s_register_operand" "=l,l") (ior:SI (match_operator:SI 2 "arm_comparison_operator" [(match_operand 3 "cc_register" "") (const_int 0)]) (match_operand:SI 1 "s_register_operand" "0,?l")))] "TARGET_THUMB2 && arm_restrict_it" "@ it\\t%d2\;mov%d2\\t%0, #1\;it\\t%d2\;orr%d2\\t%0, %1 <<<=== Alternative 1 mov\\t%0, #1\;orr\\t%0, %1\;it\\t%D2\;mov%D2\\t%0, %1" <<<=== Alternative 2 It seemd to me: alternative 1, when register %1 == register %0 (which is asserted in the insn constraints), the first move "mov%d2\\t%0, #1" apparently destroys the value in the register. The result of this being register %0 = register %1 = 1. A quick fix, which we currently use as workaround, is: it\\t%d2\;orr%d2\\t%0, %1, #1 <<<=== Alternative 1 Which is a fallback to "thumb2_ior_scc" and assembly warns about 32-bit thumb within armv8 itblocks. A better fix is welcomed!