LLVM 19.0.0git
Macros | Typedefs | Functions | Variables
DeadStoreElimination.cpp File Reference
#include "llvm/Transforms/Scalar/DeadStoreElimination.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/MustExecute.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
#include "llvm/Transforms/Utils/Local.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <map>
#include <optional>
#include <utility>

Go to the source code of this file.

Macros

#define DEBUG_TYPE   "dse"
 

Typedefs

using OverlapIntervalsTy = std::map< int64_t, int64_t >
 
using InstOverlapIntervalsTy = DenseMap< Instruction *, OverlapIntervalsTy >
 

Functions

 STATISTIC (NumRemainingStores, "Number of stores remaining after DSE")
 
 STATISTIC (NumRedundantStores, "Number of redundant stores deleted")
 
 STATISTIC (NumFastStores, "Number of stores deleted")
 
 STATISTIC (NumFastOther, "Number of other instrs removed")
 
 STATISTIC (NumCompletePartials, "Number of stores dead by later partials")
 
 STATISTIC (NumModifiedStores, "Number of stores modified")
 
 STATISTIC (NumCFGChecks, "Number of stores modified")
 
 STATISTIC (NumCFGTries, "Number of stores modified")
 
 STATISTIC (NumCFGSuccess, "Number of stores modified")
 
 STATISTIC (NumGetDomMemoryDefPassed, "Number of times a valid candidate is returned from getDomMemoryDef")
 
 STATISTIC (NumDomMemDefChecks, "Number iterations check for reads in getDomMemoryDef")
 
 DEBUG_COUNTER (MemorySSACounter, "dse-memoryssa", "Controls which MemoryDefs are eliminated.")
 
static bool isShortenableAtTheEnd (Instruction *I)
 Returns true if the end of this instruction can be safely shortened in length.
 
static bool isShortenableAtTheBeginning (Instruction *I)
 Returns true if the beginning of this instruction can be safely shortened in length.
 
static std::optional< TypeSizegetPointerSize (const Value *V, const DataLayout &DL, const TargetLibraryInfo &TLI, const Function *F)
 
static OverwriteResult isMaskedStoreOverwrite (const Instruction *KillingI, const Instruction *DeadI, BatchAAResults &AA)
 Check if two instruction are masked stores that completely overwrite one another.
 
static OverwriteResult isPartialOverwrite (const MemoryLocation &KillingLoc, const MemoryLocation &DeadLoc, int64_t KillingOff, int64_t DeadOff, Instruction *DeadI, InstOverlapIntervalsTy &IOL)
 Return 'OW_Complete' if a store to the 'KillingLoc' location completely overwrites a store to the 'DeadLoc' location, 'OW_End' if the end of the 'DeadLoc' location is completely overwritten by 'KillingLoc', 'OW_Begin' if the beginning of the 'DeadLoc' location is overwritten by 'KillingLoc'.
 
static bool memoryIsNotModifiedBetween (Instruction *FirstI, Instruction *SecondI, BatchAAResults &AA, const DataLayout &DL, DominatorTree *DT)
 Returns true if the memory which is accessed by the second instruction is not modified between the first and the second instruction.
 
static void shortenAssignment (Instruction *Inst, Value *OriginalDest, uint64_t OldOffsetInBits, uint64_t OldSizeInBits, uint64_t NewSizeInBits, bool IsOverwriteEnd)
 
static bool tryToShorten (Instruction *DeadI, int64_t &DeadStart, uint64_t &DeadSize, int64_t KillingStart, uint64_t KillingSize, bool IsOverwriteEnd)
 
static bool tryToShortenEnd (Instruction *DeadI, OverlapIntervalsTy &IntervalMap, int64_t &DeadStart, uint64_t &DeadSize)
 
static bool tryToShortenBegin (Instruction *DeadI, OverlapIntervalsTy &IntervalMap, int64_t &DeadStart, uint64_t &DeadSize)
 
static ConstanttryToMergePartialOverlappingStores (StoreInst *KillingI, StoreInst *DeadI, int64_t KillingOffset, int64_t DeadOffset, const DataLayout &DL, BatchAAResults &AA, DominatorTree *DT)
 

Variables

static cl::opt< boolEnablePartialOverwriteTracking ("enable-dse-partial-overwrite-tracking", cl::init(true), cl::Hidden, cl::desc("Enable partial-overwrite tracking in DSE"))
 
