aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp16
-rw-r--r--test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll24
-rw-r--r--test/Transforms/InstCombine/2006-10-19-SignedToUnsignedCastAndConst.ll8
3 files changed, 23 insertions, 25 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index f0961de527..9ebb5305b6 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/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/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll b/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
index a4bf7a7a01..75e1ac663f 100644
--- a/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
+++ b/test/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 ; <uint> [#uses=1]
- %C = setlt uint %Y, 17 ; <bool> [#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 ; <uint> [#uses=1]
- %C = setgt uint %Y, 17 ; <bool> [#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/test/Transforms/InstCombine/2006-10-19-SignedToUnsignedCastAndConst.ll b/test/Transforms/InstCombine/2006-10-19-SignedToUnsignedCastAndConst.ll
new file mode 100644
index 0000000000..e35c36694f
--- /dev/null
+++ b/test/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
+}