OLD | NEW |
---|---|
(Empty) | |
1 //===- PromoteIntegers.cpp - ---------------------------------------------===// | |
Mark Seaborn
2013/05/06 17:04:06
Add a short description here?
eliben
2013/05/06 21:58:40
IMHO the name "PromoteIntegers" is a bit too gener
Derek Schuff
2013/05/08 22:33:28
Done.
Derek Schuff
2013/05/08 22:33:28
I LegalizeIntegersForPNaCl is even more generic; t
| |
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. | |
eliben
2013/05/06 21:58:40
Beef up this comment with a more detailed descript
Derek Schuff
2013/05/08 22:33:28
Done.
| |
9 // It always maintains the invariant that the upper bits (above the size of the | |
10 // original type) are zero. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 // | |
Mark Seaborn
2013/05/06 17:04:06
Add a longer description here
Derek Schuff
2013/05/08 22:33:28
Done.
| |
14 | |
15 #include "llvm/ADT/DenseMap.h" | |
16 #include "llvm/ADT/SmallVector.h" | |
17 #include "llvm/IR/DerivedTypes.h" | |
18 #include "llvm/IR/Function.h" | |
19 #include "llvm/IR/Instructions.h" | |
20 #include "llvm/IR/IRBuilder.h" | |
21 #include "llvm/Pass.h" | |
22 #include "llvm/Support/raw_ostream.h" | |
23 | |
24 using namespace llvm; | |
25 namespace { | |
26 class PromoteIntegers : public FunctionPass { | |
27 public: | |
28 static char ID; | |
29 PromoteIntegers() : FunctionPass(ID) { | |
30 initializePromoteIntegersPass(*PassRegistry::getPassRegistry()); | |
31 } | |
32 virtual bool runOnFunction(Function &F); | |
33 }; | |
34 } | |
35 | |
36 char PromoteIntegers::ID = 0; | |
37 INITIALIZE_PASS(PromoteIntegers, "nacl-promote-ints", | |
38 "Promote integer types which are illegal in PNaCl", | |
39 false, false); | |
40 | |
41 | |
42 // Legal sizes are currently 1, 8, 16, 32, 64 | |
43 // We can't yet expand types above 64 bit, so don't try to touch them for now. | |
44 static bool isLegalSize(unsigned Size) { | |
Mark Seaborn
2013/05/06 17:04:06
Nit: as a static function (not a method), should t
Derek Schuff
2013/05/08 22:33:28
I don't think LLVM style distinguishes between sta
Mark Seaborn
2013/05/09 01:00:22
http://llvm.org/docs/CodingStandards.html matches
| |
45 // TODO(dschuff): expand >64bit types or disallow >64bit packed bitfields | |
46 if (Size > 64) return true; | |
47 assert(Size <= 64 && "Don't know how to expand > 64bit types yet"); | |
Mark Seaborn
2013/05/06 17:04:06
This assert is redundant given the check above
Derek Schuff
2013/05/08 22:33:28
Done.
| |
48 return isPowerOf2_32(Size) && !(Size & 0x6); | |
Mark Seaborn
2013/05/06 17:04:06
It might be simpler just to list 1, 8, 16, 32, 64
eliben
2013/05/06 21:58:40
I agree
Derek Schuff
2013/05/08 22:33:28
Done.
| |
49 } | |
50 | |
51 // Return a legal integer or pointer-to-integer type, promoting to a larger | |
52 // size if necessary. | |
53 static Type *convertType(Type *Ty) { | |
eliben
2013/05/06 21:58:40
PromoteIntegerType? In general, pick one verb cons
Derek Schuff
2013/05/08 22:33:28
They are basically the same in this context. I ren
| |
54 assert((isa<IntegerType>(Ty) || isa<PointerType>(Ty)) && | |
55 "Trying to convert a non-integer type"); | |
56 IntegerType *ITy; | |
57 if (isa<PointerType>(Ty)) | |
eliben
2013/05/06 21:58:40
Why are you handling pointers at all? I thought we
Derek Schuff
2013/05/08 22:33:28
The general strategy with these passes has been to
| |
58 ITy = dyn_cast<IntegerType>(Ty->getContainedType(0)); | |
59 else | |
60 ITy = dyn_cast<IntegerType>(Ty); | |
61 | |
62 unsigned Width = ITy->getBitWidth(); | |
63 assert(Width <= 64 && "Don't know how to legalize >64 bit types yet"); | |
64 if (isLegalSize(Width)) | |
65 return Ty; | |
66 ITy = IntegerType::get(Ty->getContext(), NextPowerOf2(Width)); | |
67 | |
68 if (isa<PointerType>(Ty)) | |
69 return ITy->getPointerTo(); | |
70 return ITy; | |
71 } | |
72 | |
73 // Return true if Val is an int or pointer-to-int which should be converted. | |
74 static bool shouldConvert(Value *Val) { | |
75 Type *Ty = Val->getType(); | |
76 if (PointerType *Pty = dyn_cast<PointerType>(Ty)) | |
77 Ty = Pty->getContainedType(0); | |
78 if (IntegerType *ITy = dyn_cast<IntegerType>(Ty)) { | |
79 if (!isLegalSize(ITy->getBitWidth())) { | |
80 return true; | |
81 } | |
82 } | |
83 return false; | |
84 } | |
85 | |
86 // Return a constant which has been promoted to a legal size. | |
87 static Value *convertConstant(Constant *C, bool SignExt=false) { | |
88 assert(shouldConvert(C)); | |
89 ConstantInt *CInt = cast<ConstantInt>(C); | |
90 return ConstantInt::get( | |
91 convertType(cast<IntegerType>(CInt->getType())), | |
92 SignExt ? CInt->getSExtValue() : CInt->getZExtValue(), | |
93 /*isSigned=*/SignExt); | |
94 } | |
95 | |
96 class ConversionState { | |
eliben
2013/05/06 21:58:40
Document what this class does and what each of its
Derek Schuff
2013/05/08 22:48:32
Done.
| |
97 public: | |
98 // Return the promoted value for Val. If val has not yet been converted, | |
eliben
2013/05/06 21:58:40
s/val/Val/
Also, you may want to follow the LLVM
Derek Schuff
2013/05/08 22:33:28
do you mean just use doxygen? (i did add doxy comm
eliben
2013/05/09 16:42:19
Yeah, like \p Val for arguments, etc.
| |
99 // return a placeholder, which will be converted later. | |
100 Value *getConverted(Value *Val) { | |
101 if (!shouldConvert(Val)) | |
102 return Val; | |
103 assert(!isa<GlobalVariable>(Val) && "Can't convert GlobalVariables"); | |
104 if (RewrittenMap.count(Val)) | |
105 return RewrittenMap[Val]; | |
106 Value *P; | |
107 // Directly convert constants. | |
108 if (Constant *C = dyn_cast<Constant>(Val)) | |
109 P = convertConstant(C, /*SignExt=*/false); | |
Mark Seaborn
2013/05/06 17:04:06
This shouldn't be inserted into Placeholders, sure
Derek Schuff
2013/05/08 22:33:28
Done.
| |
110 else | |
Mark Seaborn
2013/05/06 17:04:06
Maybe use {}s since using 'else' (not sure if styl
Derek Schuff
2013/05/08 22:33:28
It doesn't, and I've seen it this way in LLVM, but
| |
111 // No converted value available yet, so create a placeholder. | |
112 P = new Argument(convertType(Val->getType())); | |
eliben
2013/05/06 21:58:40
Why doesn't it have a parent?
Derek Schuff
2013/05/08 22:33:28
you mean, the Argument used as a placeholder? It d
eliben
2013/05/09 16:42:19
I mean in terms of memory management. It's not imm
| |
113 RewrittenMap[Val] = P; | |
114 Placeholders[Val] = P; | |
115 return P; | |
116 } | |
117 | |
118 // Replace the uses of From with To, replace the uses of any | |
119 // placeholders for From, and optionally give From's name to To. | |
120 // Also mark To for deletion. | |
121 void recordConverted(Value *From, Value *To, bool TakeName=true) { | |
Mark Seaborn
2013/05/06 17:04:06
Use "Instruction *From" since that's what the func
Derek Schuff
2013/05/08 22:33:28
Done.
| |
122 ToErase.push_back(cast<Instruction>(From)); | |
123 if (!shouldConvert(From)) { | |
124 From->replaceAllUsesWith(To); | |
125 } else { | |
126 if (Placeholders.count(From)) { | |
127 // Resolve placeholders. | |
128 Placeholders[From]->replaceAllUsesWith(To); | |
129 Placeholders.erase(From); | |
130 } | |
131 RewrittenMap[From] = To; | |
132 } | |
133 if (TakeName) { | |
134 To->takeName(From); | |
135 } | |
136 } | |
137 ~ConversionState() { | |
138 for (SmallVectorImpl<Instruction*>::iterator I = ToErase.begin(), | |
139 E = ToErase.end(); I != E; ++I) | |
140 (*I)->dropAllReferences(); | |
141 for (SmallVectorImpl<Instruction*>::iterator I = ToErase.begin(), | |
142 E = ToErase.end(); I != E; ++I) | |
143 (*I)->eraseFromParent(); | |
144 } | |
145 private: | |
146 DenseMap<Value *, Value *> RewrittenMap; | |
147 DenseMap<Value *, Value *> Placeholders; | |
148 SmallVector<Instruction*, 8> ToErase; | |
149 }; | |
150 | |
151 // Split an illegal load into multiple legal loads and return the resulting | |
152 // promoted value. The size of the load is assumed to be a multiple of 8. | |
153 static Value *splitLoad(LoadInst *Inst, ConversionState &State) { | |
154 assert(!Inst->isVolatile() && !Inst->isAtomic() && | |
eliben
2013/05/06 21:58:40
Do we disallow/hide volatile loads for PNaCl?
Derek Schuff
2013/05/08 22:33:28
I'm not sure we've converged on that yet. but cert
| |
155 "Can't split volatile/atomic loads"); | |
156 assert(cast<IntegerType>(Inst->getType())->getBitWidth() % 8 == 0); | |
157 | |
158 Value *OrigPtr = State.getConverted(Inst->getPointerOperand()); | |
159 // OrigPtr is a placeholder in recursive calls, and so has no name | |
160 if (OrigPtr->getName().empty()) | |
161 OrigPtr->setName(Inst->getPointerOperand()->getName()); | |
162 unsigned Width = cast<IntegerType>(Inst->getType())->getBitWidth(); | |
163 Type *NewType = convertType(Inst->getType()); | |
164 unsigned LoWidth = Width; | |
165 | |
166 while (!isLegalSize(LoWidth)) LoWidth -= 8; | |
167 IntegerType *LoType = IntegerType::get(Inst->getContext(), LoWidth); | |
168 IntegerType *HiType = IntegerType::get(Inst->getContext(), Width - LoWidth); | |
169 IRBuilder<> IRB(Inst->getParent(), Inst); | |
170 | |
171 Value *BCLo = IRB.CreateBitCast( | |
172 OrigPtr, | |
173 LoType->getPointerTo(), | |
174 OrigPtr->getName() + ".loty"); | |
175 Value *LoadLo = IRB.CreateAlignedLoad( | |
176 BCLo, Inst->getAlignment(), Inst->getName() + ".lo"); | |
177 Value *LoExt = IRB.CreateZExt(LoadLo, NewType, LoadLo->getName() + ".ext"); | |
178 Value *GEPHi = IRB.CreateConstGEP1_32(BCLo, 1, OrigPtr->getName() + ".hi"); | |
179 Value *BCHi = IRB.CreateBitCast( | |
180 GEPHi, | |
181 HiType->getPointerTo(), | |
182 OrigPtr->getName() + ".hity"); | |
183 | |
184 Value *LoadHi = IRB.CreateLoad(BCHi, Inst->getName() + ".hi"); | |
185 if (!isLegalSize(Width - LoWidth)) { | |
186 LoadHi = splitLoad(cast<LoadInst>(LoadHi), State); | |
187 // BCHi was still illegal, and has been replaced with a placeholder in the | |
188 // recursive call. Since it is redundant with BCLo in the recursive call, | |
189 // just splice it out entirely. | |
190 State.recordConverted(BCHi, GEPHi, /*TakeName=*/false); | |
191 } | |
192 | |
193 Value *HiExt = IRB.CreateZExt(LoadHi, NewType, LoadHi->getName() + ".ext"); | |
194 Value *HiShift = IRB.CreateShl(HiExt, LoWidth, HiExt->getName() + ".sh"); | |
195 Value *Result = IRB.CreateOr(LoExt, HiShift); | |
196 | |
197 State.recordConverted(Inst, Result); | |
198 | |
199 return Result; | |
200 } | |
201 | |
202 static Value *splitStore(StoreInst *Inst, ConversionState &State) { | |
203 assert(!Inst->isVolatile() && !Inst->isAtomic() && | |
204 "Can't split volatile/atomic stores"); | |
205 assert(cast<IntegerType>(Inst->getValueOperand()->getType())->getBitWidth() % 8 == 0); | |
Mark Seaborn
2013/05/06 17:04:06
Line >80 chars
Derek Schuff
2013/05/08 22:33:28
Done.
| |
206 | |
207 Value *OrigPtr = State.getConverted(Inst->getPointerOperand()); | |
208 // OrigPtr is now a placeholder in recursive calls, and so has no name | |
209 if (OrigPtr->getName().empty()) | |
210 OrigPtr->setName(Inst->getPointerOperand()->getName()); | |
211 Value *OrigVal = State.getConverted(Inst->getValueOperand()); | |
212 unsigned Width = cast<IntegerType>( | |
213 Inst->getValueOperand()->getType())->getBitWidth(); | |
214 unsigned LoWidth = Width; | |
215 | |
216 while (!isLegalSize(LoWidth)) LoWidth -= 8; | |
217 IntegerType *LoType = IntegerType::get(Inst->getContext(), LoWidth); | |
218 IntegerType *HiType = IntegerType::get(Inst->getContext(), Width - LoWidth); | |
219 IRBuilder<> IRB(Inst->getParent(), Inst); | |
220 | |
221 Value *BCLo = IRB.CreateBitCast( | |
222 OrigPtr, | |
223 LoType->getPointerTo(), | |
224 OrigPtr->getName() + ".loty"); | |
225 Value *LoTrunc = IRB.CreateTrunc( | |
226 OrigVal, LoType, OrigVal->getName() + ".lo"); | |
227 IRB.CreateAlignedStore(LoTrunc, BCLo, Inst->getAlignment()); | |
228 | |
229 Value *HiLShr = IRB.CreateLShr( | |
230 OrigVal, LoWidth, OrigVal->getName() + ".hi.sh"); | |
231 Value *GEPHi = IRB.CreateConstGEP1_32(BCLo, 1, OrigPtr->getName() + ".hi"); | |
232 Value *HiTrunc = IRB.CreateTrunc( | |
233 HiLShr, HiType, OrigVal->getName() + ".hi"); | |
234 Value *BCHi = IRB.CreateBitCast( | |
235 GEPHi, | |
236 HiType->getPointerTo(), | |
237 OrigPtr->getName() + ".hity"); | |
238 | |
239 Value *StoreHi = IRB.CreateStore(HiTrunc, BCHi); | |
240 | |
241 if (!isLegalSize(Width - LoWidth)) { | |
242 // HiTrunc is still illegal, and is redundant with the truncate in the | |
243 // recursive call, so just get rid of it. | |
244 State.recordConverted(HiTrunc, HiLShr, /*TakeName=*/false); | |
245 StoreHi = splitStore(cast<StoreInst>(StoreHi), State); | |
246 // BCHi was still illegal, and has been replaced with a placeholder in the | |
247 // recursive call. Since it is redundant with BCLo in the recursive call, | |
248 // just splice it out entirely. | |
249 State.recordConverted(BCHi, GEPHi, /*TakeName=*/false); | |
250 } | |
251 State.recordConverted(Inst, StoreHi, /*TakeName=*/false); | |
252 return StoreHi; | |
253 } | |
254 | |
255 // Return a value with the bits of the operand above the size of the original | |
256 // type cleared. The operand is assumed to have been legalized already. | |
257 static Value *getClearUpper(Value *Operand, Type *OrigType, | |
258 Instruction *InsertPt) { | |
259 // If the operand is a constant, it will have been created by | |
260 // ConversionState.getConverted, which zero-extends by default. | |
261 if (isa<Constant>(Operand)) | |
262 return Operand; | |
263 return BinaryOperator::Create( | |
264 Instruction::And, | |
265 Operand, | |
266 ConstantInt::get( | |
267 convertType(OrigType), | |
268 APInt::getLowBitsSet(convertType(OrigType)->getIntegerBitWidth(), | |
269 OrigType->getIntegerBitWidth())), | |
270 Operand->getName() + ".clear", | |
271 InsertPt); | |
272 } | |
273 | |
274 // Return a value with the bits of the operand above the size of the original | |
275 // type equal to the sign bit of the original operand. The new operand is | |
276 // assumed to have been legalized already. | |
277 // This is done by shifting the sign bit of the smaller value up to the MSB | |
278 // position in the larger size, and then arithmetic-shifting it back down | |
279 static Value *getSignExtend(Value *Operand, Value *OrigOperand, | |
280 Instruction *InsertPt) { | |
281 // If OrigOperand was a constant, NewOperand will have been created by | |
282 // ConversionState.getConverted, which zero-extends by default. But that is | |
283 // wrong here, so replace it with a sign-extended constant. | |
284 if (Constant *C = dyn_cast<Constant>(OrigOperand)) | |
285 return convertConstant(C, /*SignExt=*/true); | |
286 Type *OrigType = OrigOperand->getType(); | |
287 ConstantInt *ShiftAmt = ConstantInt::getSigned( | |
288 cast<IntegerType>(convertType(OrigType)), | |
289 convertType(OrigType)->getIntegerBitWidth() - | |
290 OrigType->getIntegerBitWidth()); | |
291 BinaryOperator *Shl = BinaryOperator::Create( | |
292 Instruction::Shl, | |
293 Operand, | |
294 ShiftAmt, | |
295 Operand->getName() + ".getsign", | |
296 InsertPt); | |
297 return BinaryOperator::Create( | |
298 Instruction::AShr, | |
299 Shl, | |
300 ShiftAmt, | |
301 Operand->getName() + ".signed", | |
302 InsertPt); | |
303 } | |
304 | |
305 bool PromoteIntegers::runOnFunction(Function &F) { | |
306 ConversionState State; | |
307 // Don't support changing the function arguments. This should not be | |
308 // generated by clang. | |
309 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { | |
310 Value *Arg = I; | |
311 if (shouldConvert(Arg)) { | |
312 errs() << "Function " << F.getName() << ": " << *Arg << "\n"; | |
313 llvm_unreachable("Cannot convert function with illegal argument"); | |
eliben
2013/05/06 21:58:40
"Convert" is too generic.
"Function argument has
Derek Schuff
2013/05/08 22:33:28
Done.
| |
314 } | |
315 } | |
316 | |
317 for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) { | |
318 for (BasicBlock::iterator BBI = FI->begin(), BBE = FI->end(); BBI != BBE;) { | |
319 Instruction *Inst = BBI++; | |
320 bool ShouldConvert = shouldConvert(Inst); | |
eliben
2013/05/06 21:58:40
Comment to clarify the |=...
Derek Schuff
2013/05/08 22:33:28
Done.
| |
321 for (User::op_iterator OI = Inst->op_begin(), OE = Inst->op_end(); | |
322 OI != OE; ++OI) | |
323 ShouldConvert |= shouldConvert(cast<Value>(OI)); | |
324 if (!ShouldConvert) | |
325 continue; | |
326 | |
327 if (SExtInst *Sext = dyn_cast<SExtInst>(Inst)) { | |
Mark Seaborn
2013/05/06 17:04:06
Maybe move this if/else chain to a top-level funct
Derek Schuff
2013/05/08 22:48:32
Done.
| |
328 Value *Op = Sext->getOperand(0); | |
329 Value *NewInst = NULL; | |
330 if (shouldConvert(Op)) { | |
331 NewInst = getSignExtend(State.getConverted(Op), Op, Sext); | |
332 } | |
333 if (convertType(Op->getType()) != convertType(Sext->getType())) { | |
eliben
2013/05/06 21:58:40
Comment to explain the logic here
Derek Schuff
2013/05/08 22:33:28
Done.
| |
334 NewInst = CastInst::CreateSExtOrBitCast( | |
335 NewInst ? NewInst : State.getConverted(Op), | |
336 convertType(cast<IntegerType>(Sext->getType())), | |
337 Sext->getName() + ".sext", Sext); | |
338 } | |
339 if (shouldConvert(Sext)) { | |
340 NewInst = getClearUpper(NewInst, Sext->getType(), Sext); | |
341 } | |
342 assert(NewInst && "Failed to convert sign extension"); | |
343 State.recordConverted(Sext, NewInst); | |
344 } else if (ZExtInst *Zext = dyn_cast<ZExtInst>(Inst)) { | |
345 Value *Op = Zext->getOperand(0); | |
346 Value *NewInst = NULL; | |
347 // TODO(dschuff): Some of these zexts could be no-ops. | |
348 if (shouldConvert(Op)) { | |
349 NewInst = getClearUpper(State.getConverted(Op), | |
350 Op->getType(), | |
351 Zext); | |
352 } | |
353 if (convertType(Op->getType()) != convertType(Zext->getType())) { | |
354 NewInst = CastInst::CreateZExtOrBitCast( | |
355 NewInst ? NewInst : State.getConverted(Op), | |
356 convertType(cast<IntegerType>(Zext->getType())), | |
357 "", Zext); | |
358 } | |
359 assert(NewInst); | |
360 State.recordConverted(Zext, NewInst); | |
361 } else if (TruncInst *Trunc = dyn_cast<TruncInst>(Inst)) { | |
362 Value *Op = Trunc->getOperand(0); | |
363 Value *NewInst = NULL; | |
364 if (convertType(Op->getType()) != convertType(Trunc->getType())) { | |
365 NewInst = new TruncInst( | |
366 State.getConverted(Op), | |
367 convertType(cast<IntegerType>(Trunc->getType())), | |
368 State.getConverted(Op)->getName() + ".trunc", | |
369 Trunc); | |
370 } | |
371 if (shouldConvert(Trunc)) { | |
eliben
2013/05/06 21:58:40
Here and below, didn't you already establish Shoul
Derek Schuff
2013/05/08 22:33:28
Either the result or the operand needs to be conve
| |
372 NewInst = getClearUpper(NewInst ? NewInst : Op, | |
373 Trunc->getType(), | |
374 Trunc); | |
375 } | |
376 assert(NewInst); | |
377 State.recordConverted(Trunc, NewInst); | |
378 } else if (AllocaInst *Alloc = dyn_cast<AllocaInst>(Inst)) { | |
379 // Don't handle arrays of illegal types, but we could handle an array | |
380 // with size specified as an illegal type, as unlikely as that seems. | |
381 assert(!(shouldConvert(Alloc) && Alloc->isArrayAllocation())); | |
382 AllocaInst *NewInst = new AllocaInst( | |
383 convertType(Alloc->getAllocatedType()), | |
384 State.getConverted(Alloc->getArraySize()), | |
385 "", Alloc); | |
386 NewInst->setAlignment(Alloc->getAlignment()); | |
387 State.recordConverted(Alloc, NewInst); | |
388 } else if (BitCastInst *BCInst = dyn_cast<BitCastInst>(Inst)) { | |
389 // Only handle pointers. Ints can't be casted to/from other ints | |
Mark Seaborn
2013/05/06 17:04:06
It looks like you're trying to expand out pointers
Derek Schuff
2013/05/08 22:33:28
It's really not that much more complex to also cha
Mark Seaborn
2013/05/09 01:00:22
This seems to touch:
* getPromotedType()
* shoul
| |
390 if (shouldConvert(BCInst) || shouldConvert(BCInst->getOperand(0))) { | |
391 BitCastInst *NewInst = new BitCastInst( | |
392 State.getConverted(BCInst->getOperand(0)), | |
393 convertType(BCInst->getDestTy()), | |
394 "", BCInst); | |
395 State.recordConverted(BCInst, NewInst); | |
396 } | |
397 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { | |
398 if (shouldConvert(Load)) { | |
399 splitLoad(Load, State); | |
400 } | |
401 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { | |
402 if (shouldConvert(Store->getValueOperand())) { | |
403 splitStore(Store, State); | |
404 } | |
405 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) { | |
406 llvm_unreachable("can't convert calls"); | |
eliben
2013/05/06 21:58:40
Is this temporary? If not, why the code after it?
| |
407 for (unsigned I = 0; I < Call->getNumArgOperands(); ++I) { | |
408 Value *Arg = Call->getArgOperand(I); | |
409 Call->setArgOperand(I, State.getConverted(Arg)); | |
410 } | |
411 } else if (BinaryOperator *Binop = dyn_cast<BinaryOperator>(Inst)) { | |
412 Value *NewInst = NULL; | |
413 if (Binop->getOpcode() == Instruction::AShr) { | |
eliben
2013/05/06 21:58:40
Can't this be done in the same switch below?
Derek Schuff
2013/05/08 22:33:28
No; AShr needs to sign-extend its operand before d
| |
414 // Combine the sign-extension with the actual AShr operation. | |
415 Value *Op = Binop->getOperand(0); | |
416 Value *ShiftAmount = NULL; | |
417 APInt SignShiftAmt = APInt( | |
418 convertType(Op->getType())->getIntegerBitWidth(), | |
419 convertType(Op->getType())->getIntegerBitWidth() - | |
420 Op->getType()->getIntegerBitWidth()); | |
421 NewInst = BinaryOperator::Create( | |
422 Instruction::Shl, | |
423 State.getConverted(Op), | |
424 ConstantInt::get(convertType(Op->getType()), SignShiftAmt), | |
425 State.getConverted(Op)->getName() + ".getsign", | |
426 Binop); | |
427 if (ConstantInt *C = dyn_cast<ConstantInt>( | |
428 State.getConverted(Binop->getOperand(1)))) { | |
429 ShiftAmount = ConstantInt::get(convertType(Op->getType()), | |
430 SignShiftAmt + C->getValue()); | |
431 } else { | |
432 ShiftAmount = BinaryOperator::Create( | |
433 Instruction::Add, | |
434 State.getConverted(Binop->getOperand(1)), | |
435 ConstantInt::get(convertType(Binop->getOperand(1)->getType()), | |
436 SignShiftAmt), | |
437 State.getConverted(Op)->getName() + ".shamt", Binop); | |
438 } | |
439 NewInst = BinaryOperator::Create( | |
440 Instruction::AShr, | |
441 NewInst, | |
442 ShiftAmount, | |
443 Binop->getName() + ".result", Binop); | |
444 } else { | |
445 NewInst = BinaryOperator::Create( | |
446 Binop->getOpcode(), | |
447 NewInst ? NewInst : State.getConverted(Binop->getOperand(0)), | |
448 State.getConverted(Binop->getOperand(1)), | |
449 Binop->getName() + ".result", Binop); | |
450 } | |
451 | |
452 switch (Binop->getOpcode()) { | |
453 case Instruction::And: | |
454 case Instruction::Or: | |
455 case Instruction::Xor: | |
456 case Instruction::LShr: | |
457 // These won't change the upper bits. | |
458 break; | |
459 case Instruction::Add: | |
460 case Instruction::Sub: | |
461 case Instruction::Shl: | |
462 case Instruction::AShr: | |
463 // These can change the upper bits, so clear them now. | |
464 NewInst = getClearUpper(NewInst, Binop->getType(), Binop); | |
465 break; | |
466 | |
467 // We should not see FP operators here. | |
468 // We don't handle mul/div. | |
469 case Instruction::FAdd: | |
470 case Instruction::FSub: | |
471 case Instruction::Mul: | |
472 case Instruction::FMul: | |
473 case Instruction::UDiv: | |
474 case Instruction::SDiv: | |
475 case Instruction::FDiv: | |
476 case Instruction::URem: | |
477 case Instruction::SRem: | |
478 case Instruction::FRem: | |
479 case Instruction::BinaryOpsEnd: | |
480 errs() << *Inst << "\n"; | |
481 llvm_unreachable("Cannot handle binary operator"); | |
482 break; | |
483 } | |
484 | |
485 State.recordConverted(Binop, NewInst); | |
486 } else if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Inst)) { | |
487 Value *Op0, *Op1; | |
eliben
2013/05/06 21:58:40
Comment
Derek Schuff
2013/05/08 22:33:28
Done.
| |
488 if (Cmp->isSigned()) { | |
489 Op0 = getSignExtend(State.getConverted(Cmp->getOperand(0)), | |
490 Cmp->getOperand(0), | |
491 Cmp); | |
492 Op1 = getSignExtend(State.getConverted(Cmp->getOperand(1)), | |
493 Cmp->getOperand(1), | |
494 Cmp); | |
495 } else { | |
496 Op0 = State.getConverted(Cmp->getOperand(0)); | |
497 Op1 = State.getConverted(Cmp->getOperand(1)); | |
498 } | |
499 ICmpInst *NewInst = new ICmpInst( | |
500 Cmp, Cmp->getPredicate(), Op0, Op1, ""); | |
501 State.recordConverted(Cmp, NewInst); | |
502 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) { | |
503 SelectInst *NewInst = SelectInst::Create( | |
504 Select->getCondition(), | |
505 State.getConverted(Select->getTrueValue()), | |
506 State.getConverted(Select->getFalseValue()), | |
507 "", Select); | |
508 State.recordConverted(Select, NewInst); | |
509 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { | |
510 PHINode *NewPhi = PHINode::Create( | |
511 convertType(Phi->getType()), | |
512 Phi->getNumIncomingValues(), | |
513 "", Phi); | |
514 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; ++I) { | |
515 NewPhi->addIncoming(State.getConverted(Phi->getIncomingValue(I)), | |
516 Phi->getIncomingBlock(I)); | |
517 } | |
518 State.recordConverted(Phi, NewPhi); | |
519 } else { | |
520 errs() << *Inst<<"\n"; | |
521 llvm_unreachable("unhandled instruction"); | |
522 } | |
523 } | |
524 } | |
525 | |
526 return true; | |
527 } | |
OLD | NEW |