[cfe-commits] r171755 - in /cfe/trunk: lib/AST/ExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/SemaExpr.cpp test/CodeGen/catch-undef-behavior.c test/CodeGenOpenCL/shifts.cl test/Sema/shiftOpenCL.cl
NAKAMURA Takumi
geek4civic at gmail.com
Mon Jan 7 16:21:02 PST 2013
Fixed in r171820.
...Takumi
2013/1/8 Dmitri Gribenko <gribozavr at gmail.com>:
> On Mon, Jan 7, 2013 at 6:43 PM, David Tweed <david.tweed at arm.com> wrote:
>> Author: davidtweed
>> Date: Mon Jan 7 10:43:27 2013
>> New Revision: 171755
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=171755&view=rev
>> Log:
>> Scalar shifts in the OpenCL specification (as of v. 1.2) are defined to be
>> with respect to the lower "left-hand-side bitwidth" bits, even when negative);
>> see OpenCL spec 6.3j. This patch both implements this behaviour in the code
>> generator and "constant folding" bits of Sema, and also prevents tests
>> to detect undefinedness in terms of the weaker C99 or C++ specifications
>> from being applied.
>>
>> Added:
>> cfe/trunk/test/CodeGenOpenCL/shifts.cl
>> cfe/trunk/test/Sema/shiftOpenCL.cl
>> Modified:
>> cfe/trunk/lib/AST/ExprConstant.cpp
>> cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>> cfe/trunk/lib/Sema/SemaExpr.cpp
>> cfe/trunk/test/CodeGen/catch-undef-behavior.c
>>
>> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=171755&r1=171754&r2=171755&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
>> +++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Jan 7 10:43:27 2013
>> @@ -4708,9 +4708,14 @@
>> return Success(E->getOpcode() == BO_Rem ? LHS % RHS : LHS / RHS, E,
>> Result);
>> case BO_Shl: {
>> - // During constant-folding, a negative shift is an opposite shift. Such
>> - // a shift is not a constant expression.
>> - if (RHS.isSigned() && RHS.isNegative()) {
>> + if (Info.getLangOpts().OpenCL)
>> + // OpenCL 6.3j: shift values are effectively % word size of LHS.
>> + RHS &= APSInt(llvm::APInt(LHS.getBitWidth(),
>> + static_cast<uint64_t>(LHS.getBitWidth() - 1)),
>> + RHS.isUnsigned());
>> + else if (RHS.isSigned() && RHS.isNegative()) {
>> + // During constant-folding, a negative shift is an opposite shift. Such
>> + // a shift is not a constant expression.
>> CCEDiag(E, diag::note_constexpr_negative_shift) << RHS;
>> RHS = -RHS;
>> goto shift_right;
>> @@ -4735,9 +4740,14 @@
>> return Success(LHS << SA, E, Result);
>> }
>> case BO_Shr: {
>> - // During constant-folding, a negative shift is an opposite shift. Such a
>> - // shift is not a constant expression.
>> - if (RHS.isSigned() && RHS.isNegative()) {
>> + if (Info.getLangOpts().OpenCL)
>> + // OpenCL 6.3j: shift values are effectively % word size of LHS.
>> + RHS &= APSInt(llvm::APInt(LHS.getBitWidth(),
>> + static_cast<uint64_t>(LHS.getBitWidth() - 1)),
>> + RHS.isUnsigned());
>> + else if (RHS.isSigned() && RHS.isNegative()) {
>> + // During constant-folding, a negative shift is an opposite shift. Such a
>> + // shift is not a constant expression.
>> CCEDiag(E, diag::note_constexpr_negative_shift) << RHS;
>> RHS = -RHS;
>> goto shift_left;
>>
>> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=171755&r1=171754&r2=171755&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Jan 7 10:43:27 2013
>> @@ -429,6 +429,8 @@
>> // Check for undefined division and modulus behaviors.
>> void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops,
>> llvm::Value *Zero,bool isDiv);
>> + // Common helper for getting how wide LHS of shift is.
>> + static Value *GetWidthMinusOneValue(Value* LHS,Value* RHS);
>> Value *EmitDiv(const BinOpInfo &Ops);
>> Value *EmitRem(const BinOpInfo &Ops);
>> Value *EmitAdd(const BinOpInfo &Ops);
>> @@ -2365,6 +2367,11 @@
>> return Builder.CreateExactSDiv(diffInChars, divisor, "sub.ptr.div");
>> }
>>
>> +Value *ScalarExprEmitter::GetWidthMinusOneValue(Value* LHS,Value* RHS) {
>> + unsigned Width = cast<llvm::IntegerType>(LHS->getType())->getBitWidth();
>> + return llvm::ConstantInt::get(RHS->getType(), Width - 1);
>> +}
>> +
>> Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
>> // LLVM requires the LHS and RHS to be the same type: promote or truncate the
>> // RHS to the same size as the LHS.
>> @@ -2372,11 +2379,9 @@
>> if (Ops.LHS->getType() != RHS->getType())
>> RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
>>
>> - if (CGF.getLangOpts().SanitizeShift &&
>> - isa<llvm::IntegerType>(Ops.LHS->getType())) {
>> - unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth();
>> - llvm::Value *WidthMinusOne =
>> - llvm::ConstantInt::get(RHS->getType(), Width - 1);
>> + if (CGF.getLangOpts().SanitizeShift && !CGF.getLangOpts().OpenCL
>> + && isa<llvm::IntegerType>(Ops.LHS->getType())) {
>> + llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS);
>> // FIXME: Emit the branching explicitly rather than emitting the check
>> // twice.
>> EmitBinOpCheck(Builder.CreateICmpULE(RHS, WidthMinusOne), Ops);
>> @@ -2401,6 +2406,9 @@
>> EmitBinOpCheck(Builder.CreateICmpEQ(BitsShiftedOff, Zero), Ops);
>> }
>> }
>> + // OpenCL 6.3j: shift values are effectively % word size of LHS.
>> + if (CGF.getLangOpts().OpenCL)
>> + RHS = Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shl.mask");
>>
>> return Builder.CreateShl(Ops.LHS, RHS, "shl");
>> }
>> @@ -2412,12 +2420,13 @@
>> if (Ops.LHS->getType() != RHS->getType())
>> RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
>>
>> - if (CGF.getLangOpts().SanitizeShift &&
>> - isa<llvm::IntegerType>(Ops.LHS->getType())) {
>> - unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth();
>> - llvm::Value *WidthVal = llvm::ConstantInt::get(RHS->getType(), Width);
>> - EmitBinOpCheck(Builder.CreateICmpULT(RHS, WidthVal), Ops);
>> - }
>> + if (CGF.getLangOpts().SanitizeShift && !CGF.getLangOpts().OpenCL
>> + && isa<llvm::IntegerType>(Ops.LHS->getType()))
>> + EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops);
>> +
>> + // OpenCL 6.3j: shift values are effectively % word size of LHS.
>> + if (CGF.getLangOpts().OpenCL)
>> + RHS = Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shr.mask");
>>
>> if (Ops.Ty->hasUnsignedIntegerRepresentation())
>> return Builder.CreateLShr(Ops.LHS, RHS, "shr");
>>
>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=171755&r1=171754&r2=171755&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jan 7 10:43:27 2013
>> @@ -6578,6 +6578,11 @@
>> static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
>> SourceLocation Loc, unsigned Opc,
>> QualType LHSType) {
>> + // OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
>> + // so skip remaining warnings as we don't want to modify values within Sema.
>> + if (S.getLangOpts().OpenCL)
>> + return;
>> +
>> llvm::APSInt Right;
>> // Check right/shifter operand
>> if (RHS.get()->isValueDependent() ||
>>
>> Modified: cfe/trunk/test/CodeGen/catch-undef-behavior.c
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/catch-undef-behavior.c?rev=171755&r1=171754&r2=171755&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CodeGen/catch-undef-behavior.c (original)
>> +++ cfe/trunk/test/CodeGen/catch-undef-behavior.c Mon Jan 7 10:43:27 2013
>> @@ -99,7 +99,7 @@
>>
>> // CHECK: @rsh_inbounds
>> int rsh_inbounds(int a, int b) {
>> - // CHECK: %[[INBOUNDS:.*]] = icmp ult i32 %[[RHS:.*]], 32
>> + // CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31
>> // CHECK: br i1 %[[INBOUNDS]]
>>
>> // CHECK: %[[ARG1:.*]] = zext
>>
>> Added: cfe/trunk/test/CodeGenOpenCL/shifts.cl
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/shifts.cl?rev=171755&view=auto
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenOpenCL/shifts.cl (added)
>> +++ cfe/trunk/test/CodeGenOpenCL/shifts.cl Mon Jan 7 10:43:27 2013
>> @@ -0,0 +1,28 @@
>> +// RUN: %clang_cc1 -x cl -O1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
>> +// OpenCL essentially reduces all shift amounts to the last word-size bits before evaluating.
>> +// Test this both for variables and constants evaluated in the front-end.
>> +
>> +
>> +//CHECK: @positiveShift32
>> +int positiveShift32(int a,int b) {
>> + //CHECK: %shl.mask = and i32 %b, 31
>> + //CHECK-NEXT: %shl = shl i32 %a, %shl.mask
>> + int c = a<<b;
>> + int d = ((int)1)<<33;
>> + //CHECK-NEXT: %add = add nsw i32 %shl, 2
>> + int e = c + d;
>> + //CHECK-NEXT: ret i32 %add
>> + return e;
>> +}
>> +
>> +//CHECK: @positiveShift64
>> +long positiveShift64(long a,long b) {
>> + //CHECK: %shr.mask = and i64 %b, 63
>> + //CHECK-NEXT: %shr = ashr i64 %a, %shr.mask
>> + long c = a>>b;
>> + long d = ((long)8)>>65;
>> + //CHECK-NEXT: %add = add nsw i64 %shr, 4
>> + long e = c + d;
>> + //CHECK-NEXT: ret i64 %add
>> + return e;
>> +}
>
> This test breaks on a Release-Asserts build with CMake+ninja. The
> generated IR is:
>
> define i32 @positiveShift32(i32 %a, i32 %b) nounwind readnone {
> %1 = and i32 %b, 31
> %2 = shl i32 %a, %1
> %3 = add nsw i32 %2, 2
> ret i32 %3
> }
>
> define i64 @positiveShift64(i64 %a, i64 %b) nounwind readnone {
> %1 = and i64 %b, 63
> %2 = ashr i64 %a, %1
> %3 = add nsw i64 %2, 4
> ret i64 %3
> }
>
> Dmitri
>
> --
> main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
> (j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list