[llvm] [AMDGPU] Post-RA Peephole for Two-Address Instructions (PR #207731)

Lukas Sommer via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 03:00:43 PDT 2026


================
@@ -763,13 +802,185 @@ MachineInstrBuilder SIPreEmitPeephole::createUnpackedMI(MachineInstr &I,
   return NewMI;
 }
 
+bool SIPreEmitPeephole::isLateThreeAddrPeepholeCandidate(
+    const MachineInstr &MI) const {
+  // This is a subset of the opcodes that are convertible to three-address
+  // instructions according to . This is intended. For some cases,
+  // convertToThreeAddress could early-clobber, which would require us to roll
+  // back the transformation. However, rollback is not side-effect free for some
+  // cases in convertToThreeAddress that fold immediates. Therefore, we limit
+  // this peephole to only the instructions for which rollback will not be
+  // necessary.
+  switch (MI.getOpcode()) {
+  case AMDGPU::V_MAC_F16_e32:
+  case AMDGPU::V_MAC_F16_e64:
+  case AMDGPU::V_MAC_F32_e32:
+  case AMDGPU::V_MAC_F32_e64:
+  case AMDGPU::V_MAC_LEGACY_F32_e32:
+  case AMDGPU::V_MAC_LEGACY_F32_e64:
+  case AMDGPU::V_FMAC_F16_e32:
+  case AMDGPU::V_FMAC_F16_e64:
+  case AMDGPU::V_FMAC_F16_t16_e64:
+  case AMDGPU::V_FMAC_F16_fake16_e64:
+  case AMDGPU::V_FMAC_F32_e32:
+  case AMDGPU::V_FMAC_F32_e64:
+  case AMDGPU::V_FMAC_LEGACY_F32_e32:
+  case AMDGPU::V_FMAC_LEGACY_F32_e64:
+  case AMDGPU::V_FMAC_F64_e32:
+  case AMDGPU::V_FMAC_F64_e64:
+    return true;
+  default:
+    return false;
+  }
+}
+
+Register SIPreEmitPeephole::checkCopy(MachineInstr &TwoAddress,
+                                      MachineInstr &MaybeCopy, Register Src,
+                                      const TargetRegisterClass *NewDstRC) {
+  if (MaybeCopy.isBundle())
+    return Register();
+
+  if (!TII->isFoldableCopy(MaybeCopy) ||
+      MaybeCopy.getOpcode() == AMDGPU::WWM_COPY)
+    return Register();
+
+  if (TII->hasAnyModifiersSet(MaybeCopy))
+    return Register();
+
+  auto CopySrc = MaybeCopy.getOperand(TII->getFoldableCopySrcIdx(MaybeCopy));
+  if (!CopySrc.isReg() || CopySrc.getReg() != Src ||
+      CopySrc.getSubReg() != AMDGPU::NoSubRegister)
+    return Register();
+
+  MachineOperand Dst = MaybeCopy.getOperand(0);
+  if (!Dst.isReg() || Dst.getSubReg() != AMDGPU::NoSubRegister)
+    return Register();
+
+  Register DstReg = Dst.getReg();
+  if (TRI->getPhysRegBaseClass(DstReg) != TRI->getPhysRegBaseClass(Src))
+    return Register();
+
+  if (NewDstRC && !NewDstRC->contains(DstReg.asMCReg()))
+    return Register();
+
+  // Check that it is safe to define the copy destination register at the
+  // current position of the two-address instruction.
+  SmallPtrSet<MachineInstr *, 1> Ignore{&TwoAddress, &MaybeCopy};
+  if (!RDI->isSafeToDefRegAt(&TwoAddress, DstReg, Ignore))
+    return Register();
+
+  // Check that the two-address instruction and the copy have the same exec
+  // mask.
+  if (!RDI->hasSameReachingDef(&TwoAddress, &MaybeCopy, AMDGPU::EXEC))
----------------
sommerlukas wrote:

Yes, this works correctly for wave32, because `exec_lo` is contained in `EXEC` as physical register unit and wave32 instructions reference full `exec`. I've still changed it to use `TRI->getExec()` for clarity.

https://github.com/llvm/llvm-project/pull/207731


More information about the llvm-commits mailing list