Skip to content

Commit

Permalink
[InstSimplify] fp_binop X, NaN --> NaN
Browse files Browse the repository at this point in the history
We propagate the existing NaN value when possible.

Differential Revision: https://reviews.llvm.org/D44521

llvm-svn: 328140
  • Loading branch information
rotateright committed Mar 21, 2018
1 parent f2ab05c commit e235942
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 62 deletions.
42 changes: 32 additions & 10 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Expand Up @@ -4163,15 +4163,37 @@ Value *llvm::SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
return ::SimplifyShuffleVectorInst(Op0, Op1, Mask, RetTy, Q, RecursionLimit);
}

static Constant *propagateNaN(Constant *In) {
// If the input is a vector with undef elements, just return a default NaN.
if (!In->isNaN())
return ConstantFP::getNaN(In->getType());

// Propagate the existing NaN constant when possible.
// TODO: Should we quiet a signaling NaN?
return In;
}

static Constant *simplifyFPBinop(Value *Op0, Value *Op1) {
if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1))
return ConstantFP::getNaN(Op0->getType());

if (match(Op0, m_NaN()))
return propagateNaN(cast<Constant>(Op0));
if (match(Op1, m_NaN()))
return propagateNaN(cast<Constant>(Op1));

return nullptr;
}

/// Given operands for an FAdd, see if we can fold the result. If not, this
/// returns null.
static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
const SimplifyQuery &Q, unsigned MaxRecurse) {
if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q))
return C;

if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1))
return ConstantFP::getNaN(Op0->getType());
if (Constant *C = simplifyFPBinop(Op0, Op1))
return C;

// fadd X, -0 ==> X
if (match(Op1, m_NegZero()))
Expand Down Expand Up @@ -4203,8 +4225,8 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q))
return C;

if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1))
return ConstantFP::getNaN(Op0->getType());
if (Constant *C = simplifyFPBinop(Op0, Op1))
return C;

// fsub X, 0 ==> X
if (match(Op1, m_Zero()))
Expand Down Expand Up @@ -4238,8 +4260,8 @@ static Value *SimplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FMul, Op0, Op1, Q))
return C;

if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1))
return ConstantFP::getNaN(Op0->getType());
if (Constant *C = simplifyFPBinop(Op0, Op1))
return C;

// fmul X, 1.0 ==> X
if (match(Op1, m_FPOne()))
Expand Down Expand Up @@ -4282,8 +4304,8 @@ static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q))
return C;

if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1))
return ConstantFP::getNaN(Op0->getType());
if (Constant *C = simplifyFPBinop(Op0, Op1))
return C;

// X / 1.0 -> X
if (match(Op1, m_FPOne()))
Expand Down Expand Up @@ -4329,8 +4351,8 @@ static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q))
return C;

if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1))
return ConstantFP::getNaN(Op0->getType());
if (Constant *C = simplifyFPBinop(Op0, Op1))
return C;

// Unlike fdiv, the result of frem always matches the sign of the dividend.
// The constant match may include undef elements in a vector, so return a full
Expand Down
21 changes: 9 additions & 12 deletions llvm/test/CodeGen/AMDGPU/imm.ll
Expand Up @@ -501,32 +501,29 @@ define amdgpu_kernel void @add_inline_imm_16_f64(double addrspace(1)* %out, doub
}

; GCN-LABEL: {{^}}add_inline_imm_neg_1_f64:
; SI: s_load_dwordx2 [[VAL:s\[[0-9]+:[0-9]+\]]], {{s\[[0-9]+:[0-9]+\]}}, 0xb
; VI: s_load_dwordx2 [[VAL:s\[[0-9]+:[0-9]+\]]], {{s\[[0-9]+:[0-9]+\]}}, 0x2c
; GCN: v_add_f64 [[REG:v\[[0-9]+:[0-9]+\]]], [[VAL]], -1
; GCN: buffer_store_dwordx2 [[REG]]
; GCN: v_mov_b32_e32 v0, -1
; GCN: v_mov_b32_e32 v1, v0
; GCN: buffer_store_dwordx2 v[0:1]
define amdgpu_kernel void @add_inline_imm_neg_1_f64(double addrspace(1)* %out, double %x) {
%y = fadd double %x, 0xffffffffffffffff
store double %y, double addrspace(1)* %out
ret void
}

; GCN-LABEL: {{^}}add_inline_imm_neg_2_f64:
; SI: s_load_dwordx2 [[VAL:s\[[0-9]+:[0-9]+\]]], {{s\[[0-9]+:[0-9]+\]}}, 0xb
; VI: s_load_dwordx2 [[VAL:s\[[0-9]+:[0-9]+\]]], {{s\[[0-9]+:[0-9]+\]}}, 0x2c
; GCN: v_add_f64 [[REG:v\[[0-9]+:[0-9]+\]]], [[VAL]], -2
; GCN: buffer_store_dwordx2 [[REG]]
; GCN: v_mov_b32_e32 v0, -2
; GCN: v_mov_b32_e32 v1, -1
; GCN: buffer_store_dwordx2 v[0:1]
define amdgpu_kernel void @add_inline_imm_neg_2_f64(double addrspace(1)* %out, double %x) {
%y = fadd double %x, 0xfffffffffffffffe
store double %y, double addrspace(1)* %out
ret void
}

