summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/MemoryBuiltins.cpp49
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp15
2 files changed, 47 insertions, 17 deletions
diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp
index 00da6b46a28..e0497cbc801 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -367,29 +367,29 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
//===----------------------------------------------------------------------===//
// Utility functions to compute size of objects.
//
-
+static APInt getSizeWithOverflow(const SizeOffsetType &Data) {
+ if (Data.second.isNegative() || Data.first.ult(Data.second))
+ return APInt(Data.first.getBitWidth(), 0);
+ return Data.first - Data.second;
+}
/// \brief Compute the size of the object pointed by Ptr. Returns true and the
/// object size in Size if successful, and false otherwise.
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
/// byval arguments, and global variables.
bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
- const TargetLibraryInfo *TLI, bool RoundToAlign) {
- ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), RoundToAlign);
+ const TargetLibraryInfo *TLI, bool RoundToAlign,
+ llvm::ObjSizeMode Mode) {
+ ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(),
+ RoundToAlign, Mode);
SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr));
if (!Visitor.bothKnown(Data))
return false;
- APInt ObjSize = Data.first, Offset = Data.second;
- // check for overflow
- if (Offset.slt(0) || ObjSize.ult(Offset))
- Size = 0;
- else
- Size = (ObjSize - Offset).getZExtValue();
+ Size = getSizeWithOverflow(Data).getZExtValue();
return true;
}
-
STATISTIC(ObjectVisitorArgument,
"Number of arguments with unsolved size and offset");
STATISTIC(ObjectVisitorLoad,
@@ -405,8 +405,9 @@ APInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) {
ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL,
const TargetLibraryInfo *TLI,
LLVMContext &Context,
- bool RoundToAlign)
- : DL(DL), TLI(TLI), RoundToAlign(RoundToAlign) {
+ bool RoundToAlign,
+ ObjSizeMode Mode)
+ : DL(DL), TLI(TLI), RoundToAlign(RoundToAlign), Mode(Mode) {
// Pointer size must be rechecked for each object visited since it could have
// a different address space.
}
@@ -606,8 +607,28 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
SizeOffsetType TrueSide = compute(I.getTrueValue());
SizeOffsetType FalseSide = compute(I.getFalseValue());
- if (bothKnown(TrueSide) && bothKnown(FalseSide) && TrueSide == FalseSide)
- return TrueSide;
+ if (bothKnown(TrueSide) && bothKnown(FalseSide)) {
+ if (TrueSide == FalseSide) {
+ return TrueSide;
+ }
+
+ APInt TrueResult = getSizeWithOverflow(TrueSide);
+ APInt FalseResult = getSizeWithOverflow(FalseSide);
+
+ if (TrueResult == FalseResult) {
+ return TrueSide;
+ }
+ if (Mode == ObjSizeMode::Min) {
+ if (TrueResult.slt(FalseResult))
+ return TrueSide;
+ return FalseSide;
+ }
+ if (Mode == ObjSizeMode::Max) {
+ if (TrueResult.sgt(FalseResult))
+ return TrueSide;
+ return FalseSide;
+ }
+ }
return unknown();
}
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index e9e6146c759..ea1325a8627 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -22,6 +22,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
@@ -1807,10 +1808,18 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool& ModifiedDT) {
default: break;
case Intrinsic::objectsize: {
// Lower all uses of llvm.objectsize.*
- bool Min = (cast<ConstantInt>(II->getArgOperand(1))->getZExtValue() == 1);
+ uint64_t Size;
Type *ReturnTy = CI->getType();
- Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL);
-
+ Constant *RetVal = nullptr;
+ ConstantInt *Op1 = cast<ConstantInt>(II->getArgOperand(1));
+ ObjSizeMode Mode = Op1->isZero() ? ObjSizeMode::Max : ObjSizeMode::Min;
+ if (getObjectSize(II->getArgOperand(0),
+ Size, *DL, TLInfo, false, Mode)) {
+ RetVal = ConstantInt::get(ReturnTy, Size);
+ } else {
+ RetVal = ConstantInt::get(ReturnTy,
+ Mode == ObjSizeMode::Min ? 0 : -1ULL);
+ }
// Substituting this can cause recursive simplifications, which can
// invalidate our iterator. Use a WeakVH to hold onto it in case this
// happens.
OpenPOWER on IntegriCloud