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

Reply via email to