38 #define DEBUG_TYPE "aggressive-instcombine" 45 case Instruction::Trunc:
46 case Instruction::ZExt:
47 case Instruction::SExt:
52 case Instruction::Sub:
53 case Instruction::Mul:
54 case Instruction::And:
56 case Instruction::Xor:
65 bool TruncInstCombine::buildTruncExpressionDag() {
73 while (!Worklist.
empty()) {
76 if (isa<Constant>(Curr)) {
91 InstInfoMap.insert(std::make_pair(
I,
Info()));
95 if (InstInfoMap.count(
I)) {
103 unsigned Opc =
I->getOpcode();
105 case Instruction::Trunc:
106 case Instruction::ZExt:
107 case Instruction::SExt:
114 case Instruction::Sub:
115 case Instruction::Mul:
116 case Instruction::And:
117 case Instruction::Or:
118 case Instruction::Xor: {
121 for (
Value *Operand : Operands)
138 unsigned TruncInstCombine::getMinBitWidth() {
145 unsigned OrigBitWidth =
148 if (isa<Constant>(Src))
149 return TruncBitWidth;
152 InstInfoMap[cast<Instruction>(Src)].ValidBitWidth = TruncBitWidth;
154 while (!Worklist.
empty()) {
157 if (isa<Constant>(Curr)) {
163 auto *
I = cast<Instruction>(Curr);
165 auto &
Info = InstInfoMap[
I];
175 for (
auto *Operand : Operands)
176 if (
auto *IOp = dyn_cast<Instruction>(Operand))
178 std::max(Info.MinBitWidth, InstInfoMap[IOp].MinBitWidth);
184 unsigned ValidBitWidth = Info.ValidBitWidth;
188 Info.MinBitWidth =
std::max(Info.MinBitWidth, Info.ValidBitWidth);
190 for (
auto *Operand : Operands)
191 if (
auto *IOp = dyn_cast<Instruction>(Operand)) {
195 unsigned IOpBitwidth = InstInfoMap.lookup(IOp).ValidBitWidth;
196 if (IOpBitwidth >= ValidBitWidth)
198 InstInfoMap[IOp].ValidBitWidth =
std::max(ValidBitWidth, IOpBitwidth);
202 unsigned MinBitWidth = InstInfoMap.lookup(cast<Instruction>(Src)).MinBitWidth;
203 assert(MinBitWidth >= TruncBitWidth);
205 if (MinBitWidth > TruncBitWidth) {
221 bool FromLegal = MinBitWidth == 1 || DL.
isLegalInteger(OrigBitWidth);
222 bool ToLegal = MinBitWidth == 1 || DL.
isLegalInteger(MinBitWidth);
223 if (!DstTy->
isVectorTy() && FromLegal && !ToLegal)
229 Type *TruncInstCombine::getBestTruncatedType() {
230 if (!buildTruncExpressionDag())
237 unsigned DesiredBitWidth = 0;
238 for (
auto Itr : InstInfoMap) {
242 bool IsExtInst = (isa<ZExtInst>(
I) || isa<SExtInst>(I));
243 for (
auto *U : I->
users())
244 if (
auto *UI = dyn_cast<Instruction>(U))
245 if (UI != CurrentTruncInst && !InstInfoMap.count(UI)) {
251 unsigned ExtInstBitWidth =
253 if (DesiredBitWidth && DesiredBitWidth != ExtInstBitWidth)
255 DesiredBitWidth = ExtInstBitWidth;
259 unsigned OrigBitWidth =
264 unsigned MinBitWidth = getMinBitWidth();
268 if (MinBitWidth >= OrigBitWidth ||
269 (DesiredBitWidth && DesiredBitWidth != MinBitWidth))
280 if (
auto *VTy = dyn_cast<VectorType>(V->
getType()))
285 Value *TruncInstCombine::getReducedOperand(
Value *V,
Type *SclTy) {
287 if (
auto *
C = dyn_cast<Constant>(V)) {
295 auto *
I = cast<Instruction>(V);
296 Info Entry = InstInfoMap.lookup(
I);
298 return Entry.NewValue;
301 void TruncInstCombine::ReduceExpressionDag(
Type *SclTy) {
302 for (
auto &Itr : InstInfoMap) {
306 assert(!NodeInfo.NewValue &&
"Instruction has been evaluated");
309 Value *Res =
nullptr;
312 case Instruction::Trunc:
313 case Instruction::ZExt:
314 case Instruction::SExt: {
320 assert(!isa<TruncInst>(I) &&
"Cannot reach here with TruncInst");
327 Opc == Instruction::SExt);
334 auto Entry =
find(Worklist, I);
335 if (Entry != Worklist.end()) {
336 if (
auto *NewCI = dyn_cast<TruncInst>(Res))
339 Worklist.erase(Entry);
340 }
else if (
auto *NewCI = dyn_cast<TruncInst>(Res))
341 Worklist.push_back(NewCI);
345 case Instruction::Sub:
346 case Instruction::Mul:
347 case Instruction::And:
348 case Instruction::Or:
349 case Instruction::Xor: {
359 NodeInfo.NewValue = Res;
360 if (
auto *ResI = dyn_cast<Instruction>(Res))
364 Value *Res = getReducedOperand(CurrentTruncInst->
getOperand(0), SclTy);
369 if (
auto *ResI = dyn_cast<Instruction>(Res))
379 for (
auto I = InstInfoMap.rbegin(),
E = InstInfoMap.rend();
I !=
E; ++
I) {
383 if (
I->first->use_empty())
384 I->first->eraseFromParent();
389 bool MadeIRChange =
false;
397 if (
auto *CI = dyn_cast<TruncInst>(&
I))
398 Worklist.push_back(CI);
404 while (!Worklist.empty()) {
405 CurrentTruncInst = Worklist.pop_back_val();
407 if (
Type *NewDstSclTy = getBestTruncatedType()) {
409 dbgs() <<
"ICE: TruncInstCombine reducing type of expression dag " 411 << CurrentTruncInst <<
'\n');
412 ReduceExpressionDag(NewDstSclTy);
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
void push_back(const T &Elt)
LLVMContext & getContext() const
All values hold a context through their type.
static void getRelevantOperands(Instruction *I, SmallVectorImpl< Value *> &Ops)
Given an instruction and a container, it fills all the relevant operands of that instruction, with respect to the Trunc expression dag optimizaton.
bool isVectorTy() const
True if this is an instance of VectorType.
Type * getSmallestLegalIntType(LLVMContext &C, unsigned Width=0) const
Returns the smallest integer type with size at least as big as Width bits.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static Constant * getIntegerCast(Constant *C, Type *Ty, bool isSigned)
Create a ZExt, Bitcast or Trunc for integer -> integer casts.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Attempt to fold the constant using the specified DataLayout.
Type * getType() const
All values are typed, get the type of this value.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void takeName(Value *V)
Transfer the name from V to this value.
Value * getOperand(unsigned i) const
Analysis containing CSE Info
The instances of the Type class are immutable: once they are created, they are never changed...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool run(Function &F)
Perform TruncInst pattern optimization on given function.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type...
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
bool isLegalInteger(uint64_t Width) const
Returns true if the specified type is known to be a native integer type supported by the CPU...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< user_iterator > users()
static Type * getReducedType(Value *V, Type *Ty)
Given a reduced scalar type Ty and a V value, return a reduced type for V, according to its type...
LLVM_NODISCARD bool empty() const
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
static VectorType * get(Type *ElementType, unsigned NumElements)
This static method is the primary way to construct an VectorType.
bool hasOneUse() const
Return true if there is exactly one user of this value.