1 | //===- RISCVMatInt.h - Immediate materialisation ---------------*- C++ -*--===// |
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 | #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_MATINT_H |
10 | #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_MATINT_H |
11 | |
12 | #include "llvm/ADT/SmallVector.h" |
13 | #include "llvm/MC/MCRegister.h" |
14 | #include "llvm/MC/MCSubtargetInfo.h" |
15 | #include <cstdint> |
16 | |
17 | namespace llvm { |
18 | class APInt; |
19 | |
20 | namespace RISCVMatInt { |
21 | |
22 | enum OpndKind { |
23 | RegImm, // ADDI/ADDIW/SLLI/SRLI/BSETI/BCLRI |
24 | Imm, // LUI |
25 | RegReg, // SH1ADD/SH2ADD/SH3ADD |
26 | RegX0, // ADD_UW |
27 | }; |
28 | |
29 | class Inst { |
30 | unsigned Opc; |
31 | int32_t Imm; // The largest value we need to store is 20 bits. |
32 | |
33 | public: |
34 | Inst(unsigned Opc, int64_t I) : Opc(Opc), Imm(I) { |
35 | assert(I == Imm && "truncated" ); |
36 | } |
37 | |
38 | unsigned getOpcode() const { return Opc; } |
39 | int64_t getImm() const { return Imm; } |
40 | |
41 | OpndKind getOpndKind() const; |
42 | }; |
43 | using InstSeq = SmallVector<Inst, 8>; |
44 | |
45 | // Helper to generate an instruction sequence that will materialise the given |
46 | // immediate value into a register. A sequence of instructions represented by a |
47 | // simple struct is produced rather than directly emitting the instructions in |
48 | // order to allow this helper to be used from both the MC layer and during |
49 | // instruction selection. |
50 | InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI); |
51 | |
52 | // Helper to generate the generateInstSeq instruction sequence using MCInsts |
53 | void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, |
54 | MCRegister DestReg, SmallVectorImpl<MCInst> &Insts); |
55 | |
56 | // Helper to generate an instruction sequence that can materialize the given |
57 | // immediate value into a register using an additional temporary register. This |
58 | // handles cases where the constant can be generated by (ADD (SLLI X, C), X) or |
59 | // (ADD_UW (SLLI X, C) X). The sequence to generate X is returned. ShiftAmt is |
60 | // provides the SLLI and AddOpc indicates ADD or ADD_UW. |
61 | InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, |
62 | unsigned &ShiftAmt, unsigned &AddOpc); |
63 | |
64 | // Helper to estimate the number of instructions required to materialise the |
65 | // given immediate value into a register. This estimate does not account for |
66 | // `Val` possibly fitting into an immediate, and so may over-estimate. |
67 | // |
68 | // This will attempt to produce instructions to materialise `Val` as an |
69 | // `Size`-bit immediate. |
70 | // |
71 | // If CompressionCost is true it will use a different cost calculation if RVC is |
72 | // enabled. This should be used to compare two different sequences to determine |
73 | // which is more compressible. |
74 | // |
75 | // If FreeZeroes is true, it will be assumed free to materialize any |
76 | // XLen-sized chunks that are 0. This is appropriate to use in instances when |
77 | // the zero register can be used, e.g. when estimating the cost of |
78 | // materializing a value used by a particular operation. |
79 | int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, |
80 | bool CompressionCost = false, bool FreeZeroes = false); |
81 | } // namespace RISCVMatInt |
82 | } // namespace llvm |
83 | #endif |
84 | |