[llvm] [llvm][ARM]Add widen global arrays pass (PR #107120)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 9 12:48:43 PDT 2024
================
@@ -2029,6 +2031,172 @@ 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 *GV = dyn_cast<GlobalVariable>(CI->getArgOperand(0));
+ auto *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand(0));
+ auto *IsVolatile = dyn_cast<ConstantInt>(CI->getArgOperand(3));
+
+ if (!GV || !GV->hasInitializer())
+ return false;
+
+ if (!Alloca || !IsVolatile || IsVolatile->isOne())
+ return false;
+
+ if (!Alloca->isStaticAlloca())
+ return false;
+
+ return true;
+}
+
+static GlobalVariable *widenGlobalVariable(GlobalVariable *OldVar, Function *F,
+ 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(F->getContext(), Arr);
+ GlobalVariable *NewGV = new GlobalVariable(
+ *(F->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) {
+
+ // Dest array can be global or local
+ auto *DestGV = dyn_cast<GlobalVariable>(CI->getArgOperand(0));
+ auto *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand(0));
+ if (DestGV) {
+ auto *F = CI->getCalledFunction();
+ auto *NewDestGV =
+ widenGlobalVariable(DestGV, F, NumBytesToPad, NumBytesToCopy);
+ DestGV->replaceAllUsesWith(NewDestGV);
+ } else 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(Function *F, GlobalVariable *SourceVar,
+ const unsigned NumBytesToPad,
+ const unsigned NumBytesToCopy,
+ ConstantInt *BytesToCopyOp,
+ ConstantDataArray *SourceDataArray) {
+ if (!SourceVar->hasInitializer() || !SourceVar->isConstant() ||
+ !SourceVar->hasLocalLinkage() || !SourceVar->hasGlobalUnnamedAddr())
+ return false;
+
+ auto *NewSourceGV =
+ widenGlobalVariable(SourceVar, F, 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))
----------------
davemgreen wrote:
Check that CI->getArgOperand(1) == GV here too? It should help rule out some cases we don't want to transform.
https://github.com/llvm/llvm-project/pull/107120
More information about the llvm-commits
mailing list