diff options
| author | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-22 15:25:31 +0000 | 
|---|---|---|
| committer | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-22 15:25:31 +0000 | 
| commit | ad40c0a4252a549388c299fa80d15dc67f13242e (patch) | |
| tree | 7f844ef2326d4cbbebe01dc6f7262d9db3ee015a /llvm/lib | |
| parent | 924279ca0e2f9990e8cd6bc240f8ca5359540868 (diff) | |
| download | bcm5719-llvm-ad40c0a4252a549388c299fa80d15dc67f13242e.tar.gz bcm5719-llvm-ad40c0a4252a549388c299fa80d15dc67f13242e.zip  | |
revert my previous patches that introduced an additional parameter to the objectsize intrinsic.
After a lot of discussion, we realized it's not the best option for run-time bounds checking
llvm-svn: 157255
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 166 | ||||
| -rw-r--r-- | llvm/lib/VMCore/AutoUpgrade.cpp | 26 | 
2 files changed, 61 insertions, 131 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index c9b45d0df11..aa1cb41f008 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -165,73 +165,6 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {    return 0;  } -/// computeAllocSize - compute the object size allocated by an allocation -/// site. Returns 0 if the size is not constant (in SizeValue), 1 if the size -/// is constant (in Size), and 2 if the size could not be determined within the -/// given maximum Penalty that the computation would incurr at run-time. -static int computeAllocSize(Value *Alloc, uint64_t &Size, Value* &SizeValue, -                            uint64_t Penalty, TargetData *TD, -                            InstCombiner::BuilderTy *Builder) { -  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Alloc)) { -    if (GV->hasDefinitiveInitializer()) { -      Constant *C = GV->getInitializer(); -      Size = TD->getTypeAllocSize(C->getType()); -      return 1; -    } -    // Can't determine size of the GV. -    return 2; - -  } else if (AllocaInst *AI = dyn_cast<AllocaInst>(Alloc)) { -    if (!AI->getAllocatedType()->isSized()) -      return 2; - -    Size = TD->getTypeAllocSize(AI->getAllocatedType()); -    if (!AI->isArrayAllocation()) -      return 1; // we are done - -    Value *ArraySize = AI->getArraySize(); -    if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) { -      Size *= C->getZExtValue(); -      return 1; -    } - -    if (Penalty < 2) -      return 2; - -    SizeValue = ConstantInt::get(ArraySize->getType(), Size); -    SizeValue = Builder->CreateMul(SizeValue, ArraySize); -    return 0; - -  } else if (CallInst *MI = extractMallocCall(Alloc)) { -    SizeValue = MI->getArgOperand(0); -    if (ConstantInt *CI = dyn_cast<ConstantInt>(SizeValue)) { -      Size = CI->getZExtValue(); -      return 1; -    } -    return Penalty >= 2 ? 0 : 2; - -  } else if (CallInst *MI = extractCallocCall(Alloc)) { -    Value *Arg1 = MI->getArgOperand(0); -    Value *Arg2 = MI->getArgOperand(1); -    if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Arg1)) { -      if (ConstantInt *CI2 = dyn_cast<ConstantInt>(Arg2)) { -        Size = (CI1->getValue() * CI2->getValue()).getZExtValue(); -        return 1; -      } -    } - -    if (Penalty < 2) -      return 2; - -    SizeValue = Builder->CreateMul(Arg1, Arg2); -    return 0; -  } - -  DEBUG(errs() << "computeAllocSize failed:\n"); -  DEBUG(Alloc->dump()); -  return 2; -} -  /// visitCallInst - CallInst simplification.  This mostly only handles folding  /// of intrinsic instructions.  For normal calls, it allows visitCallSite to do  /// the heavy lifting. @@ -317,59 +250,80 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {      if (!TD) return 0;      Type *ReturnTy = CI.getType(); -    uint64_t Penalty = cast<ConstantInt>(II->getArgOperand(2))->getZExtValue(); +    uint64_t DontKnow = II->getArgOperand(1) == Builder->getTrue() ? 0 : -1ULL;      // Get to the real allocated thing and offset as fast as possible.      Value *Op1 = II->getArgOperand(0)->stripPointerCasts(); -    GEPOperator *GEP; -    if ((GEP = dyn_cast<GEPOperator>(Op1))) { -      // check if we will be able to get the offset -      if (!GEP->hasAllConstantIndices() && Penalty < 2) +    uint64_t Offset = 0; +    uint64_t Size = -1ULL; + +    // Try to look through constant GEPs. +    if (GEPOperator *GEP = dyn_cast<GEPOperator>(Op1)) { +      if (!GEP->hasAllConstantIndices()) return 0; + +      // Get the current byte offset into the thing. Use the original +      // operand in case we're looking through a bitcast. +      SmallVector<Value*, 8> Ops(GEP->idx_begin(), GEP->idx_end()); +      if (!GEP->getPointerOperandType()->isPointerTy())          return 0; +      Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops); +        Op1 = GEP->getPointerOperand()->stripPointerCasts(); + +      // Make sure we're not a constant offset from an external +      // global. +      if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op1)) +        if (!GV->hasDefinitiveInitializer()) return 0;      } -    uint64_t Size; -    Value *SizeValue; -    int ConstAlloc = computeAllocSize(Op1, Size, SizeValue, Penalty, TD, -                                      Builder); +    // If we've stripped down to a single global variable that we +    // can know the size of then just return that. +    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op1)) { +      if (GV->hasDefinitiveInitializer()) { +        Constant *C = GV->getInitializer(); +        Size = TD->getTypeAllocSize(C->getType()); +      } else { +        // Can't determine size of the GV. +        Constant *RetVal = ConstantInt::get(ReturnTy, DontKnow); +        return ReplaceInstUsesWith(CI, RetVal); +      } +    } else if (AllocaInst *AI = dyn_cast<AllocaInst>(Op1)) { +      // Get alloca size. +      if (AI->getAllocatedType()->isSized()) { +        Size = TD->getTypeAllocSize(AI->getAllocatedType()); +        if (AI->isArrayAllocation()) { +          const ConstantInt *C = dyn_cast<ConstantInt>(AI->getArraySize()); +          if (!C) return 0; +          Size *= C->getZExtValue(); +        } +      } +    } else if (CallInst *MI = extractMallocCall(Op1)) { +      // Get allocation size. +      Value *Arg = MI->getArgOperand(0); +      if (ConstantInt *CI = dyn_cast<ConstantInt>(Arg)) +          Size = CI->getZExtValue(); + +    } else if (CallInst *MI = extractCallocCall(Op1)) { +      // Get allocation size. +      Value *Arg1 = MI->getArgOperand(0); +      Value *Arg2 = MI->getArgOperand(1); +      if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Arg1)) +        if (ConstantInt *CI2 = dyn_cast<ConstantInt>(Arg2)) +          Size = (CI1->getValue() * CI2->getValue()).getZExtValue(); +    }      // Do not return "I don't know" here. Later optimization passes could      // make it possible to evaluate objectsize to a constant. -    if (ConstAlloc == 2) +    if (Size == -1ULL)        return 0; -    uint64_t Offset = 0; -    Value *OffsetValue = 0; - -    if (GEP) { -      if (GEP->hasAllConstantIndices()) { -        SmallVector<Value*, 8> Ops(GEP->idx_begin(), GEP->idx_end()); -        assert(GEP->getPointerOperandType()->isPointerTy()); -        Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops); -      } else -        OffsetValue = EmitGEPOffset(GEP, true /*NoNUW*/); -    } - -    if (!OffsetValue && ConstAlloc) { -      if (Size < Offset) { -        // Out of bounds -        return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, 0)); -      } -      return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, Size-Offset)); +    if (Size < Offset) { +      // Out of bound reference? Negative index normalized to large +      // index? Just return "I don't know". +      return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, DontKnow));      } - -    if (!OffsetValue) -      OffsetValue = ConstantInt::get(ReturnTy, Offset); -    if (ConstAlloc) -      SizeValue = ConstantInt::get(ReturnTy, Size); - -    Value *Val = Builder->CreateSub(SizeValue, OffsetValue); -    // return 0 if there's an overflow -    Value *Cmp = Builder->CreateICmpULT(SizeValue, OffsetValue); -    Val = Builder->CreateSelect(Cmp, ConstantInt::get(ReturnTy, 0), Val); -    return ReplaceInstUsesWith(CI, Val); +    return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, Size-Offset));    }    case Intrinsic::bswap:      // bswap(bswap(x)) -> x diff --git a/llvm/lib/VMCore/AutoUpgrade.cpp b/llvm/lib/VMCore/AutoUpgrade.cpp index 1b259d7f072..522b07e4545 100644 --- a/llvm/lib/VMCore/AutoUpgrade.cpp +++ b/llvm/lib/VMCore/AutoUpgrade.cpp @@ -52,20 +52,6 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {      }      break;    } -  case 'o': { -    // FIXME: remove in LLVM 3.3 -    if (Name.startswith("objectsize.") && F->arg_size() == 2) { -      Type *Tys[] = {F->getReturnType(), -                     F->arg_begin()->getType(), -                     Type::getInt1Ty(F->getContext()), -                     Type::getInt32Ty(F->getContext())}; -      NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::objectsize, -                                        Tys); -      NewFn->takeName(F); -      return true; -    } -    break; -  }    case 'x': {      if (Name.startswith("x86.sse2.pcmpeq.") ||          Name.startswith("x86.sse2.pcmpgt.") || @@ -209,7 +195,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {      llvm_unreachable("Unknown function for CallInst upgrade.");    case Intrinsic::ctlz: -  case Intrinsic::cttz: { +  case Intrinsic::cttz:      assert(CI->getNumArgOperands() == 1 &&             "Mismatch between function args and call args");      StringRef Name = CI->getName(); @@ -219,16 +205,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {      CI->eraseFromParent();      return;    } -  case Intrinsic::objectsize: { -    StringRef Name = CI->getName(); -    CI->setName(Name + ".old"); -    CI->replaceAllUsesWith(Builder.CreateCall3(NewFn, CI->getArgOperand(0), -                                               CI->getArgOperand(1), -                                               Builder.getInt32(0), Name)); -    CI->eraseFromParent(); -    return; -  } -  }  }  // This tests each Function to determine if it needs upgrading. When we find   | 

