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

Unified Diff: lib/Transforms/NaCl/ExpandMulWithOverflow.cpp

Issue 15688011: PNaCl: Extend ExpandMulWithOverflow pass to handle uadd.with.overflow too (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: 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 side-by-side diff with in-line comments
Download patch
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();
-}

Powered by Google App Engine
This is Rietveld 408576698