forked from OSchip/llvm-project
[InstSimplify] simplify FP ops harder with FMF
This is part of the IR sibling for: D75576 (I'm splitting part of the transform as a separate commit to reduce risk. I don't know of any bugs that might be exposed by this improved folding, but it's hard to see those in advance...)
This commit is contained in:
parent
1e686d2689
commit
8ec7158571
|
@ -4603,9 +4603,22 @@ static Constant *propagateNaN(Constant *In) {
|
||||||
/// Perform folds that are common to any floating-point operation. This implies
|
/// Perform folds that are common to any floating-point operation. This implies
|
||||||
/// transforms based on undef/NaN because the operation itself makes no
|
/// transforms based on undef/NaN because the operation itself makes no
|
||||||
/// difference to the result.
|
/// difference to the result.
|
||||||
static Constant *simplifyFPOp(ArrayRef<Value *> Ops) {
|
static Constant *simplifyFPOp(ArrayRef<Value *> Ops,
|
||||||
|
FastMathFlags FMF = FastMathFlags()) {
|
||||||
for (Value *V : Ops) {
|
for (Value *V : Ops) {
|
||||||
if (match(V, m_Undef()) || match(V, m_NaN()))
|
bool IsNan = match(V, m_NaN());
|
||||||
|
bool IsInf = match(V, m_Inf());
|
||||||
|
bool IsUndef = match(V, m_Undef());
|
||||||
|
|
||||||
|
// If this operation has 'nnan' or 'ninf' and at least 1 disallowed operand
|
||||||
|
// (TODO: an undef operand can be chosen to be Nan/Inf), then the result of
|
||||||
|
// this operation is poison. That result can be relaxed to undef.
|
||||||
|
if (FMF.noNaNs() && IsNan)
|
||||||
|
return UndefValue::get(V->getType());
|
||||||
|
if (FMF.noInfs() && IsInf)
|
||||||
|
return UndefValue::get(V->getType());
|
||||||
|
|
||||||
|
if (IsUndef || IsNan)
|
||||||
return propagateNaN(cast<Constant>(V));
|
return propagateNaN(cast<Constant>(V));
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -4618,7 +4631,7 @@ static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
|
||||||
if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q))
|
if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
if (Constant *C = simplifyFPOp({Op0, Op1}))
|
if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
// fadd X, -0 ==> X
|
// fadd X, -0 ==> X
|
||||||
|
@ -4665,7 +4678,7 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
|
||||||
if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q))
|
if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
if (Constant *C = simplifyFPOp({Op0, Op1}))
|
if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
// fsub X, +0 ==> X
|
// fsub X, +0 ==> X
|
||||||
|
@ -4707,7 +4720,7 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
|
||||||
|
|
||||||
static Value *SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
|
static Value *SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
|
||||||
const SimplifyQuery &Q, unsigned MaxRecurse) {
|
const SimplifyQuery &Q, unsigned MaxRecurse) {
|
||||||
if (Constant *C = simplifyFPOp({Op0, Op1}))
|
if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
// fmul X, 1.0 ==> X
|
// fmul X, 1.0 ==> X
|
||||||
|
@ -4774,7 +4787,7 @@ static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
|
||||||
if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q))
|
if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
if (Constant *C = simplifyFPOp({Op0, Op1}))
|
if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
// X / 1.0 -> X
|
// X / 1.0 -> X
|
||||||
|
@ -4819,7 +4832,7 @@ static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
|
||||||
if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q))
|
if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
if (Constant *C = simplifyFPOp({Op0, Op1}))
|
if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
// Unlike fdiv, the result of frem always matches the sign of the dividend.
|
// Unlike fdiv, the result of frem always matches the sign of the dividend.
|
||||||
|
|
|
@ -137,7 +137,7 @@ define <2 x double> @unary_fneg_nan_2(<2 x double> %x) {
|
||||||
|
|
||||||
define float @fadd_nan_op0_nnan(float %x) {
|
define float @fadd_nan_op0_nnan(float %x) {
|
||||||
; CHECK-LABEL: @fadd_nan_op0_nnan(
|
; CHECK-LABEL: @fadd_nan_op0_nnan(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fadd nnan float 0x7FF8000000000000, %x
|
%r = fadd nnan float 0x7FF8000000000000, %x
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -145,7 +145,7 @@ define float @fadd_nan_op0_nnan(float %x) {
|
||||||
|
|
||||||
define float @fadd_nan_op1_fast(float %x) {
|
define float @fadd_nan_op1_fast(float %x) {
|
||||||
; CHECK-LABEL: @fadd_nan_op1_fast(
|
; CHECK-LABEL: @fadd_nan_op1_fast(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fadd fast float %x, 0x7FF8000000000000
|
%r = fadd fast float %x, 0x7FF8000000000000
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -153,7 +153,7 @@ define float @fadd_nan_op1_fast(float %x) {
|
||||||
|
|
||||||
define float @fsub_nan_op0_fast(float %x) {
|
define float @fsub_nan_op0_fast(float %x) {
|
||||||
; CHECK-LABEL: @fsub_nan_op0_fast(
|
; CHECK-LABEL: @fsub_nan_op0_fast(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fsub fast float 0x7FF8000000000000, %x
|
%r = fsub fast float 0x7FF8000000000000, %x
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -161,7 +161,7 @@ define float @fsub_nan_op0_fast(float %x) {
|
||||||
|
|
||||||
define float @fsub_nan_op1_nnan(float %x) {
|
define float @fsub_nan_op1_nnan(float %x) {
|
||||||
; CHECK-LABEL: @fsub_nan_op1_nnan(
|
; CHECK-LABEL: @fsub_nan_op1_nnan(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fsub nnan float %x, 0x7FF8000000000000
|
%r = fsub nnan float %x, 0x7FF8000000000000
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -169,7 +169,7 @@ define float @fsub_nan_op1_nnan(float %x) {
|
||||||
|
|
||||||
define float @fmul_nan_op0_nnan(float %x) {
|
define float @fmul_nan_op0_nnan(float %x) {
|
||||||
; CHECK-LABEL: @fmul_nan_op0_nnan(
|
; CHECK-LABEL: @fmul_nan_op0_nnan(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fmul nnan float 0x7FF8000000000000, %x
|
%r = fmul nnan float 0x7FF8000000000000, %x
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -177,7 +177,7 @@ define float @fmul_nan_op0_nnan(float %x) {
|
||||||
|
|
||||||
define float @fmul_nan_op1_fast(float %x) {
|
define float @fmul_nan_op1_fast(float %x) {
|
||||||
; CHECK-LABEL: @fmul_nan_op1_fast(
|
; CHECK-LABEL: @fmul_nan_op1_fast(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fmul fast float %x, 0x7FF8000000000000
|
%r = fmul fast float %x, 0x7FF8000000000000
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -185,7 +185,7 @@ define float @fmul_nan_op1_fast(float %x) {
|
||||||
|
|
||||||
define float @fdiv_nan_op0_fast(float %x) {
|
define float @fdiv_nan_op0_fast(float %x) {
|
||||||
; CHECK-LABEL: @fdiv_nan_op0_fast(
|
; CHECK-LABEL: @fdiv_nan_op0_fast(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fdiv fast float 0x7FF8000000000000, %x
|
%r = fdiv fast float 0x7FF8000000000000, %x
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -193,7 +193,7 @@ define float @fdiv_nan_op0_fast(float %x) {
|
||||||
|
|
||||||
define float @fdiv_nan_op1_nnan(float %x) {
|
define float @fdiv_nan_op1_nnan(float %x) {
|
||||||
; CHECK-LABEL: @fdiv_nan_op1_nnan(
|
; CHECK-LABEL: @fdiv_nan_op1_nnan(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = fdiv nnan float %x, 0x7FF8000000000000
|
%r = fdiv nnan float %x, 0x7FF8000000000000
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -201,7 +201,7 @@ define float @fdiv_nan_op1_nnan(float %x) {
|
||||||
|
|
||||||
define float @frem_nan_op0_nnan(float %x) {
|
define float @frem_nan_op0_nnan(float %x) {
|
||||||
; CHECK-LABEL: @frem_nan_op0_nnan(
|
; CHECK-LABEL: @frem_nan_op0_nnan(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = frem nnan float 0x7FF8000000000000, %x
|
%r = frem nnan float 0x7FF8000000000000, %x
|
||||||
ret float %r
|
ret float %r
|
||||||
|
@ -209,7 +209,7 @@ define float @frem_nan_op0_nnan(float %x) {
|
||||||
|
|
||||||
define float @frem_nan_op1_fast(float %x) {
|
define float @frem_nan_op1_fast(float %x) {
|
||||||
; CHECK-LABEL: @frem_nan_op1_fast(
|
; CHECK-LABEL: @frem_nan_op1_fast(
|
||||||
; CHECK-NEXT: ret float 0x7FF8000000000000
|
; CHECK-NEXT: ret float undef
|
||||||
;
|
;
|
||||||
%r = frem fast float %x, 0x7FF8000000000000
|
%r = frem fast float %x, 0x7FF8000000000000
|
||||||
ret float %r
|
ret float %r
|
||||||
|
|
|
@ -179,23 +179,17 @@ define double @fadd_ninf_nan_op1(double %x) {
|
||||||
ret double %r
|
ret double %r
|
||||||
}
|
}
|
||||||
|
|
||||||
; TODO: Should simplify to undef.
|
|
||||||
|
|
||||||
define double @fdiv_ninf_inf_op0(double %x) {
|
define double @fdiv_ninf_inf_op0(double %x) {
|
||||||
; CHECK-LABEL: @fdiv_ninf_inf_op0(
|
; CHECK-LABEL: @fdiv_ninf_inf_op0(
|
||||||
; CHECK-NEXT: [[R:%.*]] = fdiv ninf double 0x7FF0000000000000, [[X:%.*]]
|
; CHECK-NEXT: ret double undef
|
||||||
; CHECK-NEXT: ret double [[R]]
|
|
||||||
;
|
;
|
||||||
%r = fdiv ninf double 0x7ff0000000000000, %x
|
%r = fdiv ninf double 0x7ff0000000000000, %x
|
||||||
ret double %r
|
ret double %r
|
||||||
}
|
}
|
||||||
|
|
||||||
; TODO: Should simplify to undef.
|
|
||||||
|
|
||||||
define double @fadd_ninf_inf_op1(double %x) {
|
define double @fadd_ninf_inf_op1(double %x) {
|
||||||
; CHECK-LABEL: @fadd_ninf_inf_op1(
|
; CHECK-LABEL: @fadd_ninf_inf_op1(
|
||||||
; CHECK-NEXT: [[R:%.*]] = fadd ninf double [[X:%.*]], 0xFFF0000000000000
|
; CHECK-NEXT: ret double undef
|
||||||
; CHECK-NEXT: ret double [[R]]
|
|
||||||
;
|
;
|
||||||
%r = fadd ninf double %x, 0xfff0000000000000
|
%r = fadd ninf double %x, 0xfff0000000000000
|
||||||
ret double %r
|
ret double %r
|
||||||
|
|
Loading…
Reference in New Issue