From 1f3d0040fc8ed27a8adb7a2466864b1fa0b80889 Mon Sep 17 00:00:00 2001 From: Austin Kerbow Date: Tue, 15 Oct 2019 19:59:45 +0000 Subject: [PATCH] AMDGPU: Fix infinite searches in SIFixSGPRCopies Summary: Two conditions could lead to infinite loops when processing PHI nodes in SIFixSGPRCopies. The first condition involves a REG_SEQUENCE that uses registers defined by both a PHI and a COPY. The second condition arises when a physical register is copied to a virtual register which is then used in a PHI node. If the same virtual register is copied to the same physical register, the result is an endless loop. %0:sgpr_64 = COPY $sgpr0_sgpr1 %2 = PHI %0, %bb.0, %1, %bb.1 $sgpr0_sgpr1 = COPY %0 Reviewers: alex-t, rampitec, arsenm Reviewed By: rampitec Subscribers: kzhuravl, jvesely, wdng, nhaehnle, yaxunl, dstuttard, tpr, t-tye, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D68970 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374944 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AMDGPU/SIFixSGPRCopies.cpp | 6 ++- lib/Target/AMDGPU/SIInstrInfo.cpp | 2 + test/CodeGen/AMDGPU/fix-sgpr-copies.mir | 50 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/lib/Target/AMDGPU/SIFixSGPRCopies.cpp b/lib/Target/AMDGPU/SIFixSGPRCopies.cpp index 02a0518ab5a..196650759f9 100644 --- a/lib/Target/AMDGPU/SIFixSGPRCopies.cpp +++ b/lib/Target/AMDGPU/SIFixSGPRCopies.cpp @@ -697,7 +697,9 @@ bool SIFixSGPRCopies::runOnMachineFunction(MachineFunction &MF) { void SIFixSGPRCopies::processPHINode(MachineInstr &MI) { unsigned numVGPRUses = 0; SetVector worklist; + SmallSet Visited; worklist.insert(&MI); + Visited.insert(&MI); while (!worklist.empty()) { const MachineInstr *Instr = worklist.pop_back_val(); unsigned Reg = Instr->getOperand(0).getReg(); @@ -709,7 +711,9 @@ void SIFixSGPRCopies::processPHINode(MachineInstr &MI) { !TRI->isSGPRReg(*MRI, UseMI->getOperand(0).getReg())) { numVGPRUses++; } - worklist.insert(UseMI); + if (Visited.insert(UseMI).second) + worklist.insert(UseMI); + continue; } diff --git a/lib/Target/AMDGPU/SIInstrInfo.cpp b/lib/Target/AMDGPU/SIInstrInfo.cpp index f75da5181ca..3bcee08267f 100644 --- a/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -4289,6 +4289,8 @@ void SIInstrInfo::legalizeGenericOperand(MachineBasicBlock &InsertMBB, bool ImpDef = Def->isImplicitDef(); while (!ImpDef && Def && Def->isCopy()) { + if (Def->getOperand(1).getReg().isPhysical()) + break; Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg()); ImpDef = Def && Def->isImplicitDef(); } diff --git a/test/CodeGen/AMDGPU/fix-sgpr-copies.mir b/test/CodeGen/AMDGPU/fix-sgpr-copies.mir index 306e62a4309..394df72a1c8 100644 --- a/test/CodeGen/AMDGPU/fix-sgpr-copies.mir +++ b/test/CodeGen/AMDGPU/fix-sgpr-copies.mir @@ -60,3 +60,53 @@ body: | bb.8: ... + +# Avoid infinite loop in SIInstrInfo::legalizeGenericOperand when checking for ImpDef. +# GCN-LABEL: name: legalize-operand-search-each-def-once +# GCN-NOT: sreg_64 PHI +--- +name: legalize-operand-search-each-def-once +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: $sgpr0_sgpr1 + + %0:sgpr_64 = COPY $sgpr0_sgpr1 + S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + S_BRANCH %bb.1 + + bb.1: + %1:vreg_64 = IMPLICIT_DEF + S_BRANCH %bb.2 + + bb.2: + %2:sgpr_64 = PHI %0, %bb.0, %1, %bb.1 + $sgpr0_sgpr1 = COPY %0 +... + +# A REG_SEQUENCE that uses registers defined by both a PHI and a COPY could +# result in an endless search. +# GCN-LABEL: name: process-phi-search-each-use-once +# GCN-NOT: sreg_32 PHI +--- +name: process-phi-search-each-use-once +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: $vgpr3 + + %0:vgpr_32 = COPY $vgpr3 + S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + S_BRANCH %bb.1 + + bb.1: + %1:sgpr_32 = IMPLICIT_DEF + S_BRANCH %bb.2 + + bb.2: + %2:sgpr_32 = PHI %0, %bb.0, %1, %bb.1 + %3:vreg_64 = REG_SEQUENCE %2, %subreg.sub0, %0, %subreg.sub1 + $vgpr3 = COPY %3.sub0 +... -- 2.40.0