Hi rsmith, chandlerc, nlewycky, nicholas, sanjoy,
For signed shifts, Op1 << Op2 in C and C++ is UB if the result cannot be
represented in the equivalent unsigned type. While a stronger statement
can be made for C, let's start small and say that a signed shift left
cannot shift out any one bits.
http://reviews.llvm.org/D8899
Files:
include/clang/Driver/Options.td
include/clang/Frontend/CodeGenOptions.def
lib/CodeGen/CGExprScalar.cpp
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
test/CodeGen/compound-type.c
test/OpenMP/atomic_update_codegen.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -802,6 +802,8 @@
def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;
def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>;
def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;
+def fno_strict_shifts : Flag<["-"], "fno-strict-shifts">, Group<f_Group>,
+ Flags<[CC1Option]>;
def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;
def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">;
@@ -928,6 +930,9 @@
def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable optimizations based on the strict definition of an enum's "
"value range">;
+def fstrict_shifts : Flag<["-"], "fstrict-shifts">, Group<f_Group>,
+ HelpText<"Enable optimizations based on the strict definition of the operands"
+ " that may be correctly passed to a shift operation">;
def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group<f_Group>;
def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>;
def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group<f_Group>;
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -116,6 +116,7 @@
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition.
+CODEGENOPT(StrictShifts , 1, 0) ///< Optimize based on strict shift definition.
CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization
///< selection.
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2716,6 +2716,7 @@
bool SanitizeBase = CGF.SanOpts.has(SanitizerKind::ShiftBase) &&
Ops.Ty->hasSignedIntegerRepresentation();
bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent);
+ bool HasNUW = false;
// OpenCL 6.3j: shift values are effectively % word size of LHS.
if (CGF.getLangOpts().OpenCL)
RHS =
@@ -2765,9 +2766,11 @@
assert(!Checks.empty());
EmitBinOpCheck(Checks, Ops);
+ } else {
+ HasNUW = Ops.Ty->isSignedIntegerOrEnumerationType() &&
+ CGF.CGM.getCodeGenOpts().StrictShifts;
}
-
- return Builder.CreateShl(Ops.LHS, RHS, "shl");
+ return Builder.CreateShl(Ops.LHS, RHS, "shl", HasNUW);
}
Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -2949,6 +2949,8 @@
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
+ if (!Args.hasFlag(options::OPT_fstrict_shifts, options::OPT_fno_strict_shifts))
+ CmdArgs.push_back("-fno-strict-shifts");
if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -464,6 +464,7 @@
Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums);
+ Opts.StrictShifts = !Args.hasArg(OPT_fno_strict_shifts);
Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
Index: test/CodeGen/compound-type.c
===================================================================
--- test/CodeGen/compound-type.c
+++ test/CodeGen/compound-type.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 < %s -emit-llvm -triple i686-pc-linux-gnu > %t
// RUN: grep "div i32" %t
-// RUN: grep "shl i32" %t
+// RUN: grep "shl nuw i32" %t
unsigned char a,b;
void c(void) {a <<= b;}
Index: test/OpenMP/atomic_update_codegen.cpp
===================================================================
--- test/OpenMP/atomic_update_codegen.cpp
+++ test/OpenMP/atomic_update_codegen.cpp
@@ -125,7 +125,7 @@
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[EXPECTED:%.+]] = phi i32 [ [[X]], %{{.+}} ], [ [[OLD_X:%.+]], %[[CONT]] ]
-// CHECK: [[DESIRED:%.+]] = shl i32 [[EXPECTED]], [[EXPR]]
+// CHECK: [[DESIRED:%.+]] = shl nuw i32 [[EXPECTED]], [[EXPR]]
// CHECK: [[RES:%.+]] = cmpxchg i32* [[X_ADDR]], i32 [[EXPECTED]], i32 [[DESIRED]] monotonic monotonic
// CHECK: [[OLD_X]] = extractvalue { i32, i1 } [[RES]], 0
// CHECK: [[SUCCESS_FAIL:%.+]] = extractvalue { i32, i1 } [[RES]], 1
@@ -432,7 +432,7 @@
// CHECK: [[CONT]]
// CHECK: [[EXPECTED:%.+]] = phi i64 [ [[X]], %{{.+}} ], [ [[OLD_X:%.+]], %[[CONT]] ]
// CHECK: [[X_RVAL:%.+]] = trunc i64 [[EXPECTED]] to i32
-// CHECK: [[SHL:%.+]] = shl i32 [[EXPR]], [[X_RVAL]]
+// CHECK: [[SHL:%.+]] = shl nuw i32 [[EXPR]], [[X_RVAL]]
// CHECK: [[DESIRED:%.+]] = sext i32 [[SHL]] to i64
// CHECK: [[RES:%.+]] = cmpxchg i64* [[ULX_ADDR]], i64 [[EXPECTED]], i64 [[DESIRED]] monotonic monotonic
// CHECK: [[OLD_X:%.+]] = extractvalue { i64, i1 } [[RES]], 0
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits