-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[AVR] Fix a bug in selection of ANY_EXTEND #132398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This is a walk around solution of llvm#132203
Can confirm, with expensive checks enabled the crash occurs, otherwise it doesn't. |
Ah, that's a nice catch, I have that turned off - let me try again. |
Minimized: define i16 @main(i8 %a) {
%1 = zext i8 %a to i16
%2 = sub i16 %1, 256
%3 = and i16 %2, 1
ret i16 %3
} I'll play a bit and see if I can dig to the underlying issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For others - the issue is that we end up generating a 16-bit instruction (subtraction, addition, ...) on a partially initialized register-pair.
Following my simplified example, after avr-isel we get:
bb.0 (%ir-block.0):
liveins: $r24
%0:gpr8 = COPY $r24
%2:dregs = IMPLICIT_DEF
%1:dldregs = INSERT_SUBREG %2:dregs(tied-def 0), %0:gpr8, %subreg.sub_lo
%3:dldregs = SUBIWRdK %1:dldregs(tied-def 0), 256, implicit-def dead $sreg
%4:dldregs = ANDIWRdK %3:dldregs(tied-def 0), 1, implicit-def dead $sreg
$r25r24 = COPY %4:dldregs
RET implicit $r25r24, implicit $r1
... which later gets expanded into:
0B bb.0 (%ir-block.0):
liveins: $r24
16B undef %4.sub_lo:dldregs = COPY $r24
64B %4:dldregs = SUBIWRdK %4:dldregs(tied-def 0), 256, implicit-def dead $sreg
96B %4:dldregs = ANDIWRdK %4:dldregs(tied-def 0), 1, implicit-def dead $sreg
112B $r25r24 = COPY %4:dldregs
128B RET implicit $r25r24, implicit $r1
... and into (via virtregrewriter
- note the lost information about partially initialized $r25r24
):
0B bb.0 (%ir-block.0):
liveins: $r24
64B $r25r24 = SUBIWRdK $r25r24(tied-def 0), 256, implicit-def dead $sreg
96B $r25r24 = ANDIWRdK killed $r25r24(tied-def 0), 1, implicit-def dead $sreg
128B RET implicit $r25r24, implicit $r1
... into:
bb.0 (%ir-block.0):
liveins: $r24
$r24 = SUBIRdK $r24(tied-def 0), 0, implicit-def $sreg
$r25 = SBCIRdK $r25(tied-def 0), 1, implicit-def dead $sreg, implicit killed $sreg
$r24 = ANDIRdK killed $r24(tied-def 0), 1, implicit-def dead $sreg
$r25 = ANDIRdK killed undef $r25(tied-def 0), 0, implicit-def dead $sreg
RET implicit $r25r24, implicit $r1
Note that the second ANDIRdK
correctly says undef $r25
, but that's just a happy accident thanks to
MIBHI->getOperand(1).setIsUndef(true); |
tl;dr it looks like somewhere in-between avr-isel and virtregrewriter we lose the information about "undef-ness" of half of the assigned register-pair - I'm not yet sure what's the correct solution (maybe explicitly inspecting liveins?), but the proposed hotfix seems to be correct (though overzealous, as noted in the commented code).
I've got a hunch this is how AArch64 solves this problem:
|
Yes. I will make a formal solution later, after I fix issue #127651 . |
This is a walk around solution of #132203