1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2020-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #ifndef LIB_GENXCODEGEN_GENXCONSTANTS_H
10 #define LIB_GENXCODEGEN_GENXCONSTANTS_H
11
12 #include "GenXSubtarget.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/IR/Constant.h"
15 #include "llvm/IR/Dominators.h"
16 #include "llvm/IR/Instructions.h"
17
18 #include "Probe/Assertion.h"
19
20 namespace llvm {
21 namespace genx {
22
23 // ConstantLoader : class to insert instruction(s) to load a constant
24 class ConstantLoader {
25 friend bool loadNonSimpleConstants(
26 Instruction *Inst, const GenXSubtarget &Subtarget, const DataLayout &DL,
27 SmallVectorImpl<Instruction *> *AddedInstructions);
28
29 Constant *C;
30 Instruction *User;
31
32 const GenXSubtarget &Subtarget;
33 const DataLayout &DL;
34
35 // NewC != nullptr signals that we should replace C with NewC in User
36 // nothing to do otherwise
37 Constant *NewC = nullptr;
38 // AddedInstructions: a vector that the caller has requested any added
39 // instructions to be pushed in to.
40 SmallVectorImpl<Instruction *> *AddedInstructions;
41 // Info from analyzing for possible packed vector constant.
42 int64_t PackedIntScale = 0; // amount to scale packed int vector by
43 int64_t PackedIntAdjust; // amount to adjust by, special casing 0 or -8
44 // when PackedIntScale is 1
45 unsigned PackedIntMax; // max value in packed vector, used when scale is
46 // 1 and adjust is 0 to tell whether it would fit
47 // in 0..7
48 bool PackedFloat = false;
49
50 public:
51 // Constructor
52 // User = the instruction that uses the constant. If this is genx.constanti,
53 // then a packed vector constant can be an isSimple() constant even
54 // when the element type is not i16. Also used to disallow a packed
55 // vector constant in a logic op. If User==0 then it is assumed that
56 // a packed vector constant with an element type other than i16 is OK.
57 // AddedInstructions = vector to add new instructions to when loading a
58 // non simple constant, so the caller can see all the newly added
59 // instructions.
60 ConstantLoader(Constant *C, const GenXSubtarget &InSubtarget,
61 const DataLayout &InDL, Instruction *User = nullptr,
62 SmallVectorImpl<Instruction *> *AddedInstructions = nullptr)
C(C)63 : C(C), User(User), Subtarget(InSubtarget), DL(InDL),
64 AddedInstructions(AddedInstructions) {
65 IGC_ASSERT_MESSAGE(!C->getType()->isAggregateType(),
66 "aggregate types are not supported by constant loader");
67 analyze();
68 }
69
70 Instruction *load(Instruction *InsertBefore);
71 Instruction *loadBig(Instruction *InsertBefore);
72
73 bool isBigSimple() const;
74 bool isSimple() const;
75 bool isLegalSize() const;
76
77 private:
78 bool allowI64Ops() const;
79
80 void analyze();
81 void analyzeForPackedInt(unsigned NumElements);
82 void analyzeForPackedFloat(unsigned NumElements);
83
84 bool isPackedIntVector() const;
85 bool isPackedFloatVector() const;
86
87 Constant *getConsolidatedConstant(Constant *C);
88 unsigned getRegionBits(unsigned NeededBits, unsigned OptionalBits,
89 unsigned VecWidth);
90
needFixingSimple()91 bool needFixingSimple() const { return NewC; }
92 void fixSimple(int OperandIdx);
93
94 Instruction *loadNonSimple(Instruction *InsertBefore);
95 Instruction *loadSplatConstant(Instruction *InsertPt);
96 Instruction *loadNonPackedIntConst(Instruction *InsertPt);
97 };
98
99 // Some instructions force their operands to be constants.
100 // Check here if operand of instruction must be constant.
opMustBeConstant(Instruction * I,unsigned OpNum)101 inline bool opMustBeConstant(Instruction *I, unsigned OpNum) {
102 // Mask of shufflevector should always be constant.
103 if (isa<ShuffleVectorInst>(I))
104 return OpNum == 2;
105 return false;
106 }
107
108 // Check whether types of two contsants are bitcastable and
109 // then check constants' contents. Most part of implementation is taken
110 // from FunctionComparator::cmpConstants
111 bool areConstantsEqual(const Constant *C1, const Constant *C2);
112
113 // Remove all genx.constant* intrinsics that have non-constant source
114 bool cleanupConstantLoads(Function *F);
115
116 // Load a constant using the llvm.genx.constant intrinsic.
117 inline Instruction *
118 loadConstant(Constant *C, Instruction *InsertBefore,
119 const GenXSubtarget &Subtarget, const DataLayout &DL,
120 SmallVectorImpl<Instruction *> *AddedInstructions = nullptr) {
121 return ConstantLoader(C, Subtarget, DL, nullptr, AddedInstructions)
122 .load(InsertBefore);
123 }
124
125 // Load non-simple constants used in an instruction.
126 bool loadNonSimpleConstants(
127 Instruction *Inst, const GenXSubtarget &Subtarget, const DataLayout &DL,
128 SmallVectorImpl<Instruction *> *AddedInstructions = nullptr);
129
130 bool loadConstantsForInlineAsm(
131 CallInst *Inst, const GenXSubtarget &Subtarget, const DataLayout &DL,
132 SmallVectorImpl<Instruction *> *AddedInstructions = nullptr);
133
134 // Load constants used in an instruction.
135 bool loadConstants(Instruction *Inst, const GenXSubtarget &Subtarget,
136 const DataLayout &DL);
137
138 // Load constants used in phi nodes in a function.
139 bool loadPhiConstants(Function &F, DominatorTree *DT,
140 const GenXSubtarget &Subtarget, const DataLayout &DL,
141 bool ExcludePredicate = false);
142
143 // Check if constant vector is replicated, e.g.
144 // Original vector: 1, 1, 1, 1, 0, 0, 0, 0
145 // Replicate vector: 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0
146 bool isReplicatedConstantVector(const ConstantVector *Orig,
147 const ConstantVector *ReplicateCandidate);
148
149 } // namespace genx
150 } // namespace llvm
151
152 #endif // LIB_GENXCODEGEN_GENXCONSTANTS_H
153