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);
160 bool isSupportedTruncToI1(
Value *V);
163 bool shouldPromote(
Value *V);
166 bool isSafeWrap(Instruction *
I);
171 bool isSupportedValue(
Value *V);
175 bool TryToPromote(
Value *V,
unsigned PromotedWidth,
const LoopInfo &LI);
179 const TargetTransformInfo &
TTI,
const LoopInfo &LI);
186 TypePromotionLegacy() : FunctionPass(ID) {}
188 void getAnalysisUsage(AnalysisUsage &AU)
const override {
195 StringRef getPassName()
const override {
return PASS_NAME; }
203 unsigned Opc =
I->getOpcode();
204 return Opc == Instruction::AShr ||
Opc == Instruction::SDiv ||
205 Opc == Instruction::SRem ||
Opc == Instruction::SExt;
210 return Trunc && Trunc->getType()->isIntegerTy(1);
213bool TypePromotionImpl::EqualTypeSize(
Value *V) {
214 return V->getType()->getScalarSizeInBits() == TypeSize;
217bool TypePromotionImpl::LessOrEqualTypeSize(
Value *V) {
218 return V->getType()->getScalarSizeInBits() <= TypeSize;
221bool TypePromotionImpl::GreaterThanTypeSize(
Value *V) {
222 return V->getType()->getScalarSizeInBits() > TypeSize;
225bool TypePromotionImpl::LessThanTypeSize(
Value *V) {
226 return V->getType()->getScalarSizeInBits() < TypeSize;
236bool TypePromotionImpl::isSource(
Value *V) {
248 return EqualTypeSize(Trunc);
255bool TypePromotionImpl::isSink(
Value *V) {
267 return LessOrEqualTypeSize(
Store->getValueOperand());
269 return LessOrEqualTypeSize(
Return->getReturnValue());
271 return GreaterThanTypeSize(ZExt);
273 return LessThanTypeSize(
Switch->getCondition());
275 return ICmp->isSigned() || LessThanTypeSize(ICmp->getOperand(0));
280bool TypePromotionImpl::isSupportedTruncToI1(
Value *V) {
285bool TypePromotionImpl::isSafeWrap(Instruction *
I) {
339 unsigned Opc =
I->getOpcode();
340 if (
Opc != Instruction::Add &&
Opc != Instruction::Sub)
349 if (CI->isSigned() || CI->isEquality())
352 ConstantInt *ICmpConstant =
nullptr;
354 ICmpConstant =
Const;
356 ICmpConstant =
Const;
360 const APInt &ICmpConst = ICmpConstant->
getValue();
362 if (
Opc == Instruction::Sub)
363 OverflowConst = -OverflowConst;
373 APInt NewConst = -((-OverflowConst).zext(64));
380 if (OverflowConst == 0 || OverflowConst.
ugt(ICmpConst)) {
382 <<
"const of " << *
I <<
"\n");
387 <<
"const of " << *
I <<
" and " << *CI <<
"\n");
392bool TypePromotionImpl::shouldPromote(
Value *V) {
418 return I->hasNoUnsignedWrap();
421void IRPromoter::ReplaceAllUsersOfWith(
Value *From,
Value *To) {
422 SmallVector<Instruction *, 4>
Users;
424 bool ReplacedAll =
true;
426 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Replacing " << *From <<
" with " << *To
429 for (Use &U : From->
uses()) {
431 if (InstTo &&
User->isIdenticalTo(InstTo)) {
435 Users.push_back(User);
438 for (
auto *U :
Users)
439 U->replaceUsesOfWith(From, To);
446void IRPromoter::ExtendSources() {
450 assert(
V->getType() != ExtTy &&
"zext already extends to i32");
451 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Inserting ZExt for " << *V <<
"\n");
459 I->moveBefore(InsertPt);
461 I->moveAfter(&*InsertPt);
465 ReplaceAllUsersOfWith(V, ZExt);
470 for (
auto *V : Sources) {
473 InsertZExt(
I,
I->getIterator());
484void IRPromoter::PromoteTree() {
489 for (
auto *V : Visited) {
490 if (Sources.count(V))
497 for (
unsigned i = 0, e =
I->getNumOperands(); i < e; ++i) {
515 if (
I->getOpcode() == Instruction::ICmp)
516 NewConst = -((-
Const->getValue()).zext(PromotedWidth));
517 else if (
I->getOpcode() == Instruction::Add && i == 1)
518 NewConst = -((-
Const->getValue()).zext(PromotedWidth));
520 NewConst =
Const->getValue().zext(PromotedWidth);
522 NewConst =
Const->getValue().zext(PromotedWidth);
524 I->setOperand(i, ConstantInt::get(
Const->getContext(), NewConst));
526 I->setOperand(i, ConstantInt::get(ExtTy, 0));
531 for (
auto Case :
SI->cases()) {
532 APInt NewConst = Case.getCaseValue()->getValue().
zext(PromotedWidth);
533 Case.setValue(ConstantInt::get(
SI->getContext(), NewConst));
542 if (!Trunc->hasNoUnsignedWrap())
543 Trunc->setHasNoSignedWrap(
false);
549 I->mutateType(ExtTy);
555void IRPromoter::TruncateSinks() {
560 auto InsertTrunc = [&](
Value *
V,
Type *TruncTy) -> Instruction * {
564 if ((!Promoted.count(V) && !NewInsts.count(V)) || Sources.count(V))
567 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Creating " << *TruncTy <<
" Trunc for "
572 NewInsts.insert(Trunc);
578 for (
auto *
I : Sinks) {
586 if (Instruction *Trunc = InsertTrunc(Arg, Ty)) {
597 if (Instruction *Trunc = InsertTrunc(
Switch->getCondition(), Ty)) {
598 Trunc->moveBefore(
Switch->getIterator());
599 Switch->setCondition(Trunc);
615 for (
unsigned i = 0; i <
I->getNumOperands(); ++i) {
616 Type *Ty = TruncTysMap[
I][i];
617 if (Instruction *Trunc = InsertTrunc(
I->getOperand(i), Ty)) {
618 Trunc->moveBefore(
I->getIterator());
619 I->setOperand(i, Trunc);
625void IRPromoter::Cleanup() {
629 for (
auto *V : Visited) {
634 if (ZExt->getDestTy() != ExtTy)
637 Value *Src = ZExt->getOperand(0);
638 if (ZExt->getSrcTy() == ZExt->getDestTy()) {
639 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Removing unnecessary cast: " << *ZExt
641 ReplaceAllUsersOfWith(ZExt, Src);
649 assert(Trunc->getOperand(0)->getType() == ExtTy &&
650 "expected inserted trunc to be operating on i32");
651 ReplaceAllUsersOfWith(ZExt, Trunc->getOperand(0));
655 for (
auto *
I : InstsToRemove) {
657 I->dropAllReferences();
661void IRPromoter::ConvertTruncs() {
665 for (
auto *V : Visited) {
684 ReplaceAllUsersOfWith(Trunc,
Masked);
688void IRPromoter::Mutate() {
690 << PromotedWidth <<
"-bits\n");
693 for (
auto *
I : Sinks) {
698 TruncTysMap[
I].push_back(
Switch->getCondition()->getType());
700 for (
const Value *
Op :
I->operands())
701 TruncTysMap[
I].push_back(
Op->getType());
704 for (
auto *V : Visited) {
708 TruncTysMap[Trunc].push_back(Trunc->getDestTy());
733bool TypePromotionImpl::isSupportedType(
Value *V) {
734 Type *Ty =
V->getType();
744 return LessOrEqualTypeSize(V);
751bool TypePromotionImpl::isSupportedValue(
Value *V) {
753 switch (
I->getOpcode()) {
757 case Instruction::GetElementPtr:
758 case Instruction::Store:
759 case Instruction::CondBr:
760 case Instruction::Switch:
762 case Instruction::PHI:
763 case Instruction::Select:
764 case Instruction::Ret:
765 case Instruction::Load:
767 case Instruction::Trunc:
769 case Instruction::BitCast:
770 return I->getOperand(0)->getType() ==
I->getType();
771 case Instruction::ZExt:
773 case Instruction::ICmp:
780 return EqualTypeSize(
I->getOperand(0));
781 case Instruction::Call: {
801bool TypePromotionImpl::isLegalToPromote(
Value *V) {
806 if (SafeToPromote.count(
I))
810 SafeToPromote.insert(
I);
816bool TypePromotionImpl::TryToPromote(
Value *V,
unsigned PromotedWidth,
817 const LoopInfo &LI) {
818 Type *OrigTy =
V->getType();
820 SafeToPromote.clear();
826 LLVM_DEBUG(
dbgs() <<
"IR Promotion: TryToPromote: " << *V <<
", from "
827 << TypeSize <<
" bits to " << PromotedWidth <<
"\n");
829 SetVector<Value *> WorkList;
830 SetVector<Value *> Sources;
831 SetVector<Instruction *> Sinks;
832 SetVector<Value *> CurrentVisited;
838 auto AddLegalInst = [&](
Value *
V) {
839 if (CurrentVisited.
count(V))
848 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Can't handle: " << *V <<
"\n");
857 while (!WorkList.
empty()) {
859 if (CurrentVisited.
count(V))
870 if (!AllVisited.
insert(V).second)
882 if (!isSink(V) && !isSource(V)) {
885 for (
auto &U :
I->operands()) {
889 if (!AddLegalInst(U))
897 if (isSource(V) || shouldPromote(V)) {
898 for (Use &U :
V->uses()) {
899 if (!AddLegalInst(
U.getUser()))
906 dbgs() <<
"IR Promotion: Visited nodes:\n";
907 for (
auto *
I : CurrentVisited)
911 unsigned ToPromote = 0;
912 unsigned NonFreeArgs = 0;
913 unsigned NonLoopSources = 0, LoopSinks = 0;
914 SmallPtrSet<BasicBlock *, 4> Blocks;
915 for (
auto *CV : CurrentVisited) {
919 if (Sources.
count(CV)) {
921 if (!Arg->hasZExtAttr() && !Arg->hasSExtAttr())
940 if (!
isa<PHINode>(V) && !(LoopSinks && NonLoopSources) &&
941 (ToPromote < 2 || (Blocks.
size() == 1 && NonFreeArgs > SafeWrap.
size())))
944 IRPromoter Promoter(*Ctx, PromotedWidth, CurrentVisited, Sources, Sinks,
945 SafeWrap, InstsToRemove);
950bool TypePromotionImpl::run(
Function &
F,
const TargetMachine *TM,
951 const TargetTransformInfo &
TTI,
952 const LoopInfo &LI) {
956 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Running on " <<
F.getName() <<
"\n");
959 SafeToPromote.clear();
961 bool MadeChange =
false;
962 const DataLayout &
DL =
F.getDataLayout();
967 Ctx = &
F.getContext();
971 auto GetPromoteWidth = [&](
Instruction *
I) -> uint32_t {
979 if (TLI->
getTypeAction(*Ctx, SrcVT) != TargetLowering::TypePromoteInteger)
986 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Couldn't find target register "
987 <<
"for promoted type\n");
995 auto BBIsInLoop = [&](
BasicBlock *BB) ->
bool {
1002 for (BasicBlock &BB :
F) {
1003 for (Instruction &
I : BB) {
1004 if (AllVisited.
count(&
I))
1010 << *
I.getOperand(0) <<
"\n");
1014 if (RegisterBitWidth < PromoteWidth) {
1016 <<
"register for ZExt type\n");
1019 MadeChange |= TryToPromote(Phi, PromoteWidth, LI);
1023 if (ICmp->isSigned())
1026 LLVM_DEBUG(
dbgs() <<
"IR Promotion: Searching from: " << *ICmp <<
"\n");
1028 for (
auto &
Op : ICmp->operands()) {
1030 if (
auto PromotedWidth = GetPromoteWidth(OpI)) {
1031 MadeChange |= TryToPromote(OpI, PromotedWidth, LI);
1043 if (
auto PromotedWidth = GetPromoteWidth(OpI))
1044 MadeChange |= TryToPromote(OpI, PromotedWidth, LI);
1048 if (!InstsToRemove.empty()) {
1049 for (
auto *
I : InstsToRemove)
1050 I->eraseFromParent();
1051 InstsToRemove.clear();
1056 SafeToPromote.clear();
1068char TypePromotionLegacy::ID = 0;
1071 if (skipFunction(
F))
1074 auto &TPC = getAnalysis<TargetPassConfig>();
1075 auto *TM = &TPC.getTM<TargetMachine>();
1076 auto &
TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1077 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1079 TypePromotionImpl TP;
1080 return TP.run(
F, TM,
TTI, LI);
1084 return new TypePromotionLegacy();
1091 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...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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)
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.
void SetCurrentDebugLocation(const 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.
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.
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.