static cl::opt< boolEnablePartialStoreMerging ("enable-dse-partial-store-merging", cl::init(true), cl::Hidden, cl::desc("Enable partial store merging in DSE"))
 
static cl::opt< unsignedMemorySSAScanLimit ("dse-memoryssa-scanlimit", cl::init(150), cl::Hidden, cl::desc("The number of memory instructions to scan for " "dead store elimination (default = 150)"))
 
static cl::opt< unsignedMemorySSAUpwardsStepLimit ("dse-memoryssa-walklimit", cl::init(90), cl::Hidden, cl::desc("The maximum number of steps while walking upwards to find " "MemoryDefs that may be killed (default = 90)"))
 
static cl::opt< unsignedMemorySSAPartialStoreLimit ("dse-memoryssa-partial-store-limit", cl::init(5), cl::Hidden, cl::desc("The maximum number candidates that only partially overwrite the " "killing MemoryDef to consider" " (default = 5)"))
 
static cl::opt< unsignedMemorySSADefsPerBlockLimit ("dse-memoryssa-defs-per-block-limit", cl::init(5000), cl::Hidden, cl::desc("The number of MemoryDefs we consider as candidates to eliminated " "other stores per basic block (default = 5000)"))
 
static cl::opt< unsignedMemorySSASameBBStepCost ("dse-memoryssa-samebb-cost", cl::init(1), cl::Hidden, cl::desc("The cost of a step in the same basic block as the killing MemoryDef" "(default = 1)"))
 
static cl::opt< unsignedMemorySSAOtherBBStepCost ("dse-memoryssa-otherbb-cost", cl::init(5), cl::Hidden, cl::desc("The cost of a step in a different basic " "block than the killing MemoryDef" "(default = 5)"))
 
static cl::opt< unsignedMemorySSAPathCheckLimit ("dse-memoryssa-path-check-limit", cl::init(50), cl::Hidden, cl::desc("The maximum number of blocks to check when trying to prove that " "all paths to an exit go through a killing block (default = 50)"))
 
static cl::opt< boolOptimizeMemorySSA ("dse-optimize-memoryssa", cl::init(true), cl::Hidden, cl::desc("Allow DSE to optimize memory accesses."))
 

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "dse"

Definition at line 90 of file DeadStoreElimination.cpp.

Typedef Documentation

◆ InstOverlapIntervalsTy

Definition at line 171 of file DeadStoreElimination.cpp.

◆ OverlapIntervalsTy

using OverlapIntervalsTy = std::map<int64_t, int64_t>

Definition at line 170 of file DeadStoreElimination.cpp.

Function Documentation

◆ DEBUG_COUNTER()

DEBUG_COUNTER ( MemorySSACounter  ,
"dse-memoryssa"  ,
"Controls which MemoryDefs are eliminated."   
)

◆ getPointerSize()

static std::optional< TypeSize > getPointerSize ( const Value V,
const DataLayout DL,
const TargetLibraryInfo TLI,
const Function F 
)
static

◆ isMaskedStoreOverwrite()

static OverwriteResult isMaskedStoreOverwrite ( const Instruction KillingI,
const Instruction DeadI,
BatchAAResults AA 
)
static

Check if two instruction are masked stores that completely overwrite one another.

More specifically, KillingI has to overwrite DeadI.

Definition at line 236 of file DeadStoreElimination.cpp.

References llvm::BatchAAResults::isMustAlias(), and llvm::Value::stripPointerCasts().

◆ isPartialOverwrite()

static OverwriteResult isPartialOverwrite ( const MemoryLocation KillingLoc,
const MemoryLocation DeadLoc,
int64_t  KillingOff,
int64_t  DeadOff,
Instruction DeadI,
InstOverlapIntervalsTy IOL 
)
static

Return 'OW_Complete' if a store to the 'KillingLoc' location completely overwrites a store to the 'DeadLoc' location, 'OW_End' if the end of the 'DeadLoc' location is completely overwritten by 'KillingLoc', 'OW_Begin' if the beginning of the 'DeadLoc' location is overwritten by 'KillingLoc'.

'OW_PartialEarlierWithFullLater' means that a dead (big) store was overwritten by a killing (smaller) store which doesn't write outside the big store's memory locations. Returns 'OW_Unknown' if nothing can be determined. NOTE: This function must only be called if both KillingLoc and DeadLoc belong to the same underlying object with valid KillingOff and DeadOff.

Definition at line 279 of file DeadStoreElimination.cpp.

