1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00

[InstCombine] loosen FP 0.0 constraint for fcmp+select substitution

It looks like we correctly removed edge cases with 0.0 from D50714,
but we were a bit conservative because getBinOpIdentity() doesn't
distinguish between +0.0 and -0.0 and 'nsz' is effectively always
true for fcmp (see discussion in:
https://bugs.llvm.org/show_bug.cgi?id=38086

Without this change, we would get regressions by canonicalizing
to +0.0 in all fcmp, and that's a step towards solving:
https://bugs.llvm.org/show_bug.cgi?id=39475

llvm-svn: 346143
This commit is contained in:
Sanjay Patel 2018-11-05 16:50:44 +00:00
parent 8b43ef1240
commit 51ca26e748
2 changed files with 27 additions and 25 deletions

View File

@ -75,13 +75,22 @@ static Instruction *foldSelectBinOpIdentity(SelectInst &Sel,
else
return nullptr;
// A select operand must be a binop, and the compare constant must be the
// identity constant for that binop.
// A select operand must be a binop.
BinaryOperator *BO;
if (!match(Sel.getOperand(IsEq ? 1 : 2), m_BinOp(BO)) ||
ConstantExpr::getBinOpIdentity(BO->getOpcode(), BO->getType(), true) != C)
if (!match(Sel.getOperand(IsEq ? 1 : 2), m_BinOp(BO)))
return nullptr;
// The compare constant must be the identity constant for that binop.
// If this a floating-point compare with 0.0, any zero constant will do.
Type *Ty = BO->getType();
Constant *IdC = ConstantExpr::getBinOpIdentity(BO->getOpcode(), Ty, true);
if (IdC != C) {
if (!IdC || !CmpInst::isFPPredicate(Pred))
return nullptr;
if (!match(IdC, m_AnyZeroFP()) || !match(C, m_AnyZeroFP()))
return nullptr;
}
// Last, match the compare variable operand with a binop operand.
Value *Y;
if (!BO->isCommutative() && !match(BO, m_BinOp(m_Value(Y), m_Specific(X))))

View File

@ -152,13 +152,12 @@ define float @select_fadd_fcmp(float %x, float %y, float %z) {
ret float %C
}
; TODO: This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
; This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
define float @select_fadd_fcmp_poszero(float %x, float %y, float %z) {
; CHECK-LABEL: @select_fadd_fcmp_poszero(
; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[B:%.*]] = fadd nsz float [[Z:%.*]], [[X]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Z:%.*]], float [[Y:%.*]]
; CHECK-NEXT: ret float [[C]]
;
%A = fcmp oeq float %x, 0.0
@ -181,14 +180,13 @@ define float @select_fadd_fcmp_2(float %x, float %y, float %v) {
ret float %C
}
; TODO: This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
; This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
define float @select_fadd_fcmp_2_poszero(float %x, float %y, float %v) {
; CHECK-LABEL: @select_fadd_fcmp_2_poszero(
; CHECK-NEXT: [[A:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[Z:%.*]] = fadd float [[V:%.*]], 0.000000e+00
; CHECK-NEXT: [[B:%.*]] = fadd float [[Z]], [[X]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float [[B]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float [[Z]]
; CHECK-NEXT: ret float [[C]]
;
%A = fcmp une float %x, 0.0
@ -210,13 +208,12 @@ define float @select_fadd_fcmp_3(float %x, float %y) {
ret float %C
}
; TODO: This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
; This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
define float @select_fadd_fcmp_3_poszero(float %x, float %y) {
; CHECK-LABEL: @select_fadd_fcmp_3_poszero(
; CHECK-NEXT: [[A:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[B:%.*]] = fadd float [[X]], 6.000000e+00
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float [[B]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float 6.000000e+00
; CHECK-NEXT: ret float [[C]]
;
%A = fcmp une float %x, 0.0
@ -237,13 +234,12 @@ define float @select_fadd_fcmp_4(float %x, float %y, float %z) {
ret float %C
}
; TODO: This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
; This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
define float @select_fadd_fcmp_4_poszero(float %x, float %y, float %z) {
; CHECK-LABEL: @select_fadd_fcmp_4_poszero(
; CHECK-NEXT: [[A:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[B:%.*]] = fadd nsz float [[Z:%.*]], [[X]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float [[B]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float [[Z:%.*]]
; CHECK-NEXT: ret float [[C]]
;
%A = fcmp une float %x, 0.0
@ -266,14 +262,13 @@ define float @select_fadd_fcmp_5(float %x, float %y, float %v) {
ret float %C
}
; TODO: This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
; This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
define float @select_fadd_fcmp_5_poszero(float %x, float %y, float %v) {
; CHECK-LABEL: @select_fadd_fcmp_5_poszero(
; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[Z:%.*]] = fadd float [[V:%.*]], 0.000000e+00
; CHECK-NEXT: [[B:%.*]] = fadd float [[Z]], [[X]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Z]], float [[Y:%.*]]
; CHECK-NEXT: ret float [[C]]
;
%A = fcmp oeq float %x, 0.0
@ -295,13 +290,12 @@ define float @select_fadd_fcmp_6(float %x, float %y, float %z) {
ret float %C
}
; TODO: This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
; This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
define float @select_fadd_fcmp_6_poszero(float %x, float %y, float %z) {
; CHECK-LABEL: @select_fadd_fcmp_6_poszero(
; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[B:%.*]] = fadd float [[X]], 6.000000e+00
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float 6.000000e+00, float [[Y:%.*]]
; CHECK-NEXT: ret float [[C]]
;
%A = fcmp oeq float %x, 0.0
@ -334,13 +328,12 @@ define float @select_fsub_fcmp(float %x, float %y, float %z) {
ret float %C
}
; TODO: This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
; This is logically equivalent to the previous test - fcmp ignores the sign of 0.0.
define float @select_fsub_fcmp_negzero(float %x, float %y, float %z) {
; CHECK-LABEL: @select_fsub_fcmp_negzero(
; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], -0.000000e+00
; CHECK-NEXT: [[B:%.*]] = fsub nsz float [[Z:%.*]], [[X]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]]
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Z:%.*]], float [[Y:%.*]]
; CHECK-NEXT: ret float [[C]]
;
%A = fcmp oeq float %x, -0.0