mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
[DAGCombiner] add helper function for store merging of extracts; NFC
This commit is contained in:
parent
44f6080ee5
commit
876f75b66f
@ -719,6 +719,14 @@ namespace {
|
||||
unsigned NumConsecutiveStores,
|
||||
EVT MemVT, bool AllowVectors, SDNode *Root);
|
||||
|
||||
/// This is a helper function for mergeConsecutiveStores. It is used for
|
||||
/// store chains that are composed entirely of extracted vector elements.
|
||||
/// When extracting multiple vector elements, try to store them in one
|
||||
/// vector store rather than a sequence of scalar stores.
|
||||
bool tryStoreMergeOfExtracts(SmallVectorImpl<MemOpLink> &StoreNodes,
|
||||
unsigned NumConsecutiveStores, EVT MemVT,
|
||||
SDNode *Root);
|
||||
|
||||
/// Merge consecutive store operations into a wide store.
|
||||
/// This optimization uses wide integers or vectors when possible.
|
||||
/// \return true if stores were merged.
|
||||
@ -16297,6 +16305,7 @@ bool DAGCombiner::tryStoreMergeOfConstants(
|
||||
int64_t ElementSizeBytes = MemVT.getStoreSize();
|
||||
unsigned NumMemElts = MemVT.isVector() ? MemVT.getVectorNumElements() : 1;
|
||||
bool MadeChange = false;
|
||||
|
||||
// Store the constants into memory as one consecutive store.
|
||||
while (NumConsecutiveStores >= 2) {
|
||||
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
|
||||
@ -16412,6 +16421,74 @@ bool DAGCombiner::tryStoreMergeOfConstants(
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
bool DAGCombiner::tryStoreMergeOfExtracts(
|
||||
SmallVectorImpl<MemOpLink> &StoreNodes, unsigned NumConsecutiveStores,
|
||||
EVT MemVT, SDNode *RootNode) {
|
||||
LLVMContext &Context = *DAG.getContext();
|
||||
const DataLayout &DL = DAG.getDataLayout();
|
||||
unsigned NumMemElts = MemVT.isVector() ? MemVT.getVectorNumElements() : 1;
|
||||
bool MadeChange = false;
|
||||
|
||||
// Loop on Consecutive Stores on success.
|
||||
while (NumConsecutiveStores >= 2) {
|
||||
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
|
||||
unsigned FirstStoreAS = FirstInChain->getAddressSpace();
|
||||
unsigned FirstStoreAlign = FirstInChain->getAlignment();
|
||||
unsigned NumStoresToMerge = 1;
|
||||
for (unsigned i = 0; i < NumConsecutiveStores; ++i) {
|
||||
// Find a legal type for the vector store.
|
||||
unsigned Elts = (i + 1) * NumMemElts;
|
||||
EVT Ty = EVT::getVectorVT(*DAG.getContext(), MemVT.getScalarType(), Elts);
|
||||
bool IsFast = false;
|
||||
|
||||
// Break early when size is too large to be legal.
|
||||
if (Ty.getSizeInBits() > MaximumLegalStoreInBits)
|
||||
break;
|
||||
|
||||
if (TLI.isTypeLegal(Ty) && TLI.canMergeStoresTo(FirstStoreAS, Ty, DAG) &&
|
||||
TLI.allowsMemoryAccess(Context, DL, Ty,
|
||||
*FirstInChain->getMemOperand(), &IsFast) &&
|
||||
IsFast)
|
||||
NumStoresToMerge = i + 1;
|
||||
}
|
||||
|
||||
// Check if we found a legal integer type creating a meaningful
|
||||
// merge.
|
||||
if (NumStoresToMerge < 2) {
|
||||
// We know that candidate stores are in order and of correct
|
||||
// shape. While there is no mergeable sequence from the
|
||||
// beginning one may start later in the sequence. The only
|
||||
// reason a merge of size N could have failed where another of
|
||||
// the same size would not have, is if the alignment has
|
||||
// improved. Drop as many candidates as we can here.
|
||||
unsigned NumSkip = 1;
|
||||
while ((NumSkip < NumConsecutiveStores) &&
|
||||
(StoreNodes[NumSkip].MemNode->getAlignment() <= FirstStoreAlign))
|
||||
NumSkip++;
|
||||
|
||||
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumSkip);
|
||||
NumConsecutiveStores -= NumSkip;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check that we can merge these candidates without causing a cycle.
|
||||
if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumStoresToMerge,
|
||||
RootNode)) {
|
||||
StoreNodes.erase(StoreNodes.begin(),
|
||||
StoreNodes.begin() + NumStoresToMerge);
|
||||
NumConsecutiveStores -= NumStoresToMerge;
|
||||
continue;
|
||||
}
|
||||
|
||||
MadeChange |= mergeStoresOfConstantsOrVecElts(
|
||||
StoreNodes, MemVT, NumStoresToMerge, false, true, false);
|
||||
|
||||
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumStoresToMerge);
|
||||
NumConsecutiveStores -= NumStoresToMerge;
|
||||
}
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
bool DAGCombiner::mergeConsecutiveStores(StoreSDNode *St) {
|
||||
if (OptLevel == CodeGenOpt::None || !EnableStoreMerging)
|
||||
return false;
|
||||
@ -16485,71 +16562,9 @@ bool DAGCombiner::mergeConsecutiveStores(StoreSDNode *St) {
|
||||
MemVT, AllowVectors, RootNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
// When extracting multiple vector elements, try to store them
|
||||
// in one vector store rather than a sequence of scalar stores.
|
||||
if (StoreSrc == StoreSource::Extract) {
|
||||
// Loop on Consecutive Stores on success.
|
||||
while (NumConsecutiveStores >= 2) {
|
||||
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
|
||||
unsigned FirstStoreAS = FirstInChain->getAddressSpace();
|
||||
unsigned FirstStoreAlign = FirstInChain->getAlignment();
|
||||
unsigned NumStoresToMerge = 1;
|
||||
for (unsigned i = 0; i < NumConsecutiveStores; ++i) {
|
||||
// Find a legal type for the vector store.
|
||||
unsigned Elts = (i + 1) * NumMemElts;
|
||||
EVT Ty =
|
||||
EVT::getVectorVT(*DAG.getContext(), MemVT.getScalarType(), Elts);
|
||||
bool IsFast = false;
|
||||
|
||||
// Break early when size is too large to be legal.
|
||||
if (Ty.getSizeInBits() > MaximumLegalStoreInBits)
|
||||
break;
|
||||
|
||||
if (TLI.isTypeLegal(Ty) &&
|
||||
TLI.canMergeStoresTo(FirstStoreAS, Ty, DAG) &&
|
||||
TLI.allowsMemoryAccess(Context, DL, Ty,
|
||||
*FirstInChain->getMemOperand(), &IsFast) &&
|
||||
IsFast)
|
||||
NumStoresToMerge = i + 1;
|
||||
}
|
||||
|
||||
// Check if we found a legal integer type creating a meaningful
|
||||
// merge.
|
||||
if (NumStoresToMerge < 2) {
|
||||
// We know that candidate stores are in order and of correct
|
||||
// shape. While there is no mergeable sequence from the
|
||||
// beginning one may start later in the sequence. The only
|
||||
// reason a merge of size N could have failed where another of
|
||||
// the same size would not have, is if the alignment has
|
||||
// improved. Drop as many candidates as we can here.
|
||||
unsigned NumSkip = 1;
|
||||
while (
|
||||
(NumSkip < NumConsecutiveStores) &&
|
||||
(StoreNodes[NumSkip].MemNode->getAlignment() <= FirstStoreAlign))
|
||||
NumSkip++;
|
||||
|
||||
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumSkip);
|
||||
NumConsecutiveStores -= NumSkip;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check that we can merge these candidates without causing a cycle.
|
||||
if (!checkMergeStoreCandidatesForDependencies(
|
||||
StoreNodes, NumStoresToMerge, RootNode)) {
|
||||
StoreNodes.erase(StoreNodes.begin(),
|
||||
StoreNodes.begin() + NumStoresToMerge);
|
||||
NumConsecutiveStores -= NumStoresToMerge;
|
||||
continue;
|
||||
}
|
||||
|
||||
MadeChange |= mergeStoresOfConstantsOrVecElts(
|
||||
StoreNodes, MemVT, NumStoresToMerge, false, true, false);
|
||||
|
||||
StoreNodes.erase(StoreNodes.begin(),
|
||||
StoreNodes.begin() + NumStoresToMerge);
|
||||
NumConsecutiveStores -= NumStoresToMerge;
|
||||
}
|
||||
MadeChange |= tryStoreMergeOfExtracts(StoreNodes, NumConsecutiveStores,
|
||||
MemVT, RootNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user