1//===- GCNVOPDUtils.h - GCN VOPD Utils ------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file This file contains the AMDGPU DAG scheduling
10/// mutation to pair VOPD instructions back to back. It also contains
11// subroutines useful in the creation of VOPD instructions
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_LIB_TARGET_AMDGPU_VOPDUTILS_H
16#define LLVM_LIB_TARGET_AMDGPU_VOPDUTILS_H
17
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/CodeGen/MachineScheduler.h"
20#include <optional>
21
22namespace llvm {
23
24class MachineInstr;
25class SIInstrInfo;
26class MCRegisterClass;
27
28/// A 32-bit immediate which the VOPD encoding cannot hold. The pair only
29/// becomes legal after the operand is replaced by a scalar register holding
30/// \p Imm.
31struct VOPDLiteralFixup {
32 /// Component holding the immediate, AMDGPU::VOPD::X or AMDGPU::VOPD::Y.
33 unsigned CompIdx;
34 /// Index of the immediate operand within that component.
35 unsigned OpIdx;
36 /// Value which has to be placed in a register.
37 int32_t Imm;
38 /// Scalar registers the VOPD source slot can read. This is the slot class
39 /// narrowed to SGPR_32, so every register in it can be used.
40 const MCRegisterClass *SlotRC;
41};
42
43/// Describes a matched VOPD pair.
44struct VOPDMatchInfo {
45 /// The component instructions in program order.
46 MachineInstr *InOrder[2];
47 /// Which entry in \p InOrder is the X component.
48 unsigned XIdx;
49 bool IsVOPD3;
50 /// Immediates which have to be moved into scalar registers before the pair
51 /// can be built. They all have the same 32-bit value, so one register serves
52 /// the whole pair. Only a VOPD3 pair can need this.
53 SmallVector<VOPDLiteralFixup, 2> LiteralFixups;
54
55 MachineInstr *getMIX() const { return InOrder[XIdx]; }
56 MachineInstr *getMIY() const { return InOrder[1 - XIdx]; }
57};
58
59/// Check whether FirstMI and SecondMI can be
60/// combined into a VOPD instruction. Returns the match info (X/Y assignment
61/// and encoding variant) on success, or std::nullopt if they cannot be paired.
62std::optional<VOPDMatchInfo> tryMatchVOPDPair(const SIInstrInfo &TII,
63 MachineInstr &FirstMI,
64 MachineInstr &SecondMI);
65
66std::unique_ptr<ScheduleDAGMutation> createVOPDPairingMutation();
67
68} // namespace llvm
69
70#endif // LLVM_LIB_TARGET_AMDGPU_VOPDUTILS_H
71