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

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

Issue 14569012: PNaCl ABI: Promote illegal integer types (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: move logic to convertInstruction Created 7 years, 7 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
« no previous file with comments | « lib/Transforms/NaCl/CMakeLists.txt ('k') | test/NaCl/PNaClABI/types.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- PromoteIntegers.cpp - Promote illegal integers for PNaCl ABI -------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 // A limited set of transformations to promote illegal-sized int types.
Mark Seaborn 2013/05/09 01:00:22 Add //==---... spacer before this, to follow the s
Derek Schuff 2013/05/09 18:30:24 Done.
9 // Legal sizes are currently 1, 8, 16, 32, 64 (and higher, see note below)
10 // Operations on illegal integers and int pointers are be changed to operate
11 // on the next-higher legal size.
12 // It always maintains the invariant that the upper bits (above the size of the
Mark Seaborn 2013/05/09 01:00:22 I don't think that's the best choice of invariant,
Derek Schuff 2013/05/09 18:30:24 I did think about doing that. For the operations t
Mark Seaborn 2013/05/09 19:27:48 FWIW, that's not true. For addition, digit n in t
Derek Schuff 2013/05/09 20:19:43 OK, true. In any case it doesn't matter for the in
13 // original type) are zero; therefore after operations which can overwrite these
14 // bits (e.g. add, shl, sext), the bits are cleared.
15 //
16 // Limitations:
17 // 1) It can't change function signatures or global variables
18 // 2) It won't promote (and can't expand) types larger than i64
19 // 3) Doesn't support mul/div operators
20 // 4) Doesn't handle arrays or structs (or GEPs) with illegal types
21 // 5) Doesn't handle constant expressions
22 //===----------------------------------------------------------------------===//
Mark Seaborn 2013/05/09 01:00:22 Follow the style here and end comment with: // //=
Derek Schuff 2013/05/09 18:30:24 Done.
23 //
24
25 #include "llvm/ADT/DenseMap.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/Instructions.h"
30 #include "llvm/IR/IRBuilder.h"
31 #include "llvm/Pass.h"
32 #include "llvm/Support/raw_ostream.h"
33
34 using namespace llvm;
Mark Seaborn 2013/05/09 01:00:22 Add empty line after this
Derek Schuff 2013/05/09 18:30:24 Done.
35 namespace {
36 class PromoteIntegers : public FunctionPass {
37 public:
38 static char ID;
39 PromoteIntegers() : FunctionPass(ID) {
40 initializePromoteIntegersPass(*PassRegistry::getPassRegistry());
41 }
42 virtual bool runOnFunction(Function &F);
43 };
44 }
45
46 char PromoteIntegers::ID = 0;
47 INITIALIZE_PASS(PromoteIntegers, "nacl-promote-ints",
48 "Promote integer types which are illegal in PNaCl",
49 false, false)
50
51
52 // Legal sizes are currently 1, 8, 16, 32, and 64.
53 // We can't yet expand types above 64 bit, so don't try to touch them for now.
54 static bool isLegalSize(unsigned Size) {
55 // TODO(dschuff): expand >64bit types or disallow >64bit packed bitfields
56 if (Size > 64) return true;
57 return Size == 1 || Size == 8 || Size == 16 || Size == 32 || Size == 64;
58 }
59
60 static Type *getPromotedIntType(IntegerType *Ty) {
61 unsigned Width = Ty->getBitWidth();
62 assert(Width <= 64 && "Don't know how to legalize >64 bit types yet");
63 if (isLegalSize(Width))
64 return Ty;
65 return IntegerType::get(Ty->getContext(), NextPowerOf2(Width));
Mark Seaborn 2013/05/09 01:00:22 NextPowerOf2() isn't right for i3, which should be
Derek Schuff 2013/05/09 18:30:24 Done.
66 }
67
68 // Return a legal integer or pointer-to-integer type, promoting to a larger
69 // size if necessary.
70 static Type *getPromotedType(Type *Ty) {
71 assert((isa<IntegerType>(Ty) || isa<PointerType>(Ty)) &&
72 "Trying to convert a non-integer type");
73
74 if (isa<PointerType>(Ty))
75 return getPromotedIntType(
76 cast<IntegerType>(Ty->getContainedType(0)))->getPointerTo();
77
78 return getPromotedIntType(cast<IntegerType>(Ty));
79 }
80
81 // Return true if Val is an int or pointer-to-int which should be converted.
82 static bool shouldConvert(Value *Val) {
83 Type *Ty = Val->getType();
84 if (PointerType *Pty = dyn_cast<PointerType>(Ty))
85 Ty = Pty->getContainedType(0);
86 if (IntegerType *ITy = dyn_cast<IntegerType>(Ty)) {
87 if (!isLegalSize(ITy->getBitWidth())) {
88 return true;
89 }
90 }
91 return false;
92 }
93
94 // Return a constant which has been promoted to a legal size.
95 static Value *convertConstant(Constant *C, bool SignExt=false) {
96 assert(shouldConvert(C));
97 ConstantInt *CInt = cast<ConstantInt>(C);
98 return ConstantInt::get(
99 getPromotedType(cast<IntegerType>(CInt->getType())),
100 SignExt ? CInt->getSExtValue() : CInt->getZExtValue(),
101 /*isSigned=*/SignExt);
102 }
103
104 // Holds the state for converting/replacing values. Conversion is done in one
105 // pass, with each value requiring conversion possibly having two stages. When
106 // an instruction needs to be replaced (i.e. it has illegal operands or result)
107 // a new instruction is created, and the pass calls getConverted to get its
108 // operands. If the original operand has already been converted, the new value
109 // is returned. Otherwise, a placeholder is created and used in the new
110 // instruction. After a new instruction is created to replace an illegal one,
111 // recordConverted is called to register the replacement. All users are updated,
112 // and if there is a placeholder, its users are also updated.
113 // recordConverted also queues the old value for deletion.
114 // This strategy avoids the need for recursion or worklists for conversion.
115 class ConversionState {
116 public:
117 // Return the promoted value for Val. If Val has not yet been converted,
118 // return a placeholder, which will be converted later.
119 Value *getConverted(Value *Val) {
120 if (!shouldConvert(Val))
121 return Val;
122 assert(!isa<GlobalVariable>(Val) && "Can't convert GlobalVariables");
123 if (RewrittenMap.count(Val))
124 return RewrittenMap[Val];
125 Value *P;
126 // Directly convert constants.
127 if (Constant *C = dyn_cast<Constant>(Val)) {
128 return convertConstant(C, /*SignExt=*/false);
jvoung (off chromium) 2013/05/09 00:06:44 Is it possible to keep constants in RewrittenMap?
Derek Schuff 2013/05/09 18:30:24 It is possible because the clients that want sign
129 } else {
130 // No converted value available yet, so create a placeholder.
131 P = new Argument(getPromotedType(Val->getType()));
132 }
133 RewrittenMap[Val] = P;
134 Placeholders[Val] = P;
135 return P;
136 }
137
138 // Replace the uses of From with To, replace the uses of any
139 // placeholders for From, and optionally give From's name to To.
140 // Also mark To for deletion.
141 void recordConverted(Instruction *From, Value *To, bool TakeName=true) {
142 ToErase.push_back(cast<Instruction>(From));
jvoung (off chromium) 2013/05/09 00:06:44 do you still need a cast?
Derek Schuff 2013/05/09 18:30:24 Done.
143 if (!shouldConvert(From)) {
jvoung (off chromium) 2013/05/09 00:06:44 Haven't read through everything, yet, but it seems
Derek Schuff 2013/05/09 18:30:24 Done.
144 From->replaceAllUsesWith(To);
145 } else {
146 if (Placeholders.count(From)) {
147 // Resolve placeholder.
148 Placeholders[From]->replaceAllUsesWith(To);
149 Placeholders.erase(From);
150 }
jvoung (off chromium) 2013/05/09 00:06:44 should there be an else { From->replaceAllUsesWi
Derek Schuff 2013/05/09 18:30:24 added comment
151 RewrittenMap[From] = To;
152 }
153 if (TakeName) {
154 To->takeName(From);
155 }
156 }
157 ~ConversionState() {
Mark Seaborn 2013/05/09 01:00:22 The destructor should come before other methods.
Derek Schuff 2013/05/09 18:30:24 Done.
158 for (SmallVectorImpl<Instruction*>::iterator I = ToErase.begin(),
159 E = ToErase.end(); I != E; ++I)
160 (*I)->dropAllReferences();
161 for (SmallVectorImpl<Instruction*>::iterator I = ToErase.begin(),
162 E = ToErase.end(); I != E; ++I)
163 (*I)->eraseFromParent();
164 }
165 private:
166 // Maps illegal values to their new converted values (or placeholders
167 // if no new value is available yet)
168 DenseMap<Value *, Value *> RewrittenMap;
169 // Maps illegal values with no conversion available yet to their placeholders
170 DenseMap<Value *, Value *> Placeholders;
171 // Illegal values which have already been converted, to erase on distruction.
jvoung (off chromium) 2013/05/09 00:06:44 nits: distruction -> destruction consistency wit
Derek Schuff 2013/05/09 18:30:24 Done.
172 SmallVector<Instruction*, 8> ToErase;
173 };
174
175 // Split an illegal load into multiple legal loads and return the resulting
176 // promoted value. The size of the load is assumed to be a multiple of 8.
Mark Seaborn 2013/05/09 01:00:22 Does this mean the pass doesn't handle i2...i7?
Derek Schuff 2013/05/09 18:30:24 Not for loads and stores. The rest of the ops shou
177 static Value *splitLoad(LoadInst *Inst, ConversionState &State) {
178 assert(!Inst->isVolatile() && !Inst->isAtomic() &&
Mark Seaborn 2013/05/09 01:00:22 This can get compiled out of release builds. Do a
Derek Schuff 2013/05/09 18:30:24 Done.
179 "Can't split volatile/atomic loads");
180 assert(cast<IntegerType>(Inst->getType())->getBitWidth() % 8 == 0);
Mark Seaborn 2013/05/09 01:00:22 This should be a report_fatal_error() too since it
Derek Schuff 2013/05/09 18:30:24 Done.
181
182 Value *OrigPtr = State.getConverted(Inst->getPointerOperand());
183 // OrigPtr is a placeholder in recursive calls, and so has no name
184 if (OrigPtr->getName().empty())
185 OrigPtr->setName(Inst->getPointerOperand()->getName());
186 unsigned Width = cast<IntegerType>(Inst->getType())->getBitWidth();
187 Type *NewType = getPromotedType(Inst->getType());
188 unsigned LoWidth = Width;
189
190 while (!isLegalSize(LoWidth)) LoWidth -= 8;
191 IntegerType *LoType = IntegerType::get(Inst->getContext(), LoWidth);
192 IntegerType *HiType = IntegerType::get(Inst->getContext(), Width - LoWidth);
193 IRBuilder<> IRB(Inst->getParent(), Inst);
194
195 Value *BCLo = IRB.CreateBitCast(
196 OrigPtr,
197 LoType->getPointerTo(),
198 OrigPtr->getName() + ".loty");
199 Value *LoadLo = IRB.CreateAlignedLoad(
200 BCLo, Inst->getAlignment(), Inst->getName() + ".lo");
201 Value *LoExt = IRB.CreateZExt(LoadLo, NewType, LoadLo->getName() + ".ext");
202 Value *GEPHi = IRB.CreateConstGEP1_32(BCLo, 1, OrigPtr->getName() + ".hi");
203 Value *BCHi = IRB.CreateBitCast(
204 GEPHi,
205 HiType->getPointerTo(),
206 OrigPtr->getName() + ".hity");
207
208 Value *LoadHi = IRB.CreateLoad(BCHi, Inst->getName() + ".hi");
209 if (!isLegalSize(Width - LoWidth)) {
210 LoadHi = splitLoad(cast<LoadInst>(LoadHi), State);
211 // BCHi was still illegal, and has been replaced with a placeholder in the
212 // recursive call. Since it is redundant with BCLo in the recursive call,
213 // just splice it out entirely.
214 State.recordConverted(cast<Instruction>(BCHi), GEPHi, /*TakeName=*/false);
215 }
216
217 Value *HiExt = IRB.CreateZExt(LoadHi, NewType, LoadHi->getName() + ".ext");
218 Value *HiShift = IRB.CreateShl(HiExt, LoWidth, HiExt->getName() + ".sh");
219 Value *Result = IRB.CreateOr(LoExt, HiShift);
220
221 State.recordConverted(Inst, Result);
222
223 return Result;
224 }
225
226 static Value *splitStore(StoreInst *Inst, ConversionState &State) {
227 assert(!Inst->isVolatile() && !Inst->isAtomic() &&
228 "Can't split volatile/atomic stores");
229 assert(cast<IntegerType>(Inst->getValueOperand()->getType())->getBitWidth() % 8
Mark Seaborn 2013/05/09 01:00:22 Line >80 chars
Derek Schuff 2013/05/09 18:30:24 Done.
230 == 0);
231
232 Value *OrigPtr = State.getConverted(Inst->getPointerOperand());
233 // OrigPtr is now a placeholder in recursive calls, and so has no name.
234 if (OrigPtr->getName().empty())
235 OrigPtr->setName(Inst->getPointerOperand()->getName());
236 Value *OrigVal = State.getConverted(Inst->getValueOperand());
237 unsigned Width = cast<IntegerType>(
238 Inst->getValueOperand()->getType())->getBitWidth();
239 unsigned LoWidth = Width;
240
241 while (!isLegalSize(LoWidth)) LoWidth -= 8;
242 IntegerType *LoType = IntegerType::get(Inst->getContext(), LoWidth);
243 IntegerType *HiType = IntegerType::get(Inst->getContext(), Width - LoWidth);
244 IRBuilder<> IRB(Inst->getParent(), Inst);
245
246 Value *BCLo = IRB.CreateBitCast(
247 OrigPtr,
248 LoType->getPointerTo(),
249 OrigPtr->getName() + ".loty");
250 Value *LoTrunc = IRB.CreateTrunc(
251 OrigVal, LoType, OrigVal->getName() + ".lo");
252 IRB.CreateAlignedStore(LoTrunc, BCLo, Inst->getAlignment());
253
254 Value *HiLShr = IRB.CreateLShr(
255 OrigVal, LoWidth, OrigVal->getName() + ".hi.sh");
256 Value *GEPHi = IRB.CreateConstGEP1_32(BCLo, 1, OrigPtr->getName() + ".hi");
257 Value *HiTrunc = IRB.CreateTrunc(
258 HiLShr, HiType, OrigVal->getName() + ".hi");
259 Value *BCHi = IRB.CreateBitCast(
260 GEPHi,
261 HiType->getPointerTo(),
262 OrigPtr->getName() + ".hity");
263
264 Value *StoreHi = IRB.CreateStore(HiTrunc, BCHi);
265
266 if (!isLegalSize(Width - LoWidth)) {
267 // HiTrunc is still illegal, and is redundant with the truncate in the
268 // recursive call, so just get rid of it.
269 State.recordConverted(cast<Instruction>(HiTrunc), HiLShr, /*TakeName=*/false );
Mark Seaborn 2013/05/09 01:00:22 Line >80 chars
Derek Schuff 2013/05/09 18:30:24 Done.
270 StoreHi = splitStore(cast<StoreInst>(StoreHi), State);
271 // BCHi was still illegal, and has been replaced with a placeholder in the
272 // recursive call. Since it is redundant with BCLo in the recursive call,
273 // just splice it out entirely.
274 State.recordConverted(cast<Instruction>(BCHi), GEPHi, /*TakeName=*/false);
275 }
276 State.recordConverted(Inst, StoreHi, /*TakeName=*/false);
277 return StoreHi;
278 }
279
280 // Return a value with the bits of the operand above the size of the original
281 // type cleared. The operand is assumed to have been legalized already.
282 static Value *getClearUpper(Value *Operand, Type *OrigType,
283 Instruction *InsertPt) {
284 // If the operand is a constant, it will have been created by
285 // ConversionState.getConverted, which zero-extends by default.
286 if (isa<Constant>(Operand))
287 return Operand;
288 return BinaryOperator::Create(
289 Instruction::And,
290 Operand,
291 ConstantInt::get(
292 getPromotedType(OrigType),
293 APInt::getLowBitsSet(getPromotedType(OrigType)->getIntegerBitWidth(),
294 OrigType->getIntegerBitWidth())),
295 Operand->getName() + ".clear",
296 InsertPt);
297 }
298
299 // Return a value with the bits of the operand above the size of the original
300 // type equal to the sign bit of the original operand. The new operand is
301 // assumed to have been legalized already.
302 // This is done by shifting the sign bit of the smaller value up to the MSB
303 // position in the larger size, and then arithmetic-shifting it back down.
304 static Value *getSignExtend(Value *Operand, Value *OrigOperand,
305 Instruction *InsertPt) {
306 // If OrigOperand was a constant, NewOperand will have been created by
307 // ConversionState.getConverted, which zero-extends by default. But that is
308 // wrong here, so replace it with a sign-extended constant.
309 if (Constant *C = dyn_cast<Constant>(OrigOperand))
310 return convertConstant(C, /*SignExt=*/true);
311 Type *OrigType = OrigOperand->getType();
312 ConstantInt *ShiftAmt = ConstantInt::getSigned(
313 cast<IntegerType>(getPromotedType(OrigType)),
314 getPromotedType(OrigType)->getIntegerBitWidth() -
315 OrigType->getIntegerBitWidth());
316 BinaryOperator *Shl = BinaryOperator::Create(
317 Instruction::Shl,
318 Operand,
319 ShiftAmt,
320 Operand->getName() + ".getsign",
321 InsertPt);
322 return BinaryOperator::Create(
323 Instruction::AShr,
324 Shl,
325 ShiftAmt,
326 Operand->getName() + ".signed",
327 InsertPt);
328 }
329
330 static void convertInstruction(Instruction *Inst, ConversionState &State) {
331 if (SExtInst *Sext = dyn_cast<SExtInst>(Inst)) {
332 Value *Op = Sext->getOperand(0);
333 Value *NewInst = NULL;
334 // If the operand to be extended is illegal, we first need to fill its
335 // upper bits (which are zero) with its sign bit.
336 if (shouldConvert(Op)) {
337 NewInst = getSignExtend(State.getConverted(Op), Op, Sext);
338 }
339 // If the converted type of the operand is the same as the converted
340 // type of the result, we won't actually be changing the type of the
341 // variable, just its value.
342 if (getPromotedType(Op->getType()) !=
343 getPromotedType(Sext->getType())) {
344 NewInst = new SExtInst(
345 NewInst ? NewInst : State.getConverted(Op),
346 getPromotedType(cast<IntegerType>(Sext->getType())),
347 Sext->getName() + ".sext", Sext);
348 }
349 // Now all the bits of the result are correct, but we need to restore
350 // the bits above its type to zero.
351 if (shouldConvert(Sext)) {
352 NewInst = getClearUpper(NewInst, Sext->getType(), Sext);
353 }
354 assert(NewInst && "Failed to convert sign extension");
355 State.recordConverted(Sext, NewInst);
356 } else if (ZExtInst *Zext = dyn_cast<ZExtInst>(Inst)) {
357 Value *Op = Zext->getOperand(0);
358 Value *NewInst = NULL;
359 // TODO(dschuff): Some of these zexts could be no-ops.
360 if (shouldConvert(Op)) {
361 NewInst = getClearUpper(State.getConverted(Op),
362 Op->getType(),
363 Zext);
364 }
365 // If the converted type of the operand is the same as the converted
366 // type of the result, we won't actually be changing the type of the
367 // variable, just its value.
368 if (getPromotedType(Op->getType()) !=
369 getPromotedType(Zext->getType())) {
370 NewInst = CastInst::CreateZExtOrBitCast(
371 NewInst ? NewInst : State.getConverted(Op),
372 getPromotedType(cast<IntegerType>(Zext->getType())),
373 "", Zext);
374 }
375 assert(NewInst);
376 State.recordConverted(Zext, NewInst);
377 } else if (TruncInst *Trunc = dyn_cast<TruncInst>(Inst)) {
378 Value *Op = Trunc->getOperand(0);
379 Value *NewInst = NULL;
380 // If the converted type of the operand is the same as the converted
381 // type of the result, we won't actually be changing the type of the
382 // variable, just its value.
383 if (getPromotedType(Op->getType()) !=
384 getPromotedType(Trunc->getType())) {
385 NewInst = new TruncInst(
386 State.getConverted(Op),
387 getPromotedType(cast<IntegerType>(Trunc->getType())),
388 State.getConverted(Op)->getName() + ".trunc",
389 Trunc);
390 }
391 // Restoring the upper-bits-are-zero invariant effectively truncates the
392 // value.
393 if (shouldConvert(Trunc)) {
394 NewInst = getClearUpper(NewInst ? NewInst : Op,
395 Trunc->getType(),
396 Trunc);
397 }
398 assert(NewInst);
399 State.recordConverted(Trunc, NewInst);
400 } else if (AllocaInst *Alloc = dyn_cast<AllocaInst>(Inst)) {
401 // Don't handle arrays of illegal types, but we could handle an array
402 // with size specified as an illegal type, as unlikely as that seems.
403 assert(!(shouldConvert(Alloc) && Alloc->isArrayAllocation()));
404 AllocaInst *NewInst = new AllocaInst(
405 getPromotedType(Alloc->getAllocatedType()),
406 State.getConverted(Alloc->getArraySize()),
407 "", Alloc);
408 NewInst->setAlignment(Alloc->getAlignment());
409 State.recordConverted(Alloc, NewInst);
410 } else if (BitCastInst *BCInst = dyn_cast<BitCastInst>(Inst)) {
411 // Only handle pointers. Ints can't be casted to/from other ints
412 if (shouldConvert(BCInst) || shouldConvert(BCInst->getOperand(0))) {
413 BitCastInst *NewInst = new BitCastInst(
414 State.getConverted(BCInst->getOperand(0)),
415 getPromotedType(BCInst->getDestTy()),
416 "", BCInst);
417 State.recordConverted(BCInst, NewInst);
418 }
419 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
420 if (shouldConvert(Load)) {
421 splitLoad(Load, State);
422 }
423 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
424 if (shouldConvert(Store->getValueOperand())) {
425 splitStore(Store, State);
426 }
427 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
428 llvm_unreachable("can't convert calls");
429 for (unsigned I = 0; I < Call->getNumArgOperands(); ++I) {
Mark Seaborn 2013/05/09 01:00:22 Drop the dead code here since it's after llvm_unre
Derek Schuff 2013/05/09 18:30:24 Done.
430 Value *Arg = Call->getArgOperand(I);
431 Call->setArgOperand(I, State.getConverted(Arg));
432 }
433 } else if (BinaryOperator *Binop = dyn_cast<BinaryOperator>(Inst)) {
434 Value *NewInst = NULL;
435 if (Binop->getOpcode() == Instruction::AShr) {
436 // The AShr operand needs to be sign-extended to the promoted size
437 // before shifting. Because the sign-extension is implemented with
438 // with AShr, it can be combined with the original operation.
439 Value *Op = Binop->getOperand(0);
440 Value *ShiftAmount = NULL;
441 APInt SignShiftAmt = APInt(
442 getPromotedType(Op->getType())->getIntegerBitWidth(),
443 getPromotedType(Op->getType())->getIntegerBitWidth() -
444 Op->getType()->getIntegerBitWidth());
445 NewInst = BinaryOperator::Create(
446 Instruction::Shl,
447 State.getConverted(Op),
448 ConstantInt::get(getPromotedType(Op->getType()), SignShiftAmt),
449 State.getConverted(Op)->getName() + ".getsign",
450 Binop);
451 if (ConstantInt *C = dyn_cast<ConstantInt>(
452 State.getConverted(Binop->getOperand(1)))) {
453 ShiftAmount = ConstantInt::get(getPromotedType(Op->getType()),
454 SignShiftAmt + C->getValue());
455 } else {
456 ShiftAmount = BinaryOperator::Create(
457 Instruction::Add,
458 State.getConverted(Binop->getOperand(1)),
459 ConstantInt::get(
460 getPromotedType(Binop->getOperand(1)->getType()),
461 SignShiftAmt),
462 State.getConverted(Op)->getName() + ".shamt", Binop);
463 }
464 NewInst = BinaryOperator::Create(
465 Instruction::AShr,
466 NewInst,
467 ShiftAmount,
468 Binop->getName() + ".result", Binop);
469 } else {
470 // If the original operation is not AShr, just recreate it as usual.
471 NewInst = BinaryOperator::Create(
472 Binop->getOpcode(),
473 NewInst ? NewInst : State.getConverted(Binop->getOperand(0)),
474 State.getConverted(Binop->getOperand(1)),
475 Binop->getName() + ".result", Binop);
476 }
477
478 // Now restore the invariant if necessary.
479 // This switch also sanity-checks the operation.
480 switch (Binop->getOpcode()) {
481 case Instruction::And:
482 case Instruction::Or:
483 case Instruction::Xor:
484 case Instruction::LShr:
485 // These won't change the upper bits.
486 break;
487 case Instruction::Add:
488 case Instruction::Sub:
489 case Instruction::Shl:
490 case Instruction::AShr:
491 // These can change the upper bits, so clear them now.
492 NewInst = getClearUpper(NewInst, Binop->getType(), Binop);
493 break;
494
495 // We should not see FP operators here.
496 // We don't handle mul/div.
497 case Instruction::FAdd:
498 case Instruction::FSub:
499 case Instruction::Mul:
500 case Instruction::FMul:
501 case Instruction::UDiv:
502 case Instruction::SDiv:
503 case Instruction::FDiv:
504 case Instruction::URem:
505 case Instruction::SRem:
506 case Instruction::FRem:
507 case Instruction::BinaryOpsEnd:
508 errs() << *Inst << "\n";
509 llvm_unreachable("Cannot handle binary operator");
510 break;
511 }
512
513 State.recordConverted(Binop, NewInst);
514 } else if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Inst)) {
515 Value *Op0, *Op1;
516 // For signed compares, operands are sign-extended to their
517 // promoted type. For unsigned or equality compares, the comparison
518 // is equivalent with the larger type because they are already
519 // zero-extended.
520 if (Cmp->isSigned()) {
521 Op0 = getSignExtend(State.getConverted(Cmp->getOperand(0)),
522 Cmp->getOperand(0),
523 Cmp);
524 Op1 = getSignExtend(State.getConverted(Cmp->getOperand(1)),
525 Cmp->getOperand(1),
526 Cmp);
527 } else {
528 Op0 = State.getConverted(Cmp->getOperand(0));
529 Op1 = State.getConverted(Cmp->getOperand(1));
530 }
531 ICmpInst *NewInst = new ICmpInst(
532 Cmp, Cmp->getPredicate(), Op0, Op1, "");
533 State.recordConverted(Cmp, NewInst);
534 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
535 SelectInst *NewInst = SelectInst::Create(
536 Select->getCondition(),
537 State.getConverted(Select->getTrueValue()),
538 State.getConverted(Select->getFalseValue()),
539 "", Select);
540 State.recordConverted(Select, NewInst);
541 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
542 PHINode *NewPhi = PHINode::Create(
543 getPromotedType(Phi->getType()),
544 Phi->getNumIncomingValues(),
545 "", Phi);
546 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; ++I) {
547 NewPhi->addIncoming(State.getConverted(Phi->getIncomingValue(I)),
548 Phi->getIncomingBlock(I));
549 }
550 State.recordConverted(Phi, NewPhi);
551 } else {
552 errs() << *Inst<<"\n";
553 llvm_unreachable("unhandled instruction");
554 }
555 }
556
557 bool PromoteIntegers::runOnFunction(Function &F) {
558 // Don't support changing the function arguments. This should not be
559 // generated by clang.
560 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
561 Value *Arg = I;
562 if (shouldConvert(Arg)) {
563 errs() << "Function " << F.getName() << ": " << *Arg << "\n";
564 llvm_unreachable("Function has illegal integer/pointer argument");
565 }
566 }
567
568 ConversionState State;
569 bool Modified = false;
570 for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
571 for (BasicBlock::iterator BBI = FI->begin(), BBE = FI->end(); BBI != BBE;) {
572 Instruction *Inst = BBI++;
573 // Only attempt to convert an instruction if its result or any of its
574 // operands are illegal.
575 bool ShouldConvert = shouldConvert(Inst);
576 for (User::op_iterator OI = Inst->op_begin(), OE = Inst->op_end();
577 OI != OE; ++OI)
578 ShouldConvert |= shouldConvert(cast<Value>(OI));
579
580 if (ShouldConvert) {
581 convertInstruction(Inst, State);
582 Modified = true;
583 }
584 }
585 }
586
587 return Modified;
588 }
OLDNEW
« no previous file with comments | « lib/Transforms/NaCl/CMakeLists.txt ('k') | test/NaCl/PNaClABI/types.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698