; GCN-LABEL: {{^}}add_inline_imm_neg_16_f64:
; SI: s_load_dwordx2 [[VAL:s\[[0-9]+:[0-9]+\]]], {{s\[[0-9]+:[0-9]+\]}}, 0xb
; VI: s_load_dwordx2 [[VAL:s\[[0-9]+:[0-9]+\]]], {{s\[[0-9]+:[0-9]+\]}}, 0x2c
; GCN: v_add_f64 [[REG:v\[[0-9]+:[0-9]+\]]], [[VAL]], -16
; GCN: buffer_store_dwordx2 [[REG]]
; GCN: v_mov_b32_e32 v0, -16
; GCN: v_mov_b32_e32 v1, -1
; GCN: buffer_store_dwordx2 v[0:1]
define amdgpu_kernel void @add_inline_imm_neg_16_f64(double addrspace(1)* %out, double %x) {
%y = fadd double %x, 0xfffffffffffffff0
store double %y, double addrspace(1)* %out
Expand Down
60 changes: 20 additions & 40 deletions llvm/test/Transforms/InstSimplify/fp-nan.ll
Expand Up @@ -5,8 +5,7 @@

define double @fadd_nan_op0(double %x) {
; CHECK-LABEL: @fadd_nan_op0(
; CHECK-NEXT: [[R:%.*]] = fadd double 0x7FF8000000000000, [[X:%.*]]
; CHECK-NEXT: ret double [[R]]
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fadd double 0x7FF8000000000000, %x
ret double %r
Expand All @@ -16,8 +15,7 @@ define double @fadd_nan_op0(double %x) {

define double @fadd_nan_op1(double %x) {
; CHECK-LABEL: @fadd_nan_op1(
; CHECK-NEXT: [[R:%.*]] = fadd double [[X:%.*]], 0xFFF8000000000000
; CHECK-NEXT: ret double [[R]]
; CHECK-NEXT: ret double 0xFFF8000000000000
;
%r = fadd double %x, 0xFFF8000000000000
ret double %r
Expand All @@ -27,8 +25,7 @@ define double @fadd_nan_op1(double %x) {

define float @fsub_nan_op0(float %x) {
; CHECK-LABEL: @fsub_nan_op0(
; CHECK-NEXT: [[R:%.*]] = fsub float 0x7FFFFF0000000000, [[X:%.*]]
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FFFFF0000000000
;
%r = fsub float 0x7FFFFF0000000000, %x
ret float %r
Expand All @@ -38,8 +35,7 @@ define float @fsub_nan_op0(float %x) {

define float @fsub_nan_op1(float %x) {
; CHECK-LABEL: @fsub_nan_op1(
; CHECK-NEXT: [[R:%.*]] = fsub float [[X:%.*]], 0x7FF1000000000000
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF1000000000000
;
%r = fsub float %x, 0x7FF1000000000000
ret float %r
Expand All @@ -49,8 +45,7 @@ define float @fsub_nan_op1(float %x) {

define double @fmul_nan_op0(double %x) {
; CHECK-LABEL: @fmul_nan_op0(
; CHECK-NEXT: [[R:%.*]] = fmul double 0xFFF0000000000001, [[X:%.*]]
; CHECK-NEXT: ret double [[R]]
; CHECK-NEXT: ret double 0xFFF0000000000001
;
%r = fmul double 0xFFF0000000000001, %x
ret double %r
Expand All @@ -60,8 +55,7 @@ define double @fmul_nan_op0(double %x) {

define <2 x float> @fmul_nan_op1(<2 x float> %x) {
; CHECK-LABEL: @fmul_nan_op1(
; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[X:%.*]], <float 0x7FF8000000000000, float 0x7FF8000000000000>
; CHECK-NEXT: ret <2 x float> [[R]]
; CHECK-NEXT: ret <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
;
%r = fmul <2 x float> %x, <float 0x7FF8000000000000, float 0x7FF8000000000000>
ret <2 x float> %r
Expand All @@ -71,8 +65,7 @@ define <2 x float> @fmul_nan_op1(<2 x float> %x) {

define <2 x double> @fdiv_nan_op0(<2 x double> %x) {
; CHECK-LABEL: @fdiv_nan_op0(
; CHECK-NEXT: [[R:%.*]] = fdiv <2 x double> <double 0xFFF800000000000F, double 0xFFF800000000000F>, [[X:%.*]]
; CHECK-NEXT: ret <2 x double> [[R]]
; CHECK-NEXT: ret <2 x double> <double 0xFFF800000000000F, double 0xFFF800000000000F>
;
%r = fdiv <2 x double> <double 0xFFF800000000000F, double 0xFFF800000000000F>, %x
ret <2 x double> %r
Expand All @@ -82,8 +75,7 @@ define <2 x double> @fdiv_nan_op0(<2 x double> %x) {

define <2 x half> @fdiv_nan_op1(<2 x half> %x) {
; CHECK-LABEL: @fdiv_nan_op1(
; CHECK-NEXT: [[R:%.*]] = fdiv <2 x half> [[X:%.*]], <half 0xH7FFF, half 0xHFF00>
; CHECK-NEXT: ret <2 x half> [[R]]
; CHECK-NEXT: ret <2 x half> <half 0xH7FFF, half 0xHFF00>
;
%r = fdiv <2 x half> %x, <half 0xH7FFF, half 0xHFF00>
ret <2 x half> %r
Expand All @@ -93,17 +85,15 @@ define <2 x half> @fdiv_nan_op1(<2 x half> %x) {

define <2 x double> @frem_nan_op0(<2 x double> %x) {
; CHECK-LABEL: @frem_nan_op0(
; CHECK-NEXT: [[R:%.*]] = frem <2 x double> <double 0xFFFF000000000000, double undef>, [[X:%.*]]
; CHECK-NEXT: ret <2 x double> [[R]]
; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
;
%r = frem <2 x double> <double 0xFFFF000000000000, double undef>, %x
ret <2 x double> %r
}

define float @frem_nan_op1(float %x) {
; CHECK-LABEL: @frem_nan_op1(
; CHECK-NEXT: [[R:%.*]] = frem float [[X:%.*]], 0x7FF8000000000000
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = frem float %x, 0x7FF8000000000000
ret float %r
Expand Down Expand Up @@ -131,89 +121,79 @@ define <2 x double> @fneg_nan_2(<2 x double> %x) {

define float @fadd_nan_op0_nnan(float %x) {
; CHECK-LABEL: @fadd_nan_op0_nnan(
; CHECK-NEXT: [[R:%.*]] = fadd nnan float 0x7FF8000000000000, [[X:%.*]]
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fadd nnan float 0x7FF8000000000000, %x
ret float %r
}

define float @fadd_nan_op1_fast(float %x) {
; CHECK-LABEL: @fadd_nan_op1_fast(
; CHECK-NEXT: [[R:%.*]] = fadd fast float [[X:%.*]], 0x7FF8000000000000
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fadd fast float %x, 0x7FF8000000000000
ret float %r
}

define float @fsub_nan_op0_fast(float %x) {
; CHECK-LABEL: @fsub_nan_op0_fast(
; CHECK-NEXT: [[R:%.*]] = fsub fast float 0x7FF8000000000000, [[X:%.*]]
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fsub fast float 0x7FF8000000000000, %x
ret float %r
}

define float @fsub_nan_op1_nnan(float %x) {
; CHECK-LABEL: @fsub_nan_op1_nnan(
; CHECK-NEXT: [[R:%.*]] = fsub nnan float [[X:%.*]], 0x7FF8000000000000
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fsub nnan float %x, 0x7FF8000000000000
ret float %r
}

define float @fmul_nan_op0_nnan(float %x) {
; CHECK-LABEL: @fmul_nan_op0_nnan(
; CHECK-NEXT: [[R:%.*]] = fmul nnan float 0x7FF8000000000000, [[X:%.*]]
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fmul nnan float 0x7FF8000000000000, %x
ret float %r
}

define float @fmul_nan_op1_fast(float %x) {
; CHECK-LABEL: @fmul_nan_op1_fast(
; CHECK-NEXT: [[R:%.*]] = fmul fast float [[X:%.*]], 0x7FF8000000000000
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fmul fast float %x, 0x7FF8000000000000
ret float %r
}

define float @fdiv_nan_op0_fast(float %x) {
; CHECK-LABEL: @fdiv_nan_op0_fast(
; CHECK-NEXT: [[R:%.*]] = fdiv fast float 0x7FF8000000000000, [[X:%.*]]
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fdiv fast float 0x7FF8000000000000, %x
ret float %r
}

define float @fdiv_nan_op1_nnan(float %x) {
; CHECK-LABEL: @fdiv_nan_op1_nnan(
; CHECK-NEXT: [[R:%.*]] = fdiv nnan float [[X:%.*]], 0x7FF8000000000000
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fdiv nnan float %x, 0x7FF8000000000000
ret float %r
}

define float @frem_nan_op0_nnan(float %x) {
; CHECK-LABEL: @frem_nan_op0_nnan(
; CHECK-NEXT: [[R:%.*]] = frem nnan float 0x7FF8000000000000, [[X:%.*]]
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = frem nnan float 0x7FF8000000000000, %x
ret float %r
}

define float @frem_nan_op1_fast(float %x) {
; CHECK-LABEL: @frem_nan_op1_fast(
; CHECK-NEXT: [[R:%.*]] = frem fast float [[X:%.*]], 0x7FF8000000000000
; CHECK-NEXT: ret float [[R]]
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = frem fast float %x, 0x7FF8000000000000
ret float %r
Expand Down

0 comments on commit e235942

Please sign in to comment.