References assert(), llvm::dbgs(), EnablePartialOverwriteTracking, EnablePartialStoreMerging, llvm::LocationSize::getValue(), LLVM_DEBUG, and llvm::MemoryLocation::Size.

◆ isShortenableAtTheBeginning()

static bool isShortenableAtTheBeginning ( Instruction I)
static

Returns true if the beginning of this instruction can be safely shortened in length.

Definition at line 200 of file DeadStoreElimination.cpp.

References I.

Referenced by tryToShortenBegin().

◆ isShortenableAtTheEnd()

static bool isShortenableAtTheEnd ( Instruction I)
static

Returns true if the end of this instruction can be safely shortened in length.

Definition at line 175 of file DeadStoreElimination.cpp.

References I.

Referenced by tryToShortenEnd().

◆ memoryIsNotModifiedBetween()

static bool memoryIsNotModifiedBetween ( Instruction FirstI,
Instruction SecondI,
BatchAAResults AA,
const DataLayout DL,
DominatorTree DT 
)
static

◆ shortenAssignment()

static void shortenAssignment ( Instruction Inst,
Value OriginalDest,
uint64_t  OldOffsetInBits,
uint64_t  OldSizeInBits,
uint64_t  NewSizeInBits,
bool  IsOverwriteEnd 
)
static

◆ STATISTIC() [1/11]

STATISTIC ( NumCFGChecks  ,
"Number of stores modified"   
)

◆ STATISTIC() [2/11]

STATISTIC ( NumCFGSuccess  ,
"Number of stores modified"   
)

◆ STATISTIC() [3/11]

STATISTIC ( NumCFGTries  ,
"Number of stores modified"   
)

◆ STATISTIC() [4/11]

STATISTIC ( NumCompletePartials  ,
"Number of stores dead by later partials"   
)

◆ STATISTIC() [5/11]

STATISTIC ( NumDomMemDefChecks  ,
"Number iterations check for reads in getDomMemoryDef"   
)

◆ STATISTIC() [6/11]

STATISTIC ( NumFastOther  ,
"Number of other instrs removed"   
)

◆ STATISTIC() [7/11]

STATISTIC ( NumFastStores  ,
"Number of stores deleted"   
)

◆ STATISTIC() [8/11]

STATISTIC ( NumGetDomMemoryDefPassed  ,
"Number of times a valid candidate is returned from getDomMemoryDef"   
)

◆ STATISTIC() [9/11]

STATISTIC ( NumModifiedStores  ,
"Number of stores modified"   
)

◆ STATISTIC() [10/11]

STATISTIC ( NumRedundantStores  ,
"Number of redundant stores deleted"   
)

◆ STATISTIC() [11/11]

STATISTIC ( NumRemainingStores  ,
"Number of stores remaining after DSE"   
)

◆ tryToMergePartialOverlappingStores()

static Constant * tryToMergePartialOverlappingStores ( StoreInst KillingI,
StoreInst DeadI,
int64_t  KillingOffset,
int64_t  DeadOffset,
const DataLayout DL,
BatchAAResults AA,
DominatorTree DT 
)
static

◆ tryToShorten()

static bool tryToShorten ( Instruction DeadI,
int64_t &  DeadStart,
uint64_t DeadSize,
int64_t  KillingStart,
uint64_t  KillingSize,
bool  IsOverwriteEnd 
)
static

◆ tryToShortenBegin()

static bool tryToShortenBegin ( Instruction DeadI,
OverlapIntervalsTy IntervalMap,
int64_t &  DeadStart,
uint64_t DeadSize 
)
static

◆ tryToShortenEnd()

static bool tryToShortenEnd ( Instruction DeadI,
OverlapIntervalsTy IntervalMap,
int64_t &  DeadStart,
uint64_t DeadSize 
)
static

Variable Documentation

◆ EnablePartialOverwriteTracking

