Skip to content

Commit

Permalink
[ConstantFold] fp_binop AnyConstant, undef --> NaN
Browse files Browse the repository at this point in the history
With the updated LangRef ( D44216 / rL327138 ) in place, we can proceed with more constant folding.

I'm intentionally taking the conservative path here: no matter what the constant or the FMF, we can 
always fold to NaN. This is because the undef operand can be chosen as NaN, and in our simplified 
default FP env, nothing else happens - NaN just propagates to the result. If we find some way/need 
to propagate undef instead, that can be added subsequently.

The tests show that we always choose the same quiet NaN constant (0x7FF8000000000000 in IR text). 
There were suggestions to improve that with a 'NaN' string token or not always print a 64-bit hex 
value, but those are independent changes. We might also consider setting/propagating the payload of 
NaN constants as an enhancement.

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

llvm-svn: 327208
  • Loading branch information
rotateright committed Mar 10, 2018
1 parent a7dcfa7 commit e5606b4
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 60 deletions.
10 changes: 8 additions & 2 deletions llvm/lib/IR/ConstantFold.cpp
Expand Up @@ -1012,8 +1012,14 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
// [any flop] undef, undef -> undef
if (isa<UndefValue>(C1) && isa<UndefValue>(C2))
return C1;
// TODO: Handle one undef operand and some other constant.
return nullptr;
// [any flop] C, undef -> NaN
// [any flop] undef, C -> NaN
// We could potentially specialize NaN/Inf constants vs. 'normal'
// constants (possibly differently depending on opcode and operand). This
// would allow returning undef sometimes. But it is always safe to fold to
// NaN because we can choose the undef operand as NaN, and any FP opcode
// with a NaN operand will propagate NaN.
return ConstantFP::getNaN(C1->getType());
case Instruction::BinaryOpsEnd:
llvm_unreachable("Invalid BinaryOp");
}
Expand Down
28 changes: 0 additions & 28 deletions llvm/test/Transforms/InstCombine/fsub.ll
Expand Up @@ -47,31 +47,3 @@ define float @fsub_fast_undef(float %val) {
ret float %sub
}

