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

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

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod 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
« no previous file with comments | « lib/Transforms/NaCl/ExpandIndirectBr.cpp ('k') | lib/Transforms/NaCl/ExpandShuffleVector.cpp » ('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 //===- ExpandLargeIntegers.cpp - Expand 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 expand illegal-sized int types.
9 //
10 //===----------------------------------------------------------------------===//
11 //
12 // Legal sizes for the purposes of expansion are anything 64 bits or less.
13 // Operations on large integers are split into operations on smaller-sized
14 // integers. The low parts should always be powers of 2, but the high parts may
15 // not be. A subsequent pass can promote those. For now this pass only intends
16 // to support the uses generated by clang, which is basically just for large
17 // bitfields.
18 //
19 // Limitations:
20 // 1) It can't change function signatures or global variables.
21 // 3) Doesn't support mul, div/rem, switch.
22 // 4) Doesn't handle arrays or structs (or GEPs) with illegal types.
23 // 5) Doesn't handle constant expressions (it also doesn't produce them, so it
24 // can run after ExpandConstantExpr).
25 //
26 //===----------------------------------------------------------------------===//
27
28 #include "llvm/ADT/DenseMap.h"
29 #include "llvm/ADT/PostOrderIterator.h"
30 #include "llvm/ADT/STLExtras.h"
31 #include "llvm/ADT/SmallVector.h"
32 #include "llvm/IR/CFG.h"
33 #include "llvm/IR/DataLayout.h"
34 #include "llvm/IR/DerivedTypes.h"
35 #include "llvm/IR/Function.h"
36 #include "llvm/IR/IRBuilder.h"
37 #include "llvm/IR/Instructions.h"
38 #include "llvm/Pass.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Support/MathExtras.h"
41 #include "llvm/Support/raw_ostream.h"
42 #include "llvm/Transforms/NaCl.h"
43
44 using namespace llvm;
45
46 #define DEBUG_TYPE "nacl-expand-ints"
47
48 // Break instructions up into no larger than 64-bit chunks.
49 static const unsigned kChunkBits = 64;
50 static const unsigned kChunkBytes = kChunkBits / CHAR_BIT;
51
52 namespace {
53 class ExpandLargeIntegers : public FunctionPass {
54 public:
55 static char ID;
56 ExpandLargeIntegers() : FunctionPass(ID) {
57 initializeExpandLargeIntegersPass(*PassRegistry::getPassRegistry());
58 }
59 bool runOnFunction(Function &F) override;
60 };
61
62 template <typename T> struct LoHiPair {
63 T Lo, Hi;
64 LoHiPair() : Lo(), Hi() {}
65 LoHiPair(T Lo, T Hi) : Lo(Lo), Hi(Hi) {}
66 };
67 template <typename T> struct LoHiBitTriple {
68 T Lo, Hi, Bit;
69 LoHiBitTriple() : Lo(), Hi(), Bit() {}
70 LoHiBitTriple(T Lo, T Hi, T Bit) : Lo(Lo), Hi(Hi), Bit(Bit) {}
71 };
72 typedef LoHiPair<IntegerType *> TypePair;
73 typedef LoHiPair<Value *> ValuePair;
74 typedef LoHiPair<unsigned> AlignPair;
75 typedef LoHiBitTriple<Value *> ValueTriple;
76
77 // Information needed to patch a phi node which forward-references a value.
78 struct ForwardPHI {
79 Value *Val;
80 PHINode *Lo, *Hi;
81 unsigned ValueNumber;
82 ForwardPHI(Value *Val, PHINode *Lo, PHINode *Hi, unsigned ValueNumber)
83 : Val(Val), Lo(Lo), Hi(Hi), ValueNumber(ValueNumber) {}
84 };
85 }
86
87 char ExpandLargeIntegers::ID = 0;
88 INITIALIZE_PASS(ExpandLargeIntegers, "nacl-expand-ints",
89 "Expand integer types that are illegal in PNaCl", false, false)
90
91 #define DIE_IF(COND, VAL, MSG) \
92 do { \
93 if (COND) { \
94 errs() << "Unsupported: " << *(VAL) << '\n'; \
95 report_fatal_error( \
96 MSG " not yet supported for integer types larger than 64 bits"); \
97 } \
98 } while (0)
99
100 static bool isLegalBitSize(unsigned Bits) {
101 assert(Bits && "Can't have zero-size integers");
102 return Bits <= kChunkBits;
103 }
104
105 static TypePair getExpandedIntTypes(Type *Ty) {
106 unsigned BitWidth = Ty->getIntegerBitWidth();
107 assert(!isLegalBitSize(BitWidth));
108 return {IntegerType::get(Ty->getContext(), kChunkBits),
109 IntegerType::get(Ty->getContext(), BitWidth - kChunkBits)};
110 }
111
112 // Return true if Val is an int which should be converted.
113 static bool shouldConvert(const Value *Val) {
114 Type *Ty = Val->getType();
115 if (IntegerType *ITy = dyn_cast<IntegerType>(Ty))
116 return !isLegalBitSize(ITy->getBitWidth());
117 return false;
118 }
119
120 // Return a pair of constants expanded from C.
121 static ValuePair expandConstant(Constant *C) {
122 assert(shouldConvert(C));
123 TypePair ExpandedTypes = getExpandedIntTypes(C->getType());
124 if (isa<UndefValue>(C)) {
125 return {UndefValue::get(ExpandedTypes.Lo),
126 UndefValue::get(ExpandedTypes.Hi)};
127 } else if (ConstantInt *CInt = dyn_cast<ConstantInt>(C)) {
128 Constant *ShiftAmt = ConstantInt::get(
129 CInt->getType(), ExpandedTypes.Lo->getBitWidth(), false);
130 return {ConstantExpr::getTrunc(CInt, ExpandedTypes.Lo),
131 ConstantExpr::getTrunc(ConstantExpr::getLShr(CInt, ShiftAmt),
132 ExpandedTypes.Hi)};
133 }
134 DIE_IF(true, C, "Constant value");
135 }
136
137 template <typename T>
138 static AlignPair getAlign(const DataLayout &DL, T *I, Type *PrefAlignTy) {
139 unsigned LoAlign = I->getAlignment();
140 if (LoAlign == 0)
141 LoAlign = DL.getPrefTypeAlignment(PrefAlignTy);
142 unsigned HiAlign = MinAlign(LoAlign, kChunkBytes);
143 return {LoAlign, HiAlign};
144 }
145
146 static ValuePair createBit(IRBuilder<> *IRB, const BinaryOperator *Binop,
147 const ValuePair &Lhs, const ValuePair &Rhs,
148 const TypePair &Tys, const StringRef &Name) {
149 auto Op = Binop->getOpcode();
150 Value *Lo = IRB->CreateBinOp(Op, Lhs.Lo, Rhs.Lo, Twine(Name, ".lo"));
151 Value *Hi = IRB->CreateBinOp(Op, Lhs.Hi, Rhs.Hi, Twine(Name, ".hi"));
152 return {Lo, Hi};
153 }
154
155 static ValuePair createShl(IRBuilder<> *IRB, const BinaryOperator *Binop,
156 const ValuePair &Lhs, const ValuePair &Rhs,
157 const TypePair &Tys, const StringRef &Name) {
158 ConstantInt *ShlAmount = dyn_cast<ConstantInt>(Rhs.Lo);
159 // TODO(dschuff): Expansion of variable-sized shifts isn't supported
160 // because the behavior depends on whether the shift amount is less than
161 // the size of the low part of the expanded type, and I haven't yet
162 // figured out a way to do it for variable-sized shifts without splitting
163 // the basic block. I don't believe it's actually necessary for
164 // bitfields. Likewise for LShr below.
165 DIE_IF(!ShlAmount, Binop, "Expansion of variable-sized shifts");
166 unsigned ShiftAmount = ShlAmount->getZExtValue();
167 if (ShiftAmount >= Binop->getType()->getIntegerBitWidth())
168 ShiftAmount = 0; // Undefined behavior.
169 unsigned HiBits = Tys.Hi->getIntegerBitWidth();
170 // |<------------Hi---------->|<-------Lo------>|
171 // | | |
172 // +--------+--------+--------+--------+--------+
173 // |abcdefghijklmnopqrstuvwxyz|ABCDEFGHIJKLMNOPQ|
174 // +--------+--------+--------+--------+--------+
175 // Possible shifts:
176 // |efghijklmnopqrstuvwxyzABCD|EFGHIJKLMNOPQ0000| Some Lo into Hi.
177 // |vwxyzABCDEFGHIJKLMNOPQ0000|00000000000000000| Lo is 0, keep some Hi.
178 // |DEFGHIJKLMNOPQ000000000000|00000000000000000| Lo is 0, no Hi left.
179 Value *Lo, *Hi;
180 if (ShiftAmount < kChunkBits) {
181 Lo = IRB->CreateShl(Lhs.Lo, ShiftAmount, Twine(Name, ".lo"));
182 Hi =
183 IRB->CreateZExtOrTrunc(IRB->CreateLShr(Lhs.Lo, kChunkBits - ShiftAmount,
184 Twine(Name, ".lo.shr")),
185 Tys.Hi, Twine(Name, ".lo.ext"));
186 } else {
187 Lo = ConstantInt::get(Tys.Lo, 0);
188 Hi = IRB->CreateShl(
189 IRB->CreateZExtOrTrunc(Lhs.Lo, Tys.Hi, Twine(Name, ".lo.ext")),
190 ShiftAmount - kChunkBits, Twine(Name, ".lo.shl"));
191 }
192 if (ShiftAmount < HiBits)
193 Hi = IRB->CreateOr(
194 Hi, IRB->CreateShl(Lhs.Hi, ShiftAmount, Twine(Name, ".hi.shl")),
195 Twine(Name, ".or"));
196 return {Lo, Hi};
197 }
198
199 static ValuePair createShr(IRBuilder<> *IRB, const BinaryOperator *Binop,
200 const ValuePair &Lhs, const ValuePair &Rhs,
201 const TypePair &Tys, const StringRef &Name) {
202 auto Op = Binop->getOpcode();
203 ConstantInt *ShrAmount = dyn_cast<ConstantInt>(Rhs.Lo);
204 // TODO(dschuff): Expansion of variable-sized shifts isn't supported
205 // because the behavior depends on whether the shift amount is less than
206 // the size of the low part of the expanded type, and I haven't yet
207 // figured out a way to do it for variable-sized shifts without splitting
208 // the basic block. I don't believe it's actually necessary for bitfields.
209 DIE_IF(!ShrAmount, Binop, "Expansion of variable-sized shifts");
210 bool IsArith = Op == Instruction::AShr;
211 unsigned ShiftAmount = ShrAmount->getZExtValue();
212 if (ShiftAmount >= Binop->getType()->getIntegerBitWidth())
213 ShiftAmount = 0; // Undefined behavior.
214 unsigned HiBitWidth = Tys.Hi->getIntegerBitWidth();
215 // |<--Hi-->|<-------Lo------>|
216 // | | |
217 // +--------+--------+--------+
218 // |abcdefgh|ABCDEFGHIJKLMNOPQ|
219 // +--------+--------+--------+
220 // Possible shifts (0 is sign when doing AShr):
221 // |0000abcd|defgABCDEFGHIJKLM| Some Hi into Lo.
222 // |00000000|00abcdefgABCDEFGH| Hi is 0, keep some Lo.
223 // |00000000|000000000000abcde| Hi is 0, no Lo left.
224 Value *Lo, *Hi;
225 if (ShiftAmount < kChunkBits) {
226 Lo = IRB->CreateShl(
227 IsArith
228 ? IRB->CreateSExtOrTrunc(Lhs.Hi, Tys.Lo, Twine(Name, ".hi.ext"))
229 : IRB->CreateZExtOrTrunc(Lhs.Hi, Tys.Lo, Twine(Name, ".hi.ext")),
230 kChunkBits - ShiftAmount, Twine(Name, ".hi.shl"));
231 Lo = IRB->CreateOr(
232 Lo, IRB->CreateLShr(Lhs.Lo, ShiftAmount, Twine(Name, ".lo.shr")),
233 Twine(Name, ".lo"));
234 } else {
235 Lo = IRB->CreateBinOp(Op, Lhs.Hi,
236 ConstantInt::get(Tys.Hi, ShiftAmount - kChunkBits),
237 Twine(Name, ".hi.shr"));
238 Lo = IsArith ? IRB->CreateSExtOrTrunc(Lo, Tys.Lo, Twine(Name, ".lo.ext"))
239 : IRB->CreateZExtOrTrunc(Lo, Tys.Lo, Twine(Name, ".lo.ext"));
240 }
241 if (ShiftAmount < HiBitWidth) {
242 Hi = IRB->CreateBinOp(Op, Lhs.Hi, ConstantInt::get(Tys.Hi, ShiftAmount),
243 Twine(Name, ".hi"));
244 } else {
245 Hi = IsArith ? IRB->CreateAShr(Lhs.Hi, HiBitWidth - 1, Twine(Name, ".hi"))
246 : ConstantInt::get(Tys.Hi, 0);
247 }
248 return {Lo, Hi};
249 }
250
251 static Value *createCarry(IRBuilder<> *IRB, Value *Lhs, Value *Rhs,
252 Value *Added, Type *Ty, const StringRef &Name) {
253 return IRB->CreateZExt(
254 IRB->CreateICmpULT(
255 Added,
256 IRB->CreateSelect(IRB->CreateICmpULT(Lhs, Rhs, Twine(Name, ".cmp")),
257 Rhs, Lhs, Twine(Name, ".limit")),
258 Twine(Name, ".overflowed")),
259 Ty, Twine(Name, ".carry"));
260 }
261
262 static ValueTriple createAdd(IRBuilder<> *IRB, const ValuePair &Lhs,
263 const ValuePair &Rhs, const TypePair &Tys,
264 const StringRef &Name, Type *HiCarryTy) {
265 auto Op = Instruction::Add;
266 // Don't propagate NUW/NSW to the lo operation: it can overflow.
267 Value *Lo = IRB->CreateBinOp(Op, Lhs.Lo, Rhs.Lo, Twine(Name, ".lo"));
268 Value *LoCarry = createCarry(IRB, Lhs.Lo, Rhs.Lo, Lo, Tys.Hi, Name);
269 // TODO(jfb) The hi operation could be tagged with NUW/NSW.
270 Value *HiAdd = IRB->CreateBinOp(Op, Lhs.Hi, Rhs.Hi, Twine(Name, ".hi"));
271 Value *Hi = IRB->CreateBinOp(Op, HiAdd, LoCarry, Twine(Name, ".carried"));
272 Value *HiCarry = HiCarryTy
273 ? createCarry(IRB, Lhs.Hi, Rhs.Hi, Hi, HiCarryTy, Name)
274 : nullptr;
275 return {Lo, Hi, HiCarry};
276 }
277
278 static ValuePair createSub(IRBuilder<> *IRB, const ValuePair &Lhs,
279 const ValuePair &Rhs, const TypePair &Tys,
280 const StringRef &Name) {
281 auto Op = Instruction::Sub;
282 Value *Borrowed = IRB->CreateSExt(
283 IRB->CreateICmpULT(Lhs.Lo, Rhs.Lo, Twine(Name, ".borrow")), Tys.Hi,
284 Twine(Name, ".borrowing"));
285 Value *Lo = IRB->CreateBinOp(Op, Lhs.Lo, Rhs.Lo, Twine(Name, ".lo"));
286 Value *Hi =
287 IRB->CreateBinOp(Instruction::Add,
288 IRB->CreateBinOp(Op, Lhs.Hi, Rhs.Hi, Twine(Name, ".hi")),
289 Borrowed, Twine(Name, ".borrowed"));
290 return {Lo, Hi};
291 }
292
293 static Value *createICmpEquality(IRBuilder<> *IRB, CmpInst::Predicate Pred,
294 const ValuePair &Lhs, const ValuePair &Rhs,
295 const StringRef &Name) {
296 assert(Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE);
297 Value *Lo = IRB->CreateICmp(Pred, Lhs.Lo, Rhs.Lo, Twine(Name, ".lo"));
298 Value *Hi = IRB->CreateICmp(Pred, Lhs.Hi, Rhs.Hi, Twine(Name, ".hi"));
299 return IRB->CreateBinOp(
300 Instruction::And, Lo, Hi,
301 Twine(Name, Pred == CmpInst::ICMP_EQ ? ".eq" : ".ne"));
302 }
303
304 static Value *createICmp(IRBuilder<> *IRB, const ICmpInst *ICmp,
305 const ValuePair &Lhs, const ValuePair &Rhs,
306 const TypePair &Tys, const StringRef &Name) {
307 auto Pred = ICmp->getPredicate();
308 switch (Pred) {
309 case CmpInst::ICMP_EQ:
310 case CmpInst::ICMP_NE:
311 return createICmpEquality(IRB, ICmp->getPredicate(), Lhs, Rhs, Name);
312
313 case CmpInst::ICMP_UGT: // C == 1 and Z == 0
314 case CmpInst::ICMP_UGE: // C == 1
315 case CmpInst::ICMP_ULT: // C == 0 and Z == 0
316 case CmpInst::ICMP_ULE: // C == 0
317 {
318 Value *Carry = createAdd(IRB, Lhs, Rhs, Tys, Name, ICmp->getType()).Bit;
319 if (Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE)
320 Carry = IRB->CreateNot(Carry, Name);
321 if (Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_ULT)
322 Carry = IRB->CreateBinOp(
323 Instruction::And, Carry,
324 createICmpEquality(IRB, CmpInst::ICMP_EQ, Lhs, Rhs, Name), Name);
325 return Carry;
326 }
327
328 case CmpInst::ICMP_SGT: // N == V and Z == 0
329 case CmpInst::ICMP_SGE: // N == V
330 case CmpInst::ICMP_SLT: // N != V
331 case CmpInst::ICMP_SLE: // N != V or Z == 1
332 DIE_IF(true, ICmp, "Signed comparisons");
333 default:
334 llvm_unreachable("Invalid integer comparison");
335 }
336 }
337
338 static ValuePair createLoad(IRBuilder<> *IRB, const DataLayout &DL,
339 LoadInst *Load) {
340 DIE_IF(!Load->isSimple(), Load, "Volatile and atomic loads");
341 Value *Op = Load->getPointerOperand();
342 TypePair Tys = getExpandedIntTypes(Load->getType());
343 AlignPair Align = getAlign(DL, Load, Load->getType());
344 Value *Loty = IRB->CreateBitCast(Op, Tys.Lo->getPointerTo(),
345 Twine(Op->getName(), ".loty"));
346 Value *Lo =
347 IRB->CreateAlignedLoad(Loty, Align.Lo, Twine(Load->getName(), ".lo"));
348 Value *HiAddr =
349 IRB->CreateConstGEP1_32(Loty, 1, Twine(Op->getName(), ".hi.gep"));
350 Value *HiTy = IRB->CreateBitCast(HiAddr, Tys.Hi->getPointerTo(),
351 Twine(Op->getName(), ".hity"));
352 Value *Hi =
353 IRB->CreateAlignedLoad(HiTy, Align.Hi, Twine(Load->getName(), ".hi"));
354 return {Lo, Hi};
355 }
356
357 static ValuePair createStore(IRBuilder<> *IRB, const DataLayout &DL,
358 StoreInst *Store, const ValuePair &StoreVals) {
359 DIE_IF(!Store->isSimple(), Store, "Volatile and atomic stores");
360 Value *Ptr = Store->getPointerOperand();
361 TypePair Tys = getExpandedIntTypes(Store->getValueOperand()->getType());
362 AlignPair Align = getAlign(DL, Store, Store->getValueOperand()->getType());
363 Value *Loty = IRB->CreateBitCast(Ptr, Tys.Lo->getPointerTo(),
364 Twine(Ptr->getName(), ".loty"));
365 Value *Lo = IRB->CreateAlignedStore(StoreVals.Lo, Loty, Align.Lo);
366 Value *HiAddr =
367 IRB->CreateConstGEP1_32(Loty, 1, Twine(Ptr->getName(), ".hi.gep"));
368 Value *HiTy = IRB->CreateBitCast(HiAddr, Tys.Hi->getPointerTo(),
369 Twine(Ptr->getName(), ".hity"));
370 Value *Hi = IRB->CreateAlignedStore(StoreVals.Hi, HiTy, Align.Hi);
371 return {Lo, Hi};
372 }
373
374 namespace {
375 // Holds the state for converting/replacing values. We visit instructions in
376 // reverse post-order, phis are therefore the only instructions which can be
377 // visited before the value they use.
378 class ConversionState {
379 public:
380 // Return the expanded values for Val.
381 ValuePair getConverted(Value *Val) {
382 assert(shouldConvert(Val));
383 // Directly convert constants.
384 if (Constant *C = dyn_cast<Constant>(Val))
385 return expandConstant(C);
386 if (RewrittenIllegals.count(Val)) {
387 ValuePair Found = RewrittenIllegals[Val];
388 if (RewrittenLegals.count(Found.Lo))
389 Found.Lo = RewrittenLegals[Found.Lo];
390 if (RewrittenLegals.count(Found.Hi))
391 Found.Hi = RewrittenLegals[Found.Hi];
392 return Found;
393 }
394 errs() << "Value: " << *Val << "\n";
395 report_fatal_error("Expanded value not found in map");
396 }
397
398 // Returns whether a converted value has been recorded. This is only useful
399 // for phi instructions: they can be encountered before the incoming
400 // instruction, whereas RPO order guarantees that other instructions always
401 // use converted values.
402 bool hasConverted(Value *Val) {
403 assert(shouldConvert(Val));
404 return dyn_cast<Constant>(Val) || RewrittenIllegals.count(Val);
405 }
406
407 // Record a forward phi, temporarily setting it to use Undef. This will be
408 // patched up at the end of RPO.
409 ValuePair recordForwardPHI(Value *Val, PHINode *Lo, PHINode *Hi,
410 unsigned ValueNumber) {
411 DEBUG(dbgs() << "\tRecording as forward PHI\n");
412 ForwardPHIs.push_back(ForwardPHI(Val, Lo, Hi, ValueNumber));
413 return {UndefValue::get(Lo->getType()), UndefValue::get(Hi->getType())};
414 }
415
416 void recordConverted(Instruction *From, const ValuePair &To) {
417 DEBUG(dbgs() << "\tTo: " << *To.Lo << "\n");
418 DEBUG(dbgs() << "\tAnd: " << *To.Hi << "\n");
419 ToErase.push_back(From);
420 RewrittenIllegals[From] = To;
421 }
422
423 // Replace the uses of From with To, give From's name to To, and mark To for
424 // deletion.
425 void recordConverted(Instruction *From, Value *To) {
426 assert(!shouldConvert(From));
427 DEBUG(dbgs() << "\tTo: " << *To << "\n");
428 ToErase.push_back(From);
429 // From does not produce an illegal value, update its users in place.
430 From->replaceAllUsesWith(To);
431 To->takeName(From);
432 RewrittenLegals[From] = To;
433 }
434
435 void patchForwardPHIs() {
436 DEBUG(if (!ForwardPHIs.empty()) dbgs() << "Patching forward PHIs:\n");
437 for (ForwardPHI &F : ForwardPHIs) {
438 ValuePair Ops = getConverted(F.Val);
439 F.Lo->setIncomingValue(F.ValueNumber, Ops.Lo);
440 F.Hi->setIncomingValue(F.ValueNumber, Ops.Hi);
441 DEBUG(dbgs() << "\t" << *F.Lo << "\n\t" << *F.Hi << "\n");
442 }
443 }
444
445 void eraseReplacedInstructions() {
446 for (Instruction *I : ToErase)
447 I->dropAllReferences();
448 for (Instruction *I : ToErase)
449 I->eraseFromParent();
450 }
451
452 private:
453 // Maps illegal values to their new converted lo/hi values.
454 DenseMap<Value *, ValuePair> RewrittenIllegals;
455 // Maps legal values to their new converted value.
456 DenseMap<Value *, Value *> RewrittenLegals;
457 // Illegal values which have already been converted, will be erased.
458 SmallVector<Instruction *, 32> ToErase;
459 // PHIs which were encountered but had forward references. They need to get
460 // patched up after RPO traversal.
461 SmallVector<ForwardPHI, 32> ForwardPHIs;
462 };
463 } // Anonymous namespace
464
465 static void convertInstruction(Instruction *Inst, ConversionState &State,
466 const DataLayout &DL) {
467 DEBUG(dbgs() << "Expanding Large Integer: " << *Inst << "\n");
468 // Set the insert point *after* Inst, so that any instructions inserted here
469 // will be visited again. That allows iterative expansion of types > i128.
470 BasicBlock::iterator InsertPos(Inst);
471 IRBuilder<> IRB(++InsertPos);
472 StringRef Name = Inst->getName();
473
474 if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
475 unsigned N = Phi->getNumIncomingValues();
476 TypePair OpTys = getExpandedIntTypes(Phi->getIncomingValue(0)->getType());
477 PHINode *Lo = IRB.CreatePHI(OpTys.Lo, N, Twine(Name + ".lo"));
478 PHINode *Hi = IRB.CreatePHI(OpTys.Hi, N, Twine(Name + ".hi"));
479 for (unsigned I = 0; I != N; ++I) {
480 Value *InVal = Phi->getIncomingValue(I);
481 BasicBlock *InBB = Phi->getIncomingBlock(I);
482 // If the value hasn't already been converted then this is a
483 // forward-reference PHI which needs to be patched up after RPO traversal.
484 ValuePair Ops = State.hasConverted(InVal)
485 ? State.getConverted(InVal)
486 : State.recordForwardPHI(InVal, Lo, Hi, I);
487 Lo->addIncoming(Ops.Lo, InBB);
488 Hi->addIncoming(Ops.Hi, InBB);
489 }
490 State.recordConverted(Phi, {Lo, Hi});
491
492 } else if (ZExtInst *ZExt = dyn_cast<ZExtInst>(Inst)) {
493 Value *Operand = ZExt->getOperand(0);
494 Type *OpTy = Operand->getType();
495 TypePair Tys = getExpandedIntTypes(Inst->getType());
496 Value *Lo, *Hi;
497 if (OpTy->getIntegerBitWidth() <= kChunkBits) {
498 Lo = IRB.CreateZExt(Operand, Tys.Lo, Twine(Name, ".lo"));
499 Hi = ConstantInt::get(Tys.Hi, 0);
500 } else {
501 ValuePair Ops = State.getConverted(Operand);
502 Lo = Ops.Lo;
503 Hi = IRB.CreateZExt(Ops.Hi, Tys.Hi, Twine(Name, ".hi"));
504 }
505 State.recordConverted(ZExt, {Lo, Hi});
506
507 } else if (TruncInst *Trunc = dyn_cast<TruncInst>(Inst)) {
508 Value *Operand = Trunc->getOperand(0);
509 assert(shouldConvert(Operand) && "TruncInst is expandable but not its op");
510 ValuePair Ops = State.getConverted(Operand);
511 if (!shouldConvert(Inst)) {
512 Value *NewInst = IRB.CreateTrunc(Ops.Lo, Trunc->getType(), Name);
513 State.recordConverted(Trunc, NewInst);
514 } else {
515 TypePair Tys = getExpandedIntTypes(Trunc->getType());
516 assert(Tys.Lo == getExpandedIntTypes(Operand->getType()).Lo);
517 Value *Lo = Ops.Lo;
518 Value *Hi = IRB.CreateTrunc(Ops.Hi, Tys.Hi, Twine(Name, ".hi"));
519 State.recordConverted(Trunc, {Lo, Hi});
520 }
521
522 } else if (BinaryOperator *Binop = dyn_cast<BinaryOperator>(Inst)) {
523 ValuePair Lhs = State.getConverted(Binop->getOperand(0));
524 ValuePair Rhs = State.getConverted(Binop->getOperand(1));
525 TypePair Tys = getExpandedIntTypes(Binop->getType());
526 ValuePair Conv;
527 switch (Binop->getOpcode()) {
528 case Instruction::And:
529 case Instruction::Or:
530 case Instruction::Xor:
531 Conv = createBit(&IRB, Binop, Lhs, Rhs, Tys, Name);
532 break;
533 case Instruction::Shl:
534 Conv = createShl(&IRB, Binop, Lhs, Rhs, Tys, Name);
535 break;
536 case Instruction::AShr:
537 case Instruction::LShr:
538 Conv = createShr(&IRB, Binop, Lhs, Rhs, Tys, Name);
539 break;
540 case Instruction::Add: {
541 ValueTriple VT =
542 createAdd(&IRB, Lhs, Rhs, Tys, Name, /*HiCarryTy=*/nullptr);
543 Conv = {VT.Lo, VT.Hi}; // Ignore Hi carry.
544 } break;
545 case Instruction::Sub:
546 Conv = createSub(&IRB, Lhs, Rhs, Tys, Name);
547 break;
548 default:
549 DIE_IF(true, Binop, "Binary operator type");
550 }
551 State.recordConverted(Binop, Conv);
552
553 } else if (ICmpInst *ICmp = dyn_cast<ICmpInst>(Inst)) {
554 ValuePair Lhs = State.getConverted(ICmp->getOperand(0));
555 ValuePair Rhs = State.getConverted(ICmp->getOperand(1));
556 TypePair Tys = getExpandedIntTypes(ICmp->getOperand(0)->getType());
557 State.recordConverted(ICmp, createICmp(&IRB, ICmp, Lhs, Rhs, Tys, Name));
558
559 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
560 State.recordConverted(Load, createLoad(&IRB, DL, Load));
561
562 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
563 ValuePair StoreVals = State.getConverted(Store->getValueOperand());
564 State.recordConverted(Store, createStore(&IRB, DL, Store, StoreVals));
565
566 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
567 Value *Cond = Select->getCondition();
568 ValuePair True = State.getConverted(Select->getTrueValue());
569 ValuePair False = State.getConverted(Select->getFalseValue());
570 Value *Lo = IRB.CreateSelect(Cond, True.Lo, False.Lo, Twine(Name, ".lo"));
571 Value *Hi = IRB.CreateSelect(Cond, True.Hi, False.Hi, Twine(Name, ".hi"));
572 State.recordConverted(Select, {Lo, Hi});
573
574 } else {
575 DIE_IF(true, Inst, "Instruction");
576 }
577 }
578
579 bool ExpandLargeIntegers::runOnFunction(Function &F) {
580 // Don't support changing the function arguments. Illegal function arguments
581 // should not be generated by clang.
582 for (const Argument &Arg : F.args())
583 if (shouldConvert(&Arg))
584 report_fatal_error("Function " + F.getName() +
585 " has illegal integer argument");
586
587 // TODO(jfb) This should loop to handle nested forward PHIs.
588
589 ConversionState State;
590 DataLayout DL(F.getParent());
591 bool Modified = false;
592 ReversePostOrderTraversal<Function *> RPOT(&F);
593 for (ReversePostOrderTraversal<Function *>::rpo_iterator FI = RPOT.begin(),
594 FE = RPOT.end();
595 FI != FE; ++FI) {
596 BasicBlock *BB = *FI;
597 for (Instruction &I : *BB) {
598 // Only attempt to convert an instruction if its result or any of its
599 // operands are illegal.
600 bool ShouldConvert = shouldConvert(&I);
601 for (Value *Op : I.operands())
602 ShouldConvert |= shouldConvert(Op);
603 if (ShouldConvert) {
604 convertInstruction(&I, State, DL);
605 Modified = true;
606 }
607 }
608 }
609 State.patchForwardPHIs();
610 State.eraseReplacedInstructions();
611 return Modified;
612 }
613
614 FunctionPass *llvm::createExpandLargeIntegersPass() {
615 return new ExpandLargeIntegers();
616 }
OLDNEW
« no previous file with comments | « lib/Transforms/NaCl/ExpandIndirectBr.cpp ('k') | lib/Transforms/NaCl/ExpandShuffleVector.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698