diff options
Diffstat (limited to 'lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp')
-rw-r--r-- | lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp | 83 |
1 files changed, 70 insertions, 13 deletions
diff --git a/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp b/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp index 34f4f2bbe9..bee36e2631 100644 --- a/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp +++ b/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp @@ -44,6 +44,8 @@ NaClValueEnumerator::NaClValueEnumerator(const Module *M, uint32_t PNaClVersion) TypeCountMapType count_map; TypeCountMap = &count_map; + IntPtrType = IntegerType::get(M->getContext(), PNaClIntPtrTypeBitSize); + // Enumerate the functions. Note: We do this before global // variables, so that global variable initializations can refer to // the functions without a forward reference. @@ -429,10 +431,10 @@ void NaClValueEnumerator::purgeFunction() { } // Returns true if the bitcode writer can assume that the given -// argument of the given operation can accept a normalized pointer. +// argument of the given operation expects a normalized pointer in PNaCl. // Note: This function is based on the concept of NormalizedPtr as // defined in llvm/lib/Transforms/NaCl/ReplacePtrsWithInts.cpp. -static bool AllowsNormalizedPtr(const Value *V, const Instruction *Arg) { +static bool ExpectsNormalizedPtr(const Value *V, const Instruction *Arg) { const Instruction *I = dyn_cast<Instruction>(V); if (I == 0) return false; @@ -443,22 +445,19 @@ static bool AllowsNormalizedPtr(const Value *V, const Instruction *Arg) { default: return false; case Instruction::Load: - // Verify it is the ptr argument of the load. Note: This check is - // not really necessary in that a load only has one argument. return I->getOperand(0) == Arg; case Instruction::Store: - // Verify it is the ptr argument of the store. return I->getOperand(1) == Arg; } } // Returns true if the bitcode reader and writer can assume that the -// uses of the given inttotpr I2P allow normalized pointers (as +// uses of the given inttotpr I2P expect normalized pointers (as // defined in llvm/lib/Transforms/NaCl/ReplacePtrsWithInts.cpp). -static bool AllUsesAllowNormalizedPtr(const Instruction *I2P) { +static bool AllUsesExpectsNormalizedPtr(const Instruction *I2P) { for (Value::const_use_iterator u = I2P->use_begin(), e = I2P->use_end(); u != e; ++u) { - if (!AllowsNormalizedPtr(cast<Value>(*u), I2P)) return false; + if (!ExpectsNormalizedPtr(cast<Value>(*u), I2P)) return false; } // If reached, either all uses have a normalized pointer (and hence // we know how to automatically add it back), or there were no uses (and @@ -466,6 +465,57 @@ static bool AllUsesAllowNormalizedPtr(const Instruction *I2P) { return true; } +// Given Value that uses scalar value Arg, returns true if the bitcode +// writer can assume that Value always expects Arg to be scalar. This +// function is used to infer cases where PtrToInt casts can be +// removed. +static bool ExpectsScalarValue(const Value *V, const Instruction *Arg) { + const Instruction *I = dyn_cast<Instruction>(V); + if (I == 0) return false; + + if (I->isBinaryOp()) + return true; + else { + switch (I->getOpcode()) { + default: + return false; + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::ICmp: + return true; + case Instruction::Store: + return Arg == I->getOperand(0); + case Instruction::Select: { + const SelectInst *Op = dyn_cast<SelectInst>(I); + return Arg == Op->getTrueValue() || Arg == Op->getFalseValue(); + } + } + // TODO(kschimpf): Need to think more about how to handle following + // instructions: + // case Instruction::IntToPtr: + // case Instruction::BitCast: + // case Instruction::PHI: + // case Instruction::Call: + } +} + +// Returns true if the bitcode reader and writer can assume that the +// uses of the given PtrToInt expect scalar values (i.e. non-pointer), +// and hence, we can elide the PtrToInt cast. +static bool AllUsesExpectsScalarValue(const Instruction *I) { + for (Value::const_use_iterator Use = I->use_begin(), UseEnd = I->use_end(); + Use != UseEnd; ++Use) { + if (!ExpectsScalarValue(*Use, I)) return false; + } + // If reached, all uses expect a scalar value (and hence we know how + // to automatically add it back), or there were no uses (and hence + // represents dead code). + return true; +} + // Returns true if the value is an InherentPtr (as defined in // llvm/lib/Transforms/NaCl/ReplacePtrsWithInts.cpp). static inline bool IsInherentPtr(const Value *V) { @@ -483,14 +533,21 @@ const Value *NaClValueEnumerator::ElideCasts(const Value *V) { break; case Instruction::BitCast: if (I->getType()->isPointerTy() && - AllUsesAllowNormalizedPtr(I) && - IsInherentPtr(I->getOperand(0))) { - return ElideCasts(I->getOperand(0)); + IsInherentPtr(I->getOperand(0)) && + AllUsesExpectsNormalizedPtr(I)) { + V = I->getOperand(0); } break; case Instruction::IntToPtr: - if (AllUsesAllowNormalizedPtr(I)) { - return ElideCasts(I->getOperand(0)); + if (AllUsesExpectsNormalizedPtr(I)) { + V = ElideCasts(I->getOperand(0)); + } + break; + case Instruction::PtrToInt: + if (IsIntPtrType(I->getType()) && + IsInherentPtr(I->getOperand(0)) && + AllUsesExpectsScalarValue(I)) { + V = I->getOperand(0); } break; } |