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");
48 unsigned Opc =
I->getOpcode();
50 case Instruction::Trunc:
51 case Instruction::ZExt:
52 case Instruction::SExt:
56 case Instruction::Add:
57 case Instruction::Sub:
58 case Instruction::Mul:
59 case Instruction::And:
61 case Instruction::Xor:
62 case Instruction::Shl:
63 case Instruction::LShr:
64 case Instruction::AShr:
65 case Instruction::UDiv:
66 case Instruction::URem:
68 case Instruction::InsertElement:
70 case Instruction::ExtractElement:
72 case Instruction::Select:
74 case Instruction::PHI:
84 for (
Use &
Op :
I->operands())
86 Ops.push_back(
Op.get());
89bool TruncInstCombine::buildTruncExpressionGraph() {
90 SmallVector<Value *, 8> Worklist;
91 SmallVector<Instruction *, 8>
Stack;
95 Worklist.push_back(CurrentTruncInst->getOperand(0));
97 while (!Worklist.empty()) {
98 Value *Curr = Worklist.back();
115 InstInfoMap.try_emplace(
I);
119 if (InstInfoMap.count(
I)) {
127 unsigned Opc =
I->getOpcode();
129 case Instruction::Trunc:
130 case Instruction::ZExt:
131 case Instruction::SExt:
137 case Instruction::Add:
138 case Instruction::Sub:
139 case Instruction::Mul:
140 case Instruction::And:
141 case Instruction::Or:
142 case Instruction::Xor:
143 case Instruction::Shl:
144 case Instruction::LShr:
145 case Instruction::AShr:
146 case Instruction::UDiv:
147 case Instruction::URem:
148 case Instruction::InsertElement:
149 case Instruction::ExtractElement:
150 case Instruction::Select: {
156 case Instruction::PHI: {
162 Worklist.push_back(
Op);
176unsigned TruncInstCombine::getMinBitWidth() {
177 SmallVector<Value *, 8> Worklist;
178 SmallVector<Instruction *, 8>
Stack;
180 Value *Src = CurrentTruncInst->getOperand(0);
181 Type *DstTy = CurrentTruncInst->getType();
183 unsigned OrigBitWidth =
184 CurrentTruncInst->getOperand(0)->getType()->getScalarSizeInBits();
187 return TruncBitWidth;
189 Worklist.push_back(Src);
192 while (!Worklist.empty()) {
193 Value *Curr = Worklist.back();
203 auto &Info = InstInfoMap[
I];
216 std::max(Info.MinBitWidth, InstInfoMap[IOp].MinBitWidth);
222 unsigned ValidBitWidth = Info.ValidBitWidth;
226 Info.MinBitWidth = std::max(Info.MinBitWidth, Info.ValidBitWidth);
233 unsigned IOpBitwidth = InstInfoMap.lookup(IOp).ValidBitWidth;
234 if (IOpBitwidth >= ValidBitWidth)
236 InstInfoMap[IOp].ValidBitWidth = ValidBitWidth;
237 Worklist.push_back(IOp);
241 assert(MinBitWidth >= TruncBitWidth);
243 if (MinBitWidth > TruncBitWidth) {
250 Type *Ty = DL.getSmallestLegalIntType(DstTy->
getContext(), MinBitWidth);
259 bool FromLegal = MinBitWidth == 1 || DL.isLegalInteger(OrigBitWidth);
260 bool ToLegal = MinBitWidth == 1 || DL.isLegalInteger(MinBitWidth);
261 if (!DstTy->
isVectorTy() && FromLegal && !ToLegal)
267Type *TruncInstCombine::getBestTruncatedType() {
268 if (!buildTruncExpressionGraph())
275 unsigned DesiredBitWidth = 0;
276 for (
auto Itr : InstInfoMap) {
281 for (Use &U :
I->uses())
283 if (UI != CurrentTruncInst &&
284 (!InstInfoMap.count(UI) ||
291 unsigned ExtInstBitWidth =
292 I->getOperand(0)->getType()->getScalarSizeInBits();
293 if (DesiredBitWidth && DesiredBitWidth != ExtInstBitWidth)
295 DesiredBitWidth = ExtInstBitWidth;
299 unsigned OrigBitWidth =
300 CurrentTruncInst->getOperand(0)->getType()->getScalarSizeInBits();
310 for (
auto &Itr : InstInfoMap) {
313 KnownBits KnownRHS = computeKnownBits(
I->getOperand(1));
317 if (MinBitWidth == OrigBitWidth)
319 if (
I->getOpcode() == Instruction::LShr) {
320 KnownBits KnownLHS = computeKnownBits(
I->getOperand(0));
324 if (
I->getOpcode() == Instruction::AShr) {
325 unsigned NumSignBits = ComputeNumSignBits(
I->getOperand(0));
326 MinBitWidth = std::max(MinBitWidth, OrigBitWidth - NumSignBits + 1);
328 if (MinBitWidth >= OrigBitWidth)
330 Itr.second.MinBitWidth = MinBitWidth;
332 if (
I->getOpcode() == Instruction::UDiv ||
333 I->getOpcode() == Instruction::URem) {
334 unsigned MinBitWidth = 0;
335 for (
const auto &
Op :
I->operands()) {
336 KnownBits
Known = computeKnownBits(
Op);
338 std::max(
Known.getMaxValue().getActiveBits(), MinBitWidth);
339 if (MinBitWidth >= OrigBitWidth)
342 Itr.second.MinBitWidth = MinBitWidth;
348 unsigned MinBitWidth = getMinBitWidth();
352 if (MinBitWidth >= OrigBitWidth ||
353 (DesiredBitWidth && DesiredBitWidth != MinBitWidth))
363 assert(Ty && !Ty->isVectorTy() &&
"Expect Scalar Type");
369Value *TruncInstCombine::getReducedOperand(
Value *V,
Type *SclTy) {
378 Info
Entry = InstInfoMap.lookup(
I);
380 return Entry.NewValue;
383void TruncInstCombine::ReduceExpressionGraph(
Type *SclTy) {
384 NumInstrsReduced += InstInfoMap.size();
387 for (
auto &Itr : InstInfoMap) {
389 TruncInstCombine::Info &NodeInfo = Itr.second;
391 assert(!NodeInfo.NewValue &&
"Instruction has been evaluated");
394 Value *Res =
nullptr;
395 unsigned Opc =
I->getOpcode();
397 case Instruction::Trunc:
398 case Instruction::ZExt:
399 case Instruction::SExt: {
404 if (
I->getOperand(0)->getType() == Ty) {
406 NodeInfo.NewValue =
I->getOperand(0);
411 Res = Builder.CreateIntCast(
I->getOperand(0), Ty,
412 Opc == Instruction::SExt);
420 if (Entry != Worklist.end()) {
424 Worklist.erase(Entry);
426 Worklist.push_back(NewCI);
429 case Instruction::Add:
430 case Instruction::Sub:
431 case Instruction::Mul:
432 case Instruction::And:
433 case Instruction::Or:
434 case Instruction::Xor:
435 case Instruction::Shl:
436 case Instruction::LShr:
437 case Instruction::AShr:
438 case Instruction::UDiv:
439 case Instruction::URem: {
440 Value *
LHS = getReducedOperand(
I->getOperand(0), SclTy);
441 Value *
RHS = getReducedOperand(
I->getOperand(1), SclTy);
446 ResI->setIsExact(PEO->isExact());
449 case Instruction::ExtractElement: {
450 Value *Vec = getReducedOperand(
I->getOperand(0), SclTy);
451 Value *Idx =
I->getOperand(1);
452 Res = Builder.CreateExtractElement(Vec, Idx);
455 case Instruction::InsertElement: {
456 Value *Vec = getReducedOperand(
I->getOperand(0), SclTy);
457 Value *NewElt = getReducedOperand(
I->getOperand(1), SclTy);
458 Value *Idx =
I->getOperand(2);
459 Res = Builder.CreateInsertElement(Vec, NewElt, Idx);
462 case Instruction::Select: {
463 Value *Op0 =
I->getOperand(0);
464 Value *
LHS = getReducedOperand(
I->getOperand(1), SclTy);
465 Value *
RHS = getReducedOperand(
I->getOperand(2), SclTy);
466 Res = Builder.CreateSelect(Op0,
LHS,
RHS,
"",
I);
469 case Instruction::PHI: {
479 NodeInfo.NewValue = Res;
484 for (
auto &Node : OldNewPHINodes) {
485 PHINode *OldPN =
Node.first;
486 PHINode *NewPN =
Node.second;
488 NewPN->
addIncoming(getReducedOperand(std::get<0>(Incoming), SclTy),
489 std::get<1>(Incoming));
492 Value *Res = getReducedOperand(CurrentTruncInst->getOperand(0), SclTy);
493 Type *DstTy = CurrentTruncInst->getType();
496 Res = Builder.CreateIntCast(Res, DstTy,
false);
500 CurrentTruncInst->replaceAllUsesWith(Res);
504 CurrentTruncInst->eraseFromParent();
506 for (
auto &Node : OldNewPHINodes) {
507 PHINode *OldPN =
Node.first;
509 InstInfoMap.erase(OldPN);
520 if (
I.first->use_empty())
521 I.first->eraseFromParent();
524 "Only {SExt, ZExt}Inst might have unreduced users");
529 bool MadeIRChange =
false;
534 if (!DT.isReachableFromEntry(&BB))
538 Worklist.push_back(CI);
544 while (!Worklist.empty()) {
545 CurrentTruncInst = Worklist.pop_back_val();
547 if (
Type *NewDstSclTy = getBestTruncatedType()) {
549 dbgs() <<
"ICE: TruncInstCombine reducing type of expression graph "
551 << CurrentTruncInst <<
'\n');
552 ReduceExpressionGraph(NewDstSclTy);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
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,...
static bool isRelevantOperand(const Instruction *I, unsigned OpNo)
Return whether operand OpNo of I is reducible.
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.
A Use represents the edge between a Value definition and its users.
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.
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.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
@ Known
Known to have no common set bits.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.