diff options
Diffstat (limited to 'lib/Transforms/IPO')
| -rw-r--r-- | lib/Transforms/IPO/DeadArgumentElimination.cpp | 10 | ||||
| -rw-r--r-- | lib/Transforms/IPO/FunctionAttrs.cpp | 2 | ||||
| -rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 118 | ||||
| -rw-r--r-- | lib/Transforms/IPO/IPConstantPropagation.cpp | 16 | ||||
| -rw-r--r-- | lib/Transforms/IPO/MergeFunctions.cpp | 10 | ||||
| -rw-r--r-- | lib/Transforms/IPO/PruneEH.cpp | 4 |
6 files changed, 68 insertions, 92 deletions
diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 31e771da3bd3..cd2bd734eb26 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -56,7 +56,7 @@ using namespace llvm; STATISTIC(NumArgumentsEliminated, "Number of unread args removed"); STATISTIC(NumRetValsEliminated , "Number of unused return values removed"); -STATISTIC(NumArgumentsReplacedWithUndef, +STATISTIC(NumArgumentsReplacedWithUndef, "Number of unread args replaced with undef"); namespace { @@ -109,7 +109,7 @@ namespace { char DAH::ID = 0; -INITIALIZE_PASS(DAH, "deadarghaX0r", +INITIALIZE_PASS(DAH, "deadarghaX0r", "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)", false, false) @@ -256,7 +256,7 @@ bool DeadArgumentEliminationPass::DeleteDeadVarargs(Function &Fn) { return true; } -/// RemoveDeadArgumentsFromCallers - Checks if the given function has any +/// RemoveDeadArgumentsFromCallers - Checks if the given function has any /// arguments that are unused, and changes the caller parameters to be undefined /// instead. bool DeadArgumentEliminationPass::RemoveDeadArgumentsFromCallers(Function &Fn) { @@ -640,7 +640,7 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) { Result = Live; } else { // See what the effect of this use is (recording any uses that cause - // MaybeLive in MaybeLiveArgUses). + // MaybeLive in MaybeLiveArgUses). Result = SurveyUses(&*AI, MaybeLiveArgUses); } @@ -777,7 +777,7 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { // argument. // 2) Retain the 'returned' attribute and treat the return value (but not the // entire function) as live so that it is not eliminated. - // + // // It's not clear in the general case which option is more profitable because, // even in the absence of explicit uses of the return value, code generation // is free to use the 'returned' attribute to do things like eliding diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index 2797da6c0abd..010b0a29807d 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/lib/Transforms/IPO/FunctionAttrs.cpp @@ -617,7 +617,7 @@ static bool addArgumentAttrsFromCallsites(Function &F) { if (!isGuaranteedToTransferExecutionToSuccessor(&I)) break; } - + return Changed; } diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 1af7e6894777..1761d7faff57 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -357,6 +357,41 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init, return Changed; } +static bool isSafeSROAElementUse(Value *V); + +/// Return true if the specified GEP is a safe user of a derived +/// expression from a global that we want to SROA. +static bool isSafeSROAGEP(User *U) { + // Check to see if this ConstantExpr GEP is SRA'able. In particular, we + // don't like < 3 operand CE's, and we don't like non-constant integer + // indices. This enforces that all uses are 'gep GV, 0, C, ...' for some + // value of C. + if (U->getNumOperands() < 3 || !isa<Constant>(U->getOperand(1)) || + !cast<Constant>(U->getOperand(1))->isNullValue()) + return false; + + gep_type_iterator GEPI = gep_type_begin(U), E = gep_type_end(U); + ++GEPI; // Skip over the pointer index. + + // For all other level we require that the indices are constant and inrange. + // In particular, consider: A[0][i]. We cannot know that the user isn't doing + // invalid things like allowing i to index an out-of-range subscript that + // accesses A[1]. This can also happen between different members of a struct + // in llvm IR. + for (; GEPI != E; ++GEPI) { + if (GEPI.isStruct()) + continue; + + ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPI.getOperand()); + if (!IdxVal || (GEPI.isBoundedSequential() && + IdxVal->getZExtValue() >= GEPI.getSequentialNumElements())) + return false; + } + + return llvm::all_of(U->users(), + [](User *UU) { return isSafeSROAElementUse(UU); }); +} + /// Return true if the specified instruction is a safe user of a derived /// expression from a global that we want to SROA. static bool isSafeSROAElementUse(Value *V) { @@ -374,84 +409,25 @@ static bool isSafeSROAElementUse(Value *V) { if (StoreInst *SI = dyn_cast<StoreInst>(I)) return SI->getOperand(0) != V; - // Otherwise, it must be a GEP. - GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I); - if (!GEPI) return false; - - if (GEPI->getNumOperands() < 3 || !isa<Constant>(GEPI->getOperand(1)) || - !cast<Constant>(GEPI->getOperand(1))->isNullValue()) - return false; - - for (User *U : GEPI->users()) - if (!isSafeSROAElementUse(U)) - return false; - return true; -} - -/// U is a direct user of the specified global value. Look at it and its uses -/// and decide whether it is safe to SROA this global. -static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) { - // The user of the global must be a GEP Inst or a ConstantExpr GEP. - if (!isa<GetElementPtrInst>(U) && - (!isa<ConstantExpr>(U) || - cast<ConstantExpr>(U)->getOpcode() != Instruction::GetElementPtr)) - return false; - - // Check to see if this ConstantExpr GEP is SRA'able. In particular, we - // don't like < 3 operand CE's, and we don't like non-constant integer - // indices. This enforces that all uses are 'gep GV, 0, C, ...' for some - // value of C. - if (U->getNumOperands() < 3 || !isa<Constant>(U->getOperand(1)) || - !cast<Constant>(U->getOperand(1))->isNullValue() || - !isa<ConstantInt>(U->getOperand(2))) - return false; - - gep_type_iterator GEPI = gep_type_begin(U), E = gep_type_end(U); - ++GEPI; // Skip over the pointer index. - - // If this is a use of an array allocation, do a bit more checking for sanity. - if (GEPI.isSequential()) { - ConstantInt *Idx = cast<ConstantInt>(U->getOperand(2)); - - // Check to make sure that index falls within the array. If not, - // something funny is going on, so we won't do the optimization. - // - if (GEPI.isBoundedSequential() && - Idx->getZExtValue() >= GEPI.getSequentialNumElements()) - return false; - - // We cannot scalar repl this level of the array unless any array - // sub-indices are in-range constants. In particular, consider: - // A[0][i]. We cannot know that the user isn't doing invalid things like - // allowing i to index an out-of-range subscript that accesses A[1]. - // - // Scalar replacing *just* the outer index of the array is probably not - // going to be a win anyway, so just give up. - for (++GEPI; // Skip array index. - GEPI != E; - ++GEPI) { - if (GEPI.isStruct()) - continue; - - ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPI.getOperand()); - if (!IdxVal || - (GEPI.isBoundedSequential() && - IdxVal->getZExtValue() >= GEPI.getSequentialNumElements())) - return false; - } - } - - return llvm::all_of(U->users(), - [](User *UU) { return isSafeSROAElementUse(UU); }); + // Otherwise, it must be a GEP. Check it and its users are safe to SRA. + return isa<GetElementPtrInst>(I) && isSafeSROAGEP(I); } /// Look at all uses of the global and decide whether it is safe for us to /// perform this transformation. static bool GlobalUsersSafeToSRA(GlobalValue *GV) { - for (User *U : GV->users()) - if (!IsUserOfGlobalSafeForSRA(U, GV)) + for (User *U : GV->users()) { + // The user of the global must be a GEP Inst or a ConstantExpr GEP. + if (!isa<GetElementPtrInst>(U) && + (!isa<ConstantExpr>(U) || + cast<ConstantExpr>(U)->getOpcode() != Instruction::GetElementPtr)) return false; + // Check the gep and it's users are safe to SRA + if (!isSafeSROAGEP(U)) + return false; + } + return true; } diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index f79b61037f1d..7d55ebecbf92 100644 --- a/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -61,12 +61,12 @@ static bool PropagateConstantsIntoArguments(Function &F) { User *UR = U.getUser(); // Ignore blockaddress uses. if (isa<BlockAddress>(UR)) continue; - + // Used by a non-instruction, or not the callee of a function, do not // transform. if (!isa<CallInst>(UR) && !isa<InvokeInst>(UR)) return false; - + CallSite CS(cast<Instruction>(UR)); if (!CS.isCallee(&U)) return false; @@ -77,11 +77,11 @@ static bool PropagateConstantsIntoArguments(Function &F) { Function::arg_iterator Arg = F.arg_begin(); for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI, ++Arg) { - + // If this argument is known non-constant, ignore it. if (ArgumentConstants[i].second) continue; - + Constant *C = dyn_cast<Constant>(*AI); if (C && ArgumentConstants[i].first == nullptr) { ArgumentConstants[i].first = C; // First constant seen. @@ -108,7 +108,7 @@ static bool PropagateConstantsIntoArguments(Function &F) { if (ArgumentConstants[i].second || AI->use_empty() || AI->hasInAllocaAttr() || (AI->hasByValAttr() && !F.onlyReadsMemory())) continue; - + Value *V = ArgumentConstants[i].first; if (!V) V = UndefValue::get(AI->getType()); AI->replaceAllUsesWith(V); @@ -147,7 +147,7 @@ static bool PropagateConstantReturn(Function &F) { SmallVector<Value *,4> RetVals; StructType *STy = dyn_cast<StructType>(F.getReturnType()); if (STy) - for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i) + for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i) RetVals.push_back(UndefValue::get(STy->getElementType(i))); else RetVals.push_back(UndefValue::get(F.getReturnType())); @@ -172,7 +172,7 @@ static bool PropagateConstantReturn(Function &F) { // Ignore undefs, we can change them into anything if (isa<UndefValue>(V)) continue; - + // Try to see if all the rets return the same constant or argument. if (isa<Constant>(V) || isa<Argument>(V)) { if (isa<UndefValue>(RV)) { @@ -206,7 +206,7 @@ static bool PropagateConstantReturn(Function &F) { // directly? if (!Call || !CS.isCallee(&U)) continue; - + // Call result not used? if (Call->use_empty()) continue; diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index 139941127dee..3bebb96c6d35 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -27,7 +27,7 @@ // -- We define Function* container class with custom "operator<" (FunctionPtr). // -- "FunctionPtr" instances are stored in std::set collection, so every // std::set::insert operation will give you result in log(N) time. -// +// // As an optimization, a hash of the function structure is calculated first, and // two functions are only compared if they have the same hash. This hash is // cheap to compute, and has the property that if function F == G according to @@ -383,7 +383,7 @@ bool MergeFunctions::runOnModule(Module &M) { for (Function &Func : M) { if (!Func.isDeclaration() && !Func.hasAvailableExternallyLinkage()) { HashedFuncs.push_back({FunctionComparator::functionHash(Func), &Func}); - } + } } std::stable_sort( @@ -402,7 +402,7 @@ bool MergeFunctions::runOnModule(Module &M) { Deferred.push_back(WeakTrackingVH(I->second)); } } - + do { std::vector<WeakTrackingVH> Worklist; Deferred.swap(Worklist); @@ -802,11 +802,11 @@ void MergeFunctions::replaceFunctionInTree(const FunctionNode &FN, Function *F = FN.getFunc(); assert(FunctionComparator(F, G, &GlobalNumbers).compare() == 0 && "The two functions must be equal"); - + auto I = FNodesInTree.find(F); assert(I != FNodesInTree.end() && "F should be in FNodesInTree"); assert(FNodesInTree.count(G) == 0 && "FNodesInTree should not contain G"); - + FnTreeType::iterator IterToFNInFnTree = I->second; assert(&(*IterToFNInFnTree) == &FN && "F should map to FN in FNodesInTree."); // Remove F -> FN and insert G -> FN diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp index 27d791857314..2be654258aa8 100644 --- a/lib/Transforms/IPO/PruneEH.cpp +++ b/lib/Transforms/IPO/PruneEH.cpp @@ -77,13 +77,13 @@ static bool runImpl(CallGraphSCC &SCC, CallGraph &CG) { // Next, check to see if any callees might throw or if there are any external // functions in this SCC: if so, we cannot prune any functions in this SCC. - // Definitions that are weak and not declared non-throwing might be + // Definitions that are weak and not declared non-throwing might be // overridden at linktime with something that throws, so assume that. // If this SCC includes the unwind instruction, we KNOW it throws, so // obviously the SCC might throw. // bool SCCMightUnwind = false, SCCMightReturn = false; - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); + for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); (!SCCMightUnwind || !SCCMightReturn) && I != E; ++I) { Function *F = (*I)->getFunction(); if (!F) { |
