diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -27,6 +27,7 @@ CODEGENOPT(Name, Bits, Default) #endif +CODEGENOPT(SignedWrap , 1, 0) ///< -fwarpv CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as ENUM_CODEGENOPT(CompressDebugSections, llvm::DebugCompressionType, 2, llvm::DebugCompressionType::None) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3613,7 +3613,12 @@ if (!E->getType()->isVariableArrayType()) { assert(isa(Addr.getElementType()) && "Expected pointer to array"); + + if (CGM.getCodeGenOpts().SignedWrap) + llvm::setSignedWrap(true); + Addr = Builder.CreateConstArrayGEP(Addr, 0, "arraydecay"); + } // The result of this decay conversion points to an array element within the diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1689,6 +1689,9 @@ llvm::is_contained(DebugEntryValueArchs, T.getArch())) Opts.EmitCallSiteInfo = true; + if (Args.hasArg(OPT_fwrapv)) + Opts.SignedWrap = true; + if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) { Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export) << Opts.DIBugsReportFilePath; diff --git a/clang/test/CodeGen/inbounds.c b/clang/test/CodeGen/inbounds.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/inbounds.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fwrapv -emit-llvm -o - %s | FileCheck %s + +extern char base[]; + +char *test() { + return base + 1; +} + +// CHECK: ret ptr getelementptr (i8, ptr @base, i64 1) diff --git a/llvm/include/llvm/IR/ConstantFold.h b/llvm/include/llvm/IR/ConstantFold.h --- a/llvm/include/llvm/IR/ConstantFold.h +++ b/llvm/include/llvm/IR/ConstantFold.h @@ -26,10 +26,15 @@ namespace llvm { template class ArrayRef; + inline bool SignedWrap = false; + class Value; class Constant; class Type; + bool getSignedWrap(void); + void setSignedWrap(bool Wrap); + // Constant fold various types of instruction... Constant *ConstantFoldCastInstruction( unsigned opcode, ///< The opcode of the cast diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -347,6 +347,14 @@ } } +bool llvm::getSignedWrap() { + return llvm::SignedWrap; +} + +void llvm::setSignedWrap(bool SignedWrap) { + llvm::SignedWrap=SignedWrap; +} + Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, Type *DestTy) { if (isa(V)) diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2510,7 +2510,9 @@ ArgVec.push_back(Idx); } - unsigned SubClassOptionalData = InBounds ? GEPOperator::IsInBounds : 0; + unsigned SubClassOptionalData = ( InBounds && !llvm::getSignedWrap() ) ? + GEPOperator::IsInBounds : 0; + if (InRangeIndex && *InRangeIndex < 63) SubClassOptionalData |= (*InRangeIndex + 1) << 1; const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,