forked from OSchip/llvm-project
[ConstantFold] fp_binop AnyConstant, undef --> NaN
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
This commit is contained in:
parent
a7dcfa746e
commit
e5606b4fa5
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ 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
|
||||
|
@ -229,7 +229,7 @@ define float @fadd_undef_op0_nnan_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -237,7 +237,7 @@ define float @fadd_undef_op1_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -245,7 +245,7 @@ define float @fsub_undef_op0_fast_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -253,7 +253,7 @@ define float @fsub_undef_op1_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -261,7 +261,7 @@ define float @fmul_undef_op0_nnan_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -269,7 +269,7 @@ define float @fmul_undef_op1_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -277,7 +277,7 @@ define float @fdiv_undef_op0_fast_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -285,7 +285,7 @@ define float @fdiv_undef_op1_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -293,7 +293,7 @@ define float @frem_undef_op0_nnan_constant(float %x) {
|
|||
|
||||
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
|
||||
|
@ -303,7 +303,7 @@ 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
|
||||
|
@ -311,7 +311,7 @@ define double @fadd_undef_op0_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -319,7 +319,7 @@ define double @fadd_undef_op1_fast_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -327,7 +327,7 @@ define double @fsub_undef_op0_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -335,7 +335,7 @@ define double @fsub_undef_op1_nnan_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -343,7 +343,7 @@ define double @fmul_undef_op0_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -351,7 +351,7 @@ define double @fmul_undef_op1_fast_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -359,7 +359,7 @@ define double @fdiv_undef_op0_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -367,7 +367,7 @@ define double @fdiv_undef_op1_nnan_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -375,7 +375,7 @@ define double @frem_undef_op0_constant_nan(double %x) {
|
|||
|
||||
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
|
||||
|
@ -385,7 +385,7 @@ 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
|
||||
|
@ -393,7 +393,7 @@ define double @fadd_undef_op0_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -401,7 +401,7 @@ define double @fadd_undef_op1_fast_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -409,7 +409,7 @@ define double @fsub_undef_op0_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -417,7 +417,7 @@ define double @fsub_undef_op1_ninf_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -425,7 +425,7 @@ define double @fmul_undef_op0_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -433,7 +433,7 @@ define double @fmul_undef_op1_fast_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -441,7 +441,7 @@ define double @fdiv_undef_op0_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -449,7 +449,7 @@ define double @fdiv_undef_op1_ninf_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
@ -457,7 +457,7 @@ define double @frem_undef_op0_constant_inf(double %x) {
|
|||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue