Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 0 additions & 165 deletions llvm/lib/Transforms/IPO/GlobalOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ STATISTIC(NumInternalFunc, "Number of internal functions");
STATISTIC(NumColdCC, "Number of functions marked coldcc");
STATISTIC(NumIFuncsResolved, "Number of statically resolved IFuncs");
STATISTIC(NumIFuncsDeleted, "Number of IFuncs removed");
STATISTIC(NumGlobalArraysPadded,
"Number of global arrays padded to alignment boundary");

static cl::opt<bool>
OptimizeNonFMVCallers("optimize-non-fmv-callers",
Expand Down Expand Up @@ -2037,165 +2035,6 @@ OptimizeFunctions(Module &M,
return Changed;
}

static bool callInstIsMemcpy(CallInst *CI) {
if (!CI)
return false;

Function *F = CI->getCalledFunction();
if (!F || !F->isIntrinsic() || F->getIntrinsicID() != Intrinsic::memcpy)
return false;

return true;
}

static bool destArrayCanBeWidened(CallInst *CI) {
auto *IsVolatile = dyn_cast<ConstantInt>(CI->getArgOperand(3));
auto *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand(0));

if (!Alloca || !IsVolatile || IsVolatile->isOne())
return false;

if (!Alloca->isStaticAlloca())
return false;

if (!Alloca->getAllocatedType()->isArrayTy())
return false;

return true;
}

static GlobalVariable *widenGlobalVariable(GlobalVariable *OldVar,
unsigned NumBytesToPad,
unsigned NumBytesToCopy) {
if (!OldVar->hasInitializer())
return nullptr;

ConstantDataArray *DataArray =
dyn_cast<ConstantDataArray>(OldVar->getInitializer());
if (!DataArray)
return nullptr;

// Update to be word aligned (memcpy(...,X,...))
// create replacement with padded null bytes.
StringRef Data = DataArray->getRawDataValues();
std::vector<uint8_t> StrData(Data.begin(), Data.end());
for (unsigned int p = 0; p < NumBytesToPad; p++)
StrData.push_back('\0');
auto Arr = ArrayRef(StrData.data(), NumBytesToCopy + NumBytesToPad);
// Create new padded version of global variable.
Constant *SourceReplace = ConstantDataArray::get(OldVar->getContext(), Arr);
GlobalVariable *NewGV = new GlobalVariable(
*(OldVar->getParent()), SourceReplace->getType(), true,
OldVar->getLinkage(), SourceReplace, SourceReplace->getName());
// Copy any other attributes from original global variable
// e.g. unamed_addr
NewGV->copyAttributesFrom(OldVar);
NewGV->takeName(OldVar);
return NewGV;
}

static void widenDestArray(CallInst *CI, const unsigned NumBytesToPad,
const unsigned NumBytesToCopy,
ConstantDataArray *SourceDataArray) {

auto *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand(0));
if (Alloca) {
unsigned ElementByteWidth = SourceDataArray->getElementByteSize();
unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;
unsigned NumElementsToCopy = divideCeil(TotalBytes, ElementByteWidth);
// Update destination array to be word aligned (memcpy(X,...,...))
IRBuilder<> BuildAlloca(Alloca);
AllocaInst *NewAlloca = BuildAlloca.CreateAlloca(ArrayType::get(
Alloca->getAllocatedType()->getArrayElementType(), NumElementsToCopy));
NewAlloca->takeName(Alloca);
NewAlloca->setAlignment(Alloca->getAlign());
Alloca->replaceAllUsesWith(NewAlloca);
Alloca->eraseFromParent();
}
}

static bool tryWidenGlobalArrayAndDests(GlobalVariable *SourceVar,
const unsigned NumBytesToPad,
const unsigned NumBytesToCopy,
ConstantInt *BytesToCopyOp,
ConstantDataArray *SourceDataArray) {
auto *NewSourceGV =
widenGlobalVariable(SourceVar, NumBytesToPad, NumBytesToCopy);
if (!NewSourceGV)
return false;

// Update arguments of remaining uses that
// are memcpys.
for (auto *User : SourceVar->users()) {
auto *CI = dyn_cast<CallInst>(User);
if (!callInstIsMemcpy(CI) || !destArrayCanBeWidened(CI))
continue;

if (CI->getArgOperand(1) != SourceVar)
continue;

widenDestArray(CI, NumBytesToPad, NumBytesToCopy, SourceDataArray);

CI->setArgOperand(2, ConstantInt::get(BytesToCopyOp->getType(),
NumBytesToCopy + NumBytesToPad));
}
SourceVar->replaceAllUsesWith(NewSourceGV);

NumGlobalArraysPadded++;
return true;
}