cl::opt< bool > EnablePartialOverwriteTracking("enable-dse-partial-overwrite-tracking", cl::init(true), cl::Hidden, cl::desc("Enable partial-overwrite tracking in DSE")) ( "enable-dse-partial-overwrite-tracking"  ,
cl::init(true ,
cl::Hidden  ,
cl::desc("Enable partial-overwrite tracking in DSE")   
)
static

Referenced by isPartialOverwrite().

◆ EnablePartialStoreMerging

cl::opt< bool > EnablePartialStoreMerging("enable-dse-partial-store-merging", cl::init(true), cl::Hidden, cl::desc("Enable partial store merging in DSE")) ( "enable-dse-partial-store-merging"  ,
cl::init(true ,
cl::Hidden  ,
cl::desc("Enable partial store merging in DSE")   
)
static

Referenced by isPartialOverwrite().

◆ MemorySSADefsPerBlockLimit

cl::opt< unsigned > MemorySSADefsPerBlockLimit("dse-memoryssa-defs-per-block-limit", cl::init(5000), cl::Hidden, cl::desc("The number of MemoryDefs we consider as candidates to eliminated " "other stores per basic block (default = 5000)")) ( "dse-memoryssa-defs-per-block-limit"  ,
cl::init(5000)  ,
cl::Hidden  ,
cl::desc("The number of MemoryDefs we consider as candidates to eliminated " "other stores per basic block (default = 5000)")   
)
static

◆ MemorySSAOtherBBStepCost

cl::opt< unsigned > MemorySSAOtherBBStepCost("dse-memoryssa-otherbb-cost", cl::init(5), cl::Hidden, cl::desc("The cost of a step in a different basic " "block than the killing MemoryDef" "(default = 5)")) ( "dse-memoryssa-otherbb-cost"  ,
cl::init(5)  ,
cl::Hidden  ,
cl::desc("The cost of a step in a different basic " "block than the killing MemoryDef" "(default = 5)")   
)
static

◆ MemorySSAPartialStoreLimit

cl::opt< unsigned > MemorySSAPartialStoreLimit("dse-memoryssa-partial-store-limit", cl::init(5), cl::Hidden, cl::desc("The maximum number candidates that only partially overwrite the " "killing MemoryDef to consider" " (default = 5)")) ( "dse-memoryssa-partial-store-limit"  ,
cl::init(5)  ,
cl::Hidden  ,
cl::desc("The maximum number candidates that only partially overwrite the " "killing MemoryDef to consider" " (default = 5)")   
)
static

◆ MemorySSAPathCheckLimit

cl::opt< unsigned > MemorySSAPathCheckLimit("dse-memoryssa-path-check-limit", cl::init(50), cl::Hidden, cl::desc("The maximum number of blocks to check when trying to prove that " "all paths to an exit go through a killing block (default = 50)")) ( "dse-memoryssa-path-check-limit"  ,
cl::init(50)  ,
cl::Hidden  ,
cl::desc("The maximum number of blocks to check when trying to prove that " "all paths to an exit go through a killing block (default = 50)")   
)
static

◆ MemorySSASameBBStepCost

cl::opt< unsigned > MemorySSASameBBStepCost("dse-memoryssa-samebb-cost", cl::init(1), cl::Hidden, cl::desc( "The cost of a step in the same basic block as the killing MemoryDef" "(default = 1)")) ( "dse-memoryssa-samebb-cost"  ,
cl::init(1)  ,
cl::Hidden  ,
cl::desc( "The cost of a step in the same basic block as the killing MemoryDef" "(default = 1)")   
)
static

◆ MemorySSAScanLimit

cl::opt< unsigned > MemorySSAScanLimit("dse-memoryssa-scanlimit", cl::init(150), cl::Hidden, cl::desc("The number of memory instructions to scan for " "dead store elimination (default = 150)")) ( "dse-memoryssa-scanlimit"  ,
cl::init(150)  ,
cl::Hidden  ,
cl::desc("The number of memory instructions to scan for " "dead store elimination (default = 150)")   
)
static

◆ MemorySSAUpwardsStepLimit

cl::opt< unsigned > MemorySSAUpwardsStepLimit("dse-memoryssa-walklimit", cl::init(90), cl::Hidden, cl::desc("The maximum number of steps while walking upwards to find " "MemoryDefs that may be killed (default = 90)")) ( "dse-memoryssa-walklimit"  ,
cl::init(90)  ,
cl::Hidden  ,
cl::desc("The maximum number of steps while walking upwards to find " "MemoryDefs that may be killed (default = 90)")   
)
static

◆ OptimizeMemorySSA

cl::opt< bool > OptimizeMemorySSA("dse-optimize-memoryssa", cl::init(true), cl::Hidden, cl::desc("Allow DSE to optimize memory accesses.")) ( "dse-optimize-memoryssa"  ,
cl::init(true ,
cl::Hidden  ,
cl::desc("Allow DSE to optimize memory accesses.")   
)
static