39#define DEBUG_TYPE "aggressive-instcombine"
41STATISTIC(NumExprsReduced,
"Number of truncations eliminated by reducing bit "
42 "width of expression graph");
44 "Number of instructions whose bit width was reduced");
49 unsigned Opc =
I->getOpcode();
51 case Instruction::Trunc:
52 case Instruction::ZExt:
53 case Instruction::SExt:
57 case Instruction::Add:
58 case Instruction::Sub:
59 case Instruction::Mul:
60 case Instruction::And:
62 case Instruction::Xor:
63 case Instruction::Shl:
64 case Instruction::LShr:
65 case Instruction::AShr:
66 case Instruction::UDiv:
67 case Instruction::URem:
68 case Instruction::InsertElement:
72 case Instruction::ExtractElement:
75 case Instruction::Select:
79 case Instruction::PHI:
87bool TruncInstCombine::buildTruncExpressionGraph() {
95 while (!Worklist.
empty()) {
98 if (isa<Constant>(Curr)) {
103 auto *
I = dyn_cast<Instruction>(Curr);
113 InstInfoMap.try_emplace(
I);
117 if (InstInfoMap.count(
I)) {
125 unsigned Opc =
I->getOpcode();
127 case Instruction::Trunc:
128 case Instruction::ZExt:
129 case Instruction::SExt:
135 case Instruction::Add:
136 case Instruction::Sub:
137 case Instruction::Mul:
138 case Instruction::And:
139 case Instruction::Or:
140 case Instruction::Xor:
141 case Instruction::Shl:
142 case Instruction::LShr:
143 case Instruction::AShr:
144 case Instruction::UDiv:
145 case Instruction::URem:
146 case Instruction::InsertElement:
147 case Instruction::ExtractElement:
148 case Instruction::Select: {
154 case Instruction::PHI: {
174unsigned TruncInstCombine::getMinBitWidth() {
181 unsigned OrigBitWidth =
184 if (isa<Constant>(Src))
185 return TruncBitWidth;
188 InstInfoMap[cast<Instruction>(Src)].ValidBitWidth = TruncBitWidth;
190 while (!Worklist.
empty()) {
193 if (isa<Constant>(Curr)) {
199 auto *
I = cast<Instruction>(Curr);
201 auto &
Info = InstInfoMap[
I];
212 if (
auto *IOp = dyn_cast<Instruction>(Operand))
214 std::max(
Info.MinBitWidth, InstInfoMap[IOp].MinBitWidth);
220 unsigned ValidBitWidth =
Info.ValidBitWidth;
224 Info.MinBitWidth = std::max(
Info.MinBitWidth,
Info.ValidBitWidth);
227 if (
auto *IOp = dyn_cast<Instruction>(Operand)) {
231 unsigned IOpBitwidth = InstInfoMap.lookup(IOp).ValidBitWidth;
232 if (IOpBitwidth >= ValidBitWidth)
234 InstInfoMap[IOp].ValidBitWidth = ValidBitWidth;
238 unsigned MinBitWidth = InstInfoMap.lookup(cast<Instruction>(Src)).MinBitWidth;
239 assert(MinBitWidth >= TruncBitWidth);
241 if (MinBitWidth > TruncBitWidth) {
257 bool FromLegal = MinBitWidth == 1 || DL.
isLegalInteger(OrigBitWidth);
258 bool ToLegal = MinBitWidth == 1 || DL.
isLegalInteger(MinBitWidth);
259 if (!DstTy->
isVectorTy() && FromLegal && !ToLegal)
265Type *TruncInstCombine::getBestTruncatedType() {
266 if (!buildTruncExpressionGraph())
273 unsigned DesiredBitWidth = 0;
274 for (
auto Itr : InstInfoMap) {
278 bool IsExtInst = (isa<ZExtInst>(
I) || isa<SExtInst>(
I));
279 for (
auto *U :
I->users())
280 if (
auto *UI = dyn_cast<Instruction>(U))
281 if (UI != CurrentTruncInst && !InstInfoMap.count(UI)) {
287 unsigned ExtInstBitWidth =
288 I->getOperand(0)->getType()->getScalarSizeInBits();
289 if (DesiredBitWidth && DesiredBitWidth != ExtInstBitWidth)
291 DesiredBitWidth = ExtInstBitWidth;
295 unsigned OrigBitWidth =
306 for (
auto &Itr : InstInfoMap) {
309 KnownBits KnownRHS = computeKnownBits(
I->getOperand(1));
313 if (MinBitWidth == OrigBitWidth)
315 if (
I->getOpcode() == Instruction::LShr) {
316 KnownBits KnownLHS = computeKnownBits(
I->getOperand(0));
320 if (
I->getOpcode() == Instruction::AShr) {
321 unsigned NumSignBits = ComputeNumSignBits(
I->getOperand(0));
322 MinBitWidth = std::max(MinBitWidth, OrigBitWidth - NumSignBits + 1);
324 if (MinBitWidth >= OrigBitWidth)
326 Itr.second.MinBitWidth = MinBitWidth;
328 if (
I->getOpcode() == Instruction::UDiv ||
329 I->getOpcode() == Instruction::URem) {
330 unsigned MinBitWidth = 0;
331 for (
const auto &
Op :
I->operands()) {
335 if (MinBitWidth >= OrigBitWidth)
338 Itr.second.MinBitWidth = MinBitWidth;
344 unsigned MinBitWidth = getMinBitWidth();
348 if (MinBitWidth >= OrigBitWidth ||
349 (DesiredBitWidth && DesiredBitWidth != MinBitWidth))
360 if (
auto *VTy = dyn_cast<VectorType>(V->getType()))
365Value *TruncInstCombine::getReducedOperand(
Value *V,
Type *SclTy) {
367 if (
auto *
C = dyn_cast<Constant>(V)) {
373 auto *
I = cast<Instruction>(V);
376 return Entry.NewValue;
379void TruncInstCombine::ReduceExpressionGraph(
Type *SclTy) {
380 NumInstrsReduced += InstInfoMap.size();
383 for (
auto &Itr : InstInfoMap) {
385 TruncInstCombine::Info &NodeInfo = Itr.second;
387 assert(!NodeInfo.NewValue &&
"Instruction has been evaluated");
390 Value *Res =
nullptr;
391 unsigned Opc =
I->getOpcode();
393 case Instruction::Trunc:
394 case Instruction::ZExt:
395 case Instruction::SExt: {
400 if (
I->getOperand(0)->getType() == Ty) {
401 assert(!isa<TruncInst>(
I) &&
"Cannot reach here with TruncInst");
402 NodeInfo.NewValue =
I->getOperand(0);
407 Res = Builder.CreateIntCast(
I->getOperand(0), Ty,
408 Opc == Instruction::SExt);
416 if (Entry != Worklist.
end()) {
417 if (
auto *NewCI = dyn_cast<TruncInst>(Res))
420 Worklist.
erase(Entry);
421 }
else if (
auto *NewCI = dyn_cast<TruncInst>(Res))
425 case Instruction::Add:
426 case Instruction::Sub:
427 case Instruction::Mul:
428 case Instruction::And:
429 case Instruction::Or:
430 case Instruction::Xor:
431 case Instruction::Shl:
432 case Instruction::LShr:
433 case Instruction::AShr:
434 case Instruction::UDiv:
435 case Instruction::URem: {
436 Value *
LHS = getReducedOperand(
I->getOperand(0), SclTy);
437 Value *
RHS = getReducedOperand(
I->getOperand(1), SclTy);
440 if (
auto *PEO = dyn_cast<PossiblyExactOperator>(
I))
441 if (
auto *ResI = dyn_cast<Instruction>(Res))
442 ResI->setIsExact(PEO->isExact());
445 case Instruction::ExtractElement: {
446 Value *Vec = getReducedOperand(
I->getOperand(0), SclTy);
448 Res = Builder.CreateExtractElement(Vec,
Idx);
451 case Instruction::InsertElement: {
452 Value *Vec = getReducedOperand(
I->getOperand(0), SclTy);
453 Value *NewElt = getReducedOperand(
I->getOperand(1), SclTy);
455 Res = Builder.CreateInsertElement(Vec, NewElt,
Idx);
458 case Instruction::Select: {
459 Value *Op0 =
I->getOperand(0);
460 Value *
LHS = getReducedOperand(
I->getOperand(1), SclTy);
461 Value *
RHS = getReducedOperand(
I->getOperand(2), SclTy);
462 Res = Builder.CreateSelect(Op0, LHS, RHS);
465 case Instruction::PHI: {
468 std::make_pair(cast<PHINode>(
I), cast<PHINode>(Res)));
475 NodeInfo.NewValue = Res;
476 if (
auto *ResI = dyn_cast<Instruction>(Res))
480 for (
auto &
Node : OldNewPHINodes) {
488 Value *Res = getReducedOperand(CurrentTruncInst->
getOperand(0), SclTy);
492 Res = Builder.CreateIntCast(Res, DstTy,
false);
493 if (
auto *ResI = dyn_cast<Instruction>(Res))
502 for (
auto &
Node : OldNewPHINodes) {
505 InstInfoMap.erase(OldPN);
516 if (
I.first->use_empty())
517 I.first->eraseFromParent();
519 assert((isa<SExtInst>(
I.first) || isa<ZExtInst>(
I.first)) &&
520 "Only {SExt, ZExt}Inst might have unreduced users");
525 bool MadeIRChange =
false;
533 if (
auto *CI = dyn_cast<TruncInst>(&
I))
540 while (!Worklist.
empty()) {
543 if (
Type *NewDstSclTy = getBestTruncatedType()) {
545 dbgs() <<
"ICE: TruncInstCombine reducing type of expression graph "
547 << CurrentTruncInst <<
'\n');
548 ReduceExpressionGraph(NewDstSclTy);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
mir Rename Register Operands
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
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,...
static void getRelevantOperands(Instruction *I, SmallVectorImpl< Value * > &Ops)
Given an instruction and a container, it fills all the relevant operands of that instruction,...
Class for arbitrary precision integers.
unsigned getActiveBits() const
Compute the number of active bits in the value.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
LLVM_ABI APInt uadd_sat(const APInt &RHS) const
static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This class represents an Operation in the Expression.
bool isLegalInteger(uint64_t Width) const
Returns true if the specified type is known to be a native integer type supported by the CPU.
LLVM_ABI Type * getSmallestLegalIntType(LLVMContext &C, unsigned Width=0) const
Returns the smallest integer type with size at least as big as Width bits.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
iterator_range< const_block_iterator > blocks() const
op_range incoming_values()
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool run(Function &F)
Perform TruncInst pattern optimization on given function.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Fold the constant using the specified DataLayout.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.