comparison gen/passes/SimplifyDRuntimeCalls.cpp @ 1329:e5b57fd8307c

Turn new _d_array_slice_copy runtime call into memcpy when the slice lengths are equal and alias analysis says it's safe.
author Frits van Bommel <fvbommel wxs.nl>
date Sun, 10 May 2009 04:18:14 +0200
parents c32e27f9a61d
children f86fd3b77285
comparison
equal deleted inserted replaced
1328:c78fd2d30da1 1329:e5b57fd8307c
17 #define DEBUG_TYPE "simplify-drtcalls" 17 #define DEBUG_TYPE "simplify-drtcalls"
18 18
19 #include "Passes.h" 19 #include "Passes.h"
20 20
21 #include "llvm/Pass.h" 21 #include "llvm/Pass.h"
22 #include "llvm/Intrinsics.h"
22 #include "llvm/Support/IRBuilder.h" 23 #include "llvm/Support/IRBuilder.h"
24 #include "llvm/Analysis/AliasAnalysis.h"
23 #include "llvm/Analysis/ValueTracking.h" 25 #include "llvm/Analysis/ValueTracking.h"
24 #include "llvm/Target/TargetData.h" 26 #include "llvm/Target/TargetData.h"
25 #include "llvm/ADT/StringMap.h" 27 #include "llvm/ADT/StringMap.h"
26 #include "llvm/ADT/Statistic.h" 28 #include "llvm/ADT/Statistic.h"
27 #include "llvm/Support/Compiler.h" 29 #include "llvm/Support/Compiler.h"
40 namespace { 42 namespace {
41 class VISIBILITY_HIDDEN LibCallOptimization { 43 class VISIBILITY_HIDDEN LibCallOptimization {
42 protected: 44 protected:
43 Function *Caller; 45 Function *Caller;
44 const TargetData *TD; 46 const TargetData *TD;
47 AliasAnalysis *AA;
48
49 /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*.
50 Value *CastToCStr(Value *V, IRBuilder<> &B);
51
52 /// EmitMemCpy - Emit a call to the memcpy function to the builder. This
53 /// always expects that the size has type 'intptr_t' and Dst/Src are pointers.
54 Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len,
55 unsigned Align, IRBuilder<> &B);
45 public: 56 public:
46 LibCallOptimization() { } 57 LibCallOptimization() { }
47 virtual ~LibCallOptimization() {} 58 virtual ~LibCallOptimization() {}
48 59
49 /// CallOptimizer - This pure virtual method is implemented by base classes to 60 /// CallOptimizer - This pure virtual method is implemented by base classes to
51 /// performed. If it returns CI, then it transformed the call and CI is to be 62 /// performed. If it returns CI, then it transformed the call and CI is to be
52 /// deleted. If it returns something else, replace CI with the new value and 63 /// deleted. If it returns something else, replace CI with the new value and
53 /// delete CI. 64 /// delete CI.
54 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)=0; 65 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)=0;
55 66
56 Value *OptimizeCall(CallInst *CI, const TargetData &TD, IRBuilder<> &B) { 67 Value *OptimizeCall(CallInst *CI, const TargetData &TD,
68 AliasAnalysis& AA, IRBuilder<> &B) {
57 Caller = CI->getParent()->getParent(); 69 Caller = CI->getParent()->getParent();
58 this->TD = &TD; 70 this->TD = &TD;
71 this->AA = &AA;
59 return CallOptimizer(CI->getCalledFunction(), CI, B); 72 return CallOptimizer(CI->getCalledFunction(), CI, B);
60 } 73 }
61 }; 74 };
62 } // End anonymous namespace. 75 } // End anonymous namespace.
63 76
77 /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*.
78 Value *LibCallOptimization::CastToCStr(Value *V, IRBuilder<> &B) {
79 return B.CreateBitCast(V, PointerType::getUnqual(Type::Int8Ty), "cstr");
80 }
81
82 /// EmitMemCpy - Emit a call to the memcpy function to the builder. This always
83 /// expects that the size has type 'intptr_t' and Dst/Src are pointers.
84 Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len,
85 unsigned Align, IRBuilder<> &B) {
86 Module *M = Caller->getParent();
87 Intrinsic::ID IID = Intrinsic::memcpy;
88 const Type *Tys[1];
89 Tys[0] = Len->getType();
90 Value *MemCpy = Intrinsic::getDeclaration(M, IID, Tys, 1);
91 return B.CreateCall4(MemCpy, CastToCStr(Dst, B), CastToCStr(Src, B), Len,
92 ConstantInt::get(Type::Int32Ty, Align));
93 }
64 94
65 //===----------------------------------------------------------------------===// 95 //===----------------------------------------------------------------------===//
66 // Miscellaneous LibCall Optimizations 96 // Miscellaneous LibCall Optimizations
67 //===----------------------------------------------------------------------===// 97 //===----------------------------------------------------------------------===//
68 98
158 return CI; 188 return CI;
159 return 0; 189 return 0;
160 } 190 }
161 }; 191 };
162 192
193 /// ArraySliceCopyOpt - Turn slice copies into llvm.memcpy when safe
194 struct VISIBILITY_HIDDEN ArraySliceCopyOpt : public LibCallOptimization {
195 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
196 // Verify we have a reasonable prototype for _d_array_slice_copy
197 const FunctionType *FT = Callee->getFunctionType();
198 const Type* VoidPtrTy = PointerType::getUnqual(Type::Int8Ty);
199 if (Callee->arg_size() != 4 || FT->getReturnType() != Type::VoidTy ||
200 FT->getParamType(0) != VoidPtrTy ||
201 !isa<IntegerType>(FT->getParamType(1)) ||
202 FT->getParamType(2) != VoidPtrTy ||
203 FT->getParamType(3) != FT->getParamType(1))
204 return 0;
205
206 Value* Size = CI->getOperand(2);
207
208 // Check the lengths match
209 if (CI->getOperand(4) != Size)
210 return 0;
211
212 // Assume unknown size unless we have constant size (that fits in an uint)
213 unsigned Sz = ~0U;
214 if (ConstantInt* Int = dyn_cast<ConstantInt>(Size))
215 if (Int->getValue().isIntN(32))
216 Sz = Int->getValue().getZExtValue();
217
218 // Check if the pointers may alias
219 if (AA->alias(CI->getOperand(1), Sz, CI->getOperand(3), Sz))
220 return 0;
221
222 // Equal length and the pointers definitely don't alias, so it's safe to
223 // replace the call with memcpy
224 return EmitMemCpy(CI->getOperand(1), CI->getOperand(3), Size, 0, B);
225 }
226 };
227
163 // TODO: More optimizations! :) 228 // TODO: More optimizations! :)
164 229
165 } // end anonymous namespace. 230 } // end anonymous namespace.
166 231
167 //===----------------------------------------------------------------------===// 232 //===----------------------------------------------------------------------===//
175 StringMap<LibCallOptimization*> Optimizations; 240 StringMap<LibCallOptimization*> Optimizations;
176 241
177 // Array operations 242 // Array operations
178 ArraySetLengthOpt ArraySetLength; 243 ArraySetLengthOpt ArraySetLength;
179 ArrayCastLenOpt ArrayCastLen; 244 ArrayCastLenOpt ArrayCastLen;
245 ArraySliceCopyOpt ArraySliceCopy;
180 246
181 // GC allocations 247 // GC allocations
182 DeleteUnusedOpt DeleteUnused; 248 DeleteUnusedOpt DeleteUnused;
183 249
184 public: 250 public:
186 SimplifyDRuntimeCalls() : FunctionPass(&ID) {} 252 SimplifyDRuntimeCalls() : FunctionPass(&ID) {}
187 253
188 void InitOptimizations(); 254 void InitOptimizations();
189 bool runOnFunction(Function &F); 255 bool runOnFunction(Function &F);
190 256
191 bool runOnce(Function &F, const TargetData& TD); 257 bool runOnce(Function &F, const TargetData& TD, AliasAnalysis& AA);
192 258
193 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 259 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
194 AU.addRequired<TargetData>(); 260 AU.addRequired<TargetData>();
261 AU.addRequired<AliasAnalysis>();
195 } 262 }
196 }; 263 };
197 char SimplifyDRuntimeCalls::ID = 0; 264 char SimplifyDRuntimeCalls::ID = 0;
198 } // end anonymous namespace. 265 } // end anonymous namespace.
199 266
210 void SimplifyDRuntimeCalls::InitOptimizations() { 277 void SimplifyDRuntimeCalls::InitOptimizations() {
211 // Some array-related optimizations 278 // Some array-related optimizations
212 Optimizations["_d_arraysetlengthT"] = &ArraySetLength; 279 Optimizations["_d_arraysetlengthT"] = &ArraySetLength;
213 Optimizations["_d_arraysetlengthiT"] = &ArraySetLength; 280 Optimizations["_d_arraysetlengthiT"] = &ArraySetLength;
214 Optimizations["_d_array_cast_len"] = &ArrayCastLen; 281 Optimizations["_d_array_cast_len"] = &ArrayCastLen;
282 Optimizations["_d_array_slice_copy"] = &ArraySliceCopy;
215 283
216 /* Delete calls to runtime functions which aren't needed if their result is 284 /* Delete calls to runtime functions which aren't needed if their result is
217 * unused. That comes down to functions that don't do anything but 285 * unused. That comes down to functions that don't do anything but
218 * GC-allocate and initialize some memory. 286 * GC-allocate and initialize some memory.
219 * We don't need to do this for functions which are marked 'readnone' or 287 * We don't need to do this for functions which are marked 'readnone' or
238 bool SimplifyDRuntimeCalls::runOnFunction(Function &F) { 306 bool SimplifyDRuntimeCalls::runOnFunction(Function &F) {
239 if (Optimizations.empty()) 307 if (Optimizations.empty())
240 InitOptimizations(); 308 InitOptimizations();
241 309
242 const TargetData &TD = getAnalysis<TargetData>(); 310 const TargetData &TD = getAnalysis<TargetData>();
311 AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
243 312
244 // Iterate to catch opportunities opened up by other optimizations, 313 // Iterate to catch opportunities opened up by other optimizations,
245 // such as calls that are only used as arguments to unused calls: 314 // such as calls that are only used as arguments to unused calls:
246 // When the second call gets deleted the first call will become unused, but 315 // When the second call gets deleted the first call will become unused, but
247 // without iteration we wouldn't notice if we inspected the first call 316 // without iteration we wouldn't notice if we inspected the first call
248 // before the second one. 317 // before the second one.
249 bool EverChanged = false; 318 bool EverChanged = false;
250 bool Changed; 319 bool Changed;
251 do { 320 do {
252 Changed = runOnce(F, TD); 321 Changed = runOnce(F, TD, AA);
253 EverChanged |= Changed; 322 EverChanged |= Changed;
254 } while (Changed); 323 } while (Changed);
255 324
256 return EverChanged; 325 return EverChanged;
257 } 326 }
258 327
259 bool SimplifyDRuntimeCalls::runOnce(Function &F, const TargetData& TD) { 328 bool SimplifyDRuntimeCalls::runOnce(Function &F, const TargetData& TD, AliasAnalysis& AA) {
260 IRBuilder<> Builder; 329 IRBuilder<> Builder;
261 330
262 bool Changed = false; 331 bool Changed = false;
263 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { 332 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
264 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { 333 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
270 Function *Callee = CI->getCalledFunction(); 339 Function *Callee = CI->getCalledFunction();
271 if (Callee == 0 || !Callee->isDeclaration() || 340 if (Callee == 0 || !Callee->isDeclaration() ||
272 !(Callee->hasExternalLinkage() || Callee->hasDLLImportLinkage())) 341 !(Callee->hasExternalLinkage() || Callee->hasDLLImportLinkage()))
273 continue; 342 continue;
274 343
275 DEBUG(DOUT << "SimplifyDRuntimeCalls inspecting: " << *CI);
276
277 // Ignore unknown calls. 344 // Ignore unknown calls.
278 const char *CalleeName = Callee->getNameStart(); 345 const char *CalleeName = Callee->getNameStart();
279 StringMap<LibCallOptimization*>::iterator OMI = 346 StringMap<LibCallOptimization*>::iterator OMI =
280 Optimizations.find(CalleeName, CalleeName+Callee->getNameLen()); 347 Optimizations.find(CalleeName, CalleeName+Callee->getNameLen());
281 if (OMI == Optimizations.end()) continue; 348 if (OMI == Optimizations.end()) continue;
282 349
350 DEBUG(DOUT << "SimplifyDRuntimeCalls inspecting: " << *CI);
351
283 // Set the builder to the instruction after the call. 352 // Set the builder to the instruction after the call.
284 Builder.SetInsertPoint(BB, I); 353 Builder.SetInsertPoint(BB, I);
285 354
286 // Try to optimize this call. 355 // Try to optimize this call.
287 Value *Result = OMI->second->OptimizeCall(CI, TD, Builder); 356 Value *Result = OMI->second->OptimizeCall(CI, TD, AA, Builder);
288 if (Result == 0) continue; 357 if (Result == 0) continue;
289 358
290 DEBUG(DOUT << "SimplifyDRuntimeCalls simplified: " << *CI; 359 DEBUG(DOUT << "SimplifyDRuntimeCalls simplified: " << *CI;
291 DOUT << " into: " << *Result << "\n"); 360 DOUT << " into: " << *Result << "\n");
292 361
294 Changed = true; 363 Changed = true;
295 364
296 if (Result == CI) { 365 if (Result == CI) {
297 assert(CI->use_empty()); 366 assert(CI->use_empty());
298 ++NumDeleted; 367 ++NumDeleted;
368 AA.deleteValue(CI);
299 } else { 369 } else {
300 ++NumSimplified; 370 ++NumSimplified;
371 AA.replaceWithNewValue(CI, Result);
301 372
302 if (!CI->use_empty()) 373 if (!CI->use_empty())
303 CI->replaceAllUsesWith(Result); 374 CI->replaceAllUsesWith(Result);
304 375
305 if (!Result->hasName()) 376 if (!Result->hasName())