; This test case tests the InstructionCombining optimization that
; reduces things like:
;   %Y = sext i8 %X to i32 
;   %C = icmp ult i32 %Y, 1024
; to
;   %C = i1 true
; It includes test cases for different constant values, signedness of the
; cast operands, and types of setCC operators. In all cases, the cast should
; be eliminated. In many cases the setCC is also eliminated based on the
; constant value and the range of the casted value.
;
; RUN: opt < %s -instcombine -S | FileCheck %s
; END.
define i1 @lt_signed_to_large_unsigned(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp ult i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C1 = icmp sgt i8 %SB, -1
; CHECK: ret i1 %C1
}

define i1 @lt_signed_to_large_signed(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp slt i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 true
}

define i1 @lt_signed_to_large_negative(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp slt i32 %Y, -1024             ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 false
}

define i1 @lt_signed_to_small_unsigned(i8 %SB) {
        %Y = sext i8 %SB to i32
        %C = icmp ult i32 %Y, 17
        ret i1 %C
; CHECK: %C = icmp ult i8 %SB, 17
; CHECK: ret i1 %C
}

define i1 @lt_signed_to_small_signed(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp slt i32 %Y, 17                ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C = icmp slt i8 %SB, 17
; CHECK: ret i1 %C
}
define i1 @lt_signed_to_small_negative(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp slt i32 %Y, -17               ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C = icmp slt i8 %SB, -17
; CHECK: ret i1 %C
}

define i1 @lt_unsigned_to_large_unsigned(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp ult i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 true
}

define i1 @lt_unsigned_to_large_signed(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp slt i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 true
}

define i1 @lt_unsigned_to_large_negative(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp slt i32 %Y, -1024             ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 false
}

define i1 @lt_unsigned_to_small_unsigned(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp ult i32 %Y, 17                ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C = icmp ult i8 %SB, 17
; CHECK: ret i1 %C
}

define i1 @lt_unsigned_to_small_signed(i8 %SB) {
        %Y = zext i8 %SB to i32
        %C = icmp slt i32 %Y, 17
        ret i1 %C
; CHECK: %C = icmp ult i8 %SB, 17
; CHECK: ret i1 %C
}

define i1 @lt_unsigned_to_small_negative(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp slt i32 %Y, -17               ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 false
}

define i1 @gt_signed_to_large_unsigned(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp ugt i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C = icmp slt i8 %SB, 0
; CHECK: ret i1 %C
}

define i1 @gt_signed_to_large_signed(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp sgt i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 false
}

define i1 @gt_signed_to_large_negative(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp sgt i32 %Y, -1024             ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 true
}

define i1 @gt_signed_to_small_unsigned(i8 %SB) {
        %Y = sext i8 %SB to i32
        %C = icmp ugt i32 %Y, 17
        ret i1 %C
; CHECK: %C = icmp ugt i8 %SB, 17
; CHECK: ret i1 %C
}

define i1 @gt_signed_to_small_signed(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp sgt i32 %Y, 17                ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C = icmp sgt i8 %SB, 17
; CHECK: ret i1 %C
}

define i1 @gt_signed_to_small_negative(i8 %SB) {
        %Y = sext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp sgt i32 %Y, -17               ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C = icmp sgt i8 %SB, -17
; CHECK: ret i1 %C
}

define i1 @gt_unsigned_to_large_unsigned(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp ugt i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 false
}

define i1 @gt_unsigned_to_large_signed(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp sgt i32 %Y, 1024              ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 false
}

define i1 @gt_unsigned_to_large_negative(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp sgt i32 %Y, -1024             ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 true
}

define i1 @gt_unsigned_to_small_unsigned(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp ugt i32 %Y, 17                ; <i1> [#uses=1]
        ret i1 %C
; CHECK: %C = icmp ugt i8 %SB, 17
; CHECK: ret i1 %C
}

define i1 @gt_unsigned_to_small_signed(i8 %SB) {
        %Y = zext i8 %SB to i32
        %C = icmp sgt i32 %Y, 17
        ret i1 %C
; CHECK: %C = icmp ugt i8 %SB, 17
; CHECK: ret i1 %C
}

define i1 @gt_unsigned_to_small_negative(i8 %SB) {
        %Y = zext i8 %SB to i32         ; <i32> [#uses=1]
        %C = icmp sgt i32 %Y, -17               ; <i1> [#uses=1]
        ret i1 %C
; CHECK: ret i1 true
}