@@ -2043,9 +2043,13 @@ static bool callInstIsMemcpy(CallInst *CI) {
2043
2043
}
2044
2044
2045
2045
static bool destArrayCanBeWidened (CallInst *CI) {
2046
+ auto *GV = dyn_cast<GlobalVariable>(CI->getArgOperand (0 ));
2046
2047
auto *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand (0 ));
2047
2048
auto *IsVolatile = dyn_cast<ConstantInt>(CI->getArgOperand (3 ));
2048
2049
2050
+ if (!GV || !GV->hasInitializer ())
2051
+ return false ;
2052
+
2049
2053
if (!Alloca || !IsVolatile || IsVolatile->isOne ())
2050
2054
return false ;
2051
2055
@@ -2055,21 +2059,61 @@ static bool destArrayCanBeWidened(CallInst *CI) {
2055
2059
return true ;
2056
2060
}
2057
2061
2062
+ static GlobalVariable *widenGlobalVariable (GlobalVariable *OldVar, Function *F,
2063
+ unsigned NumBytesToPad,
2064
+ unsigned NumBytesToCopy) {
2065
+ if (!OldVar->hasInitializer ())
2066
+ return nullptr ;
2067
+
2068
+ ConstantDataArray *DataArray =
2069
+ dyn_cast<ConstantDataArray>(OldVar->getInitializer ());
2070
+ if (!DataArray)
2071
+ return nullptr ;
2072
+
2073
+ // Update to be word aligned (memcpy(...,X,...))
2074
+ // create replacement with padded null bytes.
2075
+ StringRef Data = DataArray->getRawDataValues ();
2076
+ std::vector<uint8_t > StrData (Data.begin (), Data.end ());
2077
+ for (unsigned int p = 0 ; p < NumBytesToPad; p++)
2078
+ StrData.push_back (' \0 ' );
2079
+ auto Arr = ArrayRef (StrData.data (), NumBytesToCopy + NumBytesToPad);
2080
+ // Create new padded version of global variable.
2081
+ Constant *SourceReplace = ConstantDataArray::get (F->getContext (), Arr);
2082
+ GlobalVariable *NewGV = new GlobalVariable (
2083
+ *(F->getParent ()), SourceReplace->getType (), true , OldVar->getLinkage (),
2084
+ SourceReplace, SourceReplace->getName ());
2085
+ // Copy any other attributes from original global variable
2086
+ // e.g. unamed_addr
2087
+ NewGV->copyAttributesFrom (OldVar);
2088
+ NewGV->takeName (OldVar);
2089
+ return NewGV;
2090
+ }
2091
+
2058
2092
static void widenDestArray (CallInst *CI, const unsigned NumBytesToPad,
2059
2093
const unsigned NumBytesToCopy,
2060
2094
ConstantDataArray *SourceDataArray) {
2061
- unsigned ElementByteWidth = SourceDataArray->getElementByteSize ();
2062
- unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;
2063
- unsigned NumElementsToCopy = divideCeil (TotalBytes, ElementByteWidth);
2064
- // Update destination array to be word aligned (memcpy(X,...,...))
2095
+
2096
+ // Dest array can be global or local
2097
+ auto *DestGV = dyn_cast<GlobalVariable>(CI->getArgOperand (0 ));
2065
2098
auto *Alloca = dyn_cast<AllocaInst>(CI->getArgOperand (0 ));
2066
- IRBuilder<> BuildAlloca (Alloca);
2067
- AllocaInst *NewAlloca = BuildAlloca.CreateAlloca (ArrayType::get (
2068
- Alloca->getAllocatedType ()->getArrayElementType (), NumElementsToCopy));
2069
- NewAlloca->takeName (Alloca);
2070
- NewAlloca->setAlignment (Alloca->getAlign ());
2071
- Alloca->replaceAllUsesWith (NewAlloca);
2072
- Alloca->eraseFromParent ();
2099
+ if (DestGV) {
2100
+ auto *F = CI->getCalledFunction ();
2101
+ auto *NewDestGV =
2102
+ widenGlobalVariable (DestGV, F, NumBytesToPad, NumBytesToCopy);
2103
+ DestGV->replaceAllUsesWith (NewDestGV);
2104
+ } else if (Alloca) {
2105
+ unsigned ElementByteWidth = SourceDataArray->getElementByteSize ();
2106
+ unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;
2107
+ unsigned NumElementsToCopy = divideCeil (TotalBytes, ElementByteWidth);
2108
+ // Update destination array to be word aligned (memcpy(X,...,...))
2109
+ IRBuilder<> BuildAlloca (Alloca);
2110
+ AllocaInst *NewAlloca = BuildAlloca.CreateAlloca (ArrayType::get (
2111
+ Alloca->getAllocatedType ()->getArrayElementType (), NumElementsToCopy));
2112
+ NewAlloca->takeName (Alloca);
2113
+ NewAlloca->setAlignment (Alloca->getAlign ());
2114
+ Alloca->replaceAllUsesWith (NewAlloca);
2115
+ Alloca->eraseFromParent ();
2116
+ }
2073
2117
}
2074
2118
2075
2119
static bool tryWidenGlobalArrayAndDests (Function *F, GlobalVariable *SourceVar,
@@ -2081,25 +2125,10 @@ static bool tryWidenGlobalArrayAndDests(Function *F, GlobalVariable *SourceVar,
2081
2125
!SourceVar->hasLocalLinkage () || !SourceVar->hasGlobalUnnamedAddr ())
2082
2126
return false ;
2083
2127
2084
- // Update source to be word aligned (memcpy(...,X,...))
2085
- // create replacement with padded null bytes.
2086
- StringRef Data = SourceDataArray->getRawDataValues ();
2087
- std::vector<uint8_t > StrData (Data.begin (), Data.end ());
2088
- for (unsigned int p = 0 ; p < NumBytesToPad; p++)
2089
- StrData.push_back (' \0 ' );
2090
- auto Arr = ArrayRef (StrData.data (), NumBytesToCopy + NumBytesToPad);
2091
-
2092
- // Create new padded version of global variable.
2093
- Constant *SourceReplace = ConstantDataArray::get (F->getContext (), Arr);
2094
- GlobalVariable *NewGV = new GlobalVariable (
2095
- *(F->getParent ()), SourceReplace->getType (), true ,
2096
- SourceVar->getLinkage (), SourceReplace, SourceReplace->getName ());
2097
-
2098
- // Copy any other attributes from original global variable
2099
- // e.g. unamed_addr
2100
- NewGV->copyAttributesFrom (SourceVar);
2101
- NewGV->takeName (SourceVar);
2102
-
2128
+ auto *NewSourceGV =
2129
+ widenGlobalVariable (SourceVar, F, NumBytesToPad, NumBytesToCopy);
2130
+ if (!NewSourceGV)
2131
+ return false ;
2103
2132
// Update arguments of remaining uses that
2104
2133
// are memcpys.
2105
2134
for (auto *User : SourceVar->users ()) {
@@ -2112,7 +2141,7 @@ static bool tryWidenGlobalArrayAndDests(Function *F, GlobalVariable *SourceVar,
2112
2141
CI->setArgOperand (2 , ConstantInt::get (BytesToCopyOp->getType (),
2113
2142
NumBytesToCopy + NumBytesToPad));
2114
2143
}
2115
- SourceVar->replaceAllUsesWith (NewGV );
2144
+ SourceVar->replaceAllUsesWith (NewSourceGV );
2116
2145
2117
2146
NumGlobalArraysPadded++;
2118
2147
return true ;
0 commit comments