static bool tryWidenGlobalArraysUsedByMemcpy(
GlobalVariable *GV,
function_ref<TargetTransformInfo &(Function &)> GetTTI) {

if (!GV->hasInitializer() || !GV->isConstant() || !GV->hasLocalLinkage() ||
!GV->hasGlobalUnnamedAddr())
return false;

for (auto *User : GV->users()) {
CallInst *CI = dyn_cast<CallInst>(User);
if (!callInstIsMemcpy(CI) || !destArrayCanBeWidened(CI))
continue;

auto *BytesToCopyOp = dyn_cast<ConstantInt>(CI->getArgOperand(2));
if (!BytesToCopyOp)
continue;

ConstantDataArray *SourceDataArray =
dyn_cast<ConstantDataArray>(GV->getInitializer());
if (!SourceDataArray)
continue;

unsigned NumBytesToCopy = BytesToCopyOp->getZExtValue();

auto *Alloca = cast<AllocaInst>(CI->getArgOperand(0));
uint64_t DZSize = Alloca->getAllocatedType()->getArrayNumElements();
uint64_t SZSize = SourceDataArray->getType()->getNumElements();
unsigned ElementByteWidth = SourceDataArray->getElementByteSize();
// Calculate the number of elements to copy while avoiding floored
// division of integers returning wrong values i.e. copying one byte
// from an array of i16 would yield 0 elements to copy as supposed to 1.
unsigned NumElementsToCopy = divideCeil(NumBytesToCopy, ElementByteWidth);

// For safety purposes lets add a constraint and only pad when
// NumElementsToCopy == destination array size ==
// source which is a constant
if (NumElementsToCopy != DZSize || DZSize != SZSize)
continue;

unsigned NumBytesToPad =
GetTTI(*CI->getFunction())
.getNumBytesToPadGlobalArray(NumBytesToCopy,
SourceDataArray->getType());
if (NumBytesToPad) {
return tryWidenGlobalArrayAndDests(GV, NumBytesToPad, NumBytesToCopy,
BytesToCopyOp, SourceDataArray);
}
}
return false;
}

static bool
OptimizeGlobalVars(Module &M,
function_ref<TargetTransformInfo &(Function &)> GetTTI,
Expand Down Expand Up @@ -2225,10 +2064,6 @@ OptimizeGlobalVars(Module &M,
continue;
}

// For global variable arrays called in a memcpy
// we try to pad to nearest valid alignment boundary
Changed |= tryWidenGlobalArraysUsedByMemcpy(&GV, GetTTI);

Changed |= processGlobal(GV, GetTTI, GetTLI, LookupDomTree);
}
return Changed;
Expand Down
39 changes: 0 additions & 39 deletions llvm/test/Transforms/GlobalOpt/ARM/arm-widen-dest-non-array.ll

This file was deleted.

28 changes: 0 additions & 28 deletions llvm/test/Transforms/GlobalOpt/ARM/arm-widen-global-dest.ll

This file was deleted.

22 changes: 0 additions & 22 deletions llvm/test/Transforms/GlobalOpt/ARM/arm-widen-non-byte-array.ll

This file was deleted.

21 changes: 0 additions & 21 deletions llvm/test/Transforms/GlobalOpt/ARM/arm-widen-non-const-global.ll

This file was deleted.

33 changes: 0 additions & 33 deletions llvm/test/Transforms/GlobalOpt/ARM/arm-widen-string-multi-use.ll

This file was deleted.

21 changes: 0 additions & 21 deletions llvm/test/Transforms/GlobalOpt/ARM/arm-widen-strings-1.ll

This file was deleted.

21 changes: 0 additions & 21 deletions llvm/test/Transforms/GlobalOpt/ARM/arm-widen-strings-2.ll

This file was deleted.

Loading
Loading