Skip to content
  • Jakob Stoklund Olesen's avatar
    LowerSubregsInstructionPass::LowerExtract should not extend the live range of registers. · 6304369c
    Jakob Stoklund Olesen authored
    When LowerExtract eliminates an EXTRACT_SUBREG with a kill flag, it moves the
    kill flag to the place where the sub-register is killed. This can accidentally
    overlap with the use of a sibling sub-register, and we have trouble.
    
    In the test case we have this code:
    
    Live Ins: %R0 %R1 %R2
    	%R2L<def> = EXTRACT_SUBREG %R2<kill>, 1
    	%R2H<def> = LOAD16fi <fi#-1>, 0, Mem:LD(2,4) [FixedStack-1 + 0]
    	%R1L<def> = EXTRACT_SUBREG %R1<kill>, 1
    	%R0L<def> = EXTRACT_SUBREG %R0<kill>, 1
    	%R0H<def> = ADD16 %R2H<kill>, %R2L<kill>, %AZ<imp-def>, %AN<imp-def>, %AC0<imp-def>, %V<imp-def>, %VS<imp-def>
    
    subreg: CONVERTING: %R2L<def> = EXTRACT_SUBREG %R2<kill>, 1
    subreg: eliminated!
    subreg: killed here: %R0H<def> = ADD16 %R2H, %R2L, %R2<imp-use,kill>, %AZ<imp-def>, %AN<imp-def>, %AC0<imp-def>, %V<imp-def>, %VS<imp-def>
    
    The kill flag on %R2 is moved to the last instruction, and the live range overlaps with the definition of %R2H:
    
    *** Bad machine code: Redefining a live physical register ***
    - function:    f
    - basic block:  0x18358c0 (#0)
    - instruction: %R2H<def> = LOAD16fi <fi#-1>, 0, Mem:LD(2,4) [FixedStack-1 + 0]
    Register R2H was defined but already live.
    
    The fix is to replace EXTRACT_SUBREG with IMPLICIT_DEF instead of eliminating
    it completely:
    
    subreg: CONVERTING: %R2L<def> = EXTRACT_SUBREG %R2<kill>, 1
    subreg: replace by: %R2L<def> = IMPLICIT_DEF %R2<kill>
    
    Note that these IMPLICIT_DEF instructions survive to the asm output. It is
    necessary to fix the stack-color-with-reg test case because of that.
    
    llvm-svn: 78093
    6304369c
Loading