1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[InstSimplify] fold implied cmp with zero (PR35790)

This doesn't handle the more complicated case in the bug report yet:
https://bugs.llvm.org/show_bug.cgi?id=35790

For that, we have to match / look through a cast.

llvm-svn: 322327
This commit is contained in:
Sanjay Patel 2018-01-11 23:27:37 +00:00
parent e57153960c
commit cbad481c69
2 changed files with 50 additions and 24 deletions

View File

@ -1413,6 +1413,42 @@ static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
return nullptr;
}
static Value *simplifyAndOrOfICmpsWithZero(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool IsAnd) {
ICmpInst::Predicate P0 = Cmp0->getPredicate(), P1 = Cmp1->getPredicate();
if (!match(Cmp0->getOperand(1), m_Zero()) ||
!match(Cmp1->getOperand(1), m_Zero()) || P0 != P1)
return nullptr;
if ((IsAnd && P0 != ICmpInst::ICMP_NE) || (!IsAnd && P1 != ICmpInst::ICMP_EQ))
return nullptr;
// We have one of:
// or (icmp eq X, 0), (icmp eq Y, 0)
// and (icmp ne X, 0), (icmp ne Y, 0)
Value *X = Cmp0->getOperand(0);
Value *Y = Cmp1->getOperand(0);
// If one of the compares is a masked version of a (not) null check, then
// that compare implies the other, so we eliminate the other.
// or (icmp eq X, 0), (icmp eq (and X, ?), 0) --> icmp eq (and X, ?), 0
// or (icmp eq X, 0), (icmp eq (and ?, X), 0) --> icmp eq (and ?, X), 0
// and (icmp ne X, 0), (icmp ne (and X, ?), 0) --> icmp ne (and X, ?), 0
// and (icmp ne X, 0), (icmp ne (and ?, X), 0) --> icmp ne (and ?, X), 0
if (match(Y, m_c_And(m_Specific(X), m_Value())))
return Cmp1;
// or (icmp eq (and Y, ?), 0), (icmp eq Y, 0) --> icmp eq (and Y, ?), 0
// or (icmp eq (and ?, Y), 0), (icmp eq Y, 0) --> icmp eq (and ?, Y), 0
// and (icmp ne (and Y, ?), 0), (icmp ne Y, 0) --> icmp ne (and Y, ?), 0
// and (icmp ne (and ?, Y), 0), (icmp ne Y, 0) --> icmp ne (and ?, Y), 0
if (match(X, m_c_And(m_Specific(Y), m_Value())))
return Cmp0;
return nullptr;
}
static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1) {
// (icmp (add V, C0), C1) & (icmp V, C0)
ICmpInst::Predicate Pred0, Pred1;
@ -1473,6 +1509,9 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, true))
return X;
if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, true))
return X;
if (Value *X = simplifyAndOfICmpsWithAdd(Op0, Op1))
return X;
if (Value *X = simplifyAndOfICmpsWithAdd(Op1, Op0))
@ -1541,6 +1580,9 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, false))
return X;
if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, false))
return X;
if (Value *X = simplifyOrOfICmpsWithAdd(Op0, Op1))
return X;
if (Value *X = simplifyOrOfICmpsWithAdd(Op1, Op0))

View File

