Index: lib/Transforms/NaCl/ExpandMulWithOverflow.cpp |
diff --git a/lib/Transforms/NaCl/ExpandMulWithOverflow.cpp b/lib/Transforms/NaCl/ExpandMulWithOverflow.cpp |
deleted file mode 100644 |
index 171dda1f09290fd06a04c45caf73503b73b2c402..0000000000000000000000000000000000000000 |
--- a/lib/Transforms/NaCl/ExpandMulWithOverflow.cpp |
+++ /dev/null |
@@ -1,141 +0,0 @@ |
-//===- ExpandMulWithOverflow.cpp - Expand out usage of umul.with.overflow--===// |
-// |
-// The LLVM Compiler Infrastructure |
-// |
-// This file is distributed under the University of Illinois Open Source |
-// License. See LICENSE.TXT for details. |
-// |
-//===----------------------------------------------------------------------===// |
-// |
-// The llvm.*.with.overflow.*() intrinsics are awkward for PNaCl |
-// support because they return structs, and we want to omit struct |
-// types from IR in PNaCl's stable ABI. |
-// |
-// However, llvm.umul.with.overflow.*() is used by Clang to implement |
-// an overflow check for C++'s new[] operator. This pass expands out |
-// these uses so that PNaCl does not have to support |
-// umul.with.overflow as part of PNaCl's stable ABI. |
-// |
-// This pass only handles multiplication by a constant, which is the |
-// only case of umul.with.overflow that is currently generated by |
-// Clang (unless '-ftrapv' is passed to Clang). |
-// |
-// X * Const overflows iff X > UINT_MAX / Const, where UINT_MAX is the |
-// maximum value for the integer type being multiplied. |
-// |
-//===----------------------------------------------------------------------===// |
- |
-#include "llvm/IR/Function.h" |
-#include "llvm/IR/Instructions.h" |
-#include "llvm/IR/Intrinsics.h" |
-#include "llvm/IR/Module.h" |
-#include "llvm/Pass.h" |
-#include "llvm/Support/raw_ostream.h" |
-#include "llvm/Transforms/NaCl.h" |
- |
-using namespace llvm; |
- |
-namespace { |
- // This is a ModulePass so that the pass can easily iterate over all |
- // uses of the intrinsics. |
- class ExpandMulWithOverflow : public ModulePass { |
- public: |
- static char ID; // Pass identification, replacement for typeid |
- ExpandMulWithOverflow() : ModulePass(ID) { |
- initializeExpandMulWithOverflowPass(*PassRegistry::getPassRegistry()); |
- } |
- |
- virtual bool runOnModule(Module &M); |
- }; |
-} |
- |
-char ExpandMulWithOverflow::ID = 0; |
-INITIALIZE_PASS(ExpandMulWithOverflow, "expand-mul-with-overflow", |
- "Expand out uses of llvm.umul.with.overflow intrinsics", |
- false, false) |
- |
-static uint64_t UintTypeMax(unsigned Bits) { |
- // Avoid doing 1 << 64 because that is undefined on a uint64_t. |
- if (Bits == 64) |
- return ~(uint64_t) 0; |
- return (((uint64_t) 1) << Bits) - 1; |
-} |
- |
-static bool ExpandForIntSize(Module *M, unsigned Bits) { |
- IntegerType *IntTy = IntegerType::get(M->getContext(), Bits); |
- SmallVector<Type *, 1> Types; |
- Types.push_back(IntTy); |
- std::string Name = Intrinsic::getName(Intrinsic::umul_with_overflow, Types); |
- Function *Intrinsic = M->getFunction(Name); |
- if (!Intrinsic) |
- return false; |
- for (Value::use_iterator CallIter = Intrinsic->use_begin(), |
- E = Intrinsic->use_end(); CallIter != E; ) { |
- CallInst *Call = dyn_cast<CallInst>(*CallIter++); |
- if (!Call) { |
- report_fatal_error("ExpandMulWithOverflow: Taking the address of a " |
- "umul.with.overflow intrinsic is not allowed"); |
- } |
- Value *VariableArg; |
- ConstantInt *ConstantArg; |
- if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(0))) { |
- VariableArg = Call->getArgOperand(1); |
- ConstantArg = C; |
- } else if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(1))) { |
- VariableArg = Call->getArgOperand(0); |
- ConstantArg = C; |
- } else { |
- errs() << "Use: " << *Call << "\n"; |
- report_fatal_error("ExpandMulWithOverflow: At least one argument of " |
- "umul.with.overflow must be a constant"); |
- } |
- |
- Value *Mul = BinaryOperator::Create( |
- Instruction::Mul, VariableArg, ConstantArg, |
- Call->getName() + ".mul", Call); |
- |
- uint64_t ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue(); |
- Value *Overflow = new ICmpInst( |
- Call, CmpInst::ICMP_UGT, VariableArg, ConstantInt::get(IntTy, ArgMax), |
- Call->getName() + ".overflow"); |
- |
- for (Value::use_iterator FieldIter = Call->use_begin(), |
- E = Call->use_end(); FieldIter != E; ) { |
- User *U = *FieldIter++; |
- ExtractValueInst *Field = dyn_cast<ExtractValueInst>(U); |
- if (!Field) { |
- errs() << "Use: " << *U << "\n"; |
- report_fatal_error( |
- "ExpandMulWithOverflow: Use is not an extractvalue"); |
- } |
- if (Field->getNumIndices() != 1) { |
- report_fatal_error("ExpandMulWithOverflow: Unexpected indices"); |
- } |
- unsigned Index = Field->getIndices()[0]; |
- if (Index == 0) { |
- Field->replaceAllUsesWith(Mul); |
- } else if (Index == 1) { |
- Field->replaceAllUsesWith(Overflow); |
- } else { |
- report_fatal_error("ExpandMulWithOverflow: Unexpected index"); |
- } |
- Field->eraseFromParent(); |
- } |
- Call->eraseFromParent(); |
- } |
- Intrinsic->eraseFromParent(); |
- return true; |
-} |
- |
-bool ExpandMulWithOverflow::runOnModule(Module &M) { |
- bool Modified = false; |
- Modified |= ExpandForIntSize(&M, 64); |
- Modified |= ExpandForIntSize(&M, 32); |
- Modified |= ExpandForIntSize(&M, 16); |
- Modified |= ExpandForIntSize(&M, 8); |
- return Modified; |
-} |
- |
-ModulePass *llvm::createExpandMulWithOverflowPass() { |
- return new ExpandMulWithOverflow(); |
-} |