//=======- GCNDPPCombine.cpp - optimization for DPP instructions ---==========// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // The pass combines V_MOV_B32_dpp instruction with its VALU uses as a DPP src0 // operand. If any of the use instruction cannot be combined with the mov the // whole sequence is reverted. // // $old = ... // $dpp_value = V_MOV_B32_dpp $old, $vgpr_to_be_read_from_other_lane, // dpp_controls..., $row_mask, $bank_mask, $bound_ctrl // $res = VALU $dpp_value [, src1] // // to // // $res = VALU_DPP $combined_old, $vgpr_to_be_read_from_other_lane, [src1,] // dpp_controls..., $row_mask, $bank_mask, $combined_bound_ctrl // // Combining rules : // // if $row_mask and $bank_mask are fully enabled (0xF) and // $bound_ctrl==DPP_BOUND_ZERO or $old==0 // -> $combined_old = undef, // $combined_bound_ctrl = DPP_BOUND_ZERO // // if the VALU op is binary and // $bound_ctrl==DPP_BOUND_OFF and // $old==identity value (immediate) for the VALU op // -> $combined_old = src1, // $combined_bound_ctrl = DPP_BOUND_OFF // // Otherwise cancel. // // The mov_dpp instruction should reside in the same BB as all its uses //===----------------------------------------------------------------------===// #include "GCNDPPCombine.h" #include "AMDGPU.h" #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(NumDPPMovsCombined, "Number of DPP moves combined."); namespace { class GCNDPPCombine { … }; class GCNDPPCombineLegacy : public MachineFunctionPass { … }; } // end anonymous namespace INITIALIZE_PASS(…) char GCNDPPCombineLegacy::ID = …; char &llvm::GCNDPPCombineLegacyID = …; FunctionPass *llvm::createGCNDPPCombinePass() { … } bool GCNDPPCombine::isShrinkable(MachineInstr &MI) const { … } int GCNDPPCombine::getDPPOp(unsigned Op, bool IsShrinkable) const { … } // tracks the register operand definition and returns: // 1. immediate operand used to initialize the register if found // 2. nullptr if the register operand is undef // 3. the operand itself otherwise MachineOperand *GCNDPPCombine::getOldOpndValue(MachineOperand &OldOpnd) const { … } [[maybe_unused]] static unsigned getOperandSize(MachineInstr &MI, unsigned Idx, MachineRegisterInfo &MRI) { … } MachineInstr *GCNDPPCombine::createDPPInst(MachineInstr &OrigMI, MachineInstr &MovMI, RegSubRegPair CombOldVGPR, bool CombBCZ, bool IsShrinkable) const { … } static bool isIdentityValue(unsigned OrigMIOp, MachineOperand *OldOpnd) { … } MachineInstr *GCNDPPCombine::createDPPInst( MachineInstr &OrigMI, MachineInstr &MovMI, RegSubRegPair CombOldVGPR, MachineOperand *OldOpndValue, bool CombBCZ, bool IsShrinkable) const { … } // returns true if MI doesn't have OpndName immediate operand or the // operand has Value bool GCNDPPCombine::hasNoImmOrEqual(MachineInstr &MI, unsigned OpndName, int64_t Value, int64_t Mask) const { … } bool GCNDPPCombine::combineDPPMov(MachineInstr &MovMI) const { … } bool GCNDPPCombineLegacy::runOnMachineFunction(MachineFunction &MF) { … } bool GCNDPPCombine::run(MachineFunction &MF) { … } PreservedAnalyses GCNDPPCombinePass::run(MachineFunction &MF, MachineFunctionAnalysisManager &) { … }