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:
69 Ops.push_back(
I->getOperand(0));
70 Ops.push_back(
I->getOperand(1));
72 case Instruction::ExtractElement:
73 Ops.push_back(
I->getOperand(0));
75 case Instruction::Select:
76 Ops.push_back(
I->getOperand(1));
77 Ops.push_back(
I->getOperand(2));
79 case Instruction::PHI:
87bool TruncInstCombine::buildTruncExpressionGraph() {
88 SmallVector<Value *, 8> Worklist;
89 SmallVector<Instruction *, 8>
Stack;
93 Worklist.push_back(CurrentTruncInst->getOperand(0));
95 while (!Worklist.empty()) {
96 Value *Curr = Worklist.back();
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: {
160 Worklist.push_back(
Op);
174unsigned TruncInstCombine::getMinBitWidth() {
175 SmallVector<Value *, 8> Worklist;
176 SmallVector<Instruction *, 8>
Stack;
178 Value *Src = CurrentTruncInst->getOperand(0);
179 Type *DstTy = CurrentTruncInst->getType();
181 unsigned OrigBitWidth =
182 CurrentTruncInst->getOperand(0)->getType()->getScalarSizeInBits();
185 return TruncBitWidth;
187 Worklist.push_back(Src);
190 while (!Worklist.empty()) {
191 Value *Curr = Worklist.back();
201 auto &Info = InstInfoMap[
I];
214 std::max(Info.MinBitWidth, InstInfoMap[IOp].MinBitWidth);
220 unsigned ValidBitWidth = Info.ValidBitWidth;
224 Info.MinBitWidth = std::max(Info.MinBitWidth, Info.ValidBitWidth);
231 unsigned IOpBitwidth = InstInfoMap.lookup(IOp).ValidBitWidth;
232 if (IOpBitwidth >= ValidBitWidth)
234 InstInfoMap[IOp].ValidBitWidth = ValidBitWidth;
235 Worklist.push_back(IOp);
239 assert(MinBitWidth >= TruncBitWidth);
241 if (MinBitWidth > TruncBitWidth) {
248 Type *Ty = DL.getSmallestLegalIntType(DstTy->
getContext(), MinBitWidth);
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) {
279 for (
auto *U :
I->users())
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 =
296 CurrentTruncInst->getOperand(0)->getType()->getScalarSizeInBits();
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()) {
332 KnownBits Known = computeKnownBits(
Op);
335 if (MinBitWidth >= OrigBitWidth)
338 Itr.second.MinBitWidth = MinBitWidth;
344 unsigned MinBitWidth = getMinBitWidth();
348 if (MinBitWidth >= OrigBitWidth ||
349 (DesiredBitWidth && DesiredBitWidth != MinBitWidth))
359 assert(Ty && !Ty->isVectorTy() &&
"Expect Scalar Type");
365Value *TruncInstCombine::getReducedOperand(
Value *V,
Type *SclTy) {
374 Info
Entry = InstInfoMap.lookup(
I);
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) {
402 NodeInfo.NewValue =
I->getOperand(0);
407 Res = Builder.CreateIntCast(
I->getOperand(0), Ty,
408 Opc == Instruction::SExt);
416 if (Entry != Worklist.end()) {
420 Worklist.erase(Entry);
422 Worklist.push_back(NewCI);
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);
442 ResI->setIsExact(PEO->isExact());
445 case Instruction::ExtractElement: {
446 Value *Vec = getReducedOperand(
I->getOperand(0), SclTy);
447 Value *Idx =
I->getOperand(1);
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);
454 Value *Idx =
I->getOperand(2);
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: {
475 NodeInfo.NewValue = Res;
480 for (
auto &Node : OldNewPHINodes) {
481 PHINode *OldPN =
Node.first;
482 PHINode *NewPN =
Node.second;
484 NewPN->
addIncoming(getReducedOperand(std::get<0>(Incoming), SclTy),
485 std::get<1>(Incoming));
488 Value *Res = getReducedOperand(CurrentTruncInst->getOperand(0), SclTy);
489 Type *DstTy = CurrentTruncInst->getType();
492 Res = Builder.CreateIntCast(Res, DstTy,
false);
496 CurrentTruncInst->replaceAllUsesWith(Res);
500 CurrentTruncInst->eraseFromParent();
502 for (
auto &Node : OldNewPHINodes) {
503 PHINode *OldPN =
Node.first;
505 InstInfoMap.erase(OldPN);
516 if (
I.first->use_empty())
517 I.first->eraseFromParent();
520 "Only {SExt, ZExt}Inst might have unreduced users");
525 bool MadeIRChange =
false;
530 if (!DT.isReachableFromEntry(&BB))
534 Worklist.push_back(CI);
540 while (!Worklist.empty()) {
541 CurrentTruncInst = Worklist.pop_back_val();
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!")
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
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,...
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)
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...
void push_back(const T &Elt)
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.
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 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.
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
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.
FunctionAddr VTableAddr Value
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.