42#define DEBUG_TYPE "type-promotion"
43#define PASS_NAME "Type Promotion"
49 cl::desc(
"Disable type promotion pass"));
107 unsigned PromotedWidth = 0;
118 void ReplaceAllUsersOfWith(
Value *From,
Value *To);
119 void ExtendSources();
120 void ConvertTruncs();
122 void TruncateSinks();
130 : M(M), Ctx(M.
getContext()), PromotedWidth(Width), Visited(visited),
131 Sources(sources), Sinks(sinks), SafeWrap(
wrap),
132 InstsToRemove(instsToRemove) {
139class TypePromotionImpl {
140 unsigned TypeSize = 0;
141 const TargetLowering *TLI =
nullptr;
143 LLVMContext *Ctx =
nullptr;
144 unsigned RegisterBitWidth = 0;
145 SmallPtrSet<Value *, 16> AllVisited;
146 SmallPtrSet<Instruction *, 8> SafeToPromote;
147 SmallPtrSet<Instruction *, 4> SafeWrap;
148 SmallPtrSet<Instruction *, 4> InstsToRemove;
151 bool EqualTypeSize(
Value *V);
153 bool LessOrEqualTypeSize(
Value *V);
155 bool GreaterThanTypeSize(
Value *V);
157 bool LessThanTypeSize(
Value *V);
159 bool isSource(
Value *V);
161 bool isSink(
Value *V);
163 bool isSupportedTruncToI1(
Value *V);
166 bool shouldPromote(
Value *V);
169 bool isSafeWrap(Instruction *
I);
174 bool isSupportedValue(
Value *V);
178 bool TryToPromote(
Value *V,
unsigned PromotedWidth,
const LoopInfo &LI);
182 const TargetTransformInfo &
TTI,
const LoopInfo &LI);
189 TypePromotionLegacy() : FunctionPass(ID) {}
191 void getAnalysisUsage(AnalysisUsage &AU)
const override {
198 StringRef getPassName()
const override {
return PASS_NAME; }
206 unsigned Opc =
I->getOpcode();
207 return Opc == Instruction::AShr ||
Opc == Instruction::SDiv ||
208 Opc == Instruction::SRem ||
Opc == Instruction::SExt;
213 return Trunc && Trunc->getType()->isIntegerTy(1);
216bool TypePromotionImpl::EqualTypeSize(
Value *V) {
217 return V->getType()->getScalarSizeInBits() == TypeSize;
220bool TypePromotionImpl::LessOrEqualTypeSize(
Value *V) {
221 return V->getType()->getScalarSizeInBits() <= TypeSize;
224bool TypePromotionImpl::GreaterThanTypeSize(
Value *V) {
225 return V->getType()->getScalarSizeInBits() > TypeSize;
228bool TypePromotionImpl::LessThanTypeSize(
Value *V) {
229 return V->getType()->getScalarSizeInBits() < TypeSize;
239bool TypePromotionImpl::isSource(
Value *V) {
251 return EqualTypeSize(Trunc);
258bool TypePromotionImpl::isSink(
Value *V) {
270 return LessOrEqualTypeSize(
Store->getValueOperand());
272 return LessOrEqualTypeSize(
Return->getReturnValue());
274 return GreaterThanTypeSize(ZExt);
276 return LessThanTypeSize(
Switch->getCondition());
278 return ICmp->isSigned() || LessThanTypeSize(ICmp->getOperand(0));
283bool TypePromotionImpl::isSupportedTruncToI1(
Value *V) {
288bool TypePromotionImpl::isSafeWrap(Instruction *
I) {
342 unsigned Opc =
I->getOpcode();
343 if (
Opc != Instruction::Add &&
Opc != Instruction::Sub)
352 if (CI->isSigned() || CI->isEquality())
355 ConstantInt *ICmpConstant =
nullptr;
357 ICmpConstant =
Const;
359 ICmpConstant =
Const;
363 const APInt &ICmpConst = ICmpConstant->
getValue();
365 if (
Opc == Instruction::Sub)
366 OverflowConst = -OverflowConst;
376 APInt NewConst = -((-OverflowConst).zext(64));
383 if (OverflowConst == 0 || OverflowConst.
ugt(ICmpConst)) {
385 <<
"const of " << *
I <<
"\n");
390 <<
"const of " << *
I <<
" and " << *CI <<
"\n");
395bool TypePromotionImpl::shouldPromote(
Value *V) {
421 return I->hasNoUnsignedWrap();
424void IRPromoter::ReplaceAllUsersOfWith(
Value *From,
Value *To) {
425 SmallVector<Instruction *, 4>
Users;
427 bool ReplacedAll =
true;
429 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Replacing " << *From <<
" with " << *To
432 for (Use &U : From->
uses()) {
434 if (InstTo &&
User->isIdenticalTo(InstTo)) {
438 Users.push_back(User);
441 for (
auto *U :
Users)
442 U->replaceUsesOfWith(From, To);
449void IRPromoter::ExtendSources() {
453 assert(
V->getType() != ExtTy &&
"zext already extends to i32");
454 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Inserting ZExt for " << *V <<
"\n");
455 Builder.SetInsertPoint(InsertPt);
457 Builder.SetCurrentDebugLocation(
I->getDebugLoc());
459 Value *ZExt = Builder.CreateZExt(V, ExtTy);
462 I->moveBefore(InsertPt);
464 I->moveAfter(&*InsertPt);
468 ReplaceAllUsersOfWith(V, ZExt);
473 for (
auto *V : Sources) {
476 InsertZExt(
I,
I->getIterator());
487void IRPromoter::PromoteTree() {
492 for (
auto *V : Visited) {
493 if (Sources.count(V))
500 for (
unsigned i = 0, e =
I->getNumOperands(); i < e; ++i) {
518 if (
I->getOpcode() == Instruction::ICmp)
519 NewConst = -((-
Const->getValue()).zext(PromotedWidth));
520 else if (
I->getOpcode() == Instruction::Add && i == 1)
521 NewConst = -((-
Const->getValue()).zext(PromotedWidth));
523 NewConst =
Const->getValue().zext(PromotedWidth);
525 NewConst =
Const->getValue().zext(PromotedWidth);
527 I->setOperand(i, ConstantInt::get(
Const->getContext(), NewConst));
529 I->setOperand(i, ConstantInt::get(ExtTy, 0));
534 for (
auto Case :
SI->cases()) {
535 APInt NewConst = Case.getCaseValue()->getValue().
zext(PromotedWidth);
536 Case.setValue(ConstantInt::get(
SI->getContext(), NewConst));
545 if (!Trunc->hasNoUnsignedWrap())
546 Trunc->setHasNoSignedWrap(
false);
553 ICmp->setSameSign(
false);
557 I->mutateType(ExtTy);
563void IRPromoter::TruncateSinks() {
568 auto InsertTrunc = [&](
Value *
V,
Type *TruncTy) -> Instruction * {
572 if ((!Promoted.count(V) && !NewInsts.count(V)) || Sources.count(V))
575 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Creating " << *TruncTy <<
" Trunc for "
580 NewInsts.insert(Trunc);
586 for (
auto *
I : Sinks) {
594 if (Instruction *Trunc = InsertTrunc(Arg, Ty)) {
605 if (Instruction *Trunc = InsertTrunc(
Switch->getCondition(), Ty)) {
606 Trunc->moveBefore(
Switch->getIterator());
607 Switch->setCondition(Trunc);
623 for (
unsigned i = 0; i <
I->getNumOperands(); ++i) {
624 Type *Ty = TruncTysMap[
I][i];
625 if (Instruction *Trunc = InsertTrunc(
I->getOperand(i), Ty)) {
626 Trunc->moveBefore(
I->getIterator());
627 I->setOperand(i, Trunc);
633void IRPromoter::Cleanup() {
637 for (
auto *V : Visited) {
642 if (ZExt->getDestTy() != ExtTy)
645 Value *Src = ZExt->getOperand(0);
646 if (ZExt->getSrcTy() == ZExt->getDestTy()) {
647 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Removing unnecessary cast: " << *ZExt
649 ReplaceAllUsersOfWith(ZExt, Src);
657 assert(Trunc->getOperand(0)->getType() == ExtTy &&
658 "expected inserted trunc to be operating on i32");
659 ReplaceAllUsersOfWith(ZExt, Trunc->getOperand(0));
663 for (
auto *
I : InstsToRemove) {
665 I->dropAllReferences();
669void IRPromoter::ConvertTruncs() {
673 for (
auto *V : Visited) {
678 Builder.SetInsertPoint(Trunc);
685 Value *
Masked = Builder.CreateAnd(Trunc->getOperand(0), Mask);
692 ReplaceAllUsersOfWith(Trunc,
Masked);
696void IRPromoter::Mutate() {
698 << PromotedWidth <<
"-bits\n");
701 for (
auto *
I : Sinks) {
706 TruncTysMap[
I].push_back(
Switch->getCondition()->getType());
708 for (
const Value *
Op :
I->operands())
709 TruncTysMap[
I].push_back(
Op->getType());
712 for (
auto *V : Visited) {
716 TruncTysMap[Trunc].push_back(Trunc->getDestTy());
741bool TypePromotionImpl::isSupportedType(
Value *V) {
742 Type *Ty =
V->getType();
752 return LessOrEqualTypeSize(V);
759bool TypePromotionImpl::isSupportedValue(
Value *V) {
761 switch (
I->getOpcode()) {
765 case Instruction::GetElementPtr:
766 case Instruction::Store:
767 case Instruction::CondBr:
768 case Instruction::Switch:
770 case Instruction::PHI:
771 case Instruction::Select:
772 case Instruction::Ret:
773 case Instruction::Load:
775 case Instruction::Trunc:
777 case Instruction::BitCast:
778 return I->getOperand(0)->getType() ==
I->getType();
779 case Instruction::ZExt:
781 case Instruction::ICmp:
788 return EqualTypeSize(
I->getOperand(0));
789 case Instruction::Call: {
809bool TypePromotionImpl::isLegalToPromote(
Value *V) {
814 if (SafeToPromote.count(
I))
818 SafeToPromote.insert(
I);
824bool TypePromotionImpl::TryToPromote(
Value *V,
unsigned PromotedWidth,
825 const LoopInfo &LI) {
826 Type *OrigTy =
V->getType();
828 SafeToPromote.clear();
834 LLVM_DEBUG(
dbgs() <<
"IR Promotion: TryToPromote: " << *V <<
", from "
835 << TypeSize <<
" bits to " << PromotedWidth <<
"\n");
837 SetVector<Value *> WorkList;
838 SetVector<Value *> Sources;
839 SetVector<Instruction *> Sinks;
840 SetVector<Value *> CurrentVisited;
846 auto AddLegalInst = [&](
Value *
V) {
847 if (CurrentVisited.
count(V))
856 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Can't handle: " << *V <<
"\n");
865 while (!WorkList.
empty()) {
867 if (CurrentVisited.
count(V))
878 if (!AllVisited.
insert(V).second)
890 if (!isSink(V) && !isSource(V)) {
893 for (
auto &U :
I->operands()) {
897 if (!AddLegalInst(U))
905 if (isSource(V) || shouldPromote(V)) {
906 for (Use &U :
V->uses()) {
907 if (!AddLegalInst(
U.getUser()))
914 dbgs() <<
"IR Promotion: Visited nodes:\n";
915 for (
auto *
I : CurrentVisited)
919 unsigned ToPromote = 0;
920 unsigned NonFreeArgs = 0;
921 unsigned NonLoopSources = 0, LoopSinks = 0;
922 SmallPtrSet<BasicBlock *, 4> Blocks;
923 for (
auto *CV : CurrentVisited) {
927 if (Sources.
count(CV)) {
929 if (!Arg->hasZExtAttr() && !Arg->hasSExtAttr())
948 if (!
isa<PHINode>(V) && !(LoopSinks && NonLoopSources) &&
949 (ToPromote < 2 || (Blocks.
size() == 1 && NonFreeArgs > SafeWrap.
size())))
952 IRPromoter Promoter(*M, PromotedWidth, CurrentVisited, Sources, Sinks,
953 SafeWrap, InstsToRemove);
958bool TypePromotionImpl::run(
Function &
F,
const TargetMachine *TM,
959 const TargetTransformInfo &
TTI,
960 const LoopInfo &LI) {
964 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Running on " <<
F.getName() <<
"\n");
967 SafeToPromote.clear();
969 bool MadeChange =
false;
970 const DataLayout &
DL =
F.getDataLayout();
976 Ctx = &
F.getContext();
980 auto GetPromoteWidth = [&](
Instruction *
I) -> uint32_t {
988 if (TLI->
getTypeAction(*Ctx, SrcVT) != TargetLowering::TypePromoteInteger)
995 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Couldn't find target register "
996 <<
"for promoted type\n");
1004 auto BBIsInLoop = [&](
BasicBlock *BB) ->
bool {
1006 if (
L->contains(BB))
1011 for (BasicBlock &BB :
F) {
1012 for (Instruction &
I : BB) {
1013 if (AllVisited.
count(&
I))
1019 << *
I.getOperand(0) <<
"\n");
1023 if (RegisterBitWidth < PromoteWidth) {
1025 <<
"register for ZExt type\n");
1028 MadeChange |= TryToPromote(Phi, PromoteWidth, LI);
1032 if (ICmp->isSigned())
1035 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Searching from: " << *ICmp <<
"\n");
1037 for (
auto &
Op : ICmp->operands()) {
1039 if (
auto PromotedWidth = GetPromoteWidth(OpI)) {
1040 MadeChange |= TryToPromote(OpI, PromotedWidth, LI);
1052 if (
auto PromotedWidth = GetPromoteWidth(OpI))
1053 MadeChange |= TryToPromote(OpI, PromotedWidth, LI);
1057 if (!InstsToRemove.empty()) {
1058 for (
auto *
I : InstsToRemove)
1059 I->eraseFromParent();
1060 InstsToRemove.clear();
1065 SafeToPromote.clear();
1077char TypePromotionLegacy::ID = 0;
1080 if (skipFunction(
F))
1083 auto &TPC = getAnalysis<TargetPassConfig>();
1084 auto *TM = &TPC.getTM<TargetMachine>();
1085 auto &
TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1086 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1088 TypePromotionImpl TP;
1089 return TP.run(
F, TM,
TTI, LI);
1093 return new TypePromotionLegacy();
1100 TypePromotionImpl TP;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI, Type *T)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
ManagedStatic< HTTPClientCleanup > Cleanup
iv Induction Variable Users
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
This file implements a set that has insertion order iteration characteristics.
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNonPositive() const
Determine if this APInt Value is non-positive (<= 0).
int64_t getSExtValue() const
Get sign extended value.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
InstListType::iterator iterator
Instruction iterators...
Represents analyses that only rely on functions' control flow.
bool hasRetAttr(Attribute::AttrKind Kind) const
Determine whether the return value has the given attribute.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
const APInt & getValue() const
Return the constant as an APInt value reference.
FunctionPass class - This class is used to implement most global optimizations.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
This is an important class for using LLVM in a threaded context.
Analysis pass that exposes the LoopInfo for a function.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
A vector that has set insertion semantics.
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Analysis pass providing the TargetTransformInfo.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual bool isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual bool isLegalAddImmediate(int64_t) const
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
virtual const TargetLowering * getTargetLowering() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< use_iterator > uses()
constexpr ScalarTy getFixedValue() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason=nullptr)
Return true if the given indirect call site can be made to call Callee.
LLVM_ABI FunctionPass * createTypePromotionLegacyPass()
Create IR Type Promotion pass.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Store
The extracted value is stored (ExtractElement only).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVMAttributeRef wrap(Attribute Attr)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.