@@ -92,8 +92,6 @@ STATISTIC(NumInternalFunc, "Number of internal functions");
9292STATISTIC (NumColdCC, " Number of functions marked coldcc"  );
9393STATISTIC (NumIFuncsResolved, " Number of statically resolved IFuncs"  );
9494STATISTIC (NumIFuncsDeleted, " Number of IFuncs removed"  );
95- STATISTIC (NumGlobalArraysPadded,
96-           " Number of global arrays padded to alignment boundary"  );
9795
9896static  cl::opt<bool >
9997    OptimizeNonFMVCallers (" optimize-non-fmv-callers"  ,
@@ -2037,165 +2035,6 @@ OptimizeFunctions(Module &M,
20372035  return  Changed;
20382036}
20392037
2040- static  bool  callInstIsMemcpy (CallInst *CI) {
2041-   if  (!CI)
2042-     return  false ;
2043- 
2044-   Function *F = CI->getCalledFunction ();
2045-   if  (!F || !F->isIntrinsic () || F->getIntrinsicID () != Intrinsic::memcpy)
2046-     return  false ;
2047- 
2048-   return  true ;
2049- }
2050- 
2051- static  bool  destArrayCanBeWidened (CallInst *CI) {
2052-   auto  *IsVolatile = dyn_cast<ConstantInt>(CI->getArgOperand (3 ));
2053-   auto  *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand (0 ));
2054- 
2055-   if  (!Alloca || !IsVolatile || IsVolatile->isOne ())
2056-     return  false ;
2057- 
2058-   if  (!Alloca->isStaticAlloca ())
2059-     return  false ;
2060- 
2061-   if  (!Alloca->getAllocatedType ()->isArrayTy ())
2062-     return  false ;
2063- 
2064-   return  true ;
2065- }
2066- 
2067- static  GlobalVariable *widenGlobalVariable (GlobalVariable *OldVar,
2068-                                            unsigned  NumBytesToPad,
2069-                                            unsigned  NumBytesToCopy) {
2070-   if  (!OldVar->hasInitializer ())
2071-     return  nullptr ;
2072- 
2073-   ConstantDataArray *DataArray =
2074-       dyn_cast<ConstantDataArray>(OldVar->getInitializer ());
2075-   if  (!DataArray)
2076-     return  nullptr ;
2077- 
2078-   //  Update to be word aligned (memcpy(...,X,...))
2079-   //  create replacement with padded null bytes.
2080-   StringRef Data = DataArray->getRawDataValues ();
2081-   std::vector<uint8_t > StrData (Data.begin (), Data.end ());
2082-   for  (unsigned  int  p = 0 ; p < NumBytesToPad; p++)
2083-     StrData.push_back (' \0 '  );
2084-   auto  Arr = ArrayRef (StrData.data (), NumBytesToCopy + NumBytesToPad);
2085-   //  Create new padded version of global variable.
2086-   Constant *SourceReplace = ConstantDataArray::get (OldVar->getContext (), Arr);
2087-   GlobalVariable *NewGV = new  GlobalVariable (
2088-       *(OldVar->getParent ()), SourceReplace->getType (), true ,
2089-       OldVar->getLinkage (), SourceReplace, SourceReplace->getName ());
2090-   //  Copy any other attributes from original global variable
2091-   //  e.g. unamed_addr
2092-   NewGV->copyAttributesFrom (OldVar);
2093-   NewGV->takeName (OldVar);
2094-   return  NewGV;
2095- }
2096- 
2097- static  void  widenDestArray (CallInst *CI, const  unsigned  NumBytesToPad,
2098-                            const  unsigned  NumBytesToCopy,
2099-                            ConstantDataArray *SourceDataArray) {
2100- 
2101-   auto  *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand (0 ));
2102-   if  (Alloca) {
2103-     unsigned  ElementByteWidth = SourceDataArray->getElementByteSize ();
2104-     unsigned  int  TotalBytes = NumBytesToCopy + NumBytesToPad;
2105-     unsigned  NumElementsToCopy = divideCeil (TotalBytes, ElementByteWidth);
2106-     //  Update destination array to be word aligned (memcpy(X,...,...))
2107-     IRBuilder<> BuildAlloca (Alloca);
2108-     AllocaInst *NewAlloca = BuildAlloca.CreateAlloca (ArrayType::get (
2109-         Alloca->getAllocatedType ()->getArrayElementType (), NumElementsToCopy));
2110-     NewAlloca->takeName (Alloca);
2111-     NewAlloca->setAlignment (Alloca->getAlign ());
2112-     Alloca->replaceAllUsesWith (NewAlloca);
2113-     Alloca->eraseFromParent ();
2114-   }
2115- }
2116- 
2117- static  bool  tryWidenGlobalArrayAndDests (GlobalVariable *SourceVar,
2118-                                         const  unsigned  NumBytesToPad,
2119-                                         const  unsigned  NumBytesToCopy,
2120-                                         ConstantInt *BytesToCopyOp,
2121-                                         ConstantDataArray *SourceDataArray) {
2122-   auto  *NewSourceGV =
2123-       widenGlobalVariable (SourceVar, NumBytesToPad, NumBytesToCopy);
2124-   if  (!NewSourceGV)
2125-     return  false ;
2126- 
2127-   //  Update arguments of remaining uses  that
2128-   //  are memcpys.
2129-   for  (auto  *User : SourceVar->users ()) {
2130-     auto  *CI = dyn_cast<CallInst>(User);
2131-     if  (!callInstIsMemcpy (CI) || !destArrayCanBeWidened (CI))
2132-       continue ;
2133- 
2134-     if  (CI->getArgOperand (1 ) != SourceVar)
2135-       continue ;
2136- 
2137-     widenDestArray (CI, NumBytesToPad, NumBytesToCopy, SourceDataArray);
2138- 
2139-     CI->setArgOperand (2 , ConstantInt::get (BytesToCopyOp->getType (),
2140-                                           NumBytesToCopy + NumBytesToPad));
2141-   }
2142-   SourceVar->replaceAllUsesWith (NewSourceGV);
2143- 
2144-   NumGlobalArraysPadded++;
2145-   return  true ;
2146- }
2147- 
2148- static  bool  tryWidenGlobalArraysUsedByMemcpy (
2149-     GlobalVariable *GV,
2150-     function_ref<TargetTransformInfo &(Function &)> GetTTI) {
2151- 
2152-   if  (!GV->hasInitializer () || !GV->isConstant () || !GV->hasLocalLinkage () ||
2153-       !GV->hasGlobalUnnamedAddr ())
2154-     return  false ;
2155- 
2156-   for  (auto  *User : GV->users ()) {
2157-     CallInst *CI = dyn_cast<CallInst>(User);
2158-     if  (!callInstIsMemcpy (CI) || !destArrayCanBeWidened (CI))
2159-       continue ;
2160- 
2161-     auto  *BytesToCopyOp = dyn_cast<ConstantInt>(CI->getArgOperand (2 ));
2162-     if  (!BytesToCopyOp)
2163-       continue ;
2164- 
2165-     ConstantDataArray *SourceDataArray =
2166-         dyn_cast<ConstantDataArray>(GV->getInitializer ());
2167-     if  (!SourceDataArray)
2168-       continue ;
2169- 
2170-     unsigned  NumBytesToCopy = BytesToCopyOp->getZExtValue ();
2171- 
2172-     auto  *Alloca = cast<AllocaInst>(CI->getArgOperand (0 ));
2173-     uint64_t  DZSize = Alloca->getAllocatedType ()->getArrayNumElements ();
2174-     uint64_t  SZSize = SourceDataArray->getType ()->getNumElements ();
2175-     unsigned  ElementByteWidth = SourceDataArray->getElementByteSize ();
2176-     //  Calculate the number of elements to copy while avoiding floored
2177-     //  division of integers returning wrong values i.e. copying one byte
2178-     //  from an array of i16 would yield 0 elements to copy as supposed to 1.
2179-     unsigned  NumElementsToCopy = divideCeil (NumBytesToCopy, ElementByteWidth);
2180- 
2181-     //  For safety purposes lets add a constraint and only pad when
2182-     //  NumElementsToCopy == destination array size ==
2183-     //  source which is a constant
2184-     if  (NumElementsToCopy != DZSize || DZSize != SZSize)
2185-       continue ;
2186- 
2187-     unsigned  NumBytesToPad =
2188-         GetTTI (*CI->getFunction ())
2189-             .getNumBytesToPadGlobalArray (NumBytesToCopy,
2190-                                          SourceDataArray->getType ());
2191-     if  (NumBytesToPad) {
2192-       return  tryWidenGlobalArrayAndDests (GV, NumBytesToPad, NumBytesToCopy,
2193-                                          BytesToCopyOp, SourceDataArray);
2194-     }
2195-   }
2196-   return  false ;
2197- }
2198- 
21992038static  bool 
22002039OptimizeGlobalVars (Module &M,
22012040                   function_ref<TargetTransformInfo &(Function &)> GetTTI,
@@ -2225,10 +2064,6 @@ OptimizeGlobalVars(Module &M,
22252064      continue ;
22262065    }
22272066
2228-     //  For global variable arrays called in a memcpy
2229-     //  we try to pad to nearest valid alignment boundary
2230-     Changed |= tryWidenGlobalArraysUsedByMemcpy (&GV, GetTTI);
2231- 
22322067    Changed |= processGlobal (GV, GetTTI, GetTLI, LookupDomTree);
22332068  }
22342069  return  Changed;
0 commit comments