AMDGPU/GlobalISel: Avoid handling registers twice in waterfall loops
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Sat, 1 Feb 2020 16:29:41 +0000 (11:29 -0500)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 6 Feb 2020 17:38:24 +0000 (09:38 -0800)
When multiple instructions are moved into a waterfall loop, it's
possible some of them re-use the same operands. Avoid creating
multiple sequences of readfirstlanes for them. None of the current
uses will hit this, but will be used in a future patch.

llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp

index 0d27f00..dedb7b0 100644 (file)
@@ -747,6 +747,10 @@ bool AMDGPURegisterBankInfo::executeInWaterfallLoop(
   SmallVector<Register, 4> InitResultRegs;
   SmallVector<Register, 4> PhiRegs;
 
+  // Track use registers which have already been expanded with a readfirstlane
+  // sequence. This may have multiple uses if moving a sequence.
+  DenseMap<Register, Register> WaterfalledRegMap;
+
   MachineBasicBlock &MBB = B.getMBB();
   MachineFunction *MF = &B.getMF();
 
@@ -853,9 +857,18 @@ bool AMDGPURegisterBankInfo::executeInWaterfallLoop(
       if (!Op.isReg() || Op.isDef())
         continue;
 
-      if (!SGPROperandRegs.count(Op.getReg()))
+      Register OldReg = Op.getReg();
+      if (!SGPROperandRegs.count(OldReg))
         continue;
 
+      // See if we already processed this register in another instruction in the
+      // sequence.
+      auto OldVal = WaterfalledRegMap.find(OldReg);
+      if (OldVal != WaterfalledRegMap.end()) {
+        Op.setReg(OldVal->second);
+        continue;
+      }
+
       LLT OpTy = MRI.getType(Op.getReg());
       unsigned OpSize = OpTy.getSizeInBits();
 
@@ -1001,6 +1014,9 @@ bool AMDGPURegisterBankInfo::executeInWaterfallLoop(
 
         MRI.setRegBank(Op.getReg(), AMDGPU::SGPRRegBank);
       }
+
+      // Make sure we don't re-process this register again.
+      WaterfalledRegMap.insert(std::make_pair(OldReg, Op.getReg()));
     }
   }