2019-04-17 12:52:47 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
|
|
|
|
target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
|
|
|
|
|
|
|
define i32 @test1(i32 %X) {
|
|
|
|
; CHECK-LABEL: @test1(
|
|
|
|
; CHECK-NEXT: [[X_LOBIT:%.*]] = lshr i32 [[X:%.*]], 31
|
|
|
|
; CHECK-NEXT: ret i32 [[X_LOBIT]]
|
|
|
|
;
|
|
|
|
%a = icmp slt i32 %X, 0
|
|
|
|
%b = zext i1 %a to i32
|
|
|
|
ret i32 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i32> @test1vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @test1vec(
|
|
|
|
; CHECK-NEXT: [[X_LOBIT:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 31, i32 31>
|
|
|
|
; CHECK-NEXT: ret <2 x i32> [[X_LOBIT]]
|
|
|
|
;
|
|
|
|
%a = icmp slt <2 x i32> %X, zeroinitializer
|
|
|
|
%b = zext <2 x i1> %a to <2 x i32>
|
|
|
|
ret <2 x i32> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test2(i32 %X) {
|
|
|
|
; CHECK-LABEL: @test2(
|
|
|
|
; CHECK-NEXT: [[X_LOBIT:%.*]] = lshr i32 [[X:%.*]], 31
|
|
|
|
; CHECK-NEXT: [[X_LOBIT_NOT:%.*]] = xor i32 [[X_LOBIT]], 1
|
|
|
|
; CHECK-NEXT: ret i32 [[X_LOBIT_NOT]]
|
|
|
|
;
|
|
|
|
%a = icmp ult i32 %X, -2147483648
|
|
|
|
%b = zext i1 %a to i32
|
|
|
|
ret i32 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i32> @test2vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @test2vec(
|
|
|
|
; CHECK-NEXT: [[X_LOBIT:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 31, i32 31>
|
|
|
|
; CHECK-NEXT: [[X_LOBIT_NOT:%.*]] = xor <2 x i32> [[X_LOBIT]], <i32 1, i32 1>
|
|
|
|
; CHECK-NEXT: ret <2 x i32> [[X_LOBIT_NOT]]
|
|
|
|
;
|
|
|
|
%a = icmp ult <2 x i32> %X, <i32 -2147483648, i32 -2147483648>
|
|
|
|
%b = zext <2 x i1> %a to <2 x i32>
|
|
|
|
ret <2 x i32> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test3(i32 %X) {
|
|
|
|
; CHECK-LABEL: @test3(
|
|
|
|
; CHECK-NEXT: [[X_LOBIT:%.*]] = ashr i32 [[X:%.*]], 31
|
|
|
|
; CHECK-NEXT: ret i32 [[X_LOBIT]]
|
|
|
|
;
|
|
|
|
%a = icmp slt i32 %X, 0
|
|
|
|
%b = sext i1 %a to i32
|
|
|
|
ret i32 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test4(i32 %X) {
|
|
|
|
; CHECK-LABEL: @test4(
|
|
|
|
; CHECK-NEXT: [[X_LOBIT:%.*]] = ashr i32 [[X:%.*]], 31
|
|
|
|
; CHECK-NEXT: [[X_LOBIT_NOT:%.*]] = xor i32 [[X_LOBIT]], -1
|
|
|
|
; CHECK-NEXT: ret i32 [[X_LOBIT_NOT]]
|
|
|
|
;
|
|
|
|
%a = icmp ult i32 %X, -2147483648
|
|
|
|
%b = sext i1 %a to i32
|
|
|
|
ret i32 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR4837
|
|
|
|
define <2 x i1> @test5_eq(<2 x i64> %x) {
|
|
|
|
; CHECK-LABEL: @test5_eq(
|
|
|
|
; CHECK-NEXT: ret <2 x i1> undef
|
|
|
|
;
|
|
|
|
%V = icmp eq <2 x i64> %x, undef
|
|
|
|
ret <2 x i1> %V
|
|
|
|
}
|
|
|
|
define <2 x i1> @test5_ne(<2 x i64> %x) {
|
|
|
|
; CHECK-LABEL: @test5_ne(
|
|
|
|
; CHECK-NEXT: ret <2 x i1> undef
|
|
|
|
;
|
|
|
|
%V = icmp ne <2 x i64> %x, undef
|
|
|
|
ret <2 x i1> %V
|
|
|
|
}
|
|
|
|
define <2 x i1> @test5_ugt(<2 x i64> %x) {
|
|
|
|
; CHECK-LABEL: @test5_ugt(
|
|
|
|
; CHECK-NEXT: ret <2 x i1> zeroinitializer
|
|
|
|
;
|
|
|
|
%V = icmp ugt <2 x i64> %x, undef
|
|
|
|
ret <2 x i1> %V
|
|
|
|
}
|
|
|
|
define <2 x i1> @test5_zero() {
|
|
|
|
; CHECK-LABEL: @test5_zero(
|
|
|
|
; CHECK-NEXT: ret <2 x i1> undef
|
|
|
|
;
|
|
|
|
%V = icmp eq <2 x i64> zeroinitializer, undef
|
|
|
|
ret <2 x i1> %V
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test6(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test6(
|
2020-02-09 00:02:10 +08:00
|
|
|
; CHECK-NEXT: [[A_LOBIT_NEG:%.*]] = ashr i32 [[A:%.*]], 31
|
|
|
|
; CHECK-NEXT: [[F:%.*]] = and i32 [[A_LOBIT_NEG]], [[B:%.*]]
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[F]]
|
|
|
|
;
|
|
|
|
%c = icmp sle i32 %a, -1
|
|
|
|
%d = zext i1 %c to i32
|
|
|
|
%e = sub i32 0, %d
|
|
|
|
%f = and i32 %e, %b
|
|
|
|
ret i32 %f
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define i1 @test7(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test7(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%a = add i32 %x, -1
|
|
|
|
%b = icmp ult i32 %a, %x
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test7_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test7_vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i32> [[X:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[B]]
|
|
|
|
;
|
|
|
|
%a = add <2 x i32> %x, <i32 -1, i32 -1>
|
|
|
|
%b = icmp ult <2 x i32> %a, %x
|
|
|
|
ret <2 x i1> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test8(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test8(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%a = add i32 %x, -1
|
|
|
|
%b = icmp eq i32 %a, %x
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test8_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test8_vec(
|
|
|
|
; CHECK-NEXT: ret <2 x i1> zeroinitializer
|
|
|
|
;
|
|
|
|
%a = add <2 x i32> %x, <i32 -1, i32 -1>
|
|
|
|
%b = icmp eq <2 x i32> %a, %x
|
|
|
|
ret <2 x i1> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test9(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test9(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ugt i32 [[X:%.*]], 1
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%a = add i32 %x, -2
|
|
|
|
%b = icmp ugt i32 %x, %a
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test9_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test9_vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 1, i32 1>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[B]]
|
|
|
|
;
|
|
|
|
%a = add <2 x i32> %x, <i32 -2, i32 -2>
|
|
|
|
%b = icmp ugt <2 x i32> %x, %a
|
|
|
|
ret <2 x i1> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test9b(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test9b(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ult i32 [[X:%.*]], 2
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%a = add i32 %x, -2
|
|
|
|
%b = icmp ugt i32 %a, %x
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test9b_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test9b_vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 2, i32 2>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[B]]
|
|
|
|
;
|
|
|
|
%a = add <2 x i32> %x, <i32 -2, i32 -2>
|
|
|
|
%b = icmp ugt <2 x i32> %a, %x
|
|
|
|
ret <2 x i1> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test10(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test10(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[X:%.*]], -2147483648
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%a = add i32 %x, -1
|
|
|
|
%b = icmp slt i32 %a, %x
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test10_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test10_vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i32> [[X:%.*]], <i32 -2147483648, i32 -2147483648>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[B]]
|
|
|
|
;
|
|
|
|
%a = add <2 x i32> %x, <i32 -1, i32 -1>
|
|
|
|
%b = icmp slt <2 x i32> %a, %x
|
|
|
|
ret <2 x i1> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test10b(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test10b(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[X:%.*]], -2147483648
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%a = add i32 %x, -1
|
|
|
|
%b = icmp sgt i32 %a, %x
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test10b_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test10b_vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i32> [[X:%.*]], <i32 -2147483648, i32 -2147483648>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[B]]
|
|
|
|
;
|
|
|
|
%a = add <2 x i32> %x, <i32 -1, i32 -1>
|
|
|
|
%b = icmp sgt <2 x i32> %a, %x
|
|
|
|
ret <2 x i1> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test11(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test11(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%a = add nsw i32 %x, 8
|
|
|
|
%b = icmp slt i32 %x, %a
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test11_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test11_vec(
|
|
|
|
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
|
|
|
|
;
|
|
|
|
%a = add nsw <2 x i32> %x, <i32 8, i32 8>
|
|
|
|
%b = icmp slt <2 x i32> %x, %a
|
|
|
|
ret <2 x i1> %b
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR6195
|
|
|
|
define i1 @test12(i1 %A) {
|
|
|
|
; CHECK-LABEL: @test12(
|
|
|
|
; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true
|
|
|
|
; CHECK-NEXT: ret i1 [[NOT_A]]
|
|
|
|
;
|
|
|
|
%S = select i1 %A, i64 -4294967295, i64 8589934591
|
|
|
|
%B = icmp ne i64 bitcast (<2 x i32> <i32 1, i32 -1> to i64), %S
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR6481
|
|
|
|
define i1 @test13(i8 %X) {
|
|
|
|
; CHECK-LABEL: @test13(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%cmp = icmp slt i8 undef, %X
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test14(i8 %X) {
|
|
|
|
; CHECK-LABEL: @test14(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%cmp = icmp slt i8 undef, -128
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test15() {
|
|
|
|
; CHECK-LABEL: @test15(
|
|
|
|
; CHECK-NEXT: ret i1 undef
|
|
|
|
;
|
|
|
|
%cmp = icmp eq i8 undef, -128
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test16() {
|
|
|
|
; CHECK-LABEL: @test16(
|
|
|
|
; CHECK-NEXT: ret i1 undef
|
|
|
|
;
|
|
|
|
%cmp = icmp ne i8 undef, -128
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test17(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test17(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %x
|
|
|
|
%and = and i32 %shl, 8
|
|
|
|
%cmp = icmp eq i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test17vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test17vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %x
|
|
|
|
%and = and <2 x i32> %shl, <i32 8, i32 8>
|
|
|
|
%cmp = icmp eq <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test17a(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test17a(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], 2
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %x
|
|
|
|
%and = and i32 %shl, 7
|
|
|
|
%cmp = icmp eq i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test17a_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test17a_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 2, i32 2>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %x
|
|
|
|
%and = and <2 x i32> %shl, <i32 7, i32 7>
|
|
|
|
%cmp = icmp eq <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test18_eq(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test18_eq(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sh = lshr i32 8, %x
|
|
|
|
%and = and i32 %sh, 1
|
|
|
|
%cmp = icmp eq i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test18_eq_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test18_eq_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%sh = lshr <2 x i32> <i32 8, i32 8>, %x
|
|
|
|
%and = and <2 x i32> %sh, <i32 1, i32 1>
|
|
|
|
%cmp = icmp eq <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test18_ne(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test18_ne(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sh = lshr i32 8, %x
|
|
|
|
%and = and i32 %sh, 1
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test18_ne_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test18_ne_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%sh = lshr <2 x i32> <i32 8, i32 8>, %x
|
|
|
|
%and = and <2 x i32> %sh, <i32 1, i32 1>
|
|
|
|
%cmp = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test19(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test19(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %x
|
|
|
|
%and = and i32 %shl, 8
|
|
|
|
%cmp = icmp eq i32 %and, 8
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test19vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test19vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %x
|
|
|
|
%and = and <2 x i32> %shl, <i32 8, i32 8>
|
|
|
|
%cmp = icmp eq <2 x i32> %and, <i32 8, i32 8>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @cmp_and_signbit_vec(<2 x i3> %x) {
|
|
|
|
; CHECK-LABEL: @cmp_and_signbit_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i3> [[X:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and <2 x i3> %x, <i3 4, i3 4>
|
|
|
|
%cmp = icmp ne <2 x i3> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test20(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test20(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %x
|
|
|
|
%and = and i32 %shl, 8
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test20vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test20vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %x
|
|
|
|
%and = and <2 x i32> %shl, <i32 8, i32 8>
|
|
|
|
%cmp = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test20a(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test20a(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %x
|
|
|
|
%and = and i32 %shl, 7
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test20a_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test20a_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %x
|
|
|
|
%and = and <2 x i32> %shl, <i32 7, i32 7>
|
|
|
|
%cmp = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test21(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @test21(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = or i8 %x, 1
|
|
|
|
%B = icmp ugt i8 %A, 3
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test22(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @test22(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 4
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = or i8 %x, 1
|
|
|
|
%B = icmp ult i8 %A, 4
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR2740
|
|
|
|
define i1 @test23(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test23(
|
|
|
|
; CHECK-NEXT: [[I4:%.*]] = icmp sgt i32 [[X:%.*]], 1328634634
|
|
|
|
; CHECK-NEXT: ret i1 [[I4]]
|
|
|
|
;
|
|
|
|
%i3 = sdiv i32 %x, -1328634635
|
|
|
|
%i4 = icmp eq i32 %i3, -1
|
|
|
|
ret i1 %i4
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test23vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test23vec(
|
|
|
|
; CHECK-NEXT: [[I4:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 1328634634, i32 1328634634>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[I4]]
|
|
|
|
;
|
|
|
|
%i3 = sdiv <2 x i32> %x, <i32 -1328634635, i32 -1328634635>
|
|
|
|
%i4 = icmp eq <2 x i32> %i3, <i32 -1, i32 -1>
|
|
|
|
ret <2 x i1> %i4
|
|
|
|
}
|
|
|
|
|
|
|
|
@X = global [1000 x i32] zeroinitializer
|
|
|
|
|
|
|
|
; PR8882
|
|
|
|
define i1 @test24(i64 %i) {
|
|
|
|
; CHECK-LABEL: @test24(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[I:%.*]], 1000
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%p1 = getelementptr inbounds i32, i32* getelementptr inbounds ([1000 x i32], [1000 x i32]* @X, i64 0, i64 0), i64 %i
|
|
|
|
%cmp = icmp eq i32* %p1, getelementptr inbounds ([1000 x i32], [1000 x i32]* @X, i64 1, i64 0)
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
[Analysis] Don't assume that unsigned overflow can't happen in EmitGEPOffset (PR42699)
Summary:
Currently when computing a GEP offset using the function EmitGEPOffset
for the following instruction
getelementptr inbounds i32, i32* %p, i64 %offs
we get
mul nuw i64 %offs, 4
Unfortunately we cannot assume that unsigned wrapping won't happen
here because %offs is allowed to be negative.
Making such assumptions can lead to miscompilations: see the new test
test24_neg_offs in InstCombine/icmp.ll. Without the patch InstCombine
would generate the following comparison:
icmp eq i64 %offs, 4611686018427387902; 0x3ffffffffffffffe
Whereas the correct value to compare with is -2.
This patch replaces the NUW flag with NSW in the multiplication
instructions generated by EmitGEPOffset and adjusts the test suite.
https://bugs.llvm.org/show_bug.cgi?id=42699
Reviewers: chandlerc, craig.topper, ostannard, lebedev.ri, spatel, efriedma, nlopes, aqjune
Reviewed By: lebedev.ri
Subscribers: reames, lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68342
llvm-svn: 375089
2019-10-17 16:59:06 +08:00
|
|
|
; Note: offs can be negative, LLVM used to make an incorrect assumption that
|
|
|
|
; unsigned overflow does not happen during offset computation
|
|
|
|
define i1 @test24_neg_offs(i32* %p, i64 %offs) {
|
|
|
|
; CHECK-LABEL: @test24_neg_offs(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[OFFS:%.*]], -2
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%p1 = getelementptr inbounds i32, i32* %p, i64 %offs
|
|
|
|
%conv1 = ptrtoint i32* %p to i64
|
|
|
|
%conv2 = ptrtoint i32* %p1 to i64
|
|
|
|
%delta = sub i64 %conv1, %conv2
|
|
|
|
%cmp = icmp eq i64 %delta, 8
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
2019-04-17 12:52:47 +08:00
|
|
|
@X_as1 = addrspace(1) global [1000 x i32] zeroinitializer
|
|
|
|
|
|
|
|
define i1 @test24_as1(i64 %i) {
|
|
|
|
; CHECK-LABEL: @test24_as1(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[TMP1]], 1000
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%p1 = getelementptr inbounds i32, i32 addrspace(1)* getelementptr inbounds ([1000 x i32], [1000 x i32] addrspace(1)* @X_as1, i64 0, i64 0), i64 %i
|
|
|
|
%cmp = icmp eq i32 addrspace(1)* %p1, getelementptr inbounds ([1000 x i32], [1000 x i32] addrspace(1)* @X_as1, i64 1, i64 0)
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; X - Z > Y - Z -> X > Y if there is no overflow.
|
|
|
|
define i1 @test27(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test27(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nsw i32 %x, %z
|
|
|
|
%rhs = sub nsw i32 %y, %z
|
|
|
|
%c = icmp sgt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-09-16 04:13:27 +08:00
|
|
|
define i1 @test27_extra_uses(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test27_extra_uses(
|
|
|
|
; CHECK-NEXT: [[LHS:%.*]] = sub nsw i32 [[X:%.*]], [[Z:%.*]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[LHS]])
|
|
|
|
; CHECK-NEXT: [[RHS:%.*]] = sub nsw i32 [[Y:%.*]], [[Z]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[RHS]])
|
2019-09-16 04:56:34 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X]], [[Y]]
|
2019-09-16 04:13:27 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nsw i32 %x, %z
|
|
|
|
call void @foo(i32 %lhs)
|
|
|
|
%rhs = sub nsw i32 %y, %z
|
|
|
|
call void @foo(i32 %rhs)
|
|
|
|
%c = icmp sgt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-04-17 12:52:47 +08:00
|
|
|
; X - Z > Y - Z -> X > Y if there is no overflow.
|
|
|
|
define i1 @test28(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test28(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nuw i32 %x, %z
|
|
|
|
%rhs = sub nuw i32 %y, %z
|
|
|
|
%c = icmp ugt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-09-16 04:13:27 +08:00
|
|
|
define i1 @test28_extra_uses(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test28_extra_uses(
|
|
|
|
; CHECK-NEXT: [[LHS:%.*]] = sub nuw i32 [[X:%.*]], [[Z:%.*]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[LHS]])
|
|
|
|
; CHECK-NEXT: [[RHS:%.*]] = sub nuw i32 [[Y:%.*]], [[Z]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[RHS]])
|
2019-09-16 04:56:34 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[X]], [[Y]]
|
2019-09-16 04:13:27 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nuw i32 %x, %z
|
|
|
|
call void @foo(i32 %lhs)
|
|
|
|
%rhs = sub nuw i32 %y, %z
|
|
|
|
call void @foo(i32 %rhs)
|
|
|
|
%c = icmp ugt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-09-16 22:05:19 +08:00
|
|
|
; PR36969 - https://bugs.llvm.org/show_bug.cgi?id=36969
|
2019-04-17 12:52:47 +08:00
|
|
|
|
2019-09-16 22:05:19 +08:00
|
|
|
define i1 @ugt_sub(i32 %xsrc, i32 %y) {
|
|
|
|
; CHECK-LABEL: @ugt_sub(
|
|
|
|
; CHECK-NEXT: [[X:%.*]] = udiv i32 [[XSRC:%.*]], 42
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
2019-04-17 12:52:47 +08:00
|
|
|
;
|
2019-09-16 22:05:19 +08:00
|
|
|
%x = udiv i32 %xsrc, 42 ; thwart complexity-based canonicalization
|
|
|
|
%sub = sub i32 %x, %y
|
|
|
|
%cmp = icmp ugt i32 %sub, %x
|
|
|
|
ret i1 %cmp
|
2019-04-17 12:52:47 +08:00
|
|
|
}
|
|
|
|
|
2019-09-16 22:05:19 +08:00
|
|
|
; Swap operands and predicate. Try a vector type to verify that works too.
|
2019-04-17 12:52:47 +08:00
|
|
|
|
2019-09-16 22:05:19 +08:00
|
|
|
define <2 x i1> @ult_sub(<2 x i8> %xsrc, <2 x i8> %y) {
|
|
|
|
; CHECK-LABEL: @ult_sub(
|
|
|
|
; CHECK-NEXT: [[X:%.*]] = udiv <2 x i8> [[XSRC:%.*]], <i8 42, i8 -42>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[X]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
2019-04-17 12:52:47 +08:00
|
|
|
;
|
2019-09-16 22:05:19 +08:00
|
|
|
%x = udiv <2 x i8> %xsrc, <i8 42, i8 -42> ; thwart complexity-based canonicalization
|
|
|
|
%sub = sub <2 x i8> %x, %y
|
|
|
|
%cmp = icmp ult <2 x i8> %x, %sub
|
|
|
|
ret <2 x i1> %cmp
|
2019-04-17 12:52:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
; X - Y > X -> 0 > Y if there is no overflow.
|
|
|
|
define i1 @test33(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @test33(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[Y:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nsw i32 %x, %y
|
|
|
|
%c = icmp sgt i32 %lhs, %x
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
; X - Y > X -> 0 > Y if there is no overflow.
|
|
|
|
define i1 @test34(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @test34(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%lhs = sub nuw i32 %x, %y
|
|
|
|
%c = icmp ugt i32 %lhs, %x
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
; X > X - Y -> Y > 0 if there is no overflow.
|
|
|
|
define i1 @test35(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @test35(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[Y:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%rhs = sub nsw i32 %x, %y
|
|
|
|
%c = icmp sgt i32 %x, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
; X > X - Y -> Y > 0 if there is no overflow.
|
|
|
|
define i1 @test36(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @test36(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[Y:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%rhs = sub nuw i32 %x, %y
|
|
|
|
%c = icmp ugt i32 %x, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
; X - Y > X - Z -> Z > Y if there is no overflow.
|
|
|
|
define i1 @test37(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test37(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[Z:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nsw i32 %x, %y
|
|
|
|
%rhs = sub nsw i32 %x, %z
|
|
|
|
%c = icmp sgt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-09-16 20:19:18 +08:00
|
|
|
define i1 @test37_extra_uses(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test37_extra_uses(
|
|
|
|
; CHECK-NEXT: [[LHS:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[LHS]])
|
|
|
|
; CHECK-NEXT: [[RHS:%.*]] = sub nsw i32 [[X]], [[Z:%.*]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[RHS]])
|
2019-09-16 20:54:34 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[Z]], [[Y]]
|
2019-09-16 20:19:18 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nsw i32 %x, %y
|
|
|
|
call void @foo(i32 %lhs)
|
|
|
|
%rhs = sub nsw i32 %x, %z
|
|
|
|
call void @foo(i32 %rhs)
|
|
|
|
%c = icmp sgt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-09-22 22:23:22 +08:00
|
|
|
; TODO: Min/max pattern should not prevent the fold.
|
|
|
|
|
|
|
|
define i32 @neg_max_s32(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @neg_max_s32(
|
2019-09-22 22:31:53 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[S_V:%.*]] = select i1 [[C]], i32 [[Y]], i32 [[X]]
|
|
|
|
; CHECK-NEXT: ret i32 [[S_V]]
|
2019-09-22 22:23:22 +08:00
|
|
|
;
|
|
|
|
%nx = sub nsw i32 0, %x
|
|
|
|
%ny = sub nsw i32 0, %y
|
|
|
|
%c = icmp slt i32 %nx, %ny
|
|
|
|
%s = select i1 %c, i32 %ny, i32 %nx
|
|
|
|
%r = sub nsw i32 0, %s
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define <4 x i32> @neg_max_v4s32(<4 x i32> %x, <4 x i32> %y) {
|
|
|
|
; CHECK-LABEL: @neg_max_v4s32(
|
2019-09-22 22:31:53 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt <4 x i32> [[Y:%.*]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[S_V:%.*]] = select <4 x i1> [[C]], <4 x i32> [[X]], <4 x i32> [[Y]]
|
|
|
|
; CHECK-NEXT: ret <4 x i32> [[S_V]]
|
2019-09-22 22:23:22 +08:00
|
|
|
;
|
|
|
|
%nx = sub nsw <4 x i32> zeroinitializer, %x
|
|
|
|
%ny = sub nsw <4 x i32> zeroinitializer, %y
|
|
|
|
%c = icmp sgt <4 x i32> %nx, %ny
|
|
|
|
%s = select <4 x i1> %c, <4 x i32> %nx, <4 x i32> %ny
|
|
|
|
%r = sub <4 x i32> zeroinitializer, %s
|
|
|
|
ret <4 x i32> %r
|
|
|
|
}
|
|
|
|
|
2019-04-17 12:52:47 +08:00
|
|
|
; X - Y > X - Z -> Z > Y if there is no overflow.
|
|
|
|
define i1 @test38(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test38(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[Z:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nuw i32 %x, %y
|
|
|
|
%rhs = sub nuw i32 %x, %z
|
|
|
|
%c = icmp ugt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-09-16 20:19:18 +08:00
|
|
|
define i1 @test38_extra_uses(i32 %x, i32 %y, i32 %z) {
|
|
|
|
; CHECK-LABEL: @test38_extra_uses(
|
|
|
|
; CHECK-NEXT: [[LHS:%.*]] = sub nuw i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[LHS]])
|
|
|
|
; CHECK-NEXT: [[RHS:%.*]] = sub nuw i32 [[X]], [[Z:%.*]]
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[RHS]])
|
2019-09-16 20:54:34 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[Z]], [[Y]]
|
2019-09-16 20:19:18 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%lhs = sub nuw i32 %x, %y
|
|
|
|
call void @foo(i32 %lhs)
|
|
|
|
%rhs = sub nuw i32 %x, %z
|
|
|
|
call void @foo(i32 %rhs)
|
|
|
|
%c = icmp ugt i32 %lhs, %rhs
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
2019-04-17 12:52:47 +08:00
|
|
|
; PR9343 #1
|
|
|
|
define i1 @test39(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test39(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = ashr exact i32 %X, %Y
|
|
|
|
%B = icmp eq i32 %A, 0
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test39vec(<2 x i32> %X, <2 x i32> %Y) {
|
|
|
|
; CHECK-LABEL: @test39vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i32> [[X:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[B]]
|
|
|
|
;
|
|
|
|
%A = ashr exact <2 x i32> %X, %Y
|
|
|
|
%B = icmp eq <2 x i32> %A, zeroinitializer
|
|
|
|
ret <2 x i1> %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test40(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test40(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = lshr exact i32 %X, %Y
|
|
|
|
%B = icmp ne i32 %A, 0
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test40vec(<2 x i32> %X, <2 x i32> %Y) {
|
|
|
|
; CHECK-LABEL: @test40vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i32> [[X:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[B]]
|
|
|
|
;
|
|
|
|
%A = lshr exact <2 x i32> %X, %Y
|
|
|
|
%B = icmp ne <2 x i32> %A, zeroinitializer
|
|
|
|
ret <2 x i1> %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shr_exact(i132 %x) {
|
|
|
|
; CHECK-LABEL: @shr_exact(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i132 [[X:%.*]], 32
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sh = ashr exact i132 %x, 4
|
|
|
|
%cmp = icmp eq i132 %sh, 2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @shr_exact_vec(<2 x i132> %x) {
|
|
|
|
; CHECK-LABEL: @shr_exact_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i132> [[X:%.*]], <i132 32, i132 32>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%sh = lshr exact <2 x i132> %x, <i132 4, i132 4>
|
|
|
|
%cmp = icmp ne <2 x i132> %sh, <i132 2, i132 2>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR9343 #3
|
|
|
|
define i1 @test41(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test41(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%A = urem i32 %X, %Y
|
|
|
|
%B = icmp ugt i32 %Y, %A
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test42(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test42(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp sgt i32 [[Y:%.*]], -1
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = srem i32 %X, %Y
|
|
|
|
%B = icmp slt i32 %A, %Y
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test43(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test43(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[Y:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = srem i32 %X, %Y
|
|
|
|
%B = icmp slt i32 %Y, %A
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test44(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test44(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp sgt i32 [[Y:%.*]], -1
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = srem i32 %X, %Y
|
|
|
|
%B = icmp slt i32 %A, %Y
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test45(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test45(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[Y:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%A = srem i32 %X, %Y
|
|
|
|
%B = icmp slt i32 %Y, %A
|
|
|
|
ret i1 %B
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR9343 #4
|
|
|
|
define i1 @test46(i32 %X, i32 %Y, i32 %Z) {
|
|
|
|
; CHECK-LABEL: @test46(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = ashr exact i32 %X, %Z
|
|
|
|
%B = ashr exact i32 %Y, %Z
|
|
|
|
%C = icmp ult i32 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR9343 #5
|
|
|
|
define i1 @test47(i32 %X, i32 %Y, i32 %Z) {
|
|
|
|
; CHECK-LABEL: @test47(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = ashr exact i32 %X, %Z
|
|
|
|
%B = ashr exact i32 %Y, %Z
|
|
|
|
%C = icmp ugt i32 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR9343 #8
|
|
|
|
define i1 @test48(i32 %X, i32 %Y, i32 %Z) {
|
|
|
|
; CHECK-LABEL: @test48(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = sdiv exact i32 %X, %Z
|
|
|
|
%B = sdiv exact i32 %Y, %Z
|
|
|
|
%C = icmp eq i32 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; The above transform only works for equality predicates.
|
|
|
|
|
|
|
|
define i1 @PR32949(i32 %X, i32 %Y, i32 %Z) {
|
|
|
|
; CHECK-LABEL: @PR32949(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = sdiv exact i32 [[X:%.*]], [[Z:%.*]]
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = sdiv exact i32 [[Y:%.*]], [[Z]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A]], [[B]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = sdiv exact i32 %X, %Z
|
|
|
|
%B = sdiv exact i32 %Y, %Z
|
|
|
|
%C = icmp sgt i32 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR8469
|
|
|
|
define <2 x i1> @test49(<2 x i32> %tmp3) {
|
|
|
|
; CHECK-LABEL: @test49(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
|
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%tmp11 = and <2 x i32> %tmp3, <i32 3, i32 3>
|
|
|
|
%cmp = icmp ult <2 x i32> %tmp11, <i32 4, i32 4>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR9343 #7
|
|
|
|
define i1 @test50(i16 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test50(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%A = zext i16 %X to i32
|
|
|
|
%B = srem i32 %A, %Y
|
|
|
|
%C = icmp sgt i32 %B, -1
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test51(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @test51(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], -2147483648
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = srem i32 [[A]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[B]], -1
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = and i32 %X, 2147483648
|
|
|
|
%B = srem i32 %A, %Y
|
|
|
|
%C = icmp sgt i32 %B, -1
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test52(i32 %x1) {
|
|
|
|
; CHECK-LABEL: @test52(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X1:%.*]], 16711935
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 4980863
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%conv = and i32 %x1, 255
|
|
|
|
%cmp = icmp eq i32 %conv, 127
|
|
|
|
%tmp2 = lshr i32 %x1, 16
|
|
|
|
%tmp3 = trunc i32 %tmp2 to i8
|
|
|
|
%cmp15 = icmp eq i8 %tmp3, 76
|
|
|
|
|
|
|
|
%A = and i1 %cmp, %cmp15
|
|
|
|
ret i1 %A
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test52b(i128 %x1) {
|
|
|
|
; CHECK-LABEL: @test52b(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i128 [[X1:%.*]], 16711935
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i128 [[TMP1]], 4980863
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%conv = and i128 %x1, 255
|
|
|
|
%cmp = icmp eq i128 %conv, 127
|
|
|
|
%tmp2 = lshr i128 %x1, 16
|
|
|
|
%tmp3 = trunc i128 %tmp2 to i8
|
|
|
|
%cmp15 = icmp eq i8 %tmp3, 76
|
|
|
|
|
|
|
|
%A = and i1 %cmp, %cmp15
|
|
|
|
ret i1 %A
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR9838
|
|
|
|
define i1 @test53(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test53(
|
|
|
|
; CHECK-NEXT: [[X:%.*]] = sdiv exact i32 [[A:%.*]], 30
|
|
|
|
; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[B:%.*]], 30
|
|
|
|
; CHECK-NEXT: [[Z:%.*]] = icmp eq i32 [[X]], [[Y]]
|
|
|
|
; CHECK-NEXT: ret i1 [[Z]]
|
|
|
|
;
|
|
|
|
%x = sdiv exact i32 %a, 30
|
|
|
|
%y = sdiv i32 %b, 30
|
|
|
|
%z = icmp eq i32 %x, %y
|
|
|
|
ret i1 %z
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test54(i8 %a) {
|
|
|
|
; CHECK-LABEL: @test54(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], -64
|
|
|
|
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], -128
|
|
|
|
; CHECK-NEXT: ret i1 [[RET]]
|
|
|
|
;
|
|
|
|
%ext = zext i8 %a to i32
|
|
|
|
%and = and i32 %ext, 192
|
|
|
|
%ret = icmp eq i32 %and, 128
|
|
|
|
ret i1 %ret
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test55(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test55(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], -123
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = sub i32 0, %a
|
|
|
|
%cmp = icmp eq i32 %sub, 123
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test55vec(<2 x i32> %a) {
|
|
|
|
; CHECK-LABEL: @test55vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 -123, i32 -123>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = sub <2 x i32> zeroinitializer, %a
|
|
|
|
%cmp = icmp eq <2 x i32> %sub, <i32 123, i32 123>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test56(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test56(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], -113
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = sub i32 10, %a
|
|
|
|
%cmp = icmp eq i32 %sub, 123
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test56vec(<2 x i32> %a) {
|
|
|
|
; CHECK-LABEL: @test56vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 -113, i32 -113>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = sub <2 x i32> <i32 10, i32 10>, %a
|
|
|
|
%cmp = icmp eq <2 x i32> %sub, <i32 123, i32 123>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR10267 Don't make icmps more expensive when no other inst is subsumed.
|
|
|
|
declare void @foo(i32)
|
|
|
|
define i1 @test57(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test57(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], -2
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[AND]])
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and i32 %a, -2
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
call void @foo(i32 %and)
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; rdar://problem/10482509
|
|
|
|
define zeroext i1 @cmpabs1(i64 %val) {
|
|
|
|
; CHECK-LABEL: @cmpabs1(
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[VAL:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[TOBOOL]]
|
|
|
|
;
|
|
|
|
%sub = sub nsw i64 0, %val
|
|
|
|
%cmp = icmp slt i64 %val, 0
|
|
|
|
%sub.val = select i1 %cmp, i64 %sub, i64 %val
|
|
|
|
%tobool = icmp ne i64 %sub.val, 0
|
|
|
|
ret i1 %tobool
|
|
|
|
}
|
|
|
|
|
|
|
|
define zeroext i1 @cmpabs2(i64 %val) {
|
|
|
|
; CHECK-LABEL: @cmpabs2(
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[VAL:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[TOBOOL]]
|
|
|
|
;
|
|
|
|
%sub = sub nsw i64 0, %val
|
|
|
|
%cmp = icmp slt i64 %val, 0
|
|
|
|
%sub.val = select i1 %cmp, i64 %val, i64 %sub
|
|
|
|
%tobool = icmp ne i64 %sub.val, 0
|
|
|
|
ret i1 %tobool
|
|
|
|
}
|
|
|
|
|
|
|
|
define void @test58() {
|
|
|
|
; CHECK-LABEL: @test58(
|
|
|
|
; CHECK-NEXT: [[CALL:%.*]] = call i32 @test58_d(i64 36029346783166592)
|
|
|
|
; CHECK-NEXT: ret void
|
|
|
|
;
|
|
|
|
%cast = bitcast <1 x i64> <i64 36029346783166592> to i64
|
|
|
|
%call = call i32 @test58_d( i64 %cast)
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
declare i32 @test58_d(i64)
|
|
|
|
|
|
|
|
define i1 @test59(i8* %foo) {
|
|
|
|
; CHECK-LABEL: @test59(
|
|
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, i8* [[FOO:%.*]], i64 8
|
|
|
|
; CHECK-NEXT: [[USE:%.*]] = ptrtoint i8* [[GEP1]] to i64
|
|
|
|
; CHECK-NEXT: [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%bit = bitcast i8* %foo to i32*
|
|
|
|
%gep1 = getelementptr inbounds i32, i32* %bit, i64 2
|
|
|
|
%gep2 = getelementptr inbounds i8, i8* %foo, i64 10
|
|
|
|
%cast1 = bitcast i32* %gep1 to i8*
|
|
|
|
%cmp = icmp ult i8* %cast1, %gep2
|
|
|
|
%use = ptrtoint i8* %cast1 to i64
|
|
|
|
%call = call i32 @test58_d(i64 %use)
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test59_as1(i8 addrspace(1)* %foo) {
|
|
|
|
; CHECK-LABEL: @test59_as1(
|
|
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[FOO:%.*]], i16 8
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i8 addrspace(1)* [[GEP1]] to i16
|
|
|
|
; CHECK-NEXT: [[USE:%.*]] = zext i16 [[TMP1]] to i64
|
|
|
|
; CHECK-NEXT: [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
|
|
|
|
%gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i64 2
|
|
|
|
%gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i64 10
|
|
|
|
%cast1 = bitcast i32 addrspace(1)* %gep1 to i8 addrspace(1)*
|
|
|
|
%cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
|
|
|
|
%use = ptrtoint i8 addrspace(1)* %cast1 to i64
|
|
|
|
%call = call i32 @test58_d(i64 %use)
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test60(i8* %foo, i64 %i, i64 %j) {
|
|
|
|
; CHECK-LABEL: @test60(
|
[Analysis] Don't assume that unsigned overflow can't happen in EmitGEPOffset (PR42699)
Summary:
Currently when computing a GEP offset using the function EmitGEPOffset
for the following instruction
getelementptr inbounds i32, i32* %p, i64 %offs
we get
mul nuw i64 %offs, 4
Unfortunately we cannot assume that unsigned wrapping won't happen
here because %offs is allowed to be negative.
Making such assumptions can lead to miscompilations: see the new test
test24_neg_offs in InstCombine/icmp.ll. Without the patch InstCombine
would generate the following comparison:
icmp eq i64 %offs, 4611686018427387902; 0x3ffffffffffffffe
Whereas the correct value to compare with is -2.
This patch replaces the NUW flag with NSW in the multiplication
instructions generated by EmitGEPOffset and adjusts the test suite.
https://bugs.llvm.org/show_bug.cgi?id=42699
Reviewers: chandlerc, craig.topper, ostannard, lebedev.ri, spatel, efriedma, nlopes, aqjune
Reviewed By: lebedev.ri
Subscribers: reames, lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68342
llvm-svn: 375089
2019-10-17 16:59:06 +08:00
|
|
|
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP1]]
|
|
|
|
;
|
|
|
|
%bit = bitcast i8* %foo to i32*
|
|
|
|
%gep1 = getelementptr inbounds i32, i32* %bit, i64 %i
|
|
|
|
%gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
|
|
|
|
%cast1 = bitcast i32* %gep1 to i8*
|
|
|
|
%cmp = icmp ult i8* %cast1, %gep2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test60_as1(i8 addrspace(1)* %foo, i64 %i, i64 %j) {
|
|
|
|
; CHECK-LABEL: @test60_as1(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i16
|
[Analysis] Don't assume that unsigned overflow can't happen in EmitGEPOffset (PR42699)
Summary:
Currently when computing a GEP offset using the function EmitGEPOffset
for the following instruction
getelementptr inbounds i32, i32* %p, i64 %offs
we get
mul nuw i64 %offs, 4
Unfortunately we cannot assume that unsigned wrapping won't happen
here because %offs is allowed to be negative.
Making such assumptions can lead to miscompilations: see the new test
test24_neg_offs in InstCombine/icmp.ll. Without the patch InstCombine
would generate the following comparison:
icmp eq i64 %offs, 4611686018427387902; 0x3ffffffffffffffe
Whereas the correct value to compare with is -2.
This patch replaces the NUW flag with NSW in the multiplication
instructions generated by EmitGEPOffset and adjusts the test suite.
https://bugs.llvm.org/show_bug.cgi?id=42699
Reviewers: chandlerc, craig.topper, ostannard, lebedev.ri, spatel, efriedma, nlopes, aqjune
Reviewed By: lebedev.ri
Subscribers: reames, lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68342
llvm-svn: 375089
2019-10-17 16:59:06 +08:00
|
|
|
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[TMP1]], 2
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP3]]
|
|
|
|
;
|
|
|
|
%bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
|
|
|
|
%gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i64 %i
|
|
|
|
%gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i64 %j
|
|
|
|
%cast1 = bitcast i32 addrspace(1)* %gep1 to i8 addrspace(1)*
|
|
|
|
%cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; Same as test60, but look through an addrspacecast instead of a
|
|
|
|
; bitcast. This uses the same sized addrspace.
|
|
|
|
define i1 @test60_addrspacecast(i8* %foo, i64 %i, i64 %j) {
|
|
|
|
; CHECK-LABEL: @test60_addrspacecast(
|
[Analysis] Don't assume that unsigned overflow can't happen in EmitGEPOffset (PR42699)
Summary:
Currently when computing a GEP offset using the function EmitGEPOffset
for the following instruction
getelementptr inbounds i32, i32* %p, i64 %offs
we get
mul nuw i64 %offs, 4
Unfortunately we cannot assume that unsigned wrapping won't happen
here because %offs is allowed to be negative.
Making such assumptions can lead to miscompilations: see the new test
test24_neg_offs in InstCombine/icmp.ll. Without the patch InstCombine
would generate the following comparison:
icmp eq i64 %offs, 4611686018427387902; 0x3ffffffffffffffe
Whereas the correct value to compare with is -2.
This patch replaces the NUW flag with NSW in the multiplication
instructions generated by EmitGEPOffset and adjusts the test suite.
https://bugs.llvm.org/show_bug.cgi?id=42699
Reviewers: chandlerc, craig.topper, ostannard, lebedev.ri, spatel, efriedma, nlopes, aqjune
Reviewed By: lebedev.ri
Subscribers: reames, lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68342
llvm-svn: 375089
2019-10-17 16:59:06 +08:00
|
|
|
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP1]]
|
|
|
|
;
|
|
|
|
%bit = addrspacecast i8* %foo to i32 addrspace(3)*
|
|
|
|
%gep1 = getelementptr inbounds i32, i32 addrspace(3)* %bit, i64 %i
|
|
|
|
%gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
|
|
|
|
%cast1 = addrspacecast i32 addrspace(3)* %gep1 to i8*
|
|
|
|
%cmp = icmp ult i8* %cast1, %gep2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test60_addrspacecast_smaller(i8* %foo, i16 %i, i64 %j) {
|
|
|
|
; CHECK-LABEL: @test60_addrspacecast_smaller(
|
[Analysis] Don't assume that unsigned overflow can't happen in EmitGEPOffset (PR42699)
Summary:
Currently when computing a GEP offset using the function EmitGEPOffset
for the following instruction
getelementptr inbounds i32, i32* %p, i64 %offs
we get
mul nuw i64 %offs, 4
Unfortunately we cannot assume that unsigned wrapping won't happen
here because %offs is allowed to be negative.
Making such assumptions can lead to miscompilations: see the new test
test24_neg_offs in InstCombine/icmp.ll. Without the patch InstCombine
would generate the following comparison:
icmp eq i64 %offs, 4611686018427387902; 0x3ffffffffffffffe
Whereas the correct value to compare with is -2.
This patch replaces the NUW flag with NSW in the multiplication
instructions generated by EmitGEPOffset and adjusts the test suite.
https://bugs.llvm.org/show_bug.cgi?id=42699
Reviewers: chandlerc, craig.topper, ostannard, lebedev.ri, spatel, efriedma, nlopes, aqjune
Reviewed By: lebedev.ri
Subscribers: reames, lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68342
llvm-svn: 375089
2019-10-17 16:59:06 +08:00
|
|
|
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]]
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%bit = addrspacecast i8* %foo to i32 addrspace(1)*
|
|
|
|
%gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i16 %i
|
|
|
|
%gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
|
|
|
|
%cast1 = addrspacecast i32 addrspace(1)* %gep1 to i8*
|
|
|
|
%cmp = icmp ult i8* %cast1, %gep2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test60_addrspacecast_larger(i8 addrspace(1)* %foo, i32 %i, i16 %j) {
|
|
|
|
; CHECK-LABEL: @test60_addrspacecast_larger(
|
|
|
|
; CHECK-NEXT: [[I_TR:%.*]] = trunc i32 [[I:%.*]] to i16
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl i16 [[I_TR]], 2
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i16 [[TMP1]], [[J:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%bit = addrspacecast i8 addrspace(1)* %foo to i32 addrspace(2)*
|
|
|
|
%gep1 = getelementptr inbounds i32, i32 addrspace(2)* %bit, i32 %i
|
|
|
|
%gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i16 %j
|
|
|
|
%cast1 = addrspacecast i32 addrspace(2)* %gep1 to i8 addrspace(1)*
|
|
|
|
%cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test61(i8* %foo, i64 %i, i64 %j) {
|
|
|
|
; CHECK-LABEL: @test61(
|
|
|
|
; CHECK-NEXT: [[BIT:%.*]] = bitcast i8* [[FOO:%.*]] to i32*
|
|
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, i32* [[BIT]], i64 [[I:%.*]]
|
|
|
|
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, i8* [[FOO]], i64 [[J:%.*]]
|
|
|
|
; CHECK-NEXT: [[CAST1:%.*]] = bitcast i32* [[GEP1]] to i8*
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8* [[GEP2]], [[CAST1]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%bit = bitcast i8* %foo to i32*
|
|
|
|
%gep1 = getelementptr i32, i32* %bit, i64 %i
|
|
|
|
%gep2 = getelementptr i8, i8* %foo, i64 %j
|
|
|
|
%cast1 = bitcast i32* %gep1 to i8*
|
|
|
|
%cmp = icmp ult i8* %cast1, %gep2
|
|
|
|
ret i1 %cmp
|
|
|
|
; Don't transform non-inbounds GEPs.
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test61_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
|
|
|
|
; CHECK-LABEL: @test61_as1(
|
|
|
|
; CHECK-NEXT: [[BIT:%.*]] = bitcast i8 addrspace(1)* [[FOO:%.*]] to i32 addrspace(1)*
|
|
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, i32 addrspace(1)* [[BIT]], i16 [[I:%.*]]
|
|
|
|
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, i8 addrspace(1)* [[FOO]], i16 [[J:%.*]]
|
|
|
|
; CHECK-NEXT: [[CAST1:%.*]] = bitcast i32 addrspace(1)* [[GEP1]] to i8 addrspace(1)*
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 addrspace(1)* [[GEP2]], [[CAST1]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
|
|
|
|
%gep1 = getelementptr i32, i32 addrspace(1)* %bit, i16 %i
|
|
|
|
%gep2 = getelementptr i8, i8 addrspace(1)* %foo, i16 %j
|
|
|
|
%cast1 = bitcast i32 addrspace(1)* %gep1 to i8 addrspace(1)*
|
|
|
|
%cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
|
|
|
|
ret i1 %cmp
|
|
|
|
; Don't transform non-inbounds GEPs.
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test62(i8* %a) {
|
|
|
|
; CHECK-LABEL: @test62(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%arrayidx1 = getelementptr inbounds i8, i8* %a, i64 1
|
|
|
|
%arrayidx2 = getelementptr inbounds i8, i8* %a, i64 10
|
|
|
|
%cmp = icmp slt i8* %arrayidx1, %arrayidx2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test62_as1(i8 addrspace(1)* %a) {
|
|
|
|
; CHECK-LABEL: @test62_as1(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%arrayidx1 = getelementptr inbounds i8, i8 addrspace(1)* %a, i64 1
|
|
|
|
%arrayidx2 = getelementptr inbounds i8, i8 addrspace(1)* %a, i64 10
|
|
|
|
%cmp = icmp slt i8 addrspace(1)* %arrayidx1, %arrayidx2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test63(i8 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test63(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[B:%.*]] to i8
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[TMP1]], [[A:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%z = zext i8 %a to i32
|
|
|
|
%t = and i32 %b, 255
|
|
|
|
%c = icmp eq i32 %z, %t
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test64(i8 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test64(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[B:%.*]] to i8
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[TMP1]], [[A:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%t = and i32 %b, 255
|
|
|
|
%z = zext i8 %a to i32
|
|
|
|
%c = icmp eq i32 %t, %z
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test65(i64 %A, i64 %B) {
|
|
|
|
; CHECK-LABEL: @test65(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%s1 = add i64 %A, %B
|
|
|
|
%s2 = add i64 %A, %B
|
|
|
|
%cmp = icmp eq i64 %s1, %s2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test66(i64 %A, i64 %B) {
|
|
|
|
; CHECK-LABEL: @test66(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%s1 = add i64 %A, %B
|
|
|
|
%s2 = add i64 %B, %A
|
|
|
|
%cmp = icmp eq i64 %s1, %s2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test67(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test67(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 96
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and i32 %x, 127
|
|
|
|
%cmp = icmp sgt i32 %and, 31
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test67inverse(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test67inverse(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 96
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and i32 %x, 127
|
|
|
|
%cmp = icmp sle i32 %and, 31
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; The test above relies on 3 different folds.
|
|
|
|
; This test only checks the last of those (icmp ugt -> icmp ne).
|
|
|
|
|
|
|
|
define <2 x i1> @test67vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test67vec(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], <i32 96, i32 96>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[AND]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and <2 x i32> %x, <i32 96, i32 96>
|
|
|
|
%cmp = icmp ugt <2 x i32> %and, <i32 31, i32 31>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test67vec2(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test67vec2(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], <i32 96, i32 96>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[AND]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and <2 x i32> %x, <i32 127, i32 127>
|
|
|
|
%cmp = icmp ugt <2 x i32> %and, <i32 31, i32 31>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test67vecinverse(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @test67vecinverse(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], <i32 96, i32 96>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[AND]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and <2 x i32> %x, <i32 96, i32 96>
|
|
|
|
%cmp = icmp sle <2 x i32> %and, <i32 31, i32 31>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test68(i32 %x) {
|
|
|
|
; CHECK-LABEL: @test68(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 127
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[AND]], 30
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and i32 %x, 127
|
|
|
|
%cmp = icmp sgt i32 %and, 30
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR15940
|
|
|
|
define i1 @test70(i32 %X) {
|
|
|
|
; CHECK-LABEL: @test70(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = srem i32 5, [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[A]], 2
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = srem i32 5, %X
|
|
|
|
%B = add i32 %A, 2
|
|
|
|
%C = icmp ne i32 %B, 4
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test70vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @test70vec(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], <i32 2, i32 2>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%B = add <2 x i32> %X, <i32 2, i32 2>
|
|
|
|
%C = icmp ne <2 x i32> %B, <i32 4, i32 4>
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sext16trunc(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_sext16trunc(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[TMP1]], 36
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%trunc = trunc i32 %x to i16
|
|
|
|
%sext = sext i16 %trunc to i32
|
|
|
|
%cmp = icmp slt i32 %sext, 36
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sext8trunc(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_sext8trunc(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], 36
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%trunc = trunc i32 %x to i8
|
|
|
|
%sext = sext i8 %trunc to i32
|
|
|
|
%cmp = icmp slt i32 %sext, 36
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; Vectors should fold the same way.
|
|
|
|
define <2 x i1> @icmp_sext8trunc_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_sext8trunc_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], <i8 36, i8 36>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%trunc = trunc <2 x i32> %x to <2 x i8>
|
|
|
|
%sext = sext <2 x i8> %trunc to <2 x i32>
|
|
|
|
%cmp = icmp slt <2 x i32> %sext, <i32 36, i32 36>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl16(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl16(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[TMP1]], 36
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 %x, 16
|
|
|
|
%cmp = icmp slt i32 %shl, 2359296
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; D25952: Don't create illegal types like i15 in InstCombine
|
|
|
|
|
|
|
|
define i1 @icmp_shl17(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl17(
|
|
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], 17
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[SHL]], 2359296
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 %x, 17
|
|
|
|
%cmp = icmp slt i32 %shl, 2359296
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl16_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl16_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i16>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i16> [[TMP1]], <i16 36, i16 36>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> %x, <i32 16, i32 16>
|
|
|
|
%cmp = icmp slt <2 x i32> %shl, <i32 2359296, i32 2359296>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl24(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl24(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], 36
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 %x, 24
|
|
|
|
%cmp = icmp slt i32 %shl, 603979776
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_eq(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_eq(
|
|
|
|
; CHECK-NEXT: [[MUL_MASK:%.*]] = and i32 [[X:%.*]], 134217727
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MUL_MASK]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = shl i32 %x, 5
|
|
|
|
%cmp = icmp eq i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_eq_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_eq_vec(
|
|
|
|
; CHECK-NEXT: [[MUL_MASK:%.*]] = and <2 x i32> [[X:%.*]], <i32 134217727, i32 134217727>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[MUL_MASK]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = shl <2 x i32> %x, <i32 5, i32 5>
|
|
|
|
%cmp = icmp eq <2 x i32> %mul, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_nsw_ne(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_nsw_ne(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = shl nsw i32 %x, 7
|
|
|
|
%cmp = icmp ne i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_nsw_ne_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_nsw_ne_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[X:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = shl nsw <2 x i32> %x, <i32 7, i32 7>
|
|
|
|
%cmp = icmp ne <2 x i32> %mul, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_ne(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_ne(
|
|
|
|
; CHECK-NEXT: [[MUL_MASK:%.*]] = and i32 [[X:%.*]], 33554431
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[MUL_MASK]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = shl i32 %x, 7
|
|
|
|
%cmp = icmp ne i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_ne_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_ne_vec(
|
|
|
|
; CHECK-NEXT: [[MUL_MASK:%.*]] = and <2 x i32> [[X:%.*]], <i32 33554431, i32 33554431>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[MUL_MASK]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = shl <2 x i32> %x, <i32 7, i32 7>
|
|
|
|
%cmp = icmp ne <2 x i32> %mul, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_nuw_ne_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_nuw_ne_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[X:%.*]], <i32 2, i32 2>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl nuw <2 x i32> %x, <i32 7, i32 7>
|
|
|
|
%cmp = icmp ne <2 x i32> %shl, <i32 256, i32 256>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; If the (mul x, C) preserved the sign and this is sign test,
|
|
|
|
; compare the LHS operand instead
|
|
|
|
define i1 @icmp_mul_nsw(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_nsw(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw i32 %x, 12
|
|
|
|
%cmp = icmp sgt i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul_nsw1(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_nsw1(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw i32 %x, 12
|
|
|
|
%cmp = icmp sle i32 %mul, -1
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul_nsw_neg(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_nsw_neg(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw i32 %x, -12
|
|
|
|
%cmp = icmp sge i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul_nsw_neg1(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_nsw_neg1(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw i32 %x, -12
|
|
|
|
%cmp = icmp sge i32 %mul, 1
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_mul_nsw_neg1_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_nsw_neg1_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw <2 x i32> %x, <i32 -12, i32 -12>
|
|
|
|
%cmp = icmp sge <2 x i32> %mul, <i32 1, i32 1>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul_nsw_0(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_nsw_0(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%mul = mul nsw i32 %x, 0
|
|
|
|
%cmp = icmp sgt i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul(
|
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], -12
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[MUL]], -1
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul i32 %x, -12
|
|
|
|
%cmp = icmp sge i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; Checks for icmp (eq|ne) (mul x, C), 0
|
|
|
|
define i1 @icmp_mul_neq0(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_neq0(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw i32 %x, -12
|
|
|
|
%cmp = icmp ne i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_mul_neq0_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_neq0_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[X:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw <2 x i32> %x, <i32 -12, i32 -12>
|
|
|
|
%cmp = icmp ne <2 x i32> %mul, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul_eq0(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul_eq0(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%mul = mul nsw i32 %x, 12
|
|
|
|
%cmp = icmp eq i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul0_eq0(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul0_eq0(
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%mul = mul i32 %x, 0
|
|
|
|
%cmp = icmp eq i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_mul0_ne0(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_mul0_ne0(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%mul = mul i32 %x, 0
|
|
|
|
%cmp = icmp ne i32 %mul, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sub1_sge(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_sub1_sge(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = add nsw i32 %x, -1
|
|
|
|
%cmp = icmp sge i32 %sub, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add1_sgt(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_add1_sgt(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add nsw i32 %x, 1
|
|
|
|
%cmp = icmp sgt i32 %add, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sub1_slt(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_sub1_slt(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = add nsw i32 %x, -1
|
|
|
|
%cmp = icmp slt i32 %sub, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add1_sle(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_add1_sle(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add nsw i32 %x, 1
|
|
|
|
%cmp = icmp sle i32 %add, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add20_sge_add57(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_add20_sge_add57(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[Y:%.*]], 37
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[TMP1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%1 = add nsw i32 %x, 20
|
|
|
|
%2 = add nsw i32 %y, 57
|
|
|
|
%cmp = icmp sge i32 %1, %2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sub57_sge_sub20(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_sub57_sge_sub20(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[X:%.*]], -37
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[TMP1]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%1 = add nsw i32 %x, -57
|
|
|
|
%2 = add nsw i32 %y, -20
|
|
|
|
%cmp = icmp sge i32 %1, %2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_shl_neg_ne_0(i32 %A, i32 %B) {
|
|
|
|
; CHECK-LABEL: @icmp_and_shl_neg_ne_0(
|
|
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[SHL]], [[A:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%neg = xor i32 %A, -1
|
|
|
|
%shl = shl i32 1, %B
|
|
|
|
%and = and i32 %shl, %neg
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_shl_neg_eq_0(i32 %A, i32 %B) {
|
|
|
|
; CHECK-LABEL: @icmp_and_shl_neg_eq_0(
|
|
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[SHL]], [[A:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%neg = xor i32 %A, -1
|
|
|
|
%shl = shl i32 1, %B
|
|
|
|
%and = and i32 %shl, %neg
|
|
|
|
%cmp = icmp eq i32 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add_and_shr_ne_0(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_add_and_shr_ne_0(
|
2020-02-09 00:02:10 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 240
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP1]], 224
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[TOBOOL]]
|
|
|
|
;
|
|
|
|
%shr = lshr i32 %X, 4
|
|
|
|
%and = and i32 %shr, 15
|
|
|
|
%add = add i32 %and, -14
|
|
|
|
%tobool = icmp ne i32 %add, 0
|
|
|
|
ret i1 %tobool
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_add_and_shr_ne_0_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_add_and_shr_ne_0_vec(
|
2020-02-09 00:02:10 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 240, i32 240>
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 224, i32 224>
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[TOBOOL]]
|
|
|
|
;
|
|
|
|
%shr = lshr <2 x i32> %X, <i32 4, i32 4>
|
|
|
|
%and = and <2 x i32> %shr, <i32 15, i32 15>
|
|
|
|
%add = add <2 x i32> %and, <i32 -14, i32 -14>
|
|
|
|
%tobool = icmp ne <2 x i32> %add, zeroinitializer
|
|
|
|
ret <2 x i1> %tobool
|
|
|
|
}
|
|
|
|
|
|
|
|
; Variation of the above with an extra use of the shift
|
|
|
|
define i1 @icmp_and_shr_multiuse(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_and_shr_multiuse(
|
2020-02-09 00:02:10 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 240
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP1]], 224
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[X]], 496
|
|
|
|
; CHECK-NEXT: [[TOBOOL2:%.*]] = icmp ne i32 [[TMP2]], 432
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[AND3:%.*]] = and i1 [[TOBOOL]], [[TOBOOL2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[AND3]]
|
|
|
|
;
|
|
|
|
%shr = lshr i32 %X, 4
|
|
|
|
%and = and i32 %shr, 15
|
|
|
|
%and2 = and i32 %shr, 31 ; second use of the shift
|
|
|
|
%tobool = icmp ne i32 %and, 14
|
|
|
|
%tobool2 = icmp ne i32 %and2, 27
|
|
|
|
%and3 = and i1 %tobool, %tobool2
|
|
|
|
ret i1 %and3
|
|
|
|
}
|
|
|
|
|
|
|
|
; Variation of the above with an ashr
|
|
|
|
define i1 @icmp_and_ashr_multiuse(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_multiuse(
|
2020-02-09 00:02:10 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 240
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP1]], 224
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[X]], 496
|
|
|
|
; CHECK-NEXT: [[TOBOOL2:%.*]] = icmp ne i32 [[TMP2]], 432
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[AND3:%.*]] = and i1 [[TOBOOL]], [[TOBOOL2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[AND3]]
|
|
|
|
;
|
|
|
|
%shr = ashr i32 %X, 4
|
|
|
|
%and = and i32 %shr, 15
|
|
|
|
%and2 = and i32 %shr, 31 ; second use of the shift
|
|
|
|
%tobool = icmp ne i32 %and, 14
|
|
|
|
%tobool2 = icmp ne i32 %and2, 27
|
|
|
|
%and3 = and i1 %tobool, %tobool2
|
|
|
|
ret i1 %and3
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_lshr_and_overshift(i8 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_lshr_and_overshift(
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ugt i8 [[X:%.*]], 31
|
|
|
|
; CHECK-NEXT: ret i1 [[TOBOOL]]
|
|
|
|
;
|
|
|
|
%shr = lshr i8 %X, 5
|
|
|
|
%and = and i8 %shr, 15
|
|
|
|
%tobool = icmp ne i8 %and, 0
|
|
|
|
ret i1 %tobool
|
|
|
|
}
|
|
|
|
|
|
|
|
; We shouldn't simplify this because the and uses bits that are shifted in.
|
|
|
|
define i1 @icmp_ashr_and_overshift(i8 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_ashr_and_overshift(
|
|
|
|
; CHECK-NEXT: [[SHR:%.*]] = ashr i8 [[X:%.*]], 5
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHR]], 15
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[AND]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[TOBOOL]]
|
|
|
|
;
|
|
|
|
%shr = ashr i8 %X, 5
|
|
|
|
%and = and i8 %shr, 15
|
|
|
|
%tobool = icmp ne i8 %and, 0
|
|
|
|
ret i1 %tobool
|
|
|
|
}
|
|
|
|
|
2020-02-09 16:52:38 +08:00
|
|
|
define i1 @icmp_and_ashr_neg_and_legal(i8 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_neg_and_legal(
|
[InstCombine] Relax preconditions for ashr+and+icmp fold (PR44754)
Fix for https://bugs.llvm.org/show_bug.cgi?id=44754. We already have
a fold that converts icmp (and (ashr X, C3), C2), C1 into
icmp (and C2'), C1', but it imposed overly strict requirements on the
transform.
Relax this by checking that both C2 and C1 don't shift out bits
(in a signed sense) when forming the new constants.
Alive proofs (https://rise4fun.com/Alive/PTz0):
Name: ashr_legal
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) == C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp i16 %b, C1
=>
%d = and i16 %x, C2 << C3
%c = icmp i16 %d, C1 << C3
Name: ashr_shiftout_eq
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) != C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp eq i16 %b, C1
=>
%c = false
Note that >> corresponds to ashr here. The case of an equality
comparison has some special handling in this transform, because
it will form to a true/false result if the condition on the comparison
constant it violated.
Differential Revision: https://reviews.llvm.org/D74294
2020-02-09 16:57:59 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], 16
|
2020-02-09 16:52:38 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%ashr = ashr i8 %x, 4
|
|
|
|
%and = and i8 %ashr, -2
|
|
|
|
%cmp = icmp slt i8 %and, 1
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; Negative test.
|
|
|
|
define i1 @icmp_and_ashr_mixed_and_shiftout(i8 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_mixed_and_shiftout(
|
|
|
|
; CHECK-NEXT: [[ASHR:%.*]] = ashr i8 [[X:%.*]], 4
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i8 [[ASHR]], 31
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[AND]], 8
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%ashr = ashr i8 %x, 4
|
|
|
|
%and = and i8 %ashr, 31
|
|
|
|
%cmp = icmp ugt i8 %and, 8
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_ashr_neg_cmp_slt_legal(i8 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_neg_cmp_slt_legal(
|
[InstCombine] Relax preconditions for ashr+and+icmp fold (PR44754)
Fix for https://bugs.llvm.org/show_bug.cgi?id=44754. We already have
a fold that converts icmp (and (ashr X, C3), C2), C1 into
icmp (and C2'), C1', but it imposed overly strict requirements on the
transform.
Relax this by checking that both C2 and C1 don't shift out bits
(in a signed sense) when forming the new constants.
Alive proofs (https://rise4fun.com/Alive/PTz0):
Name: ashr_legal
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) == C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp i16 %b, C1
=>
%d = and i16 %x, C2 << C3
%c = icmp i16 %d, C1 << C3
Name: ashr_shiftout_eq
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) != C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp eq i16 %b, C1
=>
%c = false
Note that >> corresponds to ashr here. The case of an equality
comparison has some special handling in this transform, because
it will form to a true/false result if the condition on the comparison
constant it violated.
Differential Revision: https://reviews.llvm.org/D74294
2020-02-09 16:57:59 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], -64
|
2020-02-09 16:52:38 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%ashr = ashr i8 %x, 4
|
|
|
|
%and = and i8 %ashr, -2
|
|
|
|
%cmp = icmp slt i8 %and, -4
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; Negative test.
|
|
|
|
define i1 @icmp_and_ashr_neg_cmp_slt_shiftout(i8 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_neg_cmp_slt_shiftout(
|
|
|
|
; CHECK-NEXT: [[ASHR:%.*]] = ashr i8 [[X:%.*]], 4
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i8 [[ASHR]], -2
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[AND]], -68
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%ashr = ashr i8 %x, 4
|
|
|
|
%and = and i8 %ashr, -2
|
|
|
|
%cmp = icmp slt i8 %and, -68
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_ashr_neg_cmp_eq_legal(i8 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_neg_cmp_eq_legal(
|
[InstCombine] Relax preconditions for ashr+and+icmp fold (PR44754)
Fix for https://bugs.llvm.org/show_bug.cgi?id=44754. We already have
a fold that converts icmp (and (ashr X, C3), C2), C1 into
icmp (and C2'), C1', but it imposed overly strict requirements on the
transform.
Relax this by checking that both C2 and C1 don't shift out bits
(in a signed sense) when forming the new constants.
Alive proofs (https://rise4fun.com/Alive/PTz0):
Name: ashr_legal
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) == C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp i16 %b, C1
=>
%d = and i16 %x, C2 << C3
%c = icmp i16 %d, C1 << C3
Name: ashr_shiftout_eq
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) != C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp eq i16 %b, C1
=>
%c = false
Note that >> corresponds to ashr here. The case of an equality
comparison has some special handling in this transform, because
it will form to a true/false result if the condition on the comparison
constant it violated.
Differential Revision: https://reviews.llvm.org/D74294
2020-02-09 16:57:59 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], -64
|
2020-02-09 16:52:38 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%ashr = ashr i8 %x, 4
|
|
|
|
%and = and i8 %ashr, -2
|
|
|
|
%cmp = icmp eq i8 %and, -4
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_ashr_neg_cmp_eq_shiftout(i8 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_neg_cmp_eq_shiftout(
|
[InstCombine] Relax preconditions for ashr+and+icmp fold (PR44754)
Fix for https://bugs.llvm.org/show_bug.cgi?id=44754. We already have
a fold that converts icmp (and (ashr X, C3), C2), C1 into
icmp (and C2'), C1', but it imposed overly strict requirements on the
transform.
Relax this by checking that both C2 and C1 don't shift out bits
(in a signed sense) when forming the new constants.
Alive proofs (https://rise4fun.com/Alive/PTz0):
Name: ashr_legal
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) == C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp i16 %b, C1
=>
%d = and i16 %x, C2 << C3
%c = icmp i16 %d, C1 << C3
Name: ashr_shiftout_eq
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) != C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp eq i16 %b, C1
=>
%c = false
Note that >> corresponds to ashr here. The case of an equality
comparison has some special handling in this transform, because
it will form to a true/false result if the condition on the comparison
constant it violated.
Differential Revision: https://reviews.llvm.org/D74294
2020-02-09 16:57:59 +08:00
|
|
|
; CHECK-NEXT: ret i1 false
|
2020-02-09 16:52:38 +08:00
|
|
|
;
|
|
|
|
%ashr = ashr i8 %x, 4
|
|
|
|
%and = and i8 %ashr, -2
|
|
|
|
%cmp = icmp eq i8 %and, -68
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_ashr_neg_cmp_ne_shiftout(i8 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_ashr_neg_cmp_ne_shiftout(
|
[InstCombine] Relax preconditions for ashr+and+icmp fold (PR44754)
Fix for https://bugs.llvm.org/show_bug.cgi?id=44754. We already have
a fold that converts icmp (and (ashr X, C3), C2), C1 into
icmp (and C2'), C1', but it imposed overly strict requirements on the
transform.
Relax this by checking that both C2 and C1 don't shift out bits
(in a signed sense) when forming the new constants.
Alive proofs (https://rise4fun.com/Alive/PTz0):
Name: ashr_legal
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) == C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp i16 %b, C1
=>
%d = and i16 %x, C2 << C3
%c = icmp i16 %d, C1 << C3
Name: ashr_shiftout_eq
Pre: ((C2 << C3) >> C3) == C2 && ((C1 << C3) >> C3) != C1
%a = ashr i16 %x, C3
%b = and i16 %a, C2
%c = icmp eq i16 %b, C1
=>
%c = false
Note that >> corresponds to ashr here. The case of an equality
comparison has some special handling in this transform, because
it will form to a true/false result if the condition on the comparison
constant it violated.
Differential Revision: https://reviews.llvm.org/D74294
2020-02-09 16:57:59 +08:00
|
|
|
; CHECK-NEXT: ret i1 true
|
2020-02-09 16:52:38 +08:00
|
|
|
;
|
|
|
|
%ashr = ashr i8 %x, 4
|
|
|
|
%and = and i8 %ashr, -2
|
|
|
|
%cmp = icmp ne i8 %and, -68
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
2019-04-17 12:52:47 +08:00
|
|
|
; PR16244
|
|
|
|
define i1 @test71(i8* %x) {
|
|
|
|
; CHECK-LABEL: @test71(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%a = getelementptr i8, i8* %x, i64 8
|
|
|
|
%b = getelementptr inbounds i8, i8* %x, i64 8
|
|
|
|
%c = icmp ugt i8* %a, %b
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test71_as1(i8 addrspace(1)* %x) {
|
|
|
|
; CHECK-LABEL: @test71_as1(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%a = getelementptr i8, i8 addrspace(1)* %x, i64 8
|
|
|
|
%b = getelementptr inbounds i8, i8 addrspace(1)* %x, i64 8
|
|
|
|
%c = icmp ugt i8 addrspace(1)* %a, %b
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_ult_32(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ult_32(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[V:%.*]], 5
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp ult i32 %shl, 32
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_ult_32_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ult_32_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[V:%.*]], <i32 5, i32 5>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp ult <2 x i32> %shl, <i32 32, i32 32>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_eq_32(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_eq_32(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V:%.*]], 5
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp eq i32 %shl, 32
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_eq_32_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_eq_32_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[V:%.*]], <i32 5, i32 5>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp eq <2 x i32> %shl, <i32 32, i32 32>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_ult_30(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ult_30(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[V:%.*]], 5
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp ult i32 %shl, 30
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_ult_30_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ult_30_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[V:%.*]], <i32 5, i32 5>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp ult <2 x i32> %shl, <i32 30, i32 30>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_ugt_30(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ugt_30(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[V:%.*]], 4
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp ugt i32 %shl, 30
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_ugt_30_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ugt_30_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[V:%.*]], <i32 4, i32 4>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp ugt <2 x i32> %shl, <i32 30, i32 30>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_ule_30(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ule_30(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[V:%.*]], 5
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp ule i32 %shl, 30
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_ule_30_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ule_30_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[V:%.*]], <i32 5, i32 5>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp ule <2 x i32> %shl, <i32 30, i32 30>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_uge_30(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_uge_30(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[V:%.*]], 4
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp uge i32 %shl, 30
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_uge_30_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_uge_30_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[V:%.*]], <i32 4, i32 4>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp uge <2 x i32> %shl, <i32 30, i32 30>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_uge_2147483648(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_uge_2147483648(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V:%.*]], 31
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp uge i32 %shl, 2147483648
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_uge_2147483648_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_uge_2147483648_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[V:%.*]], <i32 31, i32 31>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp uge <2 x i32> %shl, <i32 2147483648, i32 2147483648>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_shl_1_V_ult_2147483648(i32 %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ult_2147483648(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[V:%.*]], 31
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %V
|
|
|
|
%cmp = icmp ult i32 %shl, 2147483648
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_shl_1_V_ult_2147483648_vec(<2 x i32> %V) {
|
|
|
|
; CHECK-LABEL: @icmp_shl_1_V_ult_2147483648_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[V:%.*]], <i32 31, i32 31>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 1, i32 1>, %V
|
|
|
|
%cmp = icmp ult <2 x i32> %shl, <i32 2147483648, i32 2147483648>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @or_icmp_eq_B_0_icmp_ult_A_B(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @or_icmp_eq_B_0_icmp_ult_A_B(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[B:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i64 [[TMP1]], [[A:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%1 = icmp eq i64 %b, 0
|
|
|
|
%2 = icmp ult i64 %a, %b
|
|
|
|
%3 = or i1 %1, %2
|
|
|
|
ret i1 %3
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add_ult_2(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_add_ult_2(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -2
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 14
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add i32 %X, -14
|
|
|
|
%cmp = icmp ult i32 %add, 2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_add_X_-14_ult_2_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_add_X_-14_ult_2_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -2>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 14, i32 14>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add <2 x i32> %X, <i32 -14, i32 -14>
|
|
|
|
%cmp = icmp ult <2 x i32> %add, <i32 2, i32 2>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sub_3_X_ult_2(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_sub_3_X_ult_2(
|
[InstCombine] generalize canonicalization of masked equality comparisons
(X | MaskC) == C --> (X & ~MaskC) == C ^ MaskC
(X | MaskC) != C --> (X & ~MaskC) != C ^ MaskC
We have more analyis for 'and' patterns and already lean this way
in the existing code, so this should be neutral or better in IR.
If this does not do as well in codegen, the problem already exists
and we should fix that based on target costs/heuristics.
http://volta.cs.utah.edu:8080/z/oP3ecL
define void @src(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%or = or i8 %x, %OrC
%eq = icmp eq i8 %or, %C
store i1 %eq, i1* %p0
%ne = icmp ne i8 %or, %C
store i1 %ne, i1* %p1
ret void
}
define void @tgt(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%NotOrC = xor i8 %OrC, -1
%a = and i8 %x, %NotOrC
%NewC = xor i8 %C, %OrC
%eq = icmp eq i8 %a, %NewC
store i1 %eq, i1* %p0
%ne = icmp ne i8 %a, %NewC
store i1 %ne, i1* %p1
ret void
}
2020-04-25 23:25:03 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -2
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 2
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = sub i32 3, %X
|
|
|
|
%cmp = icmp ult i32 %add, 2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_sub_3_X_ult_2_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_sub_3_X_ult_2_vec(
|
[InstCombine] generalize canonicalization of masked equality comparisons
(X | MaskC) == C --> (X & ~MaskC) == C ^ MaskC
(X | MaskC) != C --> (X & ~MaskC) != C ^ MaskC
We have more analyis for 'and' patterns and already lean this way
in the existing code, so this should be neutral or better in IR.
If this does not do as well in codegen, the problem already exists
and we should fix that based on target costs/heuristics.
http://volta.cs.utah.edu:8080/z/oP3ecL
define void @src(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%or = or i8 %x, %OrC
%eq = icmp eq i8 %or, %C
store i1 %eq, i1* %p0
%ne = icmp ne i8 %or, %C
store i1 %ne, i1* %p1
ret void
}
define void @tgt(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%NotOrC = xor i8 %OrC, -1
%a = and i8 %x, %NotOrC
%NewC = xor i8 %C, %OrC
%eq = icmp eq i8 %a, %NewC
store i1 %eq, i1* %p0
%ne = icmp ne i8 %a, %NewC
store i1 %ne, i1* %p1
ret void
}
2020-04-25 23:25:03 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -2>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 2, i32 2>
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%add = sub <2 x i32> <i32 3, i32 3>, %X
|
|
|
|
%cmp = icmp ult <2 x i32> %add, <i32 2, i32 2>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add_X_-14_uge_2(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_add_X_-14_uge_2(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -2
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], 14
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add i32 %X, -14
|
|
|
|
%cmp = icmp uge i32 %add, 2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_add_X_-14_uge_2_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_add_X_-14_uge_2_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -2>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 14, i32 14>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add <2 x i32> %X, <i32 -14, i32 -14>
|
|
|
|
%cmp = icmp uge <2 x i32> %add, <i32 2, i32 2>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sub_3_X_uge_2(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_sub_3_X_uge_2(
|
[InstCombine] generalize canonicalization of masked equality comparisons
(X | MaskC) == C --> (X & ~MaskC) == C ^ MaskC
(X | MaskC) != C --> (X & ~MaskC) != C ^ MaskC
We have more analyis for 'and' patterns and already lean this way
in the existing code, so this should be neutral or better in IR.
If this does not do as well in codegen, the problem already exists
and we should fix that based on target costs/heuristics.
http://volta.cs.utah.edu:8080/z/oP3ecL
define void @src(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%or = or i8 %x, %OrC
%eq = icmp eq i8 %or, %C
store i1 %eq, i1* %p0
%ne = icmp ne i8 %or, %C
store i1 %ne, i1* %p1
ret void
}
define void @tgt(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%NotOrC = xor i8 %OrC, -1
%a = and i8 %x, %NotOrC
%NewC = xor i8 %C, %OrC
%eq = icmp eq i8 %a, %NewC
store i1 %eq, i1* %p0
%ne = icmp ne i8 %a, %NewC
store i1 %ne, i1* %p1
ret void
}
2020-04-25 23:25:03 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -2
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], 2
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = sub i32 3, %X
|
|
|
|
%cmp = icmp uge i32 %add, 2
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_sub_3_X_uge_2_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_sub_3_X_uge_2_vec(
|
[InstCombine] generalize canonicalization of masked equality comparisons
(X | MaskC) == C --> (X & ~MaskC) == C ^ MaskC
(X | MaskC) != C --> (X & ~MaskC) != C ^ MaskC
We have more analyis for 'and' patterns and already lean this way
in the existing code, so this should be neutral or better in IR.
If this does not do as well in codegen, the problem already exists
and we should fix that based on target costs/heuristics.
http://volta.cs.utah.edu:8080/z/oP3ecL
define void @src(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%or = or i8 %x, %OrC
%eq = icmp eq i8 %or, %C
store i1 %eq, i1* %p0
%ne = icmp ne i8 %or, %C
store i1 %ne, i1* %p1
ret void
}
define void @tgt(i8 %x, i8 %OrC, i8 %C, i1* %p0, i1* %p1) {
%NotOrC = xor i8 %OrC, -1
%a = and i8 %x, %NotOrC
%NewC = xor i8 %C, %OrC
%eq = icmp eq i8 %a, %NewC
store i1 %eq, i1* %p0
%ne = icmp ne i8 %a, %NewC
store i1 %ne, i1* %p1
ret void
}
2020-04-25 23:25:03 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -2>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 2, i32 2>
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%add = sub <2 x i32> <i32 3, i32 3>, %X
|
|
|
|
%cmp = icmp uge <2 x i32> %add, <i32 2, i32 2>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_X_-16_eq-16(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_and_X_-16_eq-16(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -17
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and i32 %X, -16
|
|
|
|
%cmp = icmp eq i32 %and, -16
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_and_X_-16_eq-16_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_and_X_-16_eq-16_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 -17, i32 -17>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and <2 x i32> %X, <i32 -16, i32 -16>
|
|
|
|
%cmp = icmp eq <2 x i32> %and, <i32 -16, i32 -16>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_X_-16_ne-16(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_and_X_-16_ne-16(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], -16
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and i32 %X, -16
|
|
|
|
%cmp = icmp ne i32 %and, -16
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_and_X_-16_ne-16_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_and_X_-16_ne-16_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 -16, i32 -16>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%and = and <2 x i32> %X, <i32 -16, i32 -16>
|
|
|
|
%cmp = icmp ne <2 x i32> %and, <i32 -16, i32 -16>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR32524: https://bugs.llvm.org/show_bug.cgi?id=32524
|
|
|
|
; X | C == C --> X <=u C (when C+1 is PowerOf2).
|
|
|
|
|
|
|
|
define i1 @or1_eq1(i32 %x) {
|
|
|
|
; CHECK-LABEL: @or1_eq1(
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp ult i32 [[X:%.*]], 2
|
|
|
|
; CHECK-NEXT: ret i1 [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or i32 %x, 1
|
|
|
|
%t1 = icmp eq i32 %t0, 1
|
|
|
|
ret i1 %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
; X | C == C --> X <=u C (when C+1 is PowerOf2).
|
|
|
|
|
|
|
|
define <2 x i1> @or3_eq3_vec(<2 x i8> %x) {
|
|
|
|
; CHECK-LABEL: @or3_eq3_vec(
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 4, i8 4>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or <2 x i8> %x, <i8 3, i8 3>
|
|
|
|
%t1 = icmp eq <2 x i8> %t0, <i8 3, i8 3>
|
|
|
|
ret <2 x i1> %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
; X | C != C --> X >u C (when C+1 is PowerOf2).
|
|
|
|
|
|
|
|
define i1 @or7_ne7(i32 %x) {
|
|
|
|
; CHECK-LABEL: @or7_ne7(
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp ugt i32 [[X:%.*]], 7
|
|
|
|
; CHECK-NEXT: ret i1 [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or i32 %x, 7
|
|
|
|
%t1 = icmp ne i32 %t0, 7
|
|
|
|
ret i1 %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
; X | C != C --> X >u C (when C+1 is PowerOf2).
|
|
|
|
|
|
|
|
define <2 x i1> @or63_ne63_vec(<2 x i8> %x) {
|
|
|
|
; CHECK-LABEL: @or63_ne63_vec(
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 63, i8 63>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or <2 x i8> %x, <i8 63, i8 63>
|
|
|
|
%t1 = icmp ne <2 x i8> %t0, <i8 63, i8 63>
|
|
|
|
ret <2 x i1> %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR40611: https://bugs.llvm.org/show_bug.cgi?id=40611
|
|
|
|
; X | C == C --> (X & ~C) == 0
|
|
|
|
|
|
|
|
define i1 @orC_eqC(i32 %x) {
|
|
|
|
; CHECK-LABEL: @orC_eqC(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -43
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[TMP1]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or i32 %x, 42
|
|
|
|
%t1 = icmp eq i32 %t0, 42
|
|
|
|
ret i1 %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
; X | C == C --> (X & ~C) == 0
|
|
|
|
|
|
|
|
define <2 x i1> @orC_eqC_vec(<2 x i8> %x) {
|
|
|
|
; CHECK-LABEL: @orC_eqC_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -44, i8 -44>
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or <2 x i8> %x, <i8 43, i8 43>
|
|
|
|
%t1 = icmp eq <2 x i8> %t0, <i8 43, i8 43>
|
|
|
|
ret <2 x i1> %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
; X | C != C --> (X & ~C) != 0
|
|
|
|
|
|
|
|
define i1 @orC_neC(i32 %x) {
|
|
|
|
; CHECK-LABEL: @orC_neC(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 41
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[TMP1]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or i32 %x, -42
|
|
|
|
%t1 = icmp ne i32 %t0, -42
|
|
|
|
ret i1 %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
; X | C != C --> (X & ~C) != 0
|
|
|
|
|
|
|
|
define <2 x i1> @orC_neC_vec(<2 x i8> %x) {
|
|
|
|
; CHECK-LABEL: @orC_neC_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 42, i8 42>
|
|
|
|
; CHECK-NEXT: [[T1:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
|
|
|
;
|
|
|
|
%t0 = or <2 x i8> %x, <i8 -43, i8 -43>
|
|
|
|
%t1 = icmp ne <2 x i8> %t0, <i8 -43, i8 -43>
|
|
|
|
ret <2 x i1> %t1
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shrink_constant(i32 %X) {
|
|
|
|
; CHECK-LABEL: @shrink_constant(
|
|
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], -12
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[XOR]], 4
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%xor = xor i32 %X, -9
|
|
|
|
%cmp = icmp ult i32 %xor, 4
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @shrink_constant_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @shrink_constant_vec(
|
|
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i32> [[X:%.*]], <i32 -12, i32 -12>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[XOR]], <i32 4, i32 4>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%xor = xor <2 x i32> %X, <i32 -9, i32 -9>
|
|
|
|
%cmp = icmp ult <2 x i32> %xor, <i32 4, i32 4>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; This test requires 3 different transforms to get to the result.
|
|
|
|
define i1 @icmp_sub_-1_X_ult_4(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_sub_-1_X_ult_4(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -5
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = sub i32 -1, %X
|
|
|
|
%cmp = icmp ult i32 %sub, 4
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_xor_neg4_X_ult_4_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_xor_neg4_X_ult_4_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 -5, i32 -5>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%xor = xor <2 x i32> %X, <i32 -4, i32 -4>
|
|
|
|
%cmp = icmp ult <2 x i32> %xor, <i32 4, i32 4>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sub_-1_X_uge_4(i32 %X) {
|
|
|
|
; CHECK-LABEL: @icmp_sub_-1_X_uge_4(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], -4
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%sub = sub i32 -1, %X
|
|
|
|
%cmp = icmp uge i32 %sub, 4
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_xor_neg4_X_uge_4_vec(<2 x i32> %X) {
|
|
|
|
; CHECK-LABEL: @icmp_xor_neg4_X_uge_4_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 -4, i32 -4>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%xor = xor <2 x i32> %X, <i32 -4, i32 -4>
|
|
|
|
%cmp = icmp uge <2 x i32> %xor, <i32 4, i32 4>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @xor_ult(<2 x i8> %x) {
|
|
|
|
; CHECK-LABEL: @xor_ult(
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 3, i8 3>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
|
|
;
|
|
|
|
%xor = xor <2 x i8> %x, <i8 -4, i8 -4>
|
|
|
|
%r = icmp ult <2 x i8> %xor, <i8 -4, i8 -4>
|
|
|
|
ret <2 x i1> %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @xor_ult_extra_use(i8 %x, i8* %p) {
|
|
|
|
; CHECK-LABEL: @xor_ult_extra_use(
|
|
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X:%.*]], -32
|
|
|
|
; CHECK-NEXT: store i8 [[XOR]], i8* [[P:%.*]], align 1
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], 31
|
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%xor = xor i8 %x, -32
|
|
|
|
store i8 %xor, i8* %p
|
|
|
|
%r = icmp ult i8 %xor, -32
|
|
|
|
ret i1 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @xor_ugt(<2 x i8> %x) {
|
|
|
|
; CHECK-LABEL: @xor_ugt(
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 7, i8 7>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
|
|
;
|
|
|
|
%xor = xor <2 x i8> %x, <i8 7, i8 7>
|
|
|
|
%r = icmp ugt <2 x i8> %xor, <i8 7, i8 7>
|
|
|
|
ret <2 x i1> %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @xor_ugt_extra_use(i8 %x, i8* %p) {
|
|
|
|
; CHECK-LABEL: @xor_ugt_extra_use(
|
|
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X:%.*]], 63
|
|
|
|
; CHECK-NEXT: store i8 [[XOR]], i8* [[P:%.*]], align 1
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], 63
|
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%xor = xor i8 %x, 63
|
|
|
|
store i8 %xor, i8* %p
|
|
|
|
%r = icmp ugt i8 %xor, 63
|
|
|
|
ret i1 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_swap_operands_for_cse(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @icmp_swap_operands_for_cse(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X]], [[Y]]
|
|
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
|
|
|
; CHECK: true:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[SUB]], 1
|
|
|
|
; CHECK-NEXT: br label [[END:%.*]]
|
|
|
|
; CHECK: false:
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[SUB]], 16
|
|
|
|
; CHECK-NEXT: br label [[END]]
|
|
|
|
; CHECK: end:
|
|
|
|
; CHECK-NEXT: [[RES_IN:%.*]] = phi i32 [ [[TMP0]], [[TRUE]] ], [ [[TMP1]], [[FALSE]] ]
|
|
|
|
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[RES_IN]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%sub = sub i32 %X, %Y
|
|
|
|
%cmp = icmp ugt i32 %Y, %X
|
|
|
|
br i1 %cmp, label %true, label %false
|
|
|
|
true:
|
|
|
|
%restrue = trunc i32 %sub to i1
|
|
|
|
br label %end
|
|
|
|
false:
|
|
|
|
%shift = lshr i32 %sub, 4
|
|
|
|
%resfalse = trunc i32 %shift to i1
|
|
|
|
br label %end
|
|
|
|
end:
|
|
|
|
%res = phi i1 [%restrue, %true], [%resfalse, %false]
|
|
|
|
ret i1 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_swap_operands_for_cse2(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @icmp_swap_operands_for_cse2(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
|
|
|
; CHECK: true:
|
|
|
|
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
|
|
|
|
; CHECK-NEXT: [[SUB1:%.*]] = sub i32 [[X]], [[Y]]
|
|
|
|
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SUB]], [[SUB1]]
|
|
|
|
; CHECK-NEXT: br label [[END:%.*]]
|
|
|
|
; CHECK: false:
|
|
|
|
; CHECK-NEXT: [[SUB2:%.*]] = sub i32 [[Y]], [[X]]
|
|
|
|
; CHECK-NEXT: br label [[END]]
|
|
|
|
; CHECK: end:
|
|
|
|
; CHECK-NEXT: [[RES_IN_IN:%.*]] = phi i32 [ [[ADD]], [[TRUE]] ], [ [[SUB2]], [[FALSE]] ]
|
|
|
|
; CHECK-NEXT: [[RES_IN:%.*]] = and i32 [[RES_IN_IN]], 1
|
|
|
|
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[RES_IN]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ugt i32 %Y, %X
|
|
|
|
br i1 %cmp, label %true, label %false
|
|
|
|
true:
|
|
|
|
%sub = sub i32 %X, %Y
|
|
|
|
%sub1 = sub i32 %X, %Y
|
|
|
|
%add = add i32 %sub, %sub1
|
|
|
|
%restrue = trunc i32 %add to i1
|
|
|
|
br label %end
|
|
|
|
false:
|
|
|
|
%sub2 = sub i32 %Y, %X
|
|
|
|
%resfalse = trunc i32 %sub2 to i1
|
|
|
|
br label %end
|
|
|
|
end:
|
|
|
|
%res = phi i1 [%restrue, %true], [%resfalse, %false]
|
|
|
|
ret i1 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_do_not_swap_operands_for_cse(i32 %X, i32 %Y) {
|
|
|
|
; CHECK-LABEL: @icmp_do_not_swap_operands_for_cse(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[Y:%.*]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
|
|
|
; CHECK: true:
|
|
|
|
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
|
|
|
|
; CHECK-NEXT: br label [[END:%.*]]
|
|
|
|
; CHECK: false:
|
|
|
|
; CHECK-NEXT: [[SUB2:%.*]] = sub i32 [[Y]], [[X]]
|
|
|
|
; CHECK-NEXT: br label [[END]]
|
|
|
|
; CHECK: end:
|
|
|
|
; CHECK-NEXT: [[RES_IN_IN:%.*]] = phi i32 [ [[SUB]], [[TRUE]] ], [ [[SUB2]], [[FALSE]] ]
|
|
|
|
; CHECK-NEXT: [[RES_IN:%.*]] = and i32 [[RES_IN_IN]], 1
|
|
|
|
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[RES_IN]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ugt i32 %Y, %X
|
|
|
|
br i1 %cmp, label %true, label %false
|
|
|
|
true:
|
|
|
|
%sub = sub i32 %X, %Y
|
|
|
|
%restrue = trunc i32 %sub to i1
|
|
|
|
br label %end
|
|
|
|
false:
|
|
|
|
%sub2 = sub i32 %Y, %X
|
|
|
|
%resfalse = trunc i32 %sub2 to i1
|
|
|
|
br label %end
|
|
|
|
end:
|
|
|
|
%res = phi i1 [%restrue, %true], [%resfalse, %false]
|
|
|
|
ret i1 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_lshr_lshr_eq(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @icmp_lshr_lshr_eq(
|
|
|
|
; CHECK-NEXT: [[Z_UNSHIFTED:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[Z:%.*]] = icmp ult i32 [[Z_UNSHIFTED]], 1073741824
|
|
|
|
; CHECK-NEXT: ret i1 [[Z]]
|
|
|
|
;
|
|
|
|
%x = lshr i32 %a, 30
|
|
|
|
%y = lshr i32 %b, 30
|
|
|
|
%z = icmp eq i32 %x, %y
|
|
|
|
ret i1 %z
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_ashr_ashr_ne(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @icmp_ashr_ashr_ne(
|
|
|
|
; CHECK-NEXT: [[Z_UNSHIFTED:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[Z:%.*]] = icmp ugt i32 [[Z_UNSHIFTED]], 255
|
|
|
|
; CHECK-NEXT: ret i1 [[Z]]
|
|
|
|
;
|
|
|
|
%x = ashr i32 %a, 8
|
|
|
|
%y = ashr i32 %b, 8
|
|
|
|
%z = icmp ne i32 %x, %y
|
|
|
|
ret i1 %z
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_neg_cst_slt(i32 %a) {
|
|
|
|
; CHECK-LABEL: @icmp_neg_cst_slt(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A:%.*]], 10
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP1]]
|
|
|
|
;
|
|
|
|
%1 = sub nsw i32 0, %a
|
|
|
|
%2 = icmp slt i32 %1, -10
|
|
|
|
ret i1 %2
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_or_lshr(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_and_or_lshr(
|
|
|
|
; CHECK-NEXT: [[SHF1:%.*]] = shl nuw i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[OR2:%.*]] = or i32 [[SHF1]], 1
|
|
|
|
; CHECK-NEXT: [[AND3:%.*]] = and i32 [[OR2]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[RET:%.*]] = icmp ne i32 [[AND3]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[RET]]
|
|
|
|
;
|
|
|
|
%shf = lshr i32 %x, %y
|
|
|
|
%or = or i32 %shf, %x
|
|
|
|
%and = and i32 %or, 1
|
|
|
|
%ret = icmp ne i32 %and, 0
|
|
|
|
ret i1 %ret
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_and_or_lshr_vec(<2 x i32> %x, <2 x i32> %y) {
|
|
|
|
; CHECK-LABEL: @icmp_and_or_lshr_vec(
|
|
|
|
; CHECK-NEXT: [[SHF:%.*]] = lshr <2 x i32> [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[SHF]], [[X]]
|
|
|
|
; CHECK-NEXT: [[RET:%.*]] = trunc <2 x i32> [[OR]] to <2 x i1>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[RET]]
|
|
|
|
;
|
|
|
|
%shf = lshr <2 x i32> %x, %y
|
|
|
|
%or = or <2 x i32> %shf, %x
|
|
|
|
%and = and <2 x i32> %or, <i32 1, i32 1>
|
|
|
|
%ret = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %ret
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_and_or_lshr_vec_commute(<2 x i32> %xp, <2 x i32> %y) {
|
|
|
|
; CHECK-LABEL: @icmp_and_or_lshr_vec_commute(
|
|
|
|
; CHECK-NEXT: [[X:%.*]] = srem <2 x i32> [[XP:%.*]], <i32 42, i32 42>
|
|
|
|
; CHECK-NEXT: [[SHF:%.*]] = lshr <2 x i32> [[X]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[X]], [[SHF]]
|
|
|
|
; CHECK-NEXT: [[RET:%.*]] = trunc <2 x i32> [[OR]] to <2 x i1>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[RET]]
|
|
|
|
;
|
|
|
|
%x = srem <2 x i32> %xp, <i32 42, i32 -42> ; prevent complexity-based canonicalization
|
|
|
|
%shf = lshr <2 x i32> %x, %y
|
|
|
|
%or = or <2 x i32> %x, %shf
|
|
|
|
%and = and <2 x i32> %or, <i32 1, i32 1>
|
|
|
|
%ret = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %ret
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_and_or_lshr_cst(i32 %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_or_lshr_cst(
|
|
|
|
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: [[RET:%.*]] = icmp ne i32 [[AND1]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[RET]]
|
|
|
|
;
|
|
|
|
%shf = lshr i32 %x, 1
|
|
|
|
%or = or i32 %shf, %x
|
|
|
|
%and = and i32 %or, 1
|
|
|
|
%ret = icmp ne i32 %and, 0
|
|
|
|
ret i1 %ret
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_and_or_lshr_cst_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @icmp_and_or_lshr_cst_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[RET]]
|
|
|
|
;
|
|
|
|
%shf = lshr <2 x i32> %x, <i32 1, i32 1>
|
|
|
|
%or = or <2 x i32> %shf, %x
|
|
|
|
%and = and <2 x i32> %or, <i32 1, i32 1>
|
|
|
|
%ret = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %ret
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @icmp_and_or_lshr_cst_vec_commute(<2 x i32> %xp) {
|
|
|
|
; CHECK-LABEL: @icmp_and_or_lshr_cst_vec_commute(
|
|
|
|
; CHECK-NEXT: [[X:%.*]] = srem <2 x i32> [[XP:%.*]], <i32 42, i32 42>
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X]], <i32 3, i32 3>
|
|
|
|
; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[RET]]
|
|
|
|
;
|
|
|
|
%x = srem <2 x i32> %xp, <i32 42, i32 -42> ; prevent complexity-based canonicalization
|
|
|
|
%shf = lshr <2 x i32> %x, <i32 1, i32 1>
|
|
|
|
%or = or <2 x i32> %x, %shf
|
|
|
|
%and = and <2 x i32> %or, <i32 1, i32 1>
|
|
|
|
%ret = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %ret
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shl_ap1_zero_ap2_non_zero_2(i32 %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_zero_ap2_non_zero_2(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 29
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 4, %a
|
|
|
|
%cmp = icmp eq i32 %shl, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @shl_ap1_zero_ap2_non_zero_2_vec(<2 x i32> %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_zero_ap2_non_zero_2_vec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[A:%.*]], <i32 29, i32 29>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl <2 x i32> <i32 4, i32 4>, %a
|
|
|
|
%cmp = icmp eq <2 x i32> %shl, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shl_ap1_zero_ap2_non_zero_4(i32 %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_zero_ap2_non_zero_4(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 30
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 -2, %a
|
|
|
|
%cmp = icmp eq i32 %shl, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shl_ap1_non_zero_ap2_non_zero_both_positive(i32 %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_both_positive(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 50, %a
|
|
|
|
%cmp = icmp eq i32 %shl, 50
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shl_ap1_non_zero_ap2_non_zero_both_negative(i32 %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_both_negative(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 -50, %a
|
|
|
|
%cmp = icmp eq i32 %shl, -50
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shl_ap1_non_zero_ap2_non_zero_ap1_1(i32 %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_ap1_1(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%shl = shl i32 50, %a
|
|
|
|
%cmp = icmp eq i32 %shl, 25
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shl_ap1_non_zero_ap2_non_zero_ap1_2(i32 %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_ap1_2(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 1
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 25, %a
|
|
|
|
%cmp = icmp eq i32 %shl, 50
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @shl_ap1_non_zero_ap2_non_zero_ap1_3(i32 %a) {
|
|
|
|
; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_ap1_3(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%shl = shl i32 26, %a
|
|
|
|
%cmp = icmp eq i32 %shl, 50
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sgt_zero_add_nsw(i32 %a) {
|
|
|
|
; CHECK-LABEL: @icmp_sgt_zero_add_nsw(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], -1
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add nsw i32 %a, 1
|
|
|
|
%cmp = icmp sgt i32 %add, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sge_zero_add_nsw(i32 %a) {
|
|
|
|
; CHECK-LABEL: @icmp_sge_zero_add_nsw(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], -2
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add nsw i32 %a, 1
|
|
|
|
%cmp = icmp sge i32 %add, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_sle_zero_add_nsw(i32 %a) {
|
|
|
|
; CHECK-LABEL: @icmp_sle_zero_add_nsw(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add nsw i32 %a, 1
|
|
|
|
%cmp = icmp sle i32 %add, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define zeroext i1 @icmp_cmpxchg_strong(i32* %sc, i32 %old_val, i32 %new_val) {
|
|
|
|
; CHECK-LABEL: @icmp_cmpxchg_strong(
|
|
|
|
; CHECK-NEXT: [[XCHG:%.*]] = cmpxchg i32* [[SC:%.*]], i32 [[OLD_VAL:%.*]], i32 [[NEW_VAL:%.*]] seq_cst seq_cst
|
|
|
|
; CHECK-NEXT: [[ICMP:%.*]] = extractvalue { i32, i1 } [[XCHG]], 1
|
|
|
|
; CHECK-NEXT: ret i1 [[ICMP]]
|
|
|
|
;
|
|
|
|
%xchg = cmpxchg i32* %sc, i32 %old_val, i32 %new_val seq_cst seq_cst
|
|
|
|
%xtrc = extractvalue { i32, i1 } %xchg, 0
|
|
|
|
%icmp = icmp eq i32 %xtrc, %old_val
|
|
|
|
ret i1 %icmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @f1(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @f1(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp sge i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw i64 %a, %b
|
|
|
|
%v = icmp sge i64 %t, 0
|
|
|
|
ret i1 %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @f1_vec(<2 x i64> %a, <2 x i64> %b) {
|
|
|
|
; CHECK-LABEL: @f1_vec(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp sge <2 x i64> [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw <2 x i64> %a, %b
|
|
|
|
%v = icmp sgt <2 x i64> %t, <i64 -1, i64 -1>
|
|
|
|
ret <2 x i1> %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @f2(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @f2(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp sgt i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw i64 %a, %b
|
|
|
|
%v = icmp sgt i64 %t, 0
|
|
|
|
ret i1 %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @f2_vec(<2 x i64> %a, <2 x i64> %b) {
|
|
|
|
; CHECK-LABEL: @f2_vec(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp sgt <2 x i64> [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw <2 x i64> %a, %b
|
|
|
|
%v = icmp sgt <2 x i64> %t, zeroinitializer
|
|
|
|
ret <2 x i1> %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @f3(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @f3(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp slt i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw i64 %a, %b
|
|
|
|
%v = icmp slt i64 %t, 0
|
|
|
|
ret i1 %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @f3_vec(<2 x i64> %a, <2 x i64> %b) {
|
|
|
|
; CHECK-LABEL: @f3_vec(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp slt <2 x i64> [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw <2 x i64> %a, %b
|
|
|
|
%v = icmp slt <2 x i64> %t, zeroinitializer
|
|
|
|
ret <2 x i1> %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @f4(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @f4(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp sle i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw i64 %a, %b
|
|
|
|
%v = icmp sle i64 %t, 0
|
|
|
|
ret i1 %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @f4_vec(<2 x i64> %a, <2 x i64> %b) {
|
|
|
|
; CHECK-LABEL: @f4_vec(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = icmp sle <2 x i64> [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[V]]
|
|
|
|
;
|
|
|
|
%t = sub nsw <2 x i64> %a, %b
|
|
|
|
%v = icmp slt <2 x i64> %t, <i64 1, i64 1>
|
|
|
|
ret <2 x i1> %v
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @f5(i8 %a, i8 %b) {
|
|
|
|
; CHECK-LABEL: @f5(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[A:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[CONV3:%.*]] = zext i8 [[B:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV3]]
|
|
|
|
; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[SUB]], 0
|
|
|
|
; CHECK-NEXT: [[SUB7:%.*]] = sub nsw i32 0, [[SUB]]
|
|
|
|
; CHECK-NEXT: [[SUB7_SUB:%.*]] = select i1 [[CMP4]], i32 [[SUB7]], i32 [[SUB]]
|
|
|
|
; CHECK-NEXT: ret i32 [[SUB7_SUB]]
|
|
|
|
;
|
|
|
|
%conv = zext i8 %a to i32
|
|
|
|
%conv3 = zext i8 %b to i32
|
|
|
|
%sub = sub nsw i32 %conv, %conv3
|
|
|
|
%cmp4 = icmp slt i32 %sub, 0
|
|
|
|
%sub7 = sub nsw i32 0, %sub
|
|
|
|
%sub7.sub = select i1 %cmp4, i32 %sub7, i32 %sub
|
|
|
|
ret i32 %sub7.sub
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @f6(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @f6(
|
|
|
|
; CHECK-NEXT: [[CMP_UNSHIFTED:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP_MASK:%.*]] = and i32 [[CMP_UNSHIFTED]], 255
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CMP_MASK]], 0
|
|
|
|
; CHECK-NEXT: [[S:%.*]] = select i1 [[CMP]], i32 10000, i32 0
|
|
|
|
; CHECK-NEXT: ret i32 [[S]]
|
|
|
|
;
|
|
|
|
%sext = shl i32 %a, 24
|
|
|
|
%conv = ashr i32 %sext, 24
|
|
|
|
%sext6 = shl i32 %b, 24
|
|
|
|
%conv4 = ashr i32 %sext6, 24
|
|
|
|
%cmp = icmp eq i32 %conv, %conv4
|
|
|
|
%s = select i1 %cmp, i32 10000, i32 0
|
|
|
|
ret i32 %s
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @f7(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @f7(
|
|
|
|
; CHECK-NEXT: [[CMP_UNSHIFTED:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP_MASK:%.*]] = and i32 [[CMP_UNSHIFTED]], 511
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CMP_MASK]], 0
|
|
|
|
; CHECK-NEXT: [[S:%.*]] = select i1 [[CMP]], i32 0, i32 10000
|
|
|
|
; CHECK-NEXT: ret i32 [[S]]
|
|
|
|
;
|
|
|
|
%sext = shl i32 %a, 23
|
|
|
|
%sext6 = shl i32 %b, 23
|
|
|
|
%cmp = icmp ne i32 %sext, %sext6
|
|
|
|
%s = select i1 %cmp, i32 10000, i32 0
|
|
|
|
ret i32 %s
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @f8(i32 %val, i32 %lim) {
|
|
|
|
; CHECK-LABEL: @f8(
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[LIM:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%lim.sub = add i32 %lim, -1
|
|
|
|
%val.and = and i32 %val, %lim.sub
|
|
|
|
%r = icmp ult i32 %val.and, %lim
|
|
|
|
ret i1 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @f9(i32 %val, i32 %lim) {
|
|
|
|
; CHECK-LABEL: @f9(
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[LIM:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%lim.sub = sub i32 %lim, 1
|
|
|
|
%val.and = and i32 %val, %lim.sub
|
|
|
|
%r = icmp ult i32 %val.and, %lim
|
|
|
|
ret i1 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @f10(i16 %p) {
|
|
|
|
; CHECK-LABEL: @f10(
|
|
|
|
; CHECK-NEXT: [[CMP580:%.*]] = icmp uge i16 [[P:%.*]], mul (i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16), i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16))
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP580]]
|
|
|
|
;
|
|
|
|
%cmp580 = icmp ule i16 mul (i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16), i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16)), %p
|
|
|
|
ret i1 %cmp580
|
|
|
|
}
|
|
|
|
|
|
|
|
; Note: fptosi is used in various tests below to ensure that operand complexity
|
|
|
|
; canonicalization does not kick in, which would make some of the tests
|
|
|
|
; equivalent to one another.
|
|
|
|
|
|
|
|
define i1 @cmp_sgt_rhs_dec(float %x, i32 %i) {
|
|
|
|
; CHECK-LABEL: @cmp_sgt_rhs_dec(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[CONV]], [[I:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%dec = sub nsw i32 %i, 1
|
|
|
|
%cmp = icmp sgt i32 %conv, %dec
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_sle_rhs_dec(float %x, i32 %i) {
|
|
|
|
; CHECK-LABEL: @cmp_sle_rhs_dec(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CONV]], [[I:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%dec = sub nsw i32 %i, 1
|
|
|
|
%cmp = icmp sle i32 %conv, %dec
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_sge_rhs_inc(float %x, i32 %i) {
|
|
|
|
; CHECK-LABEL: @cmp_sge_rhs_inc(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CONV]], [[I:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%inc = add nsw i32 %i, 1
|
|
|
|
%cmp = icmp sge i32 %conv, %inc
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_slt_rhs_inc(float %x, i32 %i) {
|
|
|
|
; CHECK-LABEL: @cmp_slt_rhs_inc(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[CONV]], [[I:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%inc = add nsw i32 %i, 1
|
|
|
|
%cmp = icmp slt i32 %conv, %inc
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @PR26407(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @PR26407(
|
|
|
|
; CHECK-NEXT: [[ADDX:%.*]] = add i32 [[X:%.*]], 2147483647
|
|
|
|
; CHECK-NEXT: [[ADDY:%.*]] = add i32 [[Y:%.*]], 2147483647
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[ADDX]], [[ADDY]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%addx = add i32 %x, 2147483647
|
|
|
|
%addy = add i32 %y, 2147483647
|
|
|
|
%cmp = icmp uge i32 %addx, %addy
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_inverse_mask_bits_set_eq(i32 %x) {
|
|
|
|
; CHECK-LABEL: @cmp_inverse_mask_bits_set_eq(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -43
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], -43
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%or = or i32 %x, 42
|
|
|
|
%cmp = icmp eq i32 %or, -1
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @cmp_inverse_mask_bits_set_eq_vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @cmp_inverse_mask_bits_set_eq_vec(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -43, i32 -43>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 -43, i32 -43>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%or = or <2 x i32> %x, <i32 42, i32 42>
|
|
|
|
%cmp = icmp eq <2 x i32> %or, <i32 -1, i32 -1>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_inverse_mask_bits_set_ne(i32 %x) {
|
|
|
|
; CHECK-LABEL: @cmp_inverse_mask_bits_set_ne(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -43
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], -43
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%or = or i32 %x, 42
|
|
|
|
%cmp = icmp ne i32 %or, -1
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; When canonicalizing to 'gt/lt', make sure the constant is correct.
|
|
|
|
|
|
|
|
define i1 @PR27792(i128 %a) {
|
|
|
|
; CHECK-LABEL: @PR27792(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i128 [[A:%.*]], -1
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%cmp = icmp sge i128 %a, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @PR27792_2(i128 %a) {
|
|
|
|
; CHECK-LABEL: @PR27792_2(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ne i128 [[A:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
%b = icmp uge i128 %a, 1
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @ugtMaxSignedVal(i8 %a) {
|
|
|
|
; CHECK-LABEL: @ugtMaxSignedVal(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A:%.*]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%cmp = icmp ugt i8 %a, 127
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @ugtMaxSignedValVec(<2 x i8> %a) {
|
|
|
|
; CHECK-LABEL: @ugtMaxSignedValVec(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%cmp = icmp ugt <2 x i8> %a, <i8 127, i8 127>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @ugtKnownBits(i8 %a) {
|
|
|
|
; CHECK-LABEL: @ugtKnownBits(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = and i8 [[A:%.*]], 17
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[B]], 17
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%b = and i8 %a, 17
|
|
|
|
%cmp = icmp ugt i8 %b, 16
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @ugtKnownBitsVec(<2 x i8> %a) {
|
|
|
|
; CHECK-LABEL: @ugtKnownBitsVec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = and <2 x i8> [[A:%.*]], <i8 17, i8 17>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[B]], <i8 17, i8 17>
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%b = and <2 x i8> %a, <i8 17, i8 17>
|
|
|
|
%cmp = icmp ugt <2 x i8> %b, <i8 16, i8 16>
|
|
|
|
ret <2 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @or_ptrtoint_mismatch(i8* %p, i32* %q) {
|
|
|
|
; CHECK-LABEL: @or_ptrtoint_mismatch(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* [[P:%.*]], null
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32* [[Q:%.*]], null
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[B]]
|
|
|
|
;
|
|
|
|
|
|
|
|
%pp = ptrtoint i8* %p to i64
|
|
|
|
%qq = ptrtoint i32* %q to i64
|
|
|
|
%o = or i64 %pp, %qq
|
|
|
|
%b = icmp eq i64 %o, 0
|
|
|
|
ret i1 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add1_ugt(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_add1_ugt(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add nuw i32 %x, 1
|
|
|
|
%cmp = icmp ugt i32 %add, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @icmp_add1_ule(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @icmp_add1_ule(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%add = add nuw i32 %x, 1
|
|
|
|
%cmp = icmp ule i32 %add, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_uge_rhs_inc(float %x, i32 %i) {
|
|
|
|
; CHECK-LABEL: @cmp_uge_rhs_inc(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[CONV]], [[I:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%inc = add nuw i32 %i, 1
|
|
|
|
%cmp = icmp uge i32 %conv, %inc
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_ult_rhs_inc(float %x, i32 %i) {
|
|
|
|
; CHECK-LABEL: @cmp_ult_rhs_inc(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[CONV]], [[I:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%inc = add nuw i32 %i, 1
|
|
|
|
%cmp = icmp ult i32 %conv, %inc
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_sge_lhs_inc(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_sge_lhs_inc(
|
|
|
|
; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[X:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[INC]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%inc = add nsw i32 %x, 1
|
|
|
|
%cmp = icmp sge i32 %inc, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_uge_lhs_inc(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_uge_lhs_inc(
|
|
|
|
; CHECK-NEXT: [[INC:%.*]] = add nuw i32 [[X:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[INC]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%inc = add nuw i32 %x, 1
|
|
|
|
%cmp = icmp uge i32 %inc, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_sgt_lhs_dec(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_sgt_lhs_dec(
|
|
|
|
; CHECK-NEXT: [[DEC:%.*]] = add nsw i32 [[X:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%dec = sub nsw i32 %x, 1
|
|
|
|
%cmp = icmp sgt i32 %dec, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_ugt_lhs_dec(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_ugt_lhs_dec(
|
|
|
|
; CHECK-NEXT: [[DEC:%.*]] = add i32 [[X:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%dec = sub nuw i32 %x, 1
|
|
|
|
%cmp = icmp ugt i32 %dec, %y
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_sle_rhs_inc(float %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_sle_rhs_inc(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[Y:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[INC]], [[CONV]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%inc = add nsw i32 %y, 1
|
|
|
|
%cmp = icmp sle i32 %conv, %inc
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_ule_rhs_inc(float %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_ule_rhs_inc(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[INC:%.*]] = add nuw i32 [[Y:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[INC]], [[CONV]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%inc = add nuw i32 %y, 1
|
|
|
|
%cmp = icmp ule i32 %conv, %inc
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_slt_rhs_dec(float %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_slt_rhs_dec(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[DEC:%.*]] = add nsw i32 [[Y:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC]], [[CONV]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%dec = sub nsw i32 %y, 1
|
|
|
|
%cmp = icmp slt i32 %conv, %dec
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @cmp_ult_rhs_dec(float %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @cmp_ult_rhs_dec(
|
|
|
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[DEC:%.*]] = add i32 [[Y:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC]], [[CONV]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%conv = fptosi float %x to i32
|
|
|
|
%dec = sub nuw i32 %y, 1
|
|
|
|
%cmp = icmp ult i32 %conv, %dec
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @eq_add_constants(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @eq_add_constants(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = add i32 %x, 5
|
|
|
|
%B = add i32 %y, 5
|
|
|
|
%C = icmp eq i32 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @eq_mul_constants(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @eq_mul_constants(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = mul i32 %x, 5
|
|
|
|
%B = mul i32 %y, 5
|
|
|
|
%C = icmp eq i32 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @eq_mul_constants_splat(<2 x i32> %x, <2 x i32> %y) {
|
|
|
|
; CHECK-LABEL: @eq_mul_constants_splat(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%A = mul <2 x i32> %x, <i32 5, i32 5>
|
|
|
|
%B = mul <2 x i32> %y, <i32 5, i32 5>
|
|
|
|
%C = icmp ne <2 x i32> %A, %B
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; If the multiply constant has any trailing zero bits, we get something completely different.
|
|
|
|
; We mask off the high bits of each input and then convert:
|
|
|
|
; (X&Z) == (Y&Z) -> (X^Y) & Z == 0
|
|
|
|
|
|
|
|
define i1 @eq_mul_constants_with_tz(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @eq_mul_constants_with_tz(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 1073741823
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP2]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = mul i32 %x, 12
|
|
|
|
%B = mul i32 %y, 12
|
|
|
|
%C = icmp ne i32 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @eq_mul_constants_with_tz_splat(<2 x i32> %x, <2 x i32> %y) {
|
|
|
|
; CHECK-LABEL: @eq_mul_constants_with_tz_splat(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 1073741823, i32 1073741823>
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%A = mul <2 x i32> %x, <i32 12, i32 12>
|
|
|
|
%B = mul <2 x i32> %y, <i32 12, i32 12>
|
|
|
|
%C = icmp eq <2 x i32> %A, %B
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
|
|
|
declare i32 @llvm.bswap.i32(i32)
|
|
|
|
|
|
|
|
define i1 @bswap_ne(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @bswap_ne(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%swapx = call i32 @llvm.bswap.i32(i32 %x)
|
|
|
|
%swapy = call i32 @llvm.bswap.i32(i32 %y)
|
|
|
|
%cmp = icmp ne i32 %swapx, %swapy
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
declare <8 x i16> @llvm.bswap.v8i16(<8 x i16>)
|
|
|
|
|
|
|
|
define <8 x i1> @bswap_vec_eq(<8 x i16> %x, <8 x i16> %y) {
|
|
|
|
; CHECK-LABEL: @bswap_vec_eq(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <8 x i16> [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret <8 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%swapx = call <8 x i16> @llvm.bswap.v8i16(<8 x i16> %x)
|
|
|
|
%swapy = call <8 x i16> @llvm.bswap.v8i16(<8 x i16> %y)
|
|
|
|
%cmp = icmp eq <8 x i16> %swapx, %swapy
|
|
|
|
ret <8 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
declare i64 @llvm.bitreverse.i64(i64)
|
|
|
|
|
|
|
|
define i1 @bitreverse_eq(i64 %x, i64 %y) {
|
|
|
|
; CHECK-LABEL: @bitreverse_eq(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%revx = call i64 @llvm.bitreverse.i64(i64 %x)
|
|
|
|
%revy = call i64 @llvm.bitreverse.i64(i64 %y)
|
|
|
|
%cmp = icmp eq i64 %revx, %revy
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
declare <8 x i16> @llvm.bitreverse.v8i16(<8 x i16>)
|
|
|
|
|
|
|
|
define <8 x i1> @bitreverse_vec_ne(<8 x i16> %x, <8 x i16> %y) {
|
|
|
|
; CHECK-LABEL: @bitreverse_vec_ne(
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <8 x i16> [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret <8 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%revx = call <8 x i16> @llvm.bitreverse.v8i16(<8 x i16> %x)
|
|
|
|
%revy = call <8 x i16> @llvm.bitreverse.v8i16(<8 x i16> %y)
|
|
|
|
%cmp = icmp ne <8 x i16> %revx, %revy
|
|
|
|
ret <8 x i1> %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; These perform a comparison of a value known to be between 4 and 5 with a value between 5 and 7.
|
|
|
|
; They should all simplify to equality compares.
|
|
|
|
define i1 @knownbits1(i8 %a, i8 %b) {
|
|
|
|
; CHECK-LABEL: @knownbits1(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and i8 [[A:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or i8 [[A1]], 4
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and i8 [[B:%.*]], 2
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or i8 [[B1]], 5
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[A2]], [[B2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and i8 %a, 5
|
|
|
|
%a2 = or i8 %a1, 4
|
|
|
|
%b1 = and i8 %b, 7
|
|
|
|
%b2 = or i8 %b1, 5
|
|
|
|
%c = icmp uge i8 %a2, %b2
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @knownbits2(i8 %a, i8 %b) {
|
|
|
|
; CHECK-LABEL: @knownbits2(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and i8 [[A:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or i8 [[A1]], 4
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and i8 [[B:%.*]], 2
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or i8 [[B1]], 5
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[A2]], [[B2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and i8 %a, 5
|
|
|
|
%a2 = or i8 %a1, 4
|
|
|
|
%b1 = and i8 %b, 7
|
|
|
|
%b2 = or i8 %b1, 5
|
|
|
|
%c = icmp ult i8 %a2, %b2
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @knownbits3(i8 %a, i8 %b) {
|
|
|
|
; CHECK-LABEL: @knownbits3(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and i8 [[A:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or i8 [[A1]], 4
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and i8 [[B:%.*]], 2
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or i8 [[B1]], 5
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[B2]], [[A2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and i8 %a, 5
|
|
|
|
%a2 = or i8 %a1, 4
|
|
|
|
%b1 = and i8 %b, 7
|
|
|
|
%b2 = or i8 %b1, 5
|
|
|
|
%c = icmp ule i8 %b2, %a2
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @knownbits4(<2 x i8> %a, <2 x i8> %b) {
|
|
|
|
; CHECK-LABEL: @knownbits4(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and <2 x i8> [[A:%.*]], <i8 1, i8 1>
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or <2 x i8> [[A1]], <i8 4, i8 4>
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and <2 x i8> [[B:%.*]], <i8 2, i8 2>
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or <2 x i8> [[B1]], <i8 5, i8 5>
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[B2]], [[A2]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and <2 x i8> %a, <i8 5, i8 5>
|
|
|
|
%a2 = or <2 x i8> %a1, <i8 4, i8 4>
|
|
|
|
%b1 = and <2 x i8> %b, <i8 7, i8 7>
|
|
|
|
%b2 = or <2 x i8> %b1, <i8 5, i8 5>
|
|
|
|
%c = icmp ugt <2 x i8> %b2, %a2
|
|
|
|
ret <2 x i1> %c
|
|
|
|
}
|
|
|
|
|
|
|
|
; These are the signed versions of the above. One value is less than or equal to 5, but maybe negative.
|
|
|
|
; The other is known to be a value 5-7. These should simplify to equality comparisons.
|
|
|
|
define i1 @knownbits5(i8 %a, i8 %b) {
|
|
|
|
; CHECK-LABEL: @knownbits5(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and i8 [[A:%.*]], -127
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or i8 [[A1]], 4
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and i8 [[B:%.*]], 2
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or i8 [[B1]], 5
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[A2]], [[B2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and i8 %a, 133
|
|
|
|
%a2 = or i8 %a1, 4
|
|
|
|
%b1 = and i8 %b, 7
|
|
|
|
%b2 = or i8 %b1, 5
|
|
|
|
%c = icmp sge i8 %a2, %b2
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @knownbits6(i8 %a, i8 %b) {
|
|
|
|
; CHECK-LABEL: @knownbits6(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and i8 [[A:%.*]], -127
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or i8 [[A1]], 4
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and i8 [[B:%.*]], 2
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or i8 [[B1]], 5
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[A2]], [[B2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and i8 %a, 133
|
|
|
|
%a2 = or i8 %a1, 4
|
|
|
|
%b1 = and i8 %b, 7
|
|
|
|
%b2 = or i8 %b1, 5
|
|
|
|
%c = icmp slt i8 %a2, %b2
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @knownbits7(<2 x i8> %a, <2 x i8> %b) {
|
|
|
|
; CHECK-LABEL: @knownbits7(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and <2 x i8> [[A:%.*]], <i8 -127, i8 -127>
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or <2 x i8> [[A1]], <i8 4, i8 4>
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and <2 x i8> [[B:%.*]], <i8 2, i8 2>
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or <2 x i8> [[B1]], <i8 5, i8 5>
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i8> [[B2]], [[A2]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and <2 x i8> %a, <i8 133, i8 133>
|
|
|
|
%a2 = or <2 x i8> %a1, <i8 4, i8 4>
|
|
|
|
%b1 = and <2 x i8> %b, <i8 7, i8 7>
|
|
|
|
%b2 = or <2 x i8> %b1, <i8 5, i8 5>
|
|
|
|
%c = icmp sle <2 x i8> %b2, %a2
|
|
|
|
ret <2 x i1> %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @knownbits8(i8 %a, i8 %b) {
|
|
|
|
; CHECK-LABEL: @knownbits8(
|
|
|
|
; CHECK-NEXT: [[A1:%.*]] = and i8 [[A:%.*]], -127
|
|
|
|
; CHECK-NEXT: [[A2:%.*]] = or i8 [[A1]], 4
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and i8 [[B:%.*]], 2
|
|
|
|
; CHECK-NEXT: [[B2:%.*]] = or i8 [[B1]], 5
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[B2]], [[A2]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%a1 = and i8 %a, 133
|
|
|
|
%a2 = or i8 %a1, 4
|
|
|
|
%b1 = and i8 %b, 7
|
|
|
|
%b2 = or i8 %b1, 5
|
|
|
|
%c = icmp sgt i8 %b2, %a2
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
; Make sure InstCombine doesn't try too hard to simplify the icmp and break the abs idiom
|
|
|
|
define i32 @abs_preserve(i32 %x) {
|
|
|
|
; CHECK-LABEL: @abs_preserve(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = shl nsw i32 [[X:%.*]], 1
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A]], 0
|
|
|
|
; CHECK-NEXT: [[NEGA:%.*]] = sub i32 0, [[A]]
|
|
|
|
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[C]], i32 [[NEGA]], i32 [[A]]
|
|
|
|
; CHECK-NEXT: ret i32 [[ABS]]
|
|
|
|
;
|
|
|
|
%a = mul nsw i32 %x, 2
|
|
|
|
%c = icmp sge i32 %a, 0
|
|
|
|
%nega = sub i32 0, %a
|
|
|
|
%abs = select i1 %c, i32 %a, i32 %nega
|
|
|
|
ret i32 %abs
|
|
|
|
}
|
|
|
|
|
|
|
|
; Don't crash by assuming the compared values are integers.
|
|
|
|
|
|
|
|
declare void @llvm.assume(i1)
|
|
|
|
define i1 @PR35794(i32* %a) {
|
|
|
|
; CHECK-LABEL: @PR35794(
|
|
|
|
; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i32* [[A:%.*]], null
|
|
|
|
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
;
|
|
|
|
%cmp = icmp sgt i32* %a, inttoptr (i64 -1 to i32*)
|
|
|
|
%maskcond = icmp eq i32* %a, null
|
|
|
|
tail call void @llvm.assume(i1 %maskcond)
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; Don't crash by assuming the compared values are integers.
|
|
|
|
define <2 x i1> @PR36583(<2 x i8*>) {
|
|
|
|
; CHECK-LABEL: @PR36583(
|
|
|
|
; CHECK-NEXT: [[RES:%.*]] = icmp eq <2 x i8*> [[TMP0:%.*]], zeroinitializer
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[RES]]
|
|
|
|
;
|
|
|
|
%cast = ptrtoint <2 x i8*> %0 to <2 x i64>
|
|
|
|
%res = icmp eq <2 x i64> %cast, zeroinitializer
|
|
|
|
ret <2 x i1> %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; fold (icmp pred (sub (0, X)) C1) for vec type
|
|
|
|
define <2 x i32> @Op1Negated_Vec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @Op1Negated_Vec(
|
|
|
|
; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X]], zeroinitializer
|
|
|
|
; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[SUB]], <2 x i32> [[X]]
|
|
|
|
; CHECK-NEXT: ret <2 x i32> [[COND]]
|
|
|
|
;
|
|
|
|
%sub = sub nsw <2 x i32> zeroinitializer, %x
|
|
|
|
%cmp = icmp sgt <2 x i32> %sub, <i32 -1, i32 -1>
|
|
|
|
%cond = select <2 x i1> %cmp, <2 x i32> %sub, <2 x i32> %x
|
|
|
|
ret <2 x i32> %cond
|
|
|
|
}
|
2020-03-28 03:22:14 +08:00
|
|
|
|
|
|
|
define i1 @signbit_bitcast_fpext(float %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fpext(
|
2020-03-28 04:55:31 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[TMP1]], 0
|
2020-03-28 03:22:14 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%f = fpext float %x to double
|
|
|
|
%b = bitcast double %f to i64
|
|
|
|
%r = icmp slt i64 %b, 0
|
|
|
|
ret i1 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @signbit_bitcast_fpext_vec(<2 x half> %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fpext_vec(
|
2020-03-28 04:55:31 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x half> [[X:%.*]] to <2 x i16>
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i16> [[TMP1]], zeroinitializer
|
2020-03-28 03:22:14 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
|
|
;
|
|
|
|
%f = fpext <2 x half> %x to <2 x float>
|
|
|
|
%b = bitcast <2 x float> %f to <2 x i32>
|
|
|
|
%r = icmp ugt <2 x i32> %b, <i32 2147483647, i32 2147483647>
|
|
|
|
ret <2 x i1> %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @signbit_bitcast_fptrunc(float %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fptrunc(
|
2020-03-28 04:55:31 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[TMP1]], -1
|
2020-03-28 03:22:14 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%f = fptrunc float %x to half
|
|
|
|
%b = bitcast half %f to i16
|
|
|
|
%r = icmp ult i16 %b, 32768
|
|
|
|
ret i1 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @signbit_bitcast_fptrunc_vec(<2 x double> %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fptrunc_vec(
|
2020-03-28 04:55:31 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x double> [[X:%.*]] to <2 x i64>
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i64> [[TMP1]], <i64 -1, i64 -1>
|
2020-03-28 03:22:14 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
|
|
;
|
|
|
|
%f = fptrunc <2 x double> %x to <2 x half>
|
|
|
|
%b = bitcast <2 x half> %f to <2 x i16>
|
|
|
|
%r = icmp sge <2 x i16> %b, zeroinitializer
|
|
|
|
ret <2 x i1> %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @signbit_bitcast_fpext_wrong_cmp(float %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fpext_wrong_cmp(
|
|
|
|
; CHECK-NEXT: [[F:%.*]] = fpext float [[X:%.*]] to double
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = bitcast double [[F]] to i64
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[B]], 1
|
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%f = fpext float %x to double
|
|
|
|
%b = bitcast double %f to i64
|
|
|
|
%r = icmp slt i64 %b, 1
|
|
|
|
ret i1 %r
|
|
|
|
}
|
|
|
|
|
2020-03-28 04:55:31 +08:00
|
|
|
define <4 x i1> @signbit_bitcast_fpext_vec_wrong_bitcast(<2 x half> %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fpext_vec_wrong_bitcast(
|
|
|
|
; CHECK-NEXT: [[F:%.*]] = fpext <2 x half> [[X:%.*]] to <2 x float>
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = bitcast <2 x float> [[F]] to <4 x i16>
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i16> [[B]], <i16 -1, i16 -1, i16 -1, i16 -1>
|
|
|
|
; CHECK-NEXT: ret <4 x i1> [[R]]
|
|
|
|
;
|
|
|
|
%f = fpext <2 x half> %x to <2 x float>
|
|
|
|
%b = bitcast <2 x float> %f to <4 x i16>
|
|
|
|
%r = icmp sgt <4 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1>
|
|
|
|
ret <4 x i1> %r
|
|
|
|
}
|
|
|
|
|
2020-03-28 03:22:14 +08:00
|
|
|
declare void @use_i64(i64)
|
|
|
|
|
|
|
|
define i1 @signbit_bitcast_fpext_extra_use(float %x, i64* %p) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fpext_extra_use(
|
|
|
|
; CHECK-NEXT: [[F:%.*]] = fpext float [[X:%.*]] to double
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = bitcast double [[F]] to i64
|
|
|
|
; CHECK-NEXT: call void @use_i64(i64 [[B]])
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[B]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
|
|
;
|
|
|
|
%f = fpext float %x to double
|
|
|
|
%b = bitcast double %f to i64
|
|
|
|
call void @use_i64(i64 %b)
|
|
|
|
%r = icmp slt i64 %b, 0
|
|
|
|
ret i1 %r
|
|
|
|
}
|
2020-04-07 19:32:52 +08:00
|
|
|
|
|
|
|
define i1 @signbit_bitcast_fpext_ppc_fp128(float %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fpext_ppc_fp128(
|
2020-04-08 20:54:28 +08:00
|
|
|
; CHECK-NEXT: [[S2:%.*]] = fpext float [[X:%.*]] to ppc_fp128
|
|
|
|
; CHECK-NEXT: [[S3:%.*]] = bitcast ppc_fp128 [[S2]] to i128
|
|
|
|
; CHECK-NEXT: [[S4:%.*]] = icmp slt i128 [[S3]], 0
|
2020-04-07 19:32:52 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[S4]]
|
|
|
|
;
|
|
|
|
%s2 = fpext float %x to ppc_fp128
|
|
|
|
%s3 = bitcast ppc_fp128 %s2 to i128
|
|
|
|
%s4 = icmp slt i128 %s3, 0
|
|
|
|
ret i1 %s4
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @signbit_bitcast_fptrunc_ppc_fp128(ppc_fp128 %x) {
|
|
|
|
; CHECK-LABEL: @signbit_bitcast_fptrunc_ppc_fp128(
|
2020-04-11 08:06:17 +08:00
|
|
|
; CHECK-NEXT: [[S2:%.*]] = fptrunc ppc_fp128 [[X:%.*]] to float
|
|
|
|
; CHECK-NEXT: [[S3:%.*]] = bitcast float [[S2]] to i32
|
|
|
|
; CHECK-NEXT: [[S4:%.*]] = icmp slt i32 [[S3]], 0
|
2020-04-07 19:32:52 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[S4]]
|
|
|
|
;
|
|
|
|
%s2 = fptrunc ppc_fp128 %x to float
|
|
|
|
%s3 = bitcast float %s2 to i32
|
|
|
|
%s4 = icmp slt i32 %s3, 0
|
|
|
|
ret i1 %s4
|
|
|
|
}
|