Skip to content

[AMDGPU] Add MachineVerifier check to detect illegal copies from vector register to SGPR #105494

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

Merged
merged 12 commits into from
Sep 19, 2024
Merged
29 changes: 26 additions & 3 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4600,15 +4600,38 @@ static bool isSubRegOf(const SIRegisterInfo &TRI,
SubReg.getReg() == SuperVec.getReg();
}

// Verify the illegal copy from vector register to SGPR for generic opcode COPY
bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
const MachineRegisterInfo &MRI,
StringRef &ErrInfo) const {
Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(1).getReg();
// This is a check for copy from vector register to SGPR
if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
ErrInfo = "illegal copy from vector register to SGPR";
return false;
}
return true;
}

bool SIInstrInfo::verifyInstruction(const MachineInstr &MI,
StringRef &ErrInfo) const {
uint16_t Opcode = MI.getOpcode();
if (SIInstrInfo::isGenericOpcode(MI.getOpcode()))
return true;

const MachineFunction *MF = MI.getParent()->getParent();
const MachineRegisterInfo &MRI = MF->getRegInfo();

// FIXME: At this point the COPY verify is done only for non-ssa forms.
// Find a better property to recognize the point where instruction selection
// is just done.
// We can only enforce this check after SIFixSGPRCopies pass so that the
// illegal copies are legalized and thereafter we don't expect a pass
// inserting similar copies.
if (!MRI.isSSA() && MI.isCopy())
return verifyCopy(MI, MRI, ErrInfo);

if (SIInstrInfo::isGenericOpcode(MI.getOpcode()))
return true;

int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {

Register findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const;

bool verifyCopy(const MachineInstr &MI, const MachineRegisterInfo &MRI,
StringRef &ErrInfo) const;

protected:
/// If the specific machine instruction is a instruction that moves/copies
/// value from one register to another register return destination and source
Expand Down
1 change: 0 additions & 1 deletion llvm/test/CodeGen/AMDGPU/phi-vgpr-input-moveimm.mir
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ body: |
S_BRANCH %bb.2
...


Copy link
Collaborator

Choose a reason for hiding this comment

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

Unwanted diff. This file shouldn't have any change now.

---
name: phi_moveimm_bad_opcode_input
tracksRegLiveness: true
Expand Down
9 changes: 4 additions & 5 deletions llvm/test/CodeGen/AMDGPU/wqm.mir
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ body: |
# Ensure that strict_wwm is not put around an EXEC copy
#CHECK-LABEL: name: copy_exec
#CHECK: %7:sreg_64 = COPY $exec
#CHECK-NEXT: %14:sreg_64 = ENTER_STRICT_WWM -1, implicit-def $exec, implicit-def $scc, implicit $exec
#CHECK-NEXT: %13:sreg_64 = ENTER_STRICT_WWM -1, implicit-def $exec, implicit-def $scc, implicit $exec
#CHECK-NEXT: %8:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
#CHECK-NEXT: $exec = EXIT_STRICT_WWM %14
#CHECK-NEXT: $exec = EXIT_STRICT_WWM %13
#CHECK-NEXT: %9:vgpr_32 = V_MBCNT_LO_U32_B32_e64 %7.sub0, 0, implicit $exec
name: copy_exec
tracksRegLiveness: true
Expand All @@ -213,10 +213,9 @@ body: |
%10:vgpr_32 = V_MBCNT_LO_U32_B32_e64 %8.sub0:sreg_64, 0, implicit $exec
%11:vgpr_32 = V_MOV_B32_dpp %9:vgpr_32, %10:vgpr_32, 312, 15, 15, 0, implicit $exec
%12:sreg_32 = V_READLANE_B32 %11:vgpr_32, 63
early-clobber %13:sreg_32 = STRICT_WWM %9:vgpr_32, implicit $exec
early-clobber %13:vgpr_32 = STRICT_WWM %9:vgpr_32, implicit $exec

%14:vgpr_32 = COPY %13
BUFFER_STORE_DWORD_OFFSET_exact killed %14, %4, %5, 4, 0, 0, implicit $exec
BUFFER_STORE_DWORD_OFFSET_exact killed %13, %4, %5, 4, 0, 0, implicit $exec
S_ENDPGM 0

...
Expand Down
59 changes: 59 additions & 0 deletions llvm/test/MachineVerifier/AMDGPU/fix-illegal-vector-copies.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# RUN: not --crash llc -march=amdgcn -mcpu=gfx1200 -run-pass=none -o /dev/null %s 2>&1 | FileCheck %s

---
name: fix-illegal-vector-copies
tracksRegLiveness: true
machineFunctionInfo:
isEntryFunction: true
body: |
bb.0:
%0:vgpr_32 = IMPLICIT_DEF
%0:vgpr_32 = IMPLICIT_DEF ; Break SSA format
%1:vgpr_32 = IMPLICIT_DEF
%2:sgpr_32 = IMPLICIT_DEF
%3:sgpr_32 = IMPLICIT_DEF
%4:agpr_32 = IMPLICIT_DEF
%5:agpr_32 = IMPLICIT_DEF

; copy from virtual VGPR to virtual SGPR
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: %6:sgpr_32 = COPY %0:vgpr_32
%6:sgpr_32 = COPY %0:vgpr_32

; copy from virtual VGPR to physical SGPR
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: $sgpr0 = COPY %0:vgpr_32
$sgpr0 = COPY %0:vgpr_32

; copy from physical VGPR to physical SGPR
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: $sgpr1 = COPY $vgpr0
$sgpr1 = COPY $vgpr0

; copy from virtual AGPR to virtual SGPR
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: %7:sgpr_32 = COPY %4:agpr_32
%7:sgpr_32 = COPY %4:agpr_32

; copy from virtual AGPR to physical SGPR
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: $sgpr2 = COPY %4:agpr_32
$sgpr2 = COPY %4:agpr_32

; copy from physical AGPR to physical SGPR
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: $sgpr3 = COPY $agpr0
$sgpr3 = COPY $agpr0

; copy from tuple of physical VGPRs to tuple of physical SGPRs
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: $sgpr4_sgpr5 = COPY $vgpr0_vgpr1
$sgpr4_sgpr5 = COPY $vgpr0_vgpr1

; copy from tuple of physical AGPRs to tuple of physical SGPRs
; CHECK: *** Bad machine code: illegal copy from vector register to SGPR ***
; CHECK: - instruction: $sgpr6_sgpr7 = COPY $agpr0_agpr1
$sgpr6_sgpr7 = COPY $agpr0_agpr1

S_ENDPGM 0
...