aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/CodeGen/GlobalISel/LegalizerHelper.h
blob: fdb61d59437a6ff9a6484d3e07a30664c01df769 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef RCC_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H
#define RCC_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H

#include "rcc/CodeGen/GenericOpcodes.h"
#include "rcc/CodeGen/GlobalISel/LegalizerInfo.h"
#include "rcc/CodeGen/MachineIRBuilder.h"
#include "rcc/Support/Error.h"

#include <vector>

namespace rcc {

class MachineFunction;
class MachineInstr;
class GISelChangeObserver;
struct LibcallLoweringInfo;

class LegalizerHelper final {
public:
  MachineIRBuilder &MIRBuilder;
  GISelChangeObserver &Observer;

  LegalizerHelper(MachineFunction &Function, const LegalizerInfo &Info,
                  GISelChangeObserver &Observer, MachineIRBuilder &MIRBuilder,
                  const LibcallLoweringInfo *Libcalls = nullptr);

  [[nodiscard]] Expected<void> legalize(MachineInstr &Instruction,
                                        const LegalizationDecision &Decision);
  [[nodiscard]] Expected<void> lower(MachineInstr &Instruction,
                                     const LegalizationDecision &Decision);
  [[nodiscard]] Expected<void> lowerAbsToAddXor(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerAbsDiffToSelect(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerAbsDiffToMinMax(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerMinMax(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerThreewayCompare(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerDivRem(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerBswap(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerRotate(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> lowerVAArg(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> libcall(MachineInstr &Instruction);
  [[nodiscard]] Expected<void> widenScalar(MachineInstr &Instruction, std::size_t TypeIndex,
                                           LowLevelType WideType);
  [[nodiscard]] Expected<void> widenScalarSrc(MachineInstr &Instruction, LowLevelType WideType,
                                              std::size_t OperandIndex,
                                              GenericOpcode ExtensionOpcode);
  [[nodiscard]] Expected<void> narrowScalarSrc(MachineInstr &Instruction, LowLevelType NarrowType,
                                               std::size_t OperandIndex);
  [[nodiscard]] Expected<void> narrowScalarDst(MachineInstr &Instruction, LowLevelType NarrowType,
                                               std::size_t OperandIndex,
                                               GenericOpcode ExtensionOpcode);
  [[nodiscard]] Expected<void> widenScalarDst(MachineInstr &Instruction, LowLevelType WideType,
                                              std::size_t OperandIndex = 0,
                                              GenericOpcode TruncOpcode = GenericOpcode::G_TRUNC);

  [[nodiscard]] Expected<void> narrowScalar(MachineInstr &Instruction, std::size_t TypeIndex,
                                            LowLevelType NarrowType);

private:
  [[nodiscard]] Expected<void> widenScalarMergeValues(MachineInstr &Instruction,
                                                      std::size_t TypeIndex, LowLevelType WideType);
  [[nodiscard]] Expected<void>
  widenScalarUnmergeValues(MachineInstr &Instruction, std::size_t TypeIndex, LowLevelType WideType);
  [[nodiscard]] Expected<void> insertParts(Register Destination, LowLevelType ResultType,
                                           LowLevelType PartType,
                                           const std::vector<Register> &PartRegisters,
                                           LowLevelType LeftoverType = {},
                                           const std::vector<Register> &LeftoverRegisters = {});
  [[nodiscard]] Expected<void> extractGCDType(std::vector<Register> &Parts, LowLevelType GCDType,
                                              Register Source);
  [[nodiscard]] Expected<LowLevelType> extractGCDType(std::vector<Register> &Parts,
                                                      LowLevelType DestinationType,
                                                      LowLevelType NarrowType, Register Source);
  [[nodiscard]] Expected<LowLevelType>
  buildLCMMergePieces(LowLevelType DestinationType, LowLevelType NarrowType, LowLevelType GCDType,
                      std::vector<Register> &Registers,
                      GenericOpcode PadStrategy = GenericOpcode::G_ANYEXT);
  [[nodiscard]] Expected<void>
  buildWidenedRemergeToDst(Register Destination, LowLevelType LCMType,
                           const std::vector<Register> &RemergeRegisters);
  [[nodiscard]] Expected<void> narrowScalarAddSub(MachineInstr &Instruction, std::size_t TypeIndex,
                                                  LowLevelType NarrowType);
  [[nodiscard]] Expected<void> narrowScalarBasic(MachineInstr &Instruction, std::size_t TypeIndex,
                                                 LowLevelType NarrowType);
  [[nodiscard]] Expected<void> narrowScalarExt(MachineInstr &Instruction, std::size_t TypeIndex,
                                               LowLevelType NarrowType);
  [[nodiscard]] Expected<void> narrowScalarSelect(MachineInstr &Instruction, std::size_t TypeIndex,
                                                  LowLevelType NarrowType);
  [[nodiscard]] Expected<void> narrowScalarShift(MachineInstr &Instruction, std::size_t TypeIndex,
                                                 LowLevelType NarrowType);
  [[nodiscard]] Expected<void> narrowScalarShiftByConstant(MachineInstr &Instruction,
                                                           const APInt &Amount,
                                                           LowLevelType HalfType,
                                                           LowLevelType AmountType);
  [[nodiscard]] Expected<void> narrowScalarShiftMultiway(MachineInstr &Instruction,
                                                         LowLevelType TargetType);
  [[nodiscard]] Expected<void> narrowScalarShiftByConstantMultiway(MachineInstr &Instruction,
                                                                   const APInt &Amount,
                                                                   LowLevelType TargetType,
                                                                   LowLevelType AmountType);

  struct ShiftParameters final {
    Register WordShift;
    Register BitShift;
    Register InverseBitShift;
    Register Zero;
    Register SignBit;
  };

  [[nodiscard]] Expected<Register>
  buildConstantShiftPart(GenericOpcode Generic, std::size_t PartIndex, std::size_t PartCount,
                         const std::vector<Register> &SourceParts,
                         const ShiftParameters &Parameters, LowLevelType TargetType);
  [[nodiscard]] Expected<Register>
  buildVariableShiftPart(GenericOpcode Generic, Register MainOperand, Register ShiftAmount,
                         LowLevelType TargetType, Register CarryOperand = {});
  [[nodiscard]] Expected<void> widenScalarAddSubOverflow(MachineInstr &Instruction,
                                                         std::size_t TypeIndex,
                                                         LowLevelType WideType);
  [[nodiscard]] Expected<void> lowerSignedAddSubOverflow(MachineInstr &Instruction);

  MachineFunction &Function;
  MachineRegisterInfo &MRI;
  const LegalizerInfo &Info;
  const LibcallLoweringInfo *Libcalls = nullptr;
};

} // namespace rcc

#endif // RCC_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H