diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index f0961de52743..9ebb5305b6f6 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -4785,7 +4785,21 @@ Instruction *InstCombiner::visitSetCondInstWithCastAndCast(SetCondInst &SCI) { Constant *Res = ConstantExpr::getCast(CI, SrcTy); if (ConstantExpr::getCast(Res, DestTy) == CI) { - RHSCIOp = Res; + // Make sure that src sign and dest sign match. For example, + // + // %A = cast short %X to uint + // %B = setgt uint %A, 1330 + // + // It is incorrect to transformt this into + // + // %B = setgt short %X, 1330 + // + // because %A may have negative value. + // However, it is OK if SrcTy is bool. See cast-set.ll testcase. + if (isSignSrc == isSignDest || SrcTy == Type::BoolTy) + RHSCIOp = Res; + else + return 0; } else { // If the value cannot be represented in the shorter type, we cannot emit // a simple comparison. diff --git a/llvm/test/Regression/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll b/llvm/test/Regression/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll index a4bf7a7a01d2..75e1ac663fa1 100644 --- a/llvm/test/Regression/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll +++ b/llvm/test/Regression/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll @@ -31,12 +31,6 @@ bool %lt_signed_to_large_negative(sbyte %SB) { ret bool %C } -bool %lt_signed_to_small_unsigned(sbyte %SB) { - %Y = cast sbyte %SB to uint ; [#uses=1] - %C = setlt uint %Y, 17 ; [#uses=1] - ret bool %C -} - bool %lt_signed_to_small_signed(sbyte %SB) { %Y = cast sbyte %SB to int %C = setlt int %Y, 17 @@ -73,12 +67,6 @@ bool %lt_unsigned_to_small_unsigned(ubyte %SB) { ret bool %C } -bool %lt_unsigned_to_small_signed(ubyte %SB) { - %Y = cast ubyte %SB to int - %C = setlt int %Y, 17 - ret bool %C -} - bool %lt_unsigned_to_small_negative(ubyte %SB) { %Y = cast ubyte %SB to int %C = setlt int %Y, -17 @@ -103,12 +91,6 @@ bool %gt_signed_to_large_negative(sbyte %SB) { ret bool %C } -bool %gt_signed_to_small_unsigned(sbyte %SB) { - %Y = cast sbyte %SB to uint ; [#uses=1] - %C = setgt uint %Y, 17 ; [#uses=1] - ret bool %C -} - bool %gt_signed_to_small_signed(sbyte %SB) { %Y = cast sbyte %SB to int %C = setgt int %Y, 17 @@ -145,12 +127,6 @@ bool %gt_unsigned_to_small_unsigned(ubyte %SB) { ret bool %C } -bool %gt_unsigned_to_small_signed(ubyte %SB) { - %Y = cast ubyte %SB to int - %C = setgt int %Y, 17 - ret bool %C -} - bool %gt_unsigned_to_small_negative(ubyte %SB) { %Y = cast ubyte %SB to int %C = setgt int %Y, -17 diff --git a/llvm/test/Regression/Transforms/InstCombine/2006-10-19-SignedToUnsignedCastAndConst.ll b/llvm/test/Regression/Transforms/InstCombine/2006-10-19-SignedToUnsignedCastAndConst.ll new file mode 100644 index 000000000000..e35c36694fe3 --- /dev/null +++ b/llvm/test/Regression/Transforms/InstCombine/2006-10-19-SignedToUnsignedCastAndConst.ll @@ -0,0 +1,8 @@ +; This test case is reduced from llvmAsmParser.cpp +; The optimizer should not remove the cast here. +; RUN: llvm-as %s -o - | opt -instcombine | llvm-dis | grep 'cast.*int' +bool %test(short %X) { +%A = cast short %X to uint +%B = setgt uint %A, 1330 +ret bool %B +}