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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2020-2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#ifndef LIB_GENXCODEGEN_GENXCONSTANTS_H
#define LIB_GENXCODEGEN_GENXCONSTANTS_H
#include "GenXSubtarget.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instructions.h"
#include "Probe/Assertion.h"
namespace llvm {
namespace genx {
// ConstantLoader : class to insert instruction(s) to load a constant
class ConstantLoader {
friend bool loadNonSimpleConstants(
Instruction *Inst, const GenXSubtarget &Subtarget, const DataLayout &DL,
SmallVectorImpl<Instruction *> *AddedInstructions);
Constant *C;
Instruction *User;
const GenXSubtarget &Subtarget;
const DataLayout &DL;
// NewC != nullptr signals that we should replace C with NewC in User
// nothing to do otherwise
Constant *NewC = nullptr;
// AddedInstructions: a vector that the caller has requested any added
// instructions to be pushed in to.
SmallVectorImpl<Instruction *> *AddedInstructions;
// Info from analyzing for possible packed vector constant.
int64_t PackedIntScale = 0; // amount to scale packed int vector by
int64_t PackedIntAdjust; // amount to adjust by, special casing 0 or -8
// when PackedIntScale is 1
unsigned PackedIntMax; // max value in packed vector, used when scale is
// 1 and adjust is 0 to tell whether it would fit
// in 0..7
bool PackedFloat = false;
public:
// Constructor
// User = the instruction that uses the constant. If this is genx.constanti,
// then a packed vector constant can be an isSimple() constant even
// when the element type is not i16. Also used to disallow a packed
// vector constant in a logic op. If User==0 then it is assumed that
// a packed vector constant with an element type other than i16 is OK.
// AddedInstructions = vector to add new instructions to when loading a
// non simple constant, so the caller can see all the newly added
// instructions.
ConstantLoader(Constant *C, const GenXSubtarget &InSubtarget,
const DataLayout &InDL, Instruction *User = nullptr,
SmallVectorImpl<Instruction *> *AddedInstructions = nullptr)
: C(C), User(User), Subtarget(InSubtarget), DL(InDL),
AddedInstructions(AddedInstructions) {
IGC_ASSERT_MESSAGE(!C->getType()->isAggregateType(),
"aggregate types are not supported by constant loader");
analyze();
}
Instruction *load(Instruction *InsertBefore);
Instruction *loadBig(Instruction *InsertBefore);
bool isBigSimple() const;
bool isSimple() const;
bool isLegalSize() const;
private:
bool allowI64Ops() const;
void analyze();
void analyzeForPackedInt(unsigned NumElements);
void analyzeForPackedFloat(unsigned NumElements);
bool isPackedIntVector() const;
bool isPackedFloatVector() const;
Constant *getConsolidatedConstant(Constant *C);
unsigned getRegionBits(unsigned NeededBits, unsigned OptionalBits,
unsigned VecWidth);
bool needFixingSimple() const { return NewC; }
void fixSimple(int OperandIdx);
Instruction *loadNonSimple(Instruction *InsertBefore);
Instruction *loadSplatConstant(Instruction *InsertPt);
Instruction *loadNonPackedIntConst(Instruction *InsertPt);
};
// Some instructions force their operands to be constants.
// Check here if operand of instruction must be constant.
inline bool opMustBeConstant(Instruction *I, unsigned OpNum) {
// Mask of shufflevector should always be constant.
if (isa<ShuffleVectorInst>(I))
return OpNum == 2;
return false;
}
// Check whether types of two contsants are bitcastable and
// then check constants' contents. Most part of implementation is taken
// from FunctionComparator::cmpConstants
bool areConstantsEqual(const Constant *C1, const Constant *C2);
// Remove all genx.constant* intrinsics that have non-constant source
bool cleanupConstantLoads(Function *F);
// Load a constant using the llvm.genx.constant intrinsic.
inline Instruction *
loadConstant(Constant *C, Instruction *InsertBefore,
const GenXSubtarget &Subtarget, const DataLayout &DL,
SmallVectorImpl<Instruction *> *AddedInstructions = nullptr) {
return ConstantLoader(C, Subtarget, DL, nullptr, AddedInstructions)
.load(InsertBefore);
}
// Load non-simple constants used in an instruction.
bool loadNonSimpleConstants(
Instruction *Inst, const GenXSubtarget &Subtarget, const DataLayout &DL,
SmallVectorImpl<Instruction *> *AddedInstructions = nullptr);
bool loadConstantsForInlineAsm(
CallInst *Inst, const GenXSubtarget &Subtarget, const DataLayout &DL,
SmallVectorImpl<Instruction *> *AddedInstructions = nullptr);
// Load constants used in an instruction.
bool loadConstants(Instruction *Inst, const GenXSubtarget &Subtarget,
const DataLayout &DL);
// Load constants used in phi nodes in a function.
bool loadPhiConstants(Function &F, DominatorTree *DT,
const GenXSubtarget &Subtarget, const DataLayout &DL,
bool ExcludePredicate = false);
// Check if constant vector is replicated, e.g.
// Original vector: 1, 1, 1, 1, 0, 0, 0, 0
// Replicate vector: 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0
bool isReplicatedConstantVector(const ConstantVector *Orig,
const ConstantVector *ReplicateCandidate);
} // namespace genx
} // namespace llvm
#endif // LIB_GENXCODEGEN_GENXCONSTANTS_H
|