-fwrapv should turn off the inbounds markers from geps used for pointer

arithmetic.  This is part of PR9256, it would be great if someone else
wired up -fno-strict-overflow in the driver to -fwrapv.

llvm-svn: 126718
This commit is contained in:
Chris Lattner 2011-03-01 00:03:48 +00:00
parent 49d15b959e
commit 2e72da947c
4 changed files with 73 additions and 37 deletions

View File

@ -239,6 +239,10 @@ public:
void setSignedOverflowBehavior(SignedOverflowBehaviorTy V) {
SignedOverflowBehavior = (unsigned)V;
}
bool isSignedOverflowDefined() const {
return getSignedOverflowBehavior() == SOB_Defined;
}
};
/// Floating point control options

View File

@ -1425,7 +1425,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
llvm::Value *Base = EmitScalarExpr(E->getBase());
Address = EmitCastToVoidPtr(Base);
Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx");
if (getContext().getLangOptions().isSignedOverflowDefined())
Address = Builder.CreateGEP(Address, Idx, "arrayidx");
else
Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx");
Address = Builder.CreateBitCast(Address, Base->getType());
} else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
// Indexing over an interface, as in "NSString *P; P[4];"
@ -1451,11 +1454,17 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
llvm::Value *Zero = llvm::ConstantInt::get(Int32Ty, 0);
llvm::Value *Args[] = { Zero, Idx };
Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, Args+2, "arrayidx");
if (getContext().getLangOptions().isSignedOverflowDefined())
Address = Builder.CreateGEP(ArrayPtr, Args, Args+2, "arrayidx");
else
Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, Args+2, "arrayidx");
} else {
// The base must be a pointer, which is not an aggregate. Emit it.
llvm::Value *Base = EmitScalarExpr(E->getBase());
Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx");
if (getContext().getLangOptions().isSignedOverflowDefined())
Address = Builder.CreateGEP(Base, Idx, "arrayidx");
else
Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx");
}
QualType T = E->getBase()->getType()->getPointeeType();

View File

@ -1295,7 +1295,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
CGF.GetVLASize(CGF.getContext().getAsVariableArrayType(type));
value = CGF.EmitCastToVoidPtr(value);
if (!isInc) vlaSize = Builder.CreateNSWNeg(vlaSize, "vla.negsize");
value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc");
if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
value = Builder.CreateGEP(value, vlaSize, "vla.inc");
else
value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc");
value = Builder.CreateBitCast(value, input->getType());
// Arithmetic on function pointers (!) is just +-1.
@ -1303,13 +1306,19 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount);
value = CGF.EmitCastToVoidPtr(value);
value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr");
if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
value = Builder.CreateGEP(value, amt, "incdec.funcptr");
else
value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr");
value = Builder.CreateBitCast(value, input->getType());
// For everything else, we can just do a simple increment.
} else {
llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount);
value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr");
if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
value = Builder.CreateGEP(value, amt, "incdec.ptr");
else
value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr");
}
// Vector increment/decrement.
@ -1357,7 +1366,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::Value *sizeValue =
llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity());
value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr");
if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
value = Builder.CreateGEP(value, sizeValue, "incdec.objptr");
else
value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr");
value = Builder.CreateBitCast(value, input->getType());
}
@ -1889,6 +1901,8 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
return Builder.CreateBitCast(Res, Ptr->getType());
}
if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
return Builder.CreateGEP(Ptr, Idx, "add.ptr");
return Builder.CreateInBoundsGEP(Ptr, Idx, "add.ptr");
}
@ -1964,38 +1978,39 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
return Builder.CreateBitCast(Res, Ops.LHS->getType());
}
if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
return Builder.CreateGEP(Ops.LHS, Idx, "sub.ptr");
return Builder.CreateInBoundsGEP(Ops.LHS, Idx, "sub.ptr");
} else {
// pointer - pointer
Value *LHS = Ops.LHS;
Value *RHS = Ops.RHS;
CharUnits ElementSize;
// Handle GCC extension for pointer arithmetic on void* and function pointer
// types.
if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) {
ElementSize = CharUnits::One();
} else {
ElementSize = CGF.getContext().getTypeSizeInChars(LHSElementType);
}
const llvm::Type *ResultType = ConvertType(Ops.Ty);
LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast");
RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast");
Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub");
// Optimize out the shift for element size of 1.
if (ElementSize.isOne())
return BytesBetween;
// Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since
// pointer difference in C is only defined in the case where both operands
// are pointing to elements of an array.
Value *BytesPerElt =
llvm::ConstantInt::get(ResultType, ElementSize.getQuantity());
return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div");
}
// pointer - pointer
Value *LHS = Ops.LHS;
Value *RHS = Ops.RHS;
CharUnits ElementSize;
// Handle GCC extension for pointer arithmetic on void* and function pointer
// types.
if (LHSElementType->isVoidType() || LHSElementType->isFunctionType())
ElementSize = CharUnits::One();
else
ElementSize = CGF.getContext().getTypeSizeInChars(LHSElementType);
const llvm::Type *ResultType = ConvertType(Ops.Ty);
LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast");
RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast");
Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub");
// Optimize out the shift for element size of 1.
if (ElementSize.isOne())
return BytesBetween;
// Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since
// pointer difference in C is only defined in the case where both operands
// are pointing to elements of an array.
Value *BytesPerElt =
llvm::ConstantInt::get(ResultType, ElementSize.getQuantity());
return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div");
}
Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {

View File

@ -49,4 +49,12 @@ void test1() {
// TRAPV: llvm.sadd.with.overflow.i32({{.*}}, i32 -1)
// TRAPV_HANDLER: foo(
--a;
// -fwrapv should turn off inbounds for GEP's, PR9256
extern int* P;
++P;
// DEFAULT: getelementptr inbounds i32*
// WRAPV: getelementptr i32*
// TRAPV: getelementptr inbounds i32*
}