OLD | NEW |
(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 } |
OLD | NEW |