Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3035,6 +3035,16 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {

if (llvm::is_contained(TRI->subregs(MOP.getReg()), Reg))
Bad = false;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above is_contained still redundant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks for the reminder. Dropped.

if (any_of(TRI->subregs(MOP.getReg()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The outer any_of should be redundant with checking the regunits of the raw register. This should also be redundant with the is_contained in subregs above.

Overall this whole verifier liveness tracking is not well implemented. BBInfo and the rest of the infrastructure should be implemented directly in terms of register units

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would encounter problems if we were to drop the outer any_of with subregs().

Take this testcase as example:

https://github.com/llvm/llvm-project/blob/main/llvm/test/MachineVerifier/AMDGPU/verifier-implicit-virtreg-invalid-physreg-liveness.mir

# RUN: not --crash llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -o /dev/null %s 2>&1 | FileCheck -check-prefix=ERROR %s

# When the verifier was detecting the invalid liveness for vcc, it would assert when trying to iterate the subregisters of the implicit virtual register use.


# ERROR: *** Bad machine code: Using an undefined physical register ***
# ERROR: instruction: S_ENDPGM 0, implicit %0:vgpr_32, implicit $vcc
# ERROR: operand 2:   implicit $vcc

...

name: invalid_implicit_physreg_use_with_implicit_virtreg
tracksRegLiveness: true

body:             |
  bb.0:
    %0:vgpr_32 = IMPLICIT_DEF
    S_ENDPGM 0, implicit %0, implicit $vcc

...

The verification process will try to check if $vcc belongs to $vcc, which will always evaluate to true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid this problem, I modified to check only when MOP.getReg() does not equal Reg.

if (MOP.getReg() != Reg && all_of(TRI->regunits(Reg), [&](const MCRegUnit RegUnit) {
      return llvm::is_contained(TRI->regunits(MOP.getReg()),
                                RegUnit);
    }))

[&](const MCRegister MOPSubReg) {
return all_of(TRI->regunits(Reg),
[&](const MCRegUnit RegUnit) {
return llvm::is_contained(
TRI->regunits(MOPSubReg), RegUnit);
});
}))
Bad = false;
}
}
if (Bad)
Expand Down
73 changes: 73 additions & 0 deletions llvm/test/CodeGen/RISCV/subreg-liveness.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=machineverifier %s -o - | FileCheck %s