@ -8,11 +8,9 @@
define i1 @or_cmps_eq_zero_with_mask_commute1(i64 %x, i64 %y) {
; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute1(
; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i64 %x, 0
; CHECK-NEXT: [[SOMEBITS:%.*]] = and i64 %x, %y
; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i64 [[SOMEBITS]], 0
; CHECK-NEXT: [[R:%.*]] = or i1 [[SOMEBITS_ARE_ZERO]], [[ISNULL]]
; CHECK-NEXT: ret i1 [[R]]
; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_ZERO]]
;
%isnull = icmp eq i64 %x, 0
%somebits = and i64 %x, %y
@ -25,11 +23,9 @@ define i1 @or_cmps_eq_zero_with_mask_commute1(i64 %x, i64 %y) {
define <2 x i1> @or_cmps_eq_zero_with_mask_commute2(<2 x i64> %x, <2 x i64> %y) {
; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute2(
; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq <2 x i64> %x, zeroinitializer
; CHECK-NEXT: [[SOMEBITS:%.*]] = and <2 x i64> %x, %y
; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i64> [[SOMEBITS]], zeroinitializer
; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[ISNULL]], [[SOMEBITS_ARE_ZERO]]
; CHECK-NEXT: ret <2 x i1> [[R]]
; CHECK-NEXT: ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
;
%isnull = icmp eq <2 x i64> %x, zeroinitializer
%somebits = and <2 x i64> %x, %y
@ -42,11 +38,9 @@ define <2 x i1> @or_cmps_eq_zero_with_mask_commute2(<2 x i64> %x, <2 x i64> %y)
define i1 @or_cmps_eq_zero_with_mask_commute3(i4 %x, i4 %y) {
; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute3(
; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i4 %x, 0
; CHECK-NEXT: [[SOMEBITS:%.*]] = and i4 %y, %x
; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i4 [[SOMEBITS]], 0
; CHECK-NEXT: [[R:%.*]] = or i1 [[SOMEBITS_ARE_ZERO]], [[ISNULL]]
; CHECK-NEXT: ret i1 [[R]]
; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_ZERO]]
;
%isnull = icmp eq i4 %x, 0
%somebits = and i4 %y, %x
@ -59,11 +53,9 @@ define i1 @or_cmps_eq_zero_with_mask_commute3(i4 %x, i4 %y) {
define <2 x i1> @or_cmps_eq_zero_with_mask_commute4(<2 x i4> %x, <2 x i4> %y) {
; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute4(
; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq <2 x i4> %x, zeroinitializer
; CHECK-NEXT: [[SOMEBITS:%.*]] = and <2 x i4> %y, %x
; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i4> [[SOMEBITS]], zeroinitializer
; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[ISNULL]], [[SOMEBITS_ARE_ZERO]]
; CHECK-NEXT: ret <2 x i1> [[R]]
; CHECK-NEXT: ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
;
%isnull = icmp eq <2 x i4> %x, zeroinitializer
%somebits = and <2 x i4> %y, %x
@ -76,11 +68,9 @@ define <2 x i1> @or_cmps_eq_zero_with_mask_commute4(<2 x i4> %x, <2 x i4> %y) {
define <3 x i1> @and_cmps_eq_zero_with_mask_commute1(<3 x i4> %x, <3 x i4> %y) {
; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute1(
; CHECK-NEXT: [[ISNOTNULL:%.*]] = icmp ne <3 x i4> %x, zeroinitializer
; CHECK-NEXT: [[SOMEBITS:%.*]] = and <3 x i4> %x, %y
; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i4> [[SOMEBITS]], zeroinitializer
; CHECK-NEXT: [[R:%.*]] = and <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]], [[ISNOTNULL]]
; CHECK-NEXT: ret <3 x i1> [[R]]
; CHECK-NEXT: ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
;
%isnotnull = icmp ne <3 x i4> %x, zeroinitializer
%somebits = and <3 x i4> %x, %y
@ -93,11 +83,9 @@ define <3 x i1> @and_cmps_eq_zero_with_mask_commute1(<3 x i4> %x, <3 x i4> %y) {
define i1 @and_cmps_eq_zero_with_mask_commute2(i4 %x, i4 %y) {
; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute2(
; CHECK-NEXT: [[ISNOTNULL:%.*]] = icmp ne i4 %x, 0
; CHECK-NEXT: [[SOMEBITS:%.*]] = and i4 %x, %y
; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i4 [[SOMEBITS]], 0
; CHECK-NEXT: [[R:%.*]] = and i1 [[ISNOTNULL]], [[SOMEBITS_ARE_NOT_ZERO]]
; CHECK-NEXT: ret i1 [[R]]
; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
;
%isnotnull = icmp ne i4 %x, 0
%somebits = and i4 %x, %y
@ -110,11 +98,9 @@ define i1 @and_cmps_eq_zero_with_mask_commute2(i4 %x, i4 %y) {
define <3 x i1> @and_cmps_eq_zero_with_mask_commute3(<3 x i64> %x, <3 x i64> %y) {
; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute3(
; CHECK-NEXT: [[ISNOTNULL:%.*]] = icmp ne <3 x i64> %x, zeroinitializer
; CHECK-NEXT: [[SOMEBITS:%.*]] = and <3 x i64> %y, %x
; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i64> [[SOMEBITS]], zeroinitializer
; CHECK-NEXT: [[R:%.*]] = and <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]], [[ISNOTNULL]]
; CHECK-NEXT: ret <3 x i1> [[R]]
; CHECK-NEXT: ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
;
%isnotnull = icmp ne <3 x i64> %x, zeroinitializer
%somebits = and <3 x i64> %y, %x
@ -127,11 +113,9 @@ define <3 x i1> @and_cmps_eq_zero_with_mask_commute3(<3 x i64> %x, <3 x i64> %y)
define i1 @and_cmps_eq_zero_with_mask_commute4(i64 %x, i64 %y) {
; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute4(
; CHECK-NEXT: [[ISNOTNULL:%.*]] = icmp ne i64 %x, 0
; CHECK-NEXT: [[SOMEBITS:%.*]] = and i64 %y, %x
; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i64 [[SOMEBITS]], 0
; CHECK-NEXT: [[R:%.*]] = and i1 [[ISNOTNULL]], [[SOMEBITS_ARE_NOT_ZERO]]
; CHECK-NEXT: ret i1 [[R]]
; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
;
%isnotnull = icmp ne i64 %x, 0
%somebits = and i64 %y, %x