From: Chris Lattner Date: Tue, 1 Mar 2011 00:03:48 +0000 (+0000) Subject: -fwrapv should turn off the inbounds markers from geps used for pointer X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2cb4222338669a3e70b546ef264fbd5d3f96aef5;p=clang -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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126718 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 35dfdb6c3a..e4205d7090 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -239,6 +239,10 @@ public: void setSignedOverflowBehavior(SignedOverflowBehaviorTy V) { SignedOverflowBehavior = (unsigned)V; } + + bool isSignedOverflowDefined() const { + return getSignedOverflowBehavior() == SOB_Defined; + } }; /// Floating point control options diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index e358496f82..0f9abc7c35 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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()){ // 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(); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 6e558e7a6b..c4ff8df381 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -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"); + } + + // pointer - pointer + Value *LHS = Ops.LHS; + Value *RHS = Ops.RHS; - // Optimize out the shift for element size of 1. - if (ElementSize.isOne()) - return BytesBetween; + CharUnits ElementSize; - // 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"); - } + // 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) { diff --git a/test/CodeGen/integer-overflow.c b/test/CodeGen/integer-overflow.c index 103cc8427b..066ef89574 100644 --- a/test/CodeGen/integer-overflow.c +++ b/test/CodeGen/integer-overflow.c @@ -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* }