blob: dbb4d074bf6e9e2d252c2b1d14fb4f60e174b272 [file] [edit]
//===- GCNVOPDUtils.h - GCN VOPD Utils ------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
/// \file This file contains the AMDGPU DAG scheduling
/// mutation to pair VOPD instructions back to back. It also contains
// subroutines useful in the creation of VOPD instructions
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_AMDGPU_VOPDUTILS_H
#define LLVM_LIB_TARGET_AMDGPU_VOPDUTILS_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include <optional>
namespace llvm {
class MachineInstr;
class SIInstrInfo;
class MCRegisterClass;
/// A 32-bit immediate which the VOPD encoding cannot hold. The pair only
/// becomes legal after the operand is replaced by a scalar register holding
/// \p Imm.
struct VOPDLiteralFixup {
/// Component holding the immediate, AMDGPU::VOPD::X or AMDGPU::VOPD::Y.
unsigned CompIdx;
/// Index of the immediate operand within that component.
unsigned OpIdx;
/// Value which has to be placed in a register.
int32_t Imm;
/// Scalar registers the VOPD source slot can read. This is the slot class
/// narrowed to SGPR_32, so every register in it can be used.
const MCRegisterClass *SlotRC;
};
/// Describes a matched VOPD pair.
struct VOPDMatchInfo {
/// The component instructions in program order.
MachineInstr *InOrder[2];
/// Which entry in \p InOrder is the X component.
unsigned XIdx;
bool IsVOPD3;
/// Immediates which have to be moved into scalar registers before the pair
/// can be built. They all have the same 32-bit value, so one register serves
/// the whole pair. Only a VOPD3 pair can need this.
SmallVector<VOPDLiteralFixup, 2> LiteralFixups;
MachineInstr *getMIX() const { return InOrder[XIdx]; }
MachineInstr *getMIY() const { return InOrder[1 - XIdx]; }
};
/// Check whether FirstMI and SecondMI can be
/// combined into a VOPD instruction. Returns the match info (X/Y assignment
/// and encoding variant) on success, or std::nullopt if they cannot be paired.
std::optional<VOPDMatchInfo> tryMatchVOPDPair(const SIInstrInfo &TII,
MachineInstr &FirstMI,
MachineInstr &SecondMI);
std::unique_ptr<ScheduleDAGMutation> createVOPDPairingMutation();
} // namespace llvm
#endif // LLVM_LIB_TARGET_AMDGPU_VOPDUTILS_H