diff options
Diffstat (limited to 'llvm/lib/CodeGen/TypePromotion.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/TypePromotion.cpp | 137 |
1 files changed, 65 insertions, 72 deletions
diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp index 01ea171e5ea2..166a3c413f6a 100644 --- a/llvm/lib/CodeGen/TypePromotion.cpp +++ b/llvm/lib/CodeGen/TypePromotion.cpp @@ -24,15 +24,13 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" -#include "llvm/IR/Verifier.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" @@ -44,9 +42,9 @@ using namespace llvm; -static cl::opt<bool> -DisablePromotion("disable-type-promotion", cl::Hidden, cl::init(false), - cl::desc("Disable type promotion pass")); +static cl::opt<bool> DisablePromotion("disable-type-promotion", cl::Hidden, + cl::init(false), + cl::desc("Disable type promotion pass")); // The goal of this pass is to enable more efficient code generation for // operations on narrow types (i.e. types with < 32-bits) and this is a @@ -103,17 +101,16 @@ DisablePromotion("disable-type-promotion", cl::Hidden, cl::init(false), namespace { class IRPromoter { LLVMContext &Ctx; - IntegerType *OrigTy = nullptr; unsigned PromotedWidth = 0; - SetVector<Value*> &Visited; - SetVector<Value*> &Sources; - SetVector<Instruction*> &Sinks; + SetVector<Value *> &Visited; + SetVector<Value *> &Sources; + SetVector<Instruction *> &Sinks; SmallPtrSetImpl<Instruction *> &SafeWrap; IntegerType *ExtTy = nullptr; - SmallPtrSet<Value*, 8> NewInsts; - SmallPtrSet<Instruction*, 4> InstsToRemove; - DenseMap<Value*, SmallVector<Type*, 4>> TruncTysMap; - SmallPtrSet<Value*, 8> Promoted; + SmallPtrSet<Value *, 8> NewInsts; + SmallPtrSet<Instruction *, 4> InstsToRemove; + DenseMap<Value *, SmallVector<Type *, 4>> TruncTysMap; + SmallPtrSet<Value *, 8> Promoted; void ReplaceAllUsersOfWith(Value *From, Value *To); void ExtendSources(); @@ -123,16 +120,13 @@ class IRPromoter { void Cleanup(); public: - IRPromoter(LLVMContext &C, IntegerType *Ty, unsigned Width, + IRPromoter(LLVMContext &C, unsigned Width, SetVector<Value *> &visited, SetVector<Value *> &sources, SetVector<Instruction *> &sinks, SmallPtrSetImpl<Instruction *> &wrap) - : Ctx(C), OrigTy(Ty), PromotedWidth(Width), Visited(visited), + : Ctx(C), PromotedWidth(Width), Visited(visited), Sources(sources), Sinks(sinks), SafeWrap(wrap) { ExtTy = IntegerType::get(Ctx, PromotedWidth); - assert(OrigTy->getPrimitiveSizeInBits().getFixedSize() < - ExtTy->getPrimitiveSizeInBits().getFixedSize() && - "Original type not smaller than extended type"); } void Mutate(); @@ -142,8 +136,8 @@ class TypePromotion : public FunctionPass { unsigned TypeSize = 0; LLVMContext *Ctx = nullptr; unsigned RegisterBitWidth = 0; - SmallPtrSet<Value*, 16> AllVisited; - SmallPtrSet<Instruction*, 8> SafeToPromote; + SmallPtrSet<Value *, 16> AllVisited; + SmallPtrSet<Instruction *, 8> SafeToPromote; SmallPtrSet<Instruction *, 4> SafeWrap; // Does V have the same size result type as TypeSize. @@ -190,7 +184,7 @@ public: bool runOnFunction(Function &F) override; }; -} +} // namespace static bool GenerateSignBits(Instruction *I) { unsigned Opc = I->getOpcode(); @@ -245,7 +239,7 @@ bool TypePromotion::isSource(Value *V) { bool TypePromotion::isSink(Value *V) { // TODO The truncate also isn't actually necessary because we would already // proved that the data value is kept within the range of the original data - // type. + // type. We currently remove any truncs inserted for handling zext sinks. // Sinks are: // - points where the value in the register is being observed, such as an @@ -269,7 +263,7 @@ bool TypePromotion::isSink(Value *V) { /// Return whether this instruction can safely wrap. bool TypePromotion::isSafeWrap(Instruction *I) { - // We can support a, potentially, wrapping instruction (I) if: + // We can support a potentially wrapping instruction (I) if: // - It is only used by an unsigned icmp. // - The icmp uses a constant. // - The wrapping value (I) is decreasing, i.e would underflow - wrapping @@ -356,7 +350,7 @@ bool TypePromotion::isSafeWrap(Instruction *I) { if (!OverflowConst.isNonPositive()) return false; - // Using C1 = OverflowConst and C2 = ICmpConst, we can use either prove that: + // Using C1 = OverflowConst and C2 = ICmpConst, we can either prove that: // zext(x) + sext(C1) <u zext(C2) if C1 < 0 and C1 >s C2 // zext(x) + sext(C1) <u sext(C2) if C1 < 0 and C1 <=s C2 if (OverflowConst.sgt(ICmpConst)) { @@ -404,7 +398,7 @@ static bool isPromotedResultSafe(Instruction *I) { } void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) { - SmallVector<Instruction*, 4> Users; + SmallVector<Instruction *, 4> Users; Instruction *InstTo = dyn_cast<Instruction>(To); bool ReplacedAll = true; @@ -485,12 +479,18 @@ void IRPromoter::PromoteTree() { continue; if (auto *Const = dyn_cast<ConstantInt>(Op)) { - Constant *NewConst = SafeWrap.contains(I) + // For subtract, we don't need to sext the constant. We only put it in + // SafeWrap because SafeWrap.size() is used elsewhere. + // For cmp, we need to sign extend a constant appearing in either + // operand. For add, we should only sign extend the RHS. + Constant *NewConst = (SafeWrap.contains(I) && + (I->getOpcode() == Instruction::ICmp || i == 1) && + I->getOpcode() != Instruction::Sub) ? ConstantExpr::getSExt(Const, ExtTy) : ConstantExpr::getZExt(Const, ExtTy); I->setOperand(i, NewConst); } else if (isa<UndefValue>(Op)) - I->setOperand(i, UndefValue::get(ExtTy)); + I->setOperand(i, ConstantInt::get(ExtTy, 0)); } // Mutate the result type, unless this is an icmp or switch. @@ -506,7 +506,7 @@ void IRPromoter::TruncateSinks() { IRBuilder<> Builder{Ctx}; - auto InsertTrunc = [&](Value *V, Type *TruncTy) -> Instruction* { + auto InsertTrunc = [&](Value *V, Type *TruncTy) -> Instruction * { if (!isa<Instruction>(V) || !isa<IntegerType>(V->getType())) return nullptr; @@ -514,7 +514,7 @@ void IRPromoter::TruncateSinks() { return nullptr; LLVM_DEBUG(dbgs() << "IR Promotion: Creating " << *TruncTy << " Trunc for " - << *V << "\n"); + << *V << "\n"); Builder.SetInsertPoint(cast<Instruction>(V)); auto *Trunc = dyn_cast<Instruction>(Builder.CreateTrunc(V, TruncTy)); if (Trunc) @@ -550,6 +550,11 @@ void IRPromoter::TruncateSinks() { continue; } + // Don't insert a trunc for a zext which can still legally promote. + if (auto ZExt = dyn_cast<ZExtInst>(I)) + if (ZExt->getType()->getScalarSizeInBits() > PromotedWidth) + continue; + // Now handle the others. for (unsigned i = 0; i < I->getNumOperands(); ++i) { Type *Ty = TruncTysMap[I][i]; @@ -576,16 +581,14 @@ void IRPromoter::Cleanup() { Value *Src = ZExt->getOperand(0); if (ZExt->getSrcTy() == ZExt->getDestTy()) { LLVM_DEBUG(dbgs() << "IR Promotion: Removing unnecessary cast: " << *ZExt - << "\n"); + << "\n"); ReplaceAllUsersOfWith(ZExt, Src); continue; } - // Unless they produce a value that is narrower than ExtTy, we can - // replace the result of the zext with the input of a newly inserted - // trunc. - if (NewInsts.count(Src) && isa<TruncInst>(Src) && - Src->getType() == OrigTy) { + // We've inserted a trunc for a zext sink, but we already know that the + // input is in range, negating the need for the trunc. + if (NewInsts.count(Src) && isa<TruncInst>(Src)) { auto *Trunc = cast<TruncInst>(Src); assert(Trunc->getOperand(0)->getType() == ExtTy && "expected inserted trunc to be operating on i32"); @@ -615,7 +618,7 @@ void IRPromoter::ConvertTruncs() { unsigned NumBits = DestTy->getScalarSizeInBits(); ConstantInt *Mask = - ConstantInt::get(SrcTy, APInt::getMaxValue(NumBits).getZExtValue()); + ConstantInt::get(SrcTy, APInt::getMaxValue(NumBits).getZExtValue()); Value *Masked = Builder.CreateAnd(Trunc->getOperand(0), Mask); if (auto *I = dyn_cast<Instruction>(Masked)) @@ -626,8 +629,8 @@ void IRPromoter::ConvertTruncs() { } void IRPromoter::Mutate() { - LLVM_DEBUG(dbgs() << "IR Promotion: Promoting use-def chains from " - << OrigTy->getBitWidth() << " to " << PromotedWidth << "-bits\n"); + LLVM_DEBUG(dbgs() << "IR Promotion: Promoting use-def chains to " + << PromotedWidth << "-bits\n"); // Cache original types of the values that will likely need truncating for (auto *I : Sinks) { @@ -677,8 +680,7 @@ bool TypePromotion::isSupportedType(Value *V) { if (Ty->isVoidTy() || Ty->isPointerTy()) return true; - if (!isa<IntegerType>(Ty) || - cast<IntegerType>(Ty)->getBitWidth() == 1 || + if (!isa<IntegerType>(Ty) || cast<IntegerType>(Ty)->getBitWidth() == 1 || cast<IntegerType>(Ty)->getBitWidth() > RegisterBitWidth) return false; @@ -738,13 +740,12 @@ bool TypePromotion::isSupportedValue(Value *V) { /// smaller than the targeted promoted type. Check that we're not trying to /// promote something larger than our base 'TypeSize' type. bool TypePromotion::isLegalToPromote(Value *V) { - auto *I = dyn_cast<Instruction>(V); if (!I) return true; if (SafeToPromote.count(I)) - return true; + return true; if (isPromotedResultSafe(I) || isSafeWrap(I)) { SafeToPromote.insert(I); @@ -765,10 +766,10 @@ bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) { LLVM_DEBUG(dbgs() << "IR Promotion: TryToPromote: " << *V << ", from " << TypeSize << " bits to " << PromotedWidth << "\n"); - SetVector<Value*> WorkList; - SetVector<Value*> Sources; - SetVector<Instruction*> Sinks; - SetVector<Value*> CurrentVisited; + SetVector<Value *> WorkList; + SetVector<Value *> Sources; + SetVector<Instruction *> Sinks; + SetVector<Value *> CurrentVisited; WorkList.insert(V); // Return true if V was added to the worklist as a supported instruction, @@ -839,14 +840,15 @@ bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) { } } - LLVM_DEBUG(dbgs() << "IR Promotion: Visited nodes:\n"; - for (auto *I : CurrentVisited) - I->dump(); - ); + LLVM_DEBUG({ + dbgs() << "IR Promotion: Visited nodes:\n"; + for (auto *I : CurrentVisited) + I->dump(); + }); unsigned ToPromote = 0; unsigned NonFreeArgs = 0; - SmallPtrSet<BasicBlock*, 4> Blocks; + SmallPtrSet<BasicBlock *, 4> Blocks; for (auto *V : CurrentVisited) { if (auto *I = dyn_cast<Instruction>(V)) Blocks.insert(I->getParent()); @@ -860,16 +862,16 @@ bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) { if (Sinks.count(cast<Instruction>(V))) continue; - ++ToPromote; - } + ++ToPromote; + } // DAG optimizations should be able to handle these cases better, especially // for function arguments. if (ToPromote < 2 || (Blocks.size() == 1 && (NonFreeArgs > SafeWrap.size()))) return false; - IRPromoter Promoter(*Ctx, cast<IntegerType>(OrigTy), PromotedWidth, - CurrentVisited, Sources, Sinks, SafeWrap); + IRPromoter Promoter(*Ctx, PromotedWidth, CurrentVisited, Sources, Sinks, + SafeWrap); Promoter.Mutate(); return true; } @@ -893,14 +895,14 @@ bool TypePromotion::runOnFunction(Function &F) { const TargetSubtargetInfo *SubtargetInfo = TM.getSubtargetImpl(F); const TargetLowering *TLI = SubtargetInfo->getTargetLowering(); const TargetTransformInfo &TII = - getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); + getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); RegisterBitWidth = TII.getRegisterBitWidth(TargetTransformInfo::RGK_Scalar).getFixedSize(); Ctx = &F.getParent()->getContext(); // Search up from icmps to try to promote their operands. for (BasicBlock &BB : F) { - for (auto &I : BB) { + for (Instruction &I : BB) { if (AllVisited.count(&I)) continue; @@ -909,8 +911,7 @@ bool TypePromotion::runOnFunction(Function &F) { auto *ICmp = cast<ICmpInst>(&I); // Skip signed or pointer compares - if (ICmp->isSigned() || - !isa<IntegerType>(ICmp->getOperand(0)->getType())) + if (ICmp->isSigned() || !isa<IntegerType>(ICmp->getOperand(0)->getType())) continue; LLVM_DEBUG(dbgs() << "IR Promotion: Searching from: " << *ICmp << "\n"); @@ -921,13 +922,13 @@ bool TypePromotion::runOnFunction(Function &F) { if (SrcVT.isSimple() && TLI->isTypeLegal(SrcVT.getSimpleVT())) break; - if (TLI->getTypeAction(ICmp->getContext(), SrcVT) != + if (TLI->getTypeAction(*Ctx, SrcVT) != TargetLowering::TypePromoteInteger) break; - EVT PromotedVT = TLI->getTypeToTransformTo(ICmp->getContext(), SrcVT); + EVT PromotedVT = TLI->getTypeToTransformTo(*Ctx, SrcVT); if (RegisterBitWidth < PromotedVT.getFixedSizeInBits()) { LLVM_DEBUG(dbgs() << "IR Promotion: Couldn't find target register " - << "for promoted type\n"); + << "for promoted type\n"); break; } @@ -936,13 +937,7 @@ bool TypePromotion::runOnFunction(Function &F) { } } } - LLVM_DEBUG(if (verifyFunction(F, &dbgs())) { - dbgs() << F; - report_fatal_error("Broken function after type promotion"); - }); } - if (MadeChange) - LLVM_DEBUG(dbgs() << "After TypePromotion: " << F << "\n"); AllVisited.clear(); SafeToPromote.clear(); @@ -956,6 +951,4 @@ INITIALIZE_PASS_END(TypePromotion, DEBUG_TYPE, PASS_NAME, false, false) char TypePromotion::ID = 0; -FunctionPass *llvm::createTypePromotionPass() { - return new TypePromotion(); -} +FunctionPass *llvm::createTypePromotionPass() { return new TypePromotion(); } |
