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