diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Scalar/SCCP.cpp')
-rw-r--r-- | contrib/llvm/lib/Transforms/Scalar/SCCP.cpp | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp b/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp index 2f6ed05c023b..4093e50ce899 100644 --- a/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1,9 +1,8 @@ //===- SCCP.cpp - Sparse Conditional Constant Propagation -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -21,6 +20,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" @@ -210,11 +210,11 @@ class SCCPSolver : public InstVisitor<SCCPSolver> { /// TrackedRetVals - If we are tracking arguments into and the return /// value out of a function, it will have an entry in this map, indicating /// what the known return value for the function is. - DenseMap<Function *, LatticeVal> TrackedRetVals; + MapVector<Function *, LatticeVal> TrackedRetVals; /// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions /// that return multiple values. - DenseMap<std::pair<Function *, unsigned>, LatticeVal> TrackedMultipleRetVals; + MapVector<std::pair<Function *, unsigned>, LatticeVal> TrackedMultipleRetVals; /// MRVFunctionsTracked - Each function in TrackedMultipleRetVals is /// represented here for efficient lookup. @@ -372,7 +372,7 @@ public: } /// getTrackedRetVals - Get the inferred return value map. - const DenseMap<Function*, LatticeVal> &getTrackedRetVals() { + const MapVector<Function*, LatticeVal> &getTrackedRetVals() { return TrackedRetVals; } @@ -614,6 +614,7 @@ private: void visitCastInst(CastInst &I); void visitSelectInst(SelectInst &I); + void visitUnaryOperator(Instruction &I); void visitBinaryOperator(Instruction &I); void visitCmpInst(CmpInst &I); void visitExtractValueInst(ExtractValueInst &EVI); @@ -639,6 +640,11 @@ private: visitTerminator(II); } + void visitCallBrInst (CallBrInst &CBI) { + visitCallSite(&CBI); + visitTerminator(CBI); + } + void visitCallSite (CallSite CS); void visitResumeInst (ResumeInst &I) { /*returns void*/ } void visitUnreachableInst(UnreachableInst &I) { /*returns void*/ } @@ -734,6 +740,13 @@ void SCCPSolver::getFeasibleSuccessors(Instruction &TI, return; } + // In case of callbr, we pessimistically assume that all successors are + // feasible. + if (isa<CallBrInst>(&TI)) { + Succs.assign(TI.getNumSuccessors(), true); + return; + } + LLVM_DEBUG(dbgs() << "Unknown terminator instruction: " << TI << '\n'); llvm_unreachable("SCCP: Don't know how to handle this terminator!"); } @@ -825,7 +838,7 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) { // If we are tracking the return value of this function, merge it in. if (!TrackedRetVals.empty() && !ResultOp->getType()->isStructTy()) { - DenseMap<Function*, LatticeVal>::iterator TFRVI = + MapVector<Function*, LatticeVal>::iterator TFRVI = TrackedRetVals.find(F); if (TFRVI != TrackedRetVals.end()) { mergeInValue(TFRVI->second, F, getValueState(ResultOp)); @@ -958,6 +971,29 @@ void SCCPSolver::visitSelectInst(SelectInst &I) { markOverdefined(&I); } +// Handle Unary Operators. +void SCCPSolver::visitUnaryOperator(Instruction &I) { + LatticeVal V0State = getValueState(I.getOperand(0)); + + LatticeVal &IV = ValueState[&I]; + if (IV.isOverdefined()) return; + + if (V0State.isConstant()) { + Constant *C = ConstantExpr::get(I.getOpcode(), V0State.getConstant()); + + // op Y -> undef. + if (isa<UndefValue>(C)) + return; + return (void)markConstant(IV, &I, C); + } + + // If something is undef, wait for it to resolve. + if (!V0State.isOverdefined()) + return; + + markOverdefined(&I); +} + // Handle Binary Operators. void SCCPSolver::visitBinaryOperator(Instruction &I) { LatticeVal V1State = getValueState(I.getOperand(0)); @@ -1232,7 +1268,7 @@ CallOverdefined: // Otherwise, if we have a single return value case, and if the function is // a declaration, maybe we can constant fold it. if (F && F->isDeclaration() && !I->getType()->isStructTy() && - canConstantFoldCallTo(CS, F)) { + canConstantFoldCallTo(cast<CallBase>(CS.getInstruction()), F)) { SmallVector<Constant*, 8> Operands; for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); AI != E; ++AI) { @@ -1253,7 +1289,8 @@ CallOverdefined: // If we can constant fold this, mark the result of the call as a // constant. - if (Constant *C = ConstantFoldCall(CS, F, Operands, TLI)) { + if (Constant *C = ConstantFoldCall(cast<CallBase>(CS.getInstruction()), F, + Operands, TLI)) { // call -> undef. if (isa<UndefValue>(C)) return; @@ -1315,7 +1352,7 @@ CallOverdefined: mergeInValue(getStructValueState(I, i), I, TrackedMultipleRetVals[std::make_pair(F, i)]); } else { - DenseMap<Function*, LatticeVal>::iterator TFRVI = TrackedRetVals.find(F); + MapVector<Function*, LatticeVal>::iterator TFRVI = TrackedRetVals.find(F); if (TFRVI == TrackedRetVals.end()) goto CallOverdefined; // Not tracking this callee. @@ -1472,6 +1509,8 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) { else markOverdefined(&I); return true; + case Instruction::FNeg: + break; // fneg undef -> undef case Instruction::ZExt: case Instruction::SExt: case Instruction::FPToUI: @@ -1598,6 +1637,7 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) { return true; case Instruction::Call: case Instruction::Invoke: + case Instruction::CallBr: // There are two reasons a call can have an undef result // 1. It could be tracked. // 2. It could be constant-foldable. @@ -2070,12 +2110,22 @@ bool llvm::runIPSCCP( // If we have forced an edge for an indeterminate value, then force the // terminator to fold to that edge. forceIndeterminateEdge(I, Solver); - bool Folded = ConstantFoldTerminator(I->getParent(), + BasicBlock *InstBB = I->getParent(); + bool Folded = ConstantFoldTerminator(InstBB, /*DeleteDeadConditions=*/false, /*TLI=*/nullptr, &DTU); assert(Folded && "Expect TermInst on constantint or blockaddress to be folded"); (void) Folded; + // If we folded the terminator to an unconditional branch to another + // dead block, replace it with Unreachable, to avoid trying to fold that + // branch again. + BranchInst *BI = cast<BranchInst>(InstBB->getTerminator()); + if (BI && BI->isUnconditional() && + !Solver.isBlockExecutable(BI->getSuccessor(0))) { + InstBB->getTerminator()->eraseFromParent(); + new UnreachableInst(InstBB->getContext(), InstBB); + } } // Mark dead BB for deletion. DTU.deleteBB(DeadBB); @@ -2109,7 +2159,7 @@ bool llvm::runIPSCCP( // whether other functions are optimizable. SmallVector<ReturnInst*, 8> ReturnsToZap; - const DenseMap<Function*, LatticeVal> &RV = Solver.getTrackedRetVals(); + const MapVector<Function*, LatticeVal> &RV = Solver.getTrackedRetVals(); for (const auto &I : RV) { Function *F = I.first; if (I.second.isOverdefined() || F->getReturnType()->isVoidTy()) |