...
---
name: func
tracksRegLiveness: true
tracksDebugUserValues: true
body: |
bb.0:
liveins: $v0, $v8, $v9, $v10, $v11
; CHECK-LABEL: name: func
; CHECK: liveins: $v0, $v8, $v9, $v10, $v11
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16
; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
; CHECK-NEXT: $x10 = frame-setup PseudoReadVLENB
; CHECK-NEXT: $x11 = frame-setup ADDI $x0, 10
; CHECK-NEXT: $x10 = frame-setup MUL killed $x10, killed $x11
; CHECK-NEXT: $x2 = frame-setup SUB $x2, killed $x10
; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x0a, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22
; CHECK-NEXT: dead renamable $x10 = PseudoVSETVLIX0 killed $x0, 193 /* e8, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
; CHECK-NEXT: renamable $v16m2 = PseudoVMV_V_I_M2 undef renamable $v16m2, 0, -1, 3 /* e8 */, 0 /* tu, mu */, implicit $vl, implicit $vtype
; CHECK-NEXT: renamable $v12m2 = PseudoVMERGE_VIM_M2 undef renamable $v12m2, renamable $v16m2, 1, $v0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
; CHECK-NEXT: $v0 = VMV1R_V killed $v8, implicit $v8
; CHECK-NEXT: renamable $v24m2 = PseudoVMERGE_VIM_M2 undef renamable $v24m2, renamable $v16m2, 1, $v0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
; CHECK-NEXT: $v18m2 = VMV2R_V $v12m2, implicit $v12_v13_v14_v15_v16
; CHECK-NEXT: $v20m2 = VMV2R_V $v14m2, implicit $v12_v13_v14_v15_v16
; CHECK-NEXT: $v22 = VMV1R_V $v16, implicit $v12_v13_v14_v15_v16
; CHECK-NEXT: $v0 = VMV1R_V $v9, implicit $v9
; CHECK-NEXT: $v19 = VMV1R_V $v24, implicit $v24
; CHECK-NEXT: renamable $v14m2 = PseudoVMERGE_VIM_M2 undef renamable $v14m2, renamable $v16m2, 1, $v0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
; CHECK-NEXT: $x12 = ADDI $x0, 1
; CHECK-NEXT: early-clobber renamable $v0 = PseudoVSLIDEUP_VX_M1 killed renamable $v0, killed renamable $v9, killed renamable $x12, $noreg, 3 /* e8 */, 1 /* ta, mu */, implicit $vl, implicit $vtype
; CHECK-NEXT: dead renamable $x10 = PseudoVSETVLIX0 killed $x0, 193 /* e8, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
; CHECK-NEXT: early-clobber renamable $v8 = PseudoVMSNE_VI_M2 killed renamable $v10m2, 0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
; CHECK-NEXT: $x10 = frame-destroy PseudoReadVLENB
; CHECK-NEXT: $x11 = frame-destroy ADDI $x0, 10
; CHECK-NEXT: $x10 = frame-destroy MUL killed $x10, killed $x11
; CHECK-NEXT: $x2 = frame-destroy ADD $x2, killed $x10
; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16
; CHECK-NEXT: PseudoRET implicit $v0, implicit $v8
$x2 = frame-setup ADDI $x2, -16
frame-setup CFI_INSTRUCTION def_cfa_offset 16
$x10 = frame-setup PseudoReadVLENB
$x11 = frame-setup ADDI $x0, 10
$x10 = frame-setup MUL killed $x10, killed $x11
$x2 = frame-setup SUB $x2, killed $x10
frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x0a, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22
dead renamable $x10 = PseudoVSETVLIX0 killed $x0, 193 /* e8, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
renamable $v16m2 = PseudoVMV_V_I_M2 undef renamable $v16m2, 0, -1, 3 /* e8 */, 0 /* tu, mu */, implicit $vl, implicit $vtype
renamable $v12m2 = PseudoVMERGE_VIM_M2 undef renamable $v12m2, renamable $v16m2, 1, $v0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
$v0 = VMV1R_V killed $v8, implicit $v8
renamable $v24m2 = PseudoVMERGE_VIM_M2 undef renamable $v24m2, renamable $v16m2, 1, $v0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
$v18m2 = VMV2R_V $v12m2, implicit $v12_v13_v14_v15_v16
$v20m2 = VMV2R_V $v14m2, implicit $v12_v13_v14_v15_v16
$v22 = VMV1R_V $v16, implicit $v12_v13_v14_v15_v16
$v0 = VMV1R_V $v9, implicit $v9
$v19 = VMV1R_V $v24, implicit $v24
renamable $v14m2 = PseudoVMERGE_VIM_M2 undef renamable $v14m2, renamable $v16m2, 1, $v0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
$x12 = ADDI $x0, 1
early-clobber renamable $v0 = PseudoVSLIDEUP_VX_M1 killed renamable $v0, killed renamable $v9, killed renamable $x12, $noreg, 3 /* e8 */, 1 /* ta, mu */, implicit $vl, implicit $vtype
dead renamable $x10 = PseudoVSETVLIX0 killed $x0, 193 /* e8, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
early-clobber renamable $v8 = PseudoVMSNE_VI_M2 killed renamable $v10m2, 0, -1, 3 /* e8 */, implicit $vl, implicit $vtype
$x10 = frame-destroy PseudoReadVLENB
$x11 = frame-destroy ADDI $x0, 10
$x10 = frame-destroy MUL killed $x10, killed $x11
$x2 = frame-destroy ADD $x2, killed $x10
$x2 = frame-destroy ADDI $x2, 16
PseudoRET implicit $v0, implicit $v8
...
Loading