mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
[InstSimplify] fold and/or of fcmp ord/uno when operand is known nnan
The 'ord' and 'uno' predicates have a logic operation for NAN built into their definitions: FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) So we can simplify patterns like this: (fcmp ord (known NNAN), X) && (fcmp ord X, Y) --> fcmp ord X, Y (fcmp uno (known NNAN), X) || (fcmp uno X, Y) --> fcmp uno X, Y It might be better to split this into (X uno 0) | (Y uno 0) as a canonicalization, but that would be another patch. Differential Revision: https://reviews.llvm.org/D40130 llvm-svn: 318627
This commit is contained in:
parent
0ccefc582c
commit
05aab75248
@ -1550,7 +1550,44 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Value *simplifyAndOrOfICmps(Value *Op0, Value *Op1, bool IsAnd) {
|
||||
static Value *simplifyAndOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd) {
|
||||
Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
|
||||
Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
|
||||
if (LHS0->getType() != RHS0->getType())
|
||||
return nullptr;
|
||||
|
||||
FCmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
|
||||
if ((PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD && IsAnd) ||
|
||||
(PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO && !IsAnd)) {
|
||||
// (fcmp ord NNAN, X) & (fcmp ord X, Y) --> fcmp ord X, Y
|
||||
// (fcmp ord NNAN, X) & (fcmp ord Y, X) --> fcmp ord Y, X
|
||||
// (fcmp ord X, NNAN) & (fcmp ord X, Y) --> fcmp ord X, Y
|
||||
// (fcmp ord X, NNAN) & (fcmp ord Y, X) --> fcmp ord Y, X
|
||||
// (fcmp uno NNAN, X) | (fcmp uno X, Y) --> fcmp uno X, Y
|
||||
// (fcmp uno NNAN, X) | (fcmp uno Y, X) --> fcmp uno Y, X
|
||||
// (fcmp uno X, NNAN) | (fcmp uno X, Y) --> fcmp uno X, Y
|
||||
// (fcmp uno X, NNAN) | (fcmp uno Y, X) --> fcmp uno Y, X
|
||||
if ((isKnownNeverNaN(LHS0) && (LHS1 == RHS0 || LHS1 == RHS1)) ||
|
||||
(isKnownNeverNaN(LHS1) && (LHS0 == RHS0 || LHS0 == RHS1)))
|
||||
return RHS;
|
||||
|
||||
// (fcmp ord X, Y) & (fcmp ord NNAN, X) --> fcmp ord X, Y
|
||||
// (fcmp ord Y, X) & (fcmp ord NNAN, X) --> fcmp ord Y, X
|
||||
// (fcmp ord X, Y) & (fcmp ord X, NNAN) --> fcmp ord X, Y
|
||||
// (fcmp ord Y, X) & (fcmp ord X, NNAN) --> fcmp ord Y, X
|
||||
// (fcmp uno X, Y) | (fcmp uno NNAN, X) --> fcmp uno X, Y
|
||||
// (fcmp uno Y, X) | (fcmp uno NNAN, X) --> fcmp uno Y, X
|
||||
// (fcmp uno X, Y) | (fcmp uno X, NNAN) --> fcmp uno X, Y
|
||||
// (fcmp uno Y, X) | (fcmp uno X, NNAN) --> fcmp uno Y, X
|
||||
if ((isKnownNeverNaN(RHS0) && (RHS1 == LHS0 || RHS1 == LHS1)) ||
|
||||
(isKnownNeverNaN(RHS1) && (RHS0 == LHS0 || RHS0 == LHS1)))
|
||||
return LHS;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Value *simplifyAndOrOfCmps(Value *Op0, Value *Op1, bool IsAnd) {
|
||||
// Look through casts of the 'and' operands to find compares.
|
||||
auto *Cast0 = dyn_cast<CastInst>(Op0);
|
||||
auto *Cast1 = dyn_cast<CastInst>(Op1);
|
||||
@ -1560,13 +1597,18 @@ static Value *simplifyAndOrOfICmps(Value *Op0, Value *Op1, bool IsAnd) {
|
||||
Op1 = Cast1->getOperand(0);
|
||||
}
|
||||
|
||||
auto *Cmp0 = dyn_cast<ICmpInst>(Op0);
|
||||
auto *Cmp1 = dyn_cast<ICmpInst>(Op1);
|
||||
if (!Cmp0 || !Cmp1)
|
||||
return nullptr;
|
||||
Value *V = nullptr;
|
||||
auto *ICmp0 = dyn_cast<ICmpInst>(Op0);
|
||||
auto *ICmp1 = dyn_cast<ICmpInst>(Op1);
|
||||
if (ICmp0 && ICmp1)
|
||||
V = IsAnd ? simplifyAndOfICmps(ICmp0, ICmp1) :
|
||||
simplifyOrOfICmps(ICmp0, ICmp1);
|
||||
|
||||
auto *FCmp0 = dyn_cast<FCmpInst>(Op0);
|
||||
auto *FCmp1 = dyn_cast<FCmpInst>(Op1);
|
||||
if (FCmp0 && FCmp1)
|
||||
V = simplifyAndOrOfFCmps(FCmp0, FCmp1, IsAnd);
|
||||
|
||||
Value *V =
|
||||
IsAnd ? simplifyAndOfICmps(Cmp0, Cmp1) : simplifyOrOfICmps(Cmp0, Cmp1);
|
||||
if (!V)
|
||||
return nullptr;
|
||||
if (!Cast0)
|
||||
@ -1645,7 +1687,7 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
|
||||
return Op1;
|
||||
}
|
||||
|
||||
if (Value *V = simplifyAndOrOfICmps(Op0, Op1, true))
|
||||
if (Value *V = simplifyAndOrOfCmps(Op0, Op1, true))
|
||||
return V;
|
||||
|
||||
// Try some generic simplifications for associative operations.
|
||||
@ -1766,7 +1808,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
|
||||
match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B)))))
|
||||
return Op0;
|
||||
|
||||
if (Value *V = simplifyAndOrOfICmps(Op0, Op1, false))
|
||||
if (Value *V = simplifyAndOrOfCmps(Op0, Op1, false))
|
||||
return V;
|
||||
|
||||
// Try some generic simplifications for associative operations.
|
||||
|
@ -5,10 +5,8 @@
|
||||
|
||||
define i1 @ord1(float %x, float %y) {
|
||||
; CHECK-LABEL: @ord1(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float 0.000000e+00, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord float %x, %y
|
||||
; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp ord float 0.0, %x
|
||||
%cmp2 = fcmp ord float %x, %y
|
||||
@ -18,10 +16,8 @@ define i1 @ord1(float %x, float %y) {
|
||||
|
||||
define i1 @ord2(double %x, double %y) {
|
||||
; CHECK-LABEL: @ord2(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord double 4.200000e+01, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord double %y, %x
|
||||
; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp ord double 42.0, %x
|
||||
%cmp2 = fcmp ord double %y, %x
|
||||
@ -31,10 +27,8 @@ define i1 @ord2(double %x, double %y) {
|
||||
|
||||
define <2 x i1> @ord3(<2 x float> %x, <2 x float> %y) {
|
||||
; CHECK-LABEL: @ord3(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <2 x float> %x, zeroinitializer
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <2 x float> %x, %y
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp ord <2 x float> %x, zeroinitializer
|
||||
%cmp2 = fcmp ord <2 x float> %x, %y
|
||||
@ -44,10 +38,8 @@ define <2 x i1> @ord3(<2 x float> %x, <2 x float> %y) {
|
||||
|
||||
define <2 x i1> @ord4(<2 x double> %x, <2 x double> %y) {
|
||||
; CHECK-LABEL: @ord4(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <2 x double> %x, <double 4.200000e+01, double 4.200000e+01>
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <2 x double> %y, %x
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp ord <2 x double> %x, <double 42.0, double 42.0>
|
||||
%cmp2 = fcmp ord <2 x double> %y, %x
|
||||
@ -57,11 +49,8 @@ define <2 x i1> @ord4(<2 x double> %x, <2 x double> %y) {
|
||||
|
||||
define i1 @ord5(float %x, float %y) {
|
||||
; CHECK-LABEL: @ord5(
|
||||
; CHECK-NEXT: [[NNAN:%.*]] = fdiv nnan float %x, %y
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float %x, %y
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord float [[NNAN]], %x
|
||||
; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP1]]
|
||||
;
|
||||
%nnan = fdiv nnan float %x, %y
|
||||
%cmp1 = fcmp ord float %x, %y
|
||||
@ -73,9 +62,7 @@ define i1 @ord5(float %x, float %y) {
|
||||
define i1 @ord6(double %x, double %y) {
|
||||
; CHECK-LABEL: @ord6(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord double %y, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord double 4.200000e+01, %x
|
||||
; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP1]]
|
||||
;
|
||||
%cmp1 = fcmp ord double %y, %x
|
||||
%cmp2 = fcmp ord double 42.0, %x
|
||||
@ -86,9 +73,7 @@ define i1 @ord6(double %x, double %y) {
|
||||
define <2 x i1> @ord7(<2 x float> %x, <2 x float> %y) {
|
||||
; CHECK-LABEL: @ord7(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <2 x float> %x, %y
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <2 x float> %x, zeroinitializer
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
||||
;
|
||||
%cmp1 = fcmp ord <2 x float> %x, %y
|
||||
%cmp2 = fcmp ord <2 x float> %x, zeroinitializer
|
||||
@ -99,9 +84,7 @@ define <2 x i1> @ord7(<2 x float> %x, <2 x float> %y) {
|
||||
define <2 x i1> @ord8(<2 x double> %x, <2 x double> %y) {
|
||||
; CHECK-LABEL: @ord8(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <2 x double> %y, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <2 x double> %x, <double 0.000000e+00, double 4.200000e+01>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
||||
;
|
||||
%cmp1 = fcmp ord <2 x double> %y, %x
|
||||
%cmp2 = fcmp ord <2 x double> %x, <double 0.0, double 42.0>
|
||||
@ -111,10 +94,8 @@ define <2 x i1> @ord8(<2 x double> %x, <2 x double> %y) {
|
||||
|
||||
define i1 @uno1(float %x, float %y) {
|
||||
; CHECK-LABEL: @uno1(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno float 0.000000e+00, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno float %x, %y
|
||||
; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp uno float 0.0, %x
|
||||
%cmp2 = fcmp uno float %x, %y
|
||||
@ -124,10 +105,8 @@ define i1 @uno1(float %x, float %y) {
|
||||
|
||||
define i1 @uno2(double %x, double %y) {
|
||||
; CHECK-LABEL: @uno2(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno double 4.200000e+01, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno double %y, %x
|
||||
; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp uno double 42.0, %x
|
||||
%cmp2 = fcmp uno double %y, %x
|
||||
@ -137,10 +116,8 @@ define i1 @uno2(double %x, double %y) {
|
||||
|
||||
define <2 x i1> @uno3(<2 x float> %x, <2 x float> %y) {
|
||||
; CHECK-LABEL: @uno3(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x float> %x, zeroinitializer
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <2 x float> %x, %y
|
||||
; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp uno <2 x float> %x, zeroinitializer
|
||||
%cmp2 = fcmp uno <2 x float> %x, %y
|
||||
@ -150,10 +127,8 @@ define <2 x i1> @uno3(<2 x float> %x, <2 x float> %y) {
|
||||
|
||||
define <2 x i1> @uno4(<2 x double> %x, <2 x double> %y) {
|
||||
; CHECK-LABEL: @uno4(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x double> %x, <double 4.200000e+01, double 4.200000e+01>
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <2 x double> %y, %x
|
||||
; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
||||
;
|
||||
%cmp1 = fcmp uno <2 x double> %x, <double 42.0, double 42.0>
|
||||
%cmp2 = fcmp uno <2 x double> %y, %x
|
||||
@ -164,9 +139,7 @@ define <2 x i1> @uno4(<2 x double> %x, <2 x double> %y) {
|
||||
define i1 @uno5(float %x, float %y) {
|
||||
; CHECK-LABEL: @uno5(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno float %x, %y
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno float 0.000000e+00, %x
|
||||
; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP1]]
|
||||
;
|
||||
%cmp1 = fcmp uno float %x, %y
|
||||
%cmp2 = fcmp uno float 0.0, %x
|
||||
@ -177,9 +150,7 @@ define i1 @uno5(float %x, float %y) {
|
||||
define i1 @uno6(double %x, double %y) {
|
||||
; CHECK-LABEL: @uno6(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno double %y, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno double 4.200000e+01, %x
|
||||
; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
; CHECK-NEXT: ret i1 [[CMP1]]
|
||||
;
|
||||
%cmp1 = fcmp uno double %y, %x
|
||||
%cmp2 = fcmp uno double 42.0, %x
|
||||
@ -189,11 +160,8 @@ define i1 @uno6(double %x, double %y) {
|
||||
|
||||
define <2 x i1> @uno7(<2 x float> %x, <2 x float> %y) {
|
||||
; CHECK-LABEL: @uno7(
|
||||
; CHECK-NEXT: [[NNAN:%.*]] = fdiv nnan <2 x float> %x, %y
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x float> %x, %y
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <2 x float> %x, [[NNAN]]
|
||||
; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
||||
;
|
||||
%nnan = fdiv nnan <2 x float> %x, %y
|
||||
%cmp1 = fcmp uno <2 x float> %x, %y
|
||||
@ -205,9 +173,7 @@ define <2 x i1> @uno7(<2 x float> %x, <2 x float> %y) {
|
||||
define <2 x i1> @uno8(<2 x double> %x, <2 x double> %y) {
|
||||
; CHECK-LABEL: @uno8(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x double> %y, %x
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <2 x double> %x, <double 0x7FF0000000000000, double 4.200000e+01>
|
||||
; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
||||
;
|
||||
%cmp1 = fcmp uno <2 x double> %y, %x
|
||||
%cmp2 = fcmp uno <2 x double> %x, <double 0x7ff0000000000000, double 42.0>
|
||||
|
Loading…
Reference in New Issue
Block a user