From aa6cf3803d29f0c129884ff0a1e911dcb3257f97 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 10 Dec 2015 04:55:31 +0000 Subject: [PATCH] [WebAssembly] Implement mixed-type ISD::FCOPYSIGN. ISD::FCOPYSIGN permits its operands to have differing types, and DAGCombiner uses this. Add some def : Pat rules to expand this out into an explicit conversion and a normal copysign operation. llvm-svn: 255220 --- .../WebAssembly/WebAssemblyInstrFloat.td | 6 ++++ .../WebAssembly/WebAssemblyInstrInfo.td | 2 +- test/CodeGen/WebAssembly/copysign-casts.ll | 28 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/WebAssembly/copysign-casts.ll diff --git a/lib/Target/WebAssembly/WebAssemblyInstrFloat.td b/lib/Target/WebAssembly/WebAssemblyInstrFloat.td index d966380e6b0..5520c6de673 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrFloat.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrFloat.td @@ -38,6 +38,12 @@ defm NEAREST : UnaryFP; } // Defs = [ARGUMENTS] +// DAGCombine oddly folds casts into the rhs of copysign. Unfold them. +def : Pat<(fcopysign F64:$lhs, F32:$rhs), + (COPYSIGN_F64 F64:$lhs, (F64_PROMOTE_F32 F32:$rhs))>; +def : Pat<(fcopysign F32:$lhs, F64:$rhs), + (COPYSIGN_F32 F32:$lhs, (F32_DEMOTE_F64 F64:$rhs))>; + // WebAssembly doesn't expose inexact exceptions, so map frint to fnearbyint. def : Pat<(frint f32:$src), (NEAREST_F32 f32:$src)>; def : Pat<(frint f64:$src), (NEAREST_F64 f64:$src)>; diff --git a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index dafe6c1ed64..5cf8664eba8 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -154,7 +154,7 @@ include "WebAssemblyInstrMemory.td" include "WebAssemblyInstrCall.td" include "WebAssemblyInstrControl.td" include "WebAssemblyInstrInteger.td" -include "WebAssemblyInstrFloat.td" include "WebAssemblyInstrConv.td" +include "WebAssemblyInstrFloat.td" include "WebAssemblyInstrAtomics.td" include "WebAssemblyInstrSIMD.td" diff --git a/test/CodeGen/WebAssembly/copysign-casts.ll b/test/CodeGen/WebAssembly/copysign-casts.ll new file mode 100644 index 00000000000..0224febb4c0 --- /dev/null +++ b/test/CodeGen/WebAssembly/copysign-casts.ll @@ -0,0 +1,28 @@ +; RUN: llc < %s -asm-verbose=false | FileCheck %s + +; DAGCombiner oddly folds casts into the rhs of copysign. Test that they get +; unfolded. + +target datalayout = "e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +declare double @copysign(double, double) nounwind readnone +declare float @copysignf(float, float) nounwind readnone + +; CHECK-LABEL: fold_promote: +; CHECK: f64.promote/f32 $push0=, $1 +; CHECK: f64.copysign $push1=, $0, $pop0 +define double @fold_promote(double %a, float %b) { + %c = fpext float %b to double + %t = call double @copysign(double %a, double %c) + ret double %t +} + +; CHECK-LABEL: fold_demote: +; CHECK: f32.demote/f64 $push0=, $1 +; CHECK: f32.copysign $push1=, $0, $pop0 +define float @fold_demote(float %a, double %b) { + %c = fptrunc double %b to float + %t = call float @copysignf(float %a, float %c) + ret float %t +}