Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1065)

Side by Side Diff: lib/Transforms/NaCl/SimplifyStructRegSignatures.cpp

Issue 992493002: Lower signatures exposing struct registers to byval struct pointers (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: determinism in output, more tests Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===- SimplifyStructRegSignatures.cpp - Change struct regs to struct ----===//
2 // pointers
JF 2015/03/12 18:36:18 That's a bit weird formatting :-) It would fit if
Mircea Trofin 2015/03/13 22:04:52 Done.
3 //
4 // The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 // This pass replaces function signatures exposing struct registers
12 // to byval pointer-based signatures.
13 //
14 // There are 2 types of signatures that are thus changed:
15 //
16 // @foo(%some_struct %val) -> @foo(%some_struct* byval %val)
17 // and
18 // %someStruct @bar(<other_args>) -> void @bar(%someStruct* sret, <other_args>)
19 //
20 // Such function types may appear in other type declarations, for example:
21 //
22 // %a_struct = type { void (%some_struct)*, i32 }
23 //
24 // We map such types to corresponding types, mapping the function types
25 // appropriately:
26 //
27 // %a_struct.0 = type { void (%some_struct*)*, i32 }
28 //===----------------------------------------------------------------------===//
29
30 #include <cassert>
31 #include <cstddef>
32
33 #include "llvm/ADT/ArrayRef.h"
34 #include "llvm/ADT/DenseSet.h"
35 #include "llvm/ADT/ilist.h"
36 #include "llvm/ADT/SetVector.h"
37 #include "llvm/ADT/SmallVector.h"
38 #include "llvm/ADT/Twine.h"
39 #include "llvm/IR/Argument.h"
40 #include "llvm/IR/Attributes.h"
41 #include "llvm/IR/BasicBlock.h"
42 #include "llvm/IR/DerivedTypes.h"
43 #include "llvm/IR/Function.h"
44 #include "llvm/IR/GlobalValue.h"
45 #include "llvm/IR/Instructions.h"
46 #include "llvm/IR/Module.h"
47 #include "llvm/IR/Type.h"
48 #include "llvm/IR/Use.h"
49 #include "llvm/IR/User.h"
50 #include "llvm/IR/Value.h"
51 #include "llvm/Pass.h"
52 #include "llvm/PassInfo.h"
53 #include "llvm/PassRegistry.h"
54 #include "llvm/PassSupport.h"
55 #include "llvm/Transforms/NaCl.h"
56 #include "llvm/Support/Debug.h"
57
58 using namespace llvm;
59
60 namespace {
61 class MappingResult {
62 public:
63 MappingResult(Type *ATy, bool Chg) {
64 Ty = ATy;
65 Changed = Chg;
66 }
67
68 bool isChanged() { return Changed; }
69
70 Type *operator->() { return Ty; }
71
72 operator Type *() { return Ty; }
73
74 private:
75 Type *Ty;
76 bool Changed;
77 };
78
79 // Utility class. For any given type, get the associated type that is free of
80 // struct register arguments.
81 class TypeMapper {
82 public:
83 Type *getSimpleType(Type *Ty);
84
85 private:
86 DenseMap<Type *, Type *> MappedTypes;
87 MappingResult getSimpleArgumentType(Type *Ty);
88 MappingResult getSimpleAggregateTypeInternal(Type *Ty);
89 };
90
91 // This is a ModulePass because the pass recreates functions in
92 // order to change their signatures.
93 class SimplifyStructRegSignatures : public ModulePass {
94 public:
95 static char ID;
96
97 SimplifyStructRegSignatures() : ModulePass(ID) {
98 initializeSimplifyStructRegSignaturesPass(*PassRegistry::getPassRegistry());
99 }
100 virtual bool runOnModule(Module &M);
101
102 private:
103 TypeMapper Mapper;
104 DenseSet<Function *> FunctionsToDelete;
105 SetVector<CallInst*> CallsToPatch;
106 SetVector<InvokeInst *> InvokesToPatch;
107 DenseMap<Function *, Function *> FunctionMap;
108 bool simplifyFunction(Function *OldFunc, Module &M);
109 void scheduleCallsForCleanup(Function *NewFunc);
110 template <class TCall> void fixCallSite(TCall *Call);
111 void fixFunctionBody(Function *OldFunc, Function *NewFunc);
112 };
113 }
114
115 static const unsigned int TypicalFuncArity = 8;
116 static const unsigned int TypicalStructArity = 8;
117
118 char SimplifyStructRegSignatures::ID = 0;
119
120 INITIALIZE_PASS(
121 SimplifyStructRegSignatures, "simplify-struct-reg-signatures",
122 "Simplify function signatures by removing struct register parameters",
123 false, false)
124
125 // The type is "simple" if it does not recursively reference a
126 // function type with at least an operand (arg or return) typed as struct
127 // register
128 Type *TypeMapper::getSimpleType(Type *Ty) {
129 if (MappedTypes.count(Ty))
130 return MappedTypes[Ty];
JF 2015/03/12 18:36:18 auto Found = MappedTypes.find(Ty); if (Found != Ma
Mircea Trofin 2015/03/13 22:04:52 or the location alternative, to avoid the double s
JF 2015/03/14 18:42:57 There's no point in having two separate functions
131 return MappedTypes[Ty] = getSimpleAggregateTypeInternal(Ty);
132 }
133
134 // transforms any type that could transitively reference a function pointer
JF 2015/03/12 18:36:18 "Transforms"
Mircea Trofin 2015/03/13 22:04:51 Done.
135 // into a simplified type.
136 MappingResult TypeMapper::getSimpleAggregateTypeInternal(Type *Ty) {
137 LLVMContext &Ctx = Ty->getContext();
138
JF 2015/03/12 18:36:18 assert(MappedTypes.end() == MappedTypes.find(Ty));
Mircea Trofin 2015/03/13 22:04:51 They don't. Struct mapping will insert the empty n
139 if (auto *OldFnTy = dyn_cast<FunctionType>(Ty)) {
140 Type *OldRetType = OldFnTy->getReturnType();
141 Type *NewRetType = OldRetType;
142 Type *Void = Type::getVoidTy(Ctx);
143 SmallVector<Type *, TypicalFuncArity> NewArgs;
144 bool HasChanges = false;
JF 2015/03/12 18:36:18 "Changed" is a more common name in LLVM.
Mircea Trofin 2015/03/13 22:04:51 Done.
145 // struct register returns become the first parameter of the new FT.
146 // the new FT has void for the return type
147 if (OldRetType->isAggregateType()) {
148 NewRetType = Void;
149 HasChanges = true;
150 NewArgs.push_back(getSimpleArgumentType(OldRetType));
151 }
152 for (auto OldParam = OldFnTy->param_begin(), E = OldFnTy->param_end();
153 OldParam != E; ++OldParam) {
JF 2015/03/12 18:36:17 for (auto P : OldFnTy->params())
Mircea Trofin 2015/03/13 22:04:52 Done.
154 auto NewType = getSimpleArgumentType(*OldParam);
155 HasChanges |= NewType.isChanged();
156 NewArgs.push_back(NewType);
157 }
158 Type *NewFuncType = FunctionType::get(NewRetType, NewArgs, false);
JF 2015/03/12 18:36:17 This should preserve vararg (and have a correspond
Mircea Trofin 2015/03/13 22:04:51 Done.
159 return MappingResult(NewFuncType, HasChanges);
JF 2015/03/12 18:36:17 C++11 initializer lists should work here and a few
Mircea Trofin 2015/03/13 22:04:51 Done.
160 }
161
162 if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
163 auto NewTy = getSimpleAggregateTypeInternal(PtrTy->getPointerElementType());
164
165 return MappingResult(NewTy->getPointerTo(), NewTy.isChanged());
JF 2015/03/12 18:36:17 This should also preserve the address space of the
Mircea Trofin 2015/03/13 22:04:51 Done.
166 }
167
168 if (auto ArrTy = dyn_cast<ArrayType>(Ty)) {
169 auto NewTy = getSimpleAggregateTypeInternal(ArrTy->getArrayElementType());
170 return MappingResult(ArrayType::get(NewTy, ArrTy->getArrayNumElements()),
171 NewTy.isChanged());
172 }
173
174 if (auto VecTy = dyn_cast<VectorType>(Ty)) {
175 auto NewTy = getSimpleAggregateTypeInternal(VecTy->getVectorElementType());
176 return MappingResult(VectorType::get(NewTy, VecTy->getVectorNumElements()),
177 NewTy.isChanged());
JF 2015/03/12 18:36:17 There's no test for this.
178 }
179
180 if (auto StructTy = dyn_cast<StructType>(Ty)) {
181 if (!StructTy->isLiteral()) {
182 // LLVM doesn't intern identified structs (the ones with a name). This,
183 // together with the fact that such structs can be recursive,
184 // complicates things a bit. We want to make sure that we only change
185 // "unsimplified" structs (those that somehow reference funcs that
186 // are not simple).
187 // We don't want to change "simplified" structs, otherwise converting
188 // instruction types will become trickier.
189 Type *&Loc = MappedTypes[StructTy];
JF 2015/03/12 18:36:17 I'd use `find` here too.
Mircea Trofin 2015/03/13 22:04:52 Done.
190 if (!Loc) {
191 // We don't have a mapping, and we don't know if the struct is recursive
192 // so we create an empty one and hypothesize that it is the
193 // mapping.
194 Loc = StructType::create(Ctx, StructTy->getStructName());
JF 2015/03/12 18:36:16 This loses `isPacked`, though I'm not sure we care
Mircea Trofin 2015/03/13 22:04:51 No, we're setting that further below, if the new s
Mircea Trofin 2015/03/13 22:04:52 It doesn't, we set it below, line 229
195 } else {
196 // We either have a finished mapping or this is the empty placeholder
197 // created above, and we are in the process of finalizing it.
198 // 1) if this is a mapping, it must have the same element count
199 // as the original struct, so we mark a change if the types are
200 // different objects
201 // 2) if this is a placeholder, the element count
202 // wgetStructNumElementsill differ.
JF 2015/03/12 18:36:17 Paste-o?
Mircea Trofin 2015/03/13 22:04:51 yup
203 // Since we don't know yet if this is a change or not - because we
204 // are constructing the mapping - we don't mark as change. We decide
205 // if it is a change below, based on the other struct elements.
206 bool hasChanged =
207 StructTy != Loc &&
208 StructTy->getStructNumElements() == Loc->getStructNumElements();
209 return MappingResult(Loc, hasChanged);
JF 2015/03/12 18:36:17 Same as above, just "Changed".
210 }
211 }
212
213 SmallVector<Type *, TypicalStructArity> ElemTypes;
214 bool HasChanges = false;
JF 2015/03/12 18:36:17 Changed
Mircea Trofin 2015/03/13 22:04:52 Done.
215 unsigned StructElemCount = StructTy->getStructNumElements();
216 for (unsigned I = 0; I < StructElemCount; I++) {
217 auto NewElem =
218 getSimpleAggregateTypeInternal(Ty->getStructElementType(I));
219 ElemTypes.push_back(NewElem);
220 HasChanges |= NewElem.isChanged();
221 }
222 if (!HasChanges) {
223 // We are leaking the created struct here, but there is no way to
224 // correctly delete it.
225 return MappingResult(MappedTypes[Ty] = Ty, false);
226 }
227
228 if (StructTy->isLiteral()) {
229 return MappingResult(MappedTypes[Ty] = StructType::get(
230 Ctx, ElemTypes, StructTy->isPacked()),
231 HasChanges);
232 } else {
233 Type *&Loc = MappedTypes[StructTy];
JF 2015/03/12 18:36:18 `find`
Mircea Trofin 2015/03/13 22:04:52 Done.
234 assert(Loc);
235 StructType *NewStruct = dyn_cast<StructType>(Loc);
JF 2015/03/12 18:36:18 Just `cast<StructType>`, which has an assert inter
Mircea Trofin 2015/03/13 22:04:51 Done.
236 NewStruct->setBody(ElemTypes, StructTy->isPacked());
237 return MappingResult(MappedTypes[Ty] = NewStruct, true);
238 }
239 }
240
241 // anything else stays the same.
JF 2015/03/12 18:36:18 Capitalize (here and below).
242 return MappingResult(Ty, false);
243 }
244
245 // get the simplified type of a function argument.
246 MappingResult TypeMapper::getSimpleArgumentType(Type *Ty) {
247 // struct registers become pointers to simple structs
248 if (Ty->isAggregateType()) {
249 return MappingResult(
250 PointerType::get(getSimpleAggregateTypeInternal(Ty), 0), true);
251 }
252
253 return getSimpleAggregateTypeInternal(Ty);
254 }
255
256 // apply 'byval' to func arguments that used to be struct regs.
257 // apply 'sret' to the argument corresponding to the return in the old signature
258 static void ApplyByValAndSRet(Function *OldFunc, Function *NewFunc) {
259 auto const &OldArgList = OldFunc->getArgumentList();
260 auto &NewArgList = NewFunc->getArgumentList();
261
262 // when calling addAttribute, the first one refers to the function, so we
263 // skip past that.
264 unsigned ArgOffset = 1;
265 if (OldFunc->getReturnType()->isAggregateType()) {
266 NewFunc->addAttribute(1, Attribute::AttrKind::StructRet);
267 ArgOffset++;
268 }
269
270 auto NewArg = NewArgList.begin();
271 for (const Argument &OldArg : OldArgList) {
JF 2015/03/12 18:36:18 Move `OldFunc->getArgumentList()` here, delete abo
Mircea Trofin 2015/03/13 22:04:51 Done.
272 if (OldArg.getType()->isAggregateType()) {
273 NewFunc->addAttribute(NewArg->getArgNo() + ArgOffset,
274 Attribute::AttrKind::ByVal);
275 }
276 NewArg++;
277 }
278 }
279
280 // update the arg names for a newly created function
281 static void UpdateArgNames(Function *OldFunc, Function *NewFunc) {
282 auto NewArgIter = NewFunc->arg_begin();
283 auto const &OldFuncArgs = OldFunc->args();
284 if (OldFunc->getReturnType()->isAggregateType()) {
285 NewArgIter->setName("retVal");
286 NewArgIter++;
287 }
288
289 for (const Argument &OldArg : OldFuncArgs) {
JF 2015/03/12 18:36:18 Same, move `NewFunc->args()` here.
Mircea Trofin 2015/03/13 22:04:51 Done.
290 Argument *NewArg = NewArgIter++;
291 if (OldArg.getType()->isAggregateType()) {
292 NewArg->setName(OldArg.getName() + ".ptr");
293 } else {
294 NewArg->setName(OldArg.getName());
295 }
296 }
297 }
298
299 // replace all uses of an old value with a new one, disregarding the type. We
300 // correct the types separately
JF 2015/03/12 18:36:17 Where is the type corrected? It's not obvious from
Mircea Trofin 2015/03/13 22:04:52 Done.
301 static void BlindReplace(Value *Old, Value *New) {
302 for (auto UseIter = Old->use_begin(), E = Old->use_end(); E != UseIter;) {
JF 2015/03/12 18:36:17 `for (auto U : Old->uses())` Actually, it would b
Mircea Trofin 2015/03/13 22:04:52 That wouldn't work, I'm not changing the content o
303 Use &AUse = *(UseIter++);
304 AUse.set(New);
305 }
306 }
307
308 // adapt the body of a function for the new arguments
309 static void ConvertArgumentValue(Value *Old, Value *New,
310 Instruction *InsPoint) {
311 if (Old == New)
312 return;
313
314 if (Old->getType() == New->getType()) {
315 Old->replaceAllUsesWith(New);
316 New->takeName(Old);
317 return;
318 }
319
320 if (Old->getType()->isAggregateType() && New->getType()->isPointerTy()) {
321 Value *Load = new LoadInst(New, Old->getName() + ".sreg", InsPoint);
322 BlindReplace(Old, Load);
323 } else {
324 BlindReplace(Old, New);
325 }
326 }
327
328 // fix returns. Return true if fixes were needed
329 static void FixReturn(Function *OldFunc, Function *NewFunc) {
330
331 Argument *FirstNewArg = NewFunc->getArgumentList().begin();
332
333 for (auto BIter = NewFunc->begin(), LastBlock = NewFunc->end();
334 LastBlock != BIter;) {
JF 2015/03/12 18:36:19 for (BasicBlock &BB : NewFunc->getBasicBlockList()
Mircea Trofin 2015/03/13 22:04:52 no, because we mutate the list (same goes for the
335 BasicBlock *BB = BIter++;
336 for (auto IIter = BB->begin(), LastI = BB->end(); LastI != IIter;) {
JF 2015/03/12 18:36:17 for (Instruction &I : BB)
337 Instruction *Instr = IIter++;
338 if (ReturnInst *Ret = dyn_cast<ReturnInst>(Instr)) {
339 auto &Ctx = Ret->getContext();
JF 2015/03/12 18:36:18 This should be loop invariant, hoist it.
Mircea Trofin 2015/03/13 22:04:52 Done.
340 auto RetVal = Ret->getReturnValue();
341 ReturnInst *NewRet = ReturnInst::Create(Ctx, nullptr, Ret);
342 Ret->eraseFromParent();
JF 2015/03/12 18:36:18 I think this invalidates your Instruction iterator
Mircea Trofin 2015/03/13 22:04:52 That's the reason I increment the iterator first t
343 Ret = nullptr;
344 new StoreInst(RetVal, FirstNewArg, NewRet);
JF 2015/03/12 18:36:16 Give it a name and copy debug location. Also, you
Mircea Trofin 2015/03/13 22:04:51 Turns out store doesn't accept a name. Otherwise,
345 }
346 }
347 }
348 }
349
350 template <class TCall>
351 void CopyCallAttributesAndMetadata(TCall *Orig, TCall *NewCall) {
352 NewCall->setCallingConv(Orig->getCallingConv());
353 NewCall->setAttributes(NewCall->getAttributes().addAttributes(
354 Orig->getContext(), AttributeSet::FunctionIndex,
355 Orig->getAttributes().getFnAttributes()));
356 NewCall->setDebugLoc(Orig->getDebugLoc());
JF 2015/03/12 18:36:17 Other metadata?
Mircea Trofin 2015/03/13 22:04:51 I believe this is it, but I added a TODO, because
357 }
358
359 static InvokeInst *CreateCallFrom(InvokeInst *Orig, Value *Target,
360 ArrayRef<Value *> &Args) {
361 InvokeInst *Ret = InvokeInst::Create(Target, Orig->getNormalDest(),
362 Orig->getUnwindDest(), Args);
JF 2015/03/12 18:36:17 Copy name.
Mircea Trofin 2015/03/13 22:04:52 Done.
363 CopyCallAttributesAndMetadata(Orig, Ret);
364 return Ret;
365 }
366
367 static CallInst *CreateCallFrom(CallInst *Orig, Value *Target,
368 ArrayRef<Value *> &Args) {
369
370 CallInst *Ret = CallInst::Create(Target, Args);
JF 2015/03/12 18:36:17 Name.
Mircea Trofin 2015/03/13 22:04:52 Done, doing this in CopyCallAttributesAndMetadata
371
372 Ret->setTailCallKind(Orig->getTailCallKind());
373 CopyCallAttributesAndMetadata(Orig, Ret);
JF 2015/03/12 18:36:18 I think you're missing NoBuiltin, NoInline, Return
Mircea Trofin 2015/03/13 22:04:52 as per http://llvm.org/docs/LangRef.html#i-call:
374 return Ret;
375 }
376
377 // fix a call site by handing return type changes and/or parameter type and
378 // attribute changes
379 template <class TCall>
380 void SimplifyStructRegSignatures::fixCallSite(TCall *OldCall) {
381 Value *NewTarget = OldCall->getCalledValue();
382
383 if (Function *CalledFunc = dyn_cast<Function>(NewTarget)) {
384 NewTarget = this->FunctionMap[CalledFunc];
385 }
386 assert(NewTarget);
387
388 FunctionType *NewType = dyn_cast<FunctionType>(
JF 2015/03/12 18:36:16 cast<FunctionType>
Mircea Trofin 2015/03/13 22:04:51 Done.
389 Mapper.getSimpleType(NewTarget->getType())->getPointerElementType());
390
391 Type *OldRetType = OldCall->getType();
392 const bool isSRet =
393 !OldCall->getType()->isVoidTy() && NewType->getReturnType()->isVoidTy();
394
395 const unsigned argOffset = isSRet ? 1 : 0;
396
397 SmallVector<Value *, TypicalFuncArity> NewArgs;
398
399 if (isSRet) {
400 AllocaInst *Alloca = new AllocaInst(OldRetType);
JF 2015/03/12 18:36:18 Alignment to preferred size. Name. You can also
Mircea Trofin 2015/03/13 22:04:52 It's simpler to use takeName than cache the old na
401 NewArgs.push_back(Alloca);
402 Alloca->insertBefore(OldCall);
403
404 LoadInst *Load = new LoadInst(Alloca, OldCall->getName() + ".sreg",
405 (Instruction *)nullptr);
JF 2015/03/12 18:36:18 Alignment.
Mircea Trofin 2015/03/13 22:04:52 Done.
406 Load->insertAfter(OldCall);
407 OldCall->replaceAllUsesWith(Load);
408 }
JF 2015/03/12 18:36:18 Why not create the new call between the alloca and
Mircea Trofin 2015/03/13 22:04:52 the call is between the alloca and the load *if* w
JF 2015/03/14 18:42:57 I mean that the order of code in this pass should
409
410 SmallSetVector<unsigned, TypicalFuncArity> ByRefPlaces;
411
412 for (unsigned ArgPos = 0;
413 ArgPos < NewType->getFunctionNumParams() - argOffset; ArgPos++) {
414
415 Use &OldArgUse = OldCall->getOperandUse(ArgPos);
416 Value *OldArg = OldArgUse;
417 Type *OldArgType = OldArg->getType();
418 unsigned NewArgPos = OldArgUse.getOperandNo() + argOffset;
419 Type *NewArgType = NewType->getFunctionParamType(NewArgPos);
420
421 if (OldArgType != NewArgType && OldArgType->isAggregateType()) {
422 AllocaInst *Alloca =
423 new AllocaInst(OldArgType, OldArg->getName() + ".ptr", OldCall);
424 new StoreInst(OldArg, Alloca, OldCall);
425 ByRefPlaces.insert(NewArgPos);
426 NewArgs.push_back(Alloca);
427 } else {
428 NewArgs.push_back(OldArg);
429 }
430 }
431
432 ArrayRef<Value *> ArrRef = NewArgs;
433 TCall *NewCall = CreateCallFrom(OldCall, NewTarget, ArrRef);
434
435 // copy the attributes over, and add byref/sret as necessary
436 const AttributeSet &OldAttrSet = OldCall->getAttributes();
437 const AttributeSet &NewAttrSet = NewCall->getAttributes();
438 LLVMContext &Ctx = OldCall->getContext();
439 AttrBuilder Builder(OldAttrSet, 0);
440
441 for (unsigned I = 0; I < NewCall->getNumArgOperands(); I++) {
442 NewCall->setAttributes(NewAttrSet.addAttributes(
443 Ctx, I + argOffset + 1, OldAttrSet.getParamAttributes(I + 1)));
444 if (ByRefPlaces.count(I)) {
445 NewCall->addAttribute(I + 1, Attribute::AttrKind::ByVal);
446 }
447 }
448
449 if (isSRet) {
450 NewAttrSet.addAttributes(Ctx, 1, OldAttrSet.getRetAttributes());
451 NewCall->addAttribute(1, Attribute::AttrKind::StructRet);
452 } else {
453 NewCall->setAttributes(NewAttrSet.addAttributes(
454 Ctx, AttributeSet::ReturnIndex, OldAttrSet.getRetAttributes()));
455 // if we still return something, this is the value to replace the old
456 // call with
457 OldCall->replaceAllUsesWith(NewCall);
458 }
459
460 NewCall->insertBefore(OldCall);
461 OldCall->eraseFromParent();
462 OldCall = NULL;
463 }
464
465 void SimplifyStructRegSignatures::scheduleCallsForCleanup(Function *NewFunc) {
466 for (auto &BBIter : NewFunc->getBasicBlockList()) {
467 for (auto &IIter : BBIter.getInstList()) {
468 if (CallInst *Call = dyn_cast<CallInst>(&IIter)) {
469 CallsToPatch.insert(Call);
470 } else if (InvokeInst *Invoke = dyn_cast<InvokeInst>(&IIter)) {
471 InvokesToPatch.insert(Invoke);
472 }
473 }
474 }
475 }
476
477 // change function body in the light of type changes
478 void SimplifyStructRegSignatures::fixFunctionBody(Function *OldFunc,
479 Function *NewFunc) {
480 if (NewFunc->empty())
481 return;
482
483 bool returnWasFixed = OldFunc->getReturnType()->isAggregateType();
484
485 Instruction *InsPoint = NewFunc->begin()->begin();
486 auto NewArgIter = NewFunc->arg_begin();
487 // advance one more if we used to return a struct register
488 if (returnWasFixed)
489 NewArgIter++;
490
491 // wire new parameters in
492 for (auto ArgIter = OldFunc->arg_begin(), E = OldFunc->arg_end();
493 E != ArgIter;) {
494 Argument *OldArg = ArgIter++;
495 Argument *NewArg = NewArgIter++;
496 ConvertArgumentValue(OldArg, NewArg, InsPoint);
497 }
498
499 // now fix instruction types. Calls are dealt with separately, but we still
500 // update the types here. We know that each value could only possibly be
501 // of a simplified type. At the end of this, call sites will be invalid, but
502 // we handle that afterwards, to make sure we have all the functions changed
503 // first (so that calls have valid targets)
504 for (auto BBIter = NewFunc->begin(), LBlock = NewFunc->end();
505 LBlock != BBIter;) {
506 auto Block = BBIter++;
507 for (auto IIter = Block->begin(), LIns = Block->end(); LIns != IIter;) {
508 auto Instr = IIter++;
509 Instr->mutateType(Mapper.getSimpleType(Instr->getType()));
510 }
511 }
512 if (returnWasFixed)
513 FixReturn(OldFunc, NewFunc);
514 }
515
516 // Ensure function is simplified, returning true if the function
517 // had to be changed.
518 bool SimplifyStructRegSignatures::simplifyFunction(Function *OldFunc,
519 Module &M) {
520 FunctionType *OldFT = OldFunc->getFunctionType();
521 FunctionType *NewFT = dyn_cast<FunctionType>(Mapper.getSimpleType(OldFT));
522 assert(NewFT);
523
524 Function *&AssociatedFctLoc = FunctionMap[OldFunc];
525 if (NewFT != OldFT) {
526 Function *NewFunc = Function::Create(NewFT, OldFunc->getLinkage());
527 AssociatedFctLoc = NewFunc;
528
529 NewFunc->copyAttributesFrom(OldFunc);
530 OldFunc->getParent()->getFunctionList().insert(OldFunc, NewFunc);
531 NewFunc->takeName(OldFunc);
532
533 UpdateArgNames(OldFunc, NewFunc);
534 ApplyByValAndSRet(OldFunc, NewFunc);
535
536 NewFunc->getBasicBlockList().splice(NewFunc->begin(),
537 OldFunc->getBasicBlockList());
538
539 fixFunctionBody(OldFunc, NewFunc);
540 FunctionsToDelete.insert(OldFunc);
541 } else {
542 AssociatedFctLoc = OldFunc;
543 }
544 scheduleCallsForCleanup(AssociatedFctLoc);
545 return NewFT != OldFT;
546 }
547
548 bool SimplifyStructRegSignatures::runOnModule(Module &M) {
549 bool Changed = false;
550
551 // change function signatures and fix a changed function body by
552 // wiring the new arguments. Call sites are unchanged at this point
553 for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E;) {
554 Function *Func = Iter++;
555 Changed |= simplifyFunction(Func, M);
556 }
557
558 // fix call sites
559 for (auto &CallToFix : CallsToPatch) {
560 fixCallSite(CallToFix);
561 }
562
563 for (auto &InvokeToFix : InvokesToPatch) {
564 fixCallSite(InvokeToFix);
565 }
566
567 // delete leftover functions - the ones with old signatures
568 for (auto &ToDelete : FunctionsToDelete) {
569 // this also frees the memory
570 ToDelete->eraseFromParent();
571 }
572 return Changed;
573 }
574
575 ModulePass *llvm::createSimplifyStructRegSignaturesPass() {
576 return new SimplifyStructRegSignatures();
577 }
OLDNEW
« no previous file with comments | « lib/Transforms/NaCl/PNaClABISimplify.cpp ('k') | test/Transforms/NaCl/simplify-struct-reg-signatures.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698