diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-03-10 15:56:25 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-03-10 15:56:25 +0000 |
commit | e5606b4fa5b8b4e66ab7c01aa274a29580366a26 (patch) | |
tree | 1b429eb54fe73a82e9fa7da2ed331248012485b4 | |
parent | a7dcfa746e8eab05e0750adc2c6dd1fabae5636d (diff) | |
download | bcm5719-llvm-e5606b4fa5b8b4e66ab7c01aa274a29580366a26.tar.gz bcm5719-llvm-e5606b4fa5b8b4e66ab7c01aa274a29580366a26.zip |
[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
-rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 10 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/fsub.ll | 28 | ||||
-rw-r--r-- | llvm/test/Transforms/InstSimplify/fp-undef.ll | 60 |
3 files changed, 38 insertions, 60 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index f6ec12dae97..92d35a27d69 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -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"); } diff --git a/llvm/test/Transforms/InstCombine/fsub.ll b/llvm/test/Transforms/InstCombine/fsub.ll index 7c44d2f2b04..d6b5e3acd13 100644 --- a/llvm/test/Transforms/InstCombine/fsub.ll +++ b/llvm/test/Transforms/InstCombine/fsub.ll @@ -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 -} - diff --git a/llvm/test/Transforms/InstSimplify/fp-undef.ll b/llvm/test/Transforms/InstSimplify/fp-undef.ll index 4510e7d2ab6..8dbb7610839 100644 --- a/llvm/test/Transforms/InstSimplify/fp-undef.ll +++ b/llvm/test/Transforms/InstSimplify/fp-undef.ll @@ -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 |