llvm-project/llvm/test/CodeGen/ARM/virtregrewriter-subregliven...

85 lines
2.3 KiB
Plaintext
Raw Normal View History

[VirtRegRewriter] Properly model the register liveness on undef subreg definition Undef subreg definition means that the content of the super register doesn't matter at this point. While that's true for virtual registers, this may not hold when replacing them with actual physical registers. Indeed, some part of the physical register may be coalesced with the related virtual register and thus, the values for those parts matter and must be live. The fix consists in checking whether or not subregs of the physical register being assigned to an undef subreg definition are live through that def and insert an implicit use if they are. Doing so, will keep them alive until that point like they should be. E.g., let vreg14 being assigned to R0_R1 then %vreg14:gsub_0<def,read-undef> = COPY %R0 ; <-- R1 is still live here %vreg14:gsub_1<def> = COPY %R1 Before this changes, the rewriter would change the code into: %R0<def> = KILL %R0, %R0_R1<imp-def> ; <-- this tells R1 is redefined %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> ; this value of this R1 ; is believed to come ; from the previous ; instruction Because of this invalid liveness, later pass could make wrong choices and in particular clobber live register as it happened with the register scavenger in llvm.org/PR34107 Now we would generate: %R0<def> = KILL %R0, %R0_R1<imp-def>, %R0_R1<imp-use> ; This tells R1 needs to ; reach this point %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> The bug has been here forever, it got exposed recently because the register scavenger got smarter. Fixes llvm.org/PR34107 llvm-svn: 310979
2017-08-16 08:17:05 +08:00
# RUN: llc -o - -mtriple=thumbv7--windows-gnu -run-pass=greedy -run-pass=virtregrewriter %s | FileCheck %s
--- |
target datalayout = "e-m:w-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv7--windows-gnu"
define void @subregLiveThrough() { ret void }
define void @subregNotLiveThrough() { ret void }
define void @subregNotLiveThrough2() { ret void }
...
---
# Check that we properly recognize that r1 is live through
# the first subreg copy.
# That will materialize as an implicit use of the big register
# on that copy.
# PR34107.
#
# CHECK-LABEL: name: subregLiveThrough
name: subregLiveThrough
tracksRegLiveness: true
registers:
- { id: 0, class: gprpair }
body: |
bb.0:
liveins: %r0, %r1
; That copy is being coalesced so we should use a KILL
; placeholder. If that's not a kill that means we probably
; not coalescing %0 and %r0_r1 and thus we are not testing
; the problematic code anymore.
;
; CHECK: %r0 = KILL %r0, implicit killed %r0_r1, implicit-def %r0_r1
; CHECK-NEXT: %r1 = KILL %r1, implicit killed %r0_r1
undef %0.gsub_0 = COPY %r0
%0.gsub_1 = COPY %r1
tBX_RET 14, %noreg, implicit %0
[VirtRegRewriter] Properly model the register liveness on undef subreg definition Undef subreg definition means that the content of the super register doesn't matter at this point. While that's true for virtual registers, this may not hold when replacing them with actual physical registers. Indeed, some part of the physical register may be coalesced with the related virtual register and thus, the values for those parts matter and must be live. The fix consists in checking whether or not subregs of the physical register being assigned to an undef subreg definition are live through that def and insert an implicit use if they are. Doing so, will keep them alive until that point like they should be. E.g., let vreg14 being assigned to R0_R1 then %vreg14:gsub_0<def,read-undef> = COPY %R0 ; <-- R1 is still live here %vreg14:gsub_1<def> = COPY %R1 Before this changes, the rewriter would change the code into: %R0<def> = KILL %R0, %R0_R1<imp-def> ; <-- this tells R1 is redefined %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> ; this value of this R1 ; is believed to come ; from the previous ; instruction Because of this invalid liveness, later pass could make wrong choices and in particular clobber live register as it happened with the register scavenger in llvm.org/PR34107 Now we would generate: %R0<def> = KILL %R0, %R0_R1<imp-def>, %R0_R1<imp-use> ; This tells R1 needs to ; reach this point %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> The bug has been here forever, it got exposed recently because the register scavenger got smarter. Fixes llvm.org/PR34107 llvm-svn: 310979
2017-08-16 08:17:05 +08:00
...
---
# Check that we properly recognize that r1 is *not* live through
# the first subreg copy.
# CHECK-LABEL: name: subregNotLiveThrough
name: subregNotLiveThrough
tracksRegLiveness: true
registers:
- { id: 0, class: gprpair }
body: |
bb.0:
liveins: %r0, %r1
; r1 is not live through so check we are not implicitly using
; the big register.
; CHECK: %r0 = KILL %r0, implicit-def %r0_r1
; CHECK-NEXT: tBX_RET
undef %0.gsub_0 = COPY %r0
tBX_RET 14, %noreg, implicit %0
[VirtRegRewriter] Properly model the register liveness on undef subreg definition Undef subreg definition means that the content of the super register doesn't matter at this point. While that's true for virtual registers, this may not hold when replacing them with actual physical registers. Indeed, some part of the physical register may be coalesced with the related virtual register and thus, the values for those parts matter and must be live. The fix consists in checking whether or not subregs of the physical register being assigned to an undef subreg definition are live through that def and insert an implicit use if they are. Doing so, will keep them alive until that point like they should be. E.g., let vreg14 being assigned to R0_R1 then %vreg14:gsub_0<def,read-undef> = COPY %R0 ; <-- R1 is still live here %vreg14:gsub_1<def> = COPY %R1 Before this changes, the rewriter would change the code into: %R0<def> = KILL %R0, %R0_R1<imp-def> ; <-- this tells R1 is redefined %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> ; this value of this R1 ; is believed to come ; from the previous ; instruction Because of this invalid liveness, later pass could make wrong choices and in particular clobber live register as it happened with the register scavenger in llvm.org/PR34107 Now we would generate: %R0<def> = KILL %R0, %R0_R1<imp-def>, %R0_R1<imp-use> ; This tells R1 needs to ; reach this point %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> The bug has been here forever, it got exposed recently because the register scavenger got smarter. Fixes llvm.org/PR34107 llvm-svn: 310979
2017-08-16 08:17:05 +08:00
...
---
# Check that we properly recognize that r1 is *not* live through
# the first subreg copy. It is defined by this copy, but is not
# through.
# CHECK-LABEL: name: subregNotLiveThrough2
name: subregNotLiveThrough2
tracksRegLiveness: true
registers:
- { id: 0, class: gprpair }
body: |
bb.0:
liveins: %r0, %r1
; r1 is not live through so check we are not implicitly using
; the big register.
; CHECK: %r0 = KILL %r0, implicit-def %r1, implicit-def %r0_r1
; CHECK-NEXT: tBX_RET
undef %0.gsub_0 = COPY %r0, implicit-def %r1
tBX_RET 14, %noreg, implicit %0
[VirtRegRewriter] Properly model the register liveness on undef subreg definition Undef subreg definition means that the content of the super register doesn't matter at this point. While that's true for virtual registers, this may not hold when replacing them with actual physical registers. Indeed, some part of the physical register may be coalesced with the related virtual register and thus, the values for those parts matter and must be live. The fix consists in checking whether or not subregs of the physical register being assigned to an undef subreg definition are live through that def and insert an implicit use if they are. Doing so, will keep them alive until that point like they should be. E.g., let vreg14 being assigned to R0_R1 then %vreg14:gsub_0<def,read-undef> = COPY %R0 ; <-- R1 is still live here %vreg14:gsub_1<def> = COPY %R1 Before this changes, the rewriter would change the code into: %R0<def> = KILL %R0, %R0_R1<imp-def> ; <-- this tells R1 is redefined %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> ; this value of this R1 ; is believed to come ; from the previous ; instruction Because of this invalid liveness, later pass could make wrong choices and in particular clobber live register as it happened with the register scavenger in llvm.org/PR34107 Now we would generate: %R0<def> = KILL %R0, %R0_R1<imp-def>, %R0_R1<imp-use> ; This tells R1 needs to ; reach this point %R1<def> = KILL %R1, %R0_R1<imp-def>, %R0_R1<imp-use> The bug has been here forever, it got exposed recently because the register scavenger got smarter. Fixes llvm.org/PR34107 llvm-svn: 310979
2017-08-16 08:17:05 +08:00
...