42#define DEBUG_TYPE "type-promotion"
43#define PASS_NAME "Type Promotion"
49 cl::desc(
"Disable type promotion pass"));
106 unsigned PromotedWidth = 0;
117 void ReplaceAllUsersOfWith(
Value *From,
Value *To);
118 void ExtendSources();
119 void ConvertTruncs();
121 void TruncateSinks();
129 : Ctx(
C), PromotedWidth(Width), Visited(visited), Sources(sources),
130 Sinks(sinks), SafeWrap(
wrap), InstsToRemove(instsToRemove) {
137class TypePromotionImpl {
138 unsigned TypeSize = 0;
139 const TargetLowering *TLI =
nullptr;
140 LLVMContext *Ctx =
nullptr;
141 unsigned RegisterBitWidth = 0;
142 SmallPtrSet<Value *, 16> AllVisited;
143 SmallPtrSet<Instruction *, 8> SafeToPromote;
144 SmallPtrSet<Instruction *, 4> SafeWrap;
145 SmallPtrSet<Instruction *, 4> InstsToRemove;
148 bool EqualTypeSize(
Value *V);
150 bool LessOrEqualTypeSize(
Value *V);
152 bool GreaterThanTypeSize(
Value *V);
154 bool LessThanTypeSize(
Value *V);
156 bool isSource(
Value *V);
158 bool isSink(
Value *V);
161 bool shouldPromote(
Value *V);
164 bool isSafeWrap(Instruction *
I);
169 bool isSupportedValue(
Value *V);
173 bool TryToPromote(
Value *V,
unsigned PromotedWidth,
const LoopInfo &LI);
176 bool run(Function &
F,
const TargetMachine *TM,
177 const TargetTransformInfo &
TTI,
const LoopInfo &LI);
184 TypePromotionLegacy() : FunctionPass(ID) {}
186 void getAnalysisUsage(AnalysisUsage &AU)
const override {
194 StringRef getPassName()
const override {
return PASS_NAME; }
202 unsigned Opc =
I->getOpcode();
203 return Opc == Instruction::AShr ||
Opc == Instruction::SDiv ||
204 Opc == Instruction::SRem ||
Opc == Instruction::SExt;
207bool TypePromotionImpl::EqualTypeSize(
Value *V) {
208 return V->getType()->getScalarSizeInBits() == TypeSize;
211bool TypePromotionImpl::LessOrEqualTypeSize(
Value *V) {
212 return V->getType()->getScalarSizeInBits() <= TypeSize;
215bool TypePromotionImpl::GreaterThanTypeSize(
Value *V) {
216 return V->getType()->getScalarSizeInBits() > TypeSize;
219bool TypePromotionImpl::LessThanTypeSize(
Value *V) {
220 return V->getType()->getScalarSizeInBits() < TypeSize;
230bool TypePromotionImpl::isSource(
Value *V) {
242 return EqualTypeSize(Trunc);
249bool TypePromotionImpl::isSink(
Value *V) {
261 return LessOrEqualTypeSize(
Store->getValueOperand());
263 return LessOrEqualTypeSize(
Return->getReturnValue());
265 return GreaterThanTypeSize(ZExt);
267 return LessThanTypeSize(
Switch->getCondition());
269 return ICmp->isSigned() || LessThanTypeSize(ICmp->getOperand(0));
275bool TypePromotionImpl::isSafeWrap(Instruction *
I) {
329 unsigned Opc =
I->getOpcode();
330 if (
Opc != Instruction::Add &&
Opc != Instruction::Sub)
339 if (CI->isSigned() || CI->isEquality())
342 ConstantInt *ICmpConstant =
nullptr;
344 ICmpConstant =
Const;
346 ICmpConstant =
Const;
350 const APInt &ICmpConst = ICmpConstant->
getValue();
352 if (
Opc == Instruction::Sub)
353 OverflowConst = -OverflowConst;
363 APInt NewConst = -((-OverflowConst).zext(64));
370 if (OverflowConst == 0 || OverflowConst.
ugt(ICmpConst)) {
372 <<
"const of " << *
I <<
"\n");
377 <<
"const of " << *
I <<
" and " << *CI <<
"\n");
382bool TypePromotionImpl::shouldPromote(
Value *V) {
408 return I->hasNoUnsignedWrap();
411void IRPromoter::ReplaceAllUsersOfWith(
Value *From,
Value *To) {
412 SmallVector<Instruction *, 4>
Users;
414 bool ReplacedAll =
true;
416 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Replacing " << *From <<
" with " << *To
419 for (Use &U : From->
uses()) {
421 if (InstTo &&
User->isIdenticalTo(InstTo)) {
425 Users.push_back(User);
428 for (
auto *U :
Users)
429 U->replaceUsesOfWith(From, To);
433 InstsToRemove.insert(
I);
436void IRPromoter::ExtendSources() {
440 assert(
V->getType() != ExtTy &&
"zext already extends to i32");
441 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Inserting ZExt for " << *V <<
"\n");
449 I->moveBefore(InsertPt);
451 I->moveAfter(&*InsertPt);
455 ReplaceAllUsersOfWith(V, ZExt);
460 for (
auto *V : Sources) {
463 InsertZExt(
I,
I->getIterator());
474void IRPromoter::PromoteTree() {
479 for (
auto *V : Visited) {
480 if (Sources.count(V))
487 for (
unsigned i = 0, e =
I->getNumOperands(); i < e; ++i) {
500 if (SafeWrap.contains(
I)) {
501 if (
I->getOpcode() == Instruction::ICmp)
502 NewConst = -((-
Const->getValue()).zext(PromotedWidth));
503 else if (
I->getOpcode() == Instruction::Add && i == 1)
504 NewConst = -((-
Const->getValue()).zext(PromotedWidth));
506 NewConst =
Const->getValue().zext(PromotedWidth);
508 NewConst =
Const->getValue().zext(PromotedWidth);
510 I->setOperand(i, ConstantInt::get(
Const->getContext(), NewConst));
512 I->setOperand(i, ConstantInt::get(ExtTy, 0));
517 I->mutateType(ExtTy);
523void IRPromoter::TruncateSinks() {
528 auto InsertTrunc = [&](
Value *
V,
Type *TruncTy) -> Instruction * {
532 if ((!Promoted.count(V) && !NewInsts.count(V)) || Sources.count(V))
535 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Creating " << *TruncTy <<
" Trunc for "
540 NewInsts.insert(Trunc);
546 for (
auto *
I : Sinks) {
554 if (Instruction *Trunc = InsertTrunc(Arg, Ty)) {
565 if (Instruction *Trunc = InsertTrunc(
Switch->getCondition(), Ty)) {
566 Trunc->moveBefore(
Switch->getIterator());
567 Switch->setCondition(Trunc);
583 for (
unsigned i = 0; i <
I->getNumOperands(); ++i) {
584 Type *Ty = TruncTysMap[
I][i];
585 if (Instruction *Trunc = InsertTrunc(
I->getOperand(i), Ty)) {
586 Trunc->moveBefore(
I->getIterator());
587 I->setOperand(i, Trunc);
593void IRPromoter::Cleanup() {
597 for (
auto *V : Visited) {
602 if (ZExt->getDestTy() != ExtTy)
605 Value *Src = ZExt->getOperand(0);
606 if (ZExt->getSrcTy() == ZExt->getDestTy()) {
607 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Removing unnecessary cast: " << *ZExt
609 ReplaceAllUsersOfWith(ZExt, Src);
617 assert(Trunc->getOperand(0)->getType() == ExtTy &&
618 "expected inserted trunc to be operating on i32");
619 ReplaceAllUsersOfWith(ZExt, Trunc->getOperand(0));
623 for (
auto *
I : InstsToRemove) {
625 I->dropAllReferences();
629void IRPromoter::ConvertTruncs() {
633 for (
auto *V : Visited) {
652 ReplaceAllUsersOfWith(Trunc,
Masked);
656void IRPromoter::Mutate() {
658 << PromotedWidth <<
"-bits\n");
661 for (
auto *
I : Sinks) {
666 TruncTysMap[
I].push_back(
Switch->getCondition()->getType());
668 for (
const Value *
Op :
I->operands())
669 TruncTysMap[
I].push_back(
Op->getType());
672 for (
auto *V : Visited) {
676 TruncTysMap[Trunc].push_back(Trunc->getDestTy());
701bool TypePromotionImpl::isSupportedType(
Value *V) {
702 Type *Ty =
V->getType();
712 return LessOrEqualTypeSize(V);
719bool TypePromotionImpl::isSupportedValue(
Value *V) {
721 switch (
I->getOpcode()) {
725 case Instruction::GetElementPtr:
726 case Instruction::Store:
727 case Instruction::Br:
728 case Instruction::Switch:
730 case Instruction::PHI:
731 case Instruction::Select:
732 case Instruction::Ret:
733 case Instruction::Load:
734 case Instruction::Trunc:
736 case Instruction::BitCast:
737 return I->getOperand(0)->getType() ==
I->getType();
738 case Instruction::ZExt:
740 case Instruction::ICmp:
747 return EqualTypeSize(
I->getOperand(0));
748 case Instruction::Call: {
768bool TypePromotionImpl::isLegalToPromote(
Value *V) {
773 if (SafeToPromote.count(
I))
777 SafeToPromote.insert(
I);
783bool TypePromotionImpl::TryToPromote(
Value *V,
unsigned PromotedWidth,
784 const LoopInfo &LI) {
785 Type *OrigTy =
V->getType();
787 SafeToPromote.clear();
793 LLVM_DEBUG(
dbgs() <<
"IR Promotion: TryToPromote: " << *V <<
", from "
794 << TypeSize <<
" bits to " << PromotedWidth <<
"\n");
796 SetVector<Value *> WorkList;
797 SetVector<Value *> Sources;
798 SetVector<Instruction *> Sinks;
799 SetVector<Value *> CurrentVisited;
805 auto AddLegalInst = [&](
Value *
V) {
806 if (CurrentVisited.
count(V))
815 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Can't handle: " << *V <<
"\n");
824 while (!WorkList.
empty()) {
826 if (CurrentVisited.
count(V))
837 if (!AllVisited.
insert(V).second)
849 if (!isSink(V) && !isSource(V)) {
852 for (
auto &U :
I->operands()) {
853 if (!AddLegalInst(U))
861 if (isSource(V) || shouldPromote(V)) {
862 for (Use &U :
V->uses()) {
863 if (!AddLegalInst(
U.getUser()))
870 dbgs() <<
"IR Promotion: Visited nodes:\n";
871 for (
auto *
I : CurrentVisited)
875 unsigned ToPromote = 0;
876 unsigned NonFreeArgs = 0;
877 unsigned NonLoopSources = 0, LoopSinks = 0;
878 SmallPtrSet<BasicBlock *, 4> Blocks;
879 for (
auto *CV : CurrentVisited) {
883 if (Sources.
count(CV)) {
885 if (!Arg->hasZExtAttr() && !Arg->hasSExtAttr())
904 if (!
isa<PHINode>(V) && !(LoopSinks && NonLoopSources) &&
905 (ToPromote < 2 || (Blocks.
size() == 1 && NonFreeArgs > SafeWrap.
size())))
908 IRPromoter Promoter(*Ctx, PromotedWidth, CurrentVisited, Sources, Sinks,
909 SafeWrap, InstsToRemove);
914bool TypePromotionImpl::run(Function &
F,
const TargetMachine *TM,
915 const TargetTransformInfo &
TTI,
916 const LoopInfo &LI) {
920 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Running on " <<
F.getName() <<
"\n");
923 SafeToPromote.clear();
925 bool MadeChange =
false;
926 const DataLayout &
DL =
F.getDataLayout();
927 const TargetSubtargetInfo *SubtargetInfo =
TM->getSubtargetImpl(
F);
931 Ctx = &
F.getContext();
935 auto GetPromoteWidth = [&](
Instruction *
I) -> uint32_t {
943 if (TLI->
getTypeAction(*Ctx, SrcVT) != TargetLowering::TypePromoteInteger)
950 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Couldn't find target register "
951 <<
"for promoted type\n");
959 auto BBIsInLoop = [&](
BasicBlock *BB) ->
bool {
966 for (BasicBlock &BB :
F) {
967 for (Instruction &
I : BB) {
974 << *
I.getOperand(0) <<
"\n");
978 if (RegisterBitWidth < PromoteWidth) {
980 <<
"register for ZExt type\n");
983 MadeChange |= TryToPromote(Phi, PromoteWidth, LI);
987 if (ICmp->isSigned())
990 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Searching from: " << *ICmp <<
"\n");
992 for (
auto &
Op : ICmp->operands()) {
994 if (
auto PromotedWidth = GetPromoteWidth(OpI)) {
995 MadeChange |= TryToPromote(OpI, PromotedWidth, LI);
1002 if (!InstsToRemove.empty()) {
1003 for (
auto *
I : InstsToRemove)
1004 I->eraseFromParent();
1005 InstsToRemove.clear();
1010 SafeToPromote.clear();
1022char TypePromotionLegacy::
ID = 0;
1025 if (skipFunction(
F))
1028 auto &TPC = getAnalysis<TargetPassConfig>();
1029 auto *
TM = &TPC.getTM<TargetMachine>();
1030 auto &
TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1031 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1033 TypePromotionImpl TP;
1034 return TP.run(
F, TM,
TTI, LI);
1038 return new TypePromotionLegacy();
1045 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)
static const 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)
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.
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()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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.
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
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 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.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
A vector that has set insertion semantics.
size_type count(const key_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.
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 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ 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.
FunctionAddr VTableAddr Value
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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
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.