define float @fneg_undef(float %val) {
; CHECK-LABEL: @fneg_undef(
; CHECK-NEXT: ret float fsub (float -0.000000e+00, float undef)
;
%sub = fsub float -0.0, undef
ret float %sub
}

define float @fneg_fast_undef(float %val) {
; CHECK-LABEL: @fneg_fast_undef(
; CHECK-NEXT: ret float fsub (float -0.000000e+00, float undef)
;
%sub = fsub fast float -0.0, undef
ret float %sub
}

; This folds to a constant expression, which produced 0 instructions
; contrary to the expected one for negation.

define float @inconsistent_numbers_fsub_undef(float %val) {
; CHECK-LABEL: @inconsistent_numbers_fsub_undef(
; CHECK-NEXT: ret float fsub (float -0.000000e+00, float undef)
;
%sub0 = fsub fast float %val, undef
%sub1 = fsub fast float %sub0, %val
ret float %sub1
}

60 changes: 30 additions & 30 deletions llvm/test/Transforms/InstSimplify/fp-undef.ll
Expand Up @@ -221,79 +221,79 @@ define double @frem_undef_undef(double %x) {

define float @fadd_undef_op0_nnan_constant(float %x) {
; CHECK-LABEL: @fadd_undef_op0_nnan_constant(
; CHECK-NEXT: ret float fadd (float undef, float 1.000000e+00)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fadd nnan float undef, 1.0
ret float %r
}

define float @fadd_undef_op1_constant(float %x) {
; CHECK-LABEL: @fadd_undef_op1_constant(
; CHECK-NEXT: ret float fadd (float 2.000000e+00, float undef)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fadd float 2.0, undef
ret float %r
}

define float @fsub_undef_op0_fast_constant(float %x) {
; CHECK-LABEL: @fsub_undef_op0_fast_constant(
; CHECK-NEXT: ret float fsub (float undef, float 3.000000e+00)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fsub fast float undef, 3.0
ret float %r
}

define float @fsub_undef_op1_constant(float %x) {
; CHECK-LABEL: @fsub_undef_op1_constant(
; CHECK-NEXT: ret float fsub (float 4.000000e+00, float undef)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fsub float 4.0, undef
ret float %r
}

define float @fmul_undef_op0_nnan_constant(float %x) {
; CHECK-LABEL: @fmul_undef_op0_nnan_constant(
; CHECK-NEXT: ret float fmul (float undef, float 5.000000e+00)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fmul nnan float undef, 5.0
ret float %r
}

define float @fmul_undef_op1_constant(float %x) {
; CHECK-LABEL: @fmul_undef_op1_constant(
; CHECK-NEXT: ret float fmul (float 6.000000e+00, float undef)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fmul float 6.0, undef
ret float %r
}

define float @fdiv_undef_op0_fast_constant(float %x) {
; CHECK-LABEL: @fdiv_undef_op0_fast_constant(
; CHECK-NEXT: ret float fdiv (float undef, float 7.000000e+00)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fdiv fast float undef, 7.0
ret float %r
}

define float @fdiv_undef_op1_constant(float %x) {
; CHECK-LABEL: @fdiv_undef_op1_constant(
; CHECK-NEXT: ret float fdiv (float 8.000000e+00, float undef)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = fdiv float 8.0, undef
ret float %r
}

define float @frem_undef_op0_nnan_constant(float %x) {
; CHECK-LABEL: @frem_undef_op0_nnan_constant(
; CHECK-NEXT: ret float frem (float undef, float 9.000000e+00)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = frem nnan float undef, 9.0
ret float %r
}

define float @frem_undef_op1_constant(float %x) {
; CHECK-LABEL: @frem_undef_op1_constant(
; CHECK-NEXT: ret float frem (float 1.000000e+01, float undef)
; CHECK-NEXT: ret float 0x7FF8000000000000
;
%r = frem float 10.0, undef
ret float %r
Expand All @@ -303,79 +303,79 @@ define float @frem_undef_op1_constant(float %x) {

define double @fadd_undef_op0_constant_nan(double %x) {
; CHECK-LABEL: @fadd_undef_op0_constant_nan(
; CHECK-NEXT: ret double fadd (double undef, double 0x7FF8000000000000)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fadd double undef, 0x7FF8000000000000
ret double %r
}

define double @fadd_undef_op1_fast_constant_nan(double %x) {
; CHECK-LABEL: @fadd_undef_op1_fast_constant_nan(
; CHECK-NEXT: ret double fadd (double 0xFFF0000000000001, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fadd fast double 0xFFF0000000000001, undef
ret double %r
}

define double @fsub_undef_op0_constant_nan(double %x) {
; CHECK-LABEL: @fsub_undef_op0_constant_nan(
; CHECK-NEXT: ret double fsub (double undef, double 0xFFF8000000000010)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fsub double undef, 0xFFF8000000000010
ret double %r
}

define double @fsub_undef_op1_nnan_constant_nan(double %x) {
; CHECK-LABEL: @fsub_undef_op1_nnan_constant_nan(
; CHECK-NEXT: ret double fsub (double 0x7FF0000000000011, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fsub nnan double 0x7FF0000000000011, undef
ret double %r
}

define double @fmul_undef_op0_constant_nan(double %x) {
; CHECK-LABEL: @fmul_undef_op0_constant_nan(
; CHECK-NEXT: ret double fmul (double undef, double 0x7FF8000000000100)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fmul double undef, 0x7FF8000000000100
ret double %r
}

define double @fmul_undef_op1_fast_constant_nan(double %x) {
; CHECK-LABEL: @fmul_undef_op1_fast_constant_nan(
; CHECK-NEXT: ret double fmul (double 0xFFF0000000000101, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fmul fast double 0xFFF0000000000101, undef
ret double %r
}

define double @fdiv_undef_op0_constant_nan(double %x) {
; CHECK-LABEL: @fdiv_undef_op0_constant_nan(
; CHECK-NEXT: ret double fdiv (double undef, double 0xFFF8000000000110)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fdiv double undef, 0xFFF8000000000110
ret double %r
}

define double @fdiv_undef_op1_nnan_constant_nan(double %x) {
; CHECK-LABEL: @fdiv_undef_op1_nnan_constant_nan(
; CHECK-NEXT: ret double fdiv (double 0x7FF0000000000111, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fdiv nnan double 0x7FF0000000000111, undef
ret double %r
}

define double @frem_undef_op0_constant_nan(double %x) {
; CHECK-LABEL: @frem_undef_op0_constant_nan(
; CHECK-NEXT: ret double frem (double undef, double 0x7FF8000000001000)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = frem double undef, 0x7FF8000000001000
ret double %r
}

define double @frem_undef_op1_fast_constant_nan(double %x) {
; CHECK-LABEL: @frem_undef_op1_fast_constant_nan(
; CHECK-NEXT: ret double frem (double 0xFFF0000000001001, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = frem fast double 0xFFF0000000001001, undef
ret double %r
Expand All @@ -385,79 +385,79 @@ define double @frem_undef_op1_fast_constant_nan(double %x) {

define double @fadd_undef_op0_constant_inf(double %x) {
; CHECK-LABEL: @fadd_undef_op0_constant_inf(
; CHECK-NEXT: ret double fadd (double undef, double 0x7FF0000000000000)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fadd double undef, 0x7FF0000000000000
ret double %r
}

define double @fadd_undef_op1_fast_constant_inf(double %x) {
; CHECK-LABEL: @fadd_undef_op1_fast_constant_inf(
; CHECK-NEXT: ret double fadd (double 0xFFF0000000000000, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fadd fast double 0xFFF0000000000000, undef
ret double %r
}

define double @fsub_undef_op0_constant_inf(double %x) {
; CHECK-LABEL: @fsub_undef_op0_constant_inf(
; CHECK-NEXT: ret double fsub (double undef, double 0xFFF0000000000000)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fsub double undef, 0xFFF0000000000000
ret double %r
}

define double @fsub_undef_op1_ninf_constant_inf(double %x) {
; CHECK-LABEL: @fsub_undef_op1_ninf_constant_inf(
; CHECK-NEXT: ret double fsub (double 0x7FF0000000000000, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fsub ninf double 0x7FF0000000000000, undef
ret double %r
}

define double @fmul_undef_op0_constant_inf(double %x) {
; CHECK-LABEL: @fmul_undef_op0_constant_inf(
; CHECK-NEXT: ret double fmul (double undef, double 0x7FF0000000000000)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fmul double undef, 0x7FF0000000000000
ret double %r
}

define double @fmul_undef_op1_fast_constant_inf(double %x) {
; CHECK-LABEL: @fmul_undef_op1_fast_constant_inf(
; CHECK-NEXT: ret double fmul (double 0xFFF0000000000000, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fmul fast double 0xFFF0000000000000, undef
ret double %r
}

define double @fdiv_undef_op0_constant_inf(double %x) {
; CHECK-LABEL: @fdiv_undef_op0_constant_inf(
; CHECK-NEXT: ret double fdiv (double undef, double 0xFFF0000000000000)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fdiv double undef, 0xFFF0000000000000
ret double %r
}

define double @fdiv_undef_op1_ninf_constant_inf(double %x) {
; CHECK-LABEL: @fdiv_undef_op1_ninf_constant_inf(
; CHECK-NEXT: ret double fdiv (double 0x7FF0000000000000, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = fdiv ninf double 0x7FF0000000000000, undef
ret double %r
}

define double @frem_undef_op0_constant_inf(double %x) {
; CHECK-LABEL: @frem_undef_op0_constant_inf(
; CHECK-NEXT: ret double frem (double undef, double 0x7FF0000000000000)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = frem double undef, 0x7FF0000000000000
ret double %r
}

define double @frem_undef_op1_fast_constant_inf(double %x) {
; CHECK-LABEL: @frem_undef_op1_fast_constant_inf(
; CHECK-NEXT: ret double frem (double 0xFFF0000000000000, double undef)
; CHECK-NEXT: ret double 0x7FF8000000000000
;
%r = frem fast double 0xFFF0000000000000, undef
ret double %r
Expand Down

0 comments on commit e5606b4

Please sign in to comment.