[NVPTX] Implement llvm.fabs.f32, llvm.max.f32, etc.
Summary:
Previously these only worked via NVPTX-specific intrinsics.
This change will allow us to convert these target-specific intrinsics
into the general LLVM versions, allowing existing LLVM passes to reason
about their behavior.
It also gets us some minor codegen improvements as-is, from situations
where we canonicalize code into one of these llvm intrinsics.
Reviewers: majnemer
Subscribers: llvm-commits, jholewinski, tra
Differential Revision: https://reviews.llvm.org/D24300
llvm-svn: 281092
diff --git a/llvm/test/CodeGen/NVPTX/math-intrins.ll b/llvm/test/CodeGen/NVPTX/math-intrins.ll
new file mode 100644
index 0000000..de911d0
--- /dev/null
+++ b/llvm/test/CodeGen/NVPTX/math-intrins.ll
@@ -0,0 +1,261 @@
+; RUN: llc < %s | FileCheck %s
+target triple = "nvptx64-nvidia-cuda"
+
+; Checks that llvm intrinsics for math functions are correctly lowered to PTX.
+
+declare float @llvm.ceil.f32(float) #0
+declare double @llvm.ceil.f64(double) #0
+declare float @llvm.floor.f32(float) #0
+declare double @llvm.floor.f64(double) #0
+declare float @llvm.round.f32(float) #0
+declare double @llvm.round.f64(double) #0
+declare float @llvm.nearbyint.f32(float) #0
+declare double @llvm.nearbyint.f64(double) #0
+declare float @llvm.rint.f32(float) #0
+declare double @llvm.rint.f64(double) #0
+declare float @llvm.trunc.f32(float) #0
+declare double @llvm.trunc.f64(double) #0
+declare float @llvm.fabs.f32(float) #0
+declare double @llvm.fabs.f64(double) #0
+declare float @llvm.minnum.f32(float, float) #0
+declare double @llvm.minnum.f64(double, double) #0
+declare float @llvm.maxnum.f32(float, float) #0
+declare double @llvm.maxnum.f64(double, double) #0
+
+; ---- ceil ----
+
+; CHECK-LABEL: ceil_float
+define float @ceil_float(float %a) {
+ ; CHECK: cvt.rpi.f32.f32
+ %b = call float @llvm.ceil.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: ceil_float_ftz
+define float @ceil_float_ftz(float %a) #1 {
+ ; CHECK: cvt.rpi.ftz.f32.f32
+ %b = call float @llvm.ceil.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: ceil_double
+define double @ceil_double(double %a) {
+ ; CHECK: cvt.rpi.f64.f64
+ %b = call double @llvm.ceil.f64(double %a)
+ ret double %b
+}
+
+; ---- floor ----
+
+; CHECK-LABEL: floor_float
+define float @floor_float(float %a) {
+ ; CHECK: cvt.rmi.f32.f32
+ %b = call float @llvm.floor.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: floor_float_ftz
+define float @floor_float_ftz(float %a) #1 {
+ ; CHECK: cvt.rmi.ftz.f32.f32
+ %b = call float @llvm.floor.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: floor_double
+define double @floor_double(double %a) {
+ ; CHECK: cvt.rmi.f64.f64
+ %b = call double @llvm.floor.f64(double %a)
+ ret double %b
+}
+
+; ---- round ----
+
+; CHECK-LABEL: round_float
+define float @round_float(float %a) {
+ ; CHECK: cvt.rni.f32.f32
+ %b = call float @llvm.round.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: round_float_ftz
+define float @round_float_ftz(float %a) #1 {
+ ; CHECK: cvt.rni.ftz.f32.f32
+ %b = call float @llvm.round.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: round_double
+define double @round_double(double %a) {
+ ; CHECK: cvt.rni.f64.f64
+ %b = call double @llvm.round.f64(double %a)
+ ret double %b
+}
+
+; ---- nearbyint ----
+
+; CHECK-LABEL: nearbyint_float
+define float @nearbyint_float(float %a) {
+ ; CHECK: cvt.rni.f32.f32
+ %b = call float @llvm.nearbyint.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: nearbyint_float_ftz
+define float @nearbyint_float_ftz(float %a) #1 {
+ ; CHECK: cvt.rni.ftz.f32.f32
+ %b = call float @llvm.nearbyint.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: nearbyint_double
+define double @nearbyint_double(double %a) {
+ ; CHECK: cvt.rni.f64.f64
+ %b = call double @llvm.nearbyint.f64(double %a)
+ ret double %b
+}
+
+; ---- rint ----
+
+; CHECK-LABEL: rint_float
+define float @rint_float(float %a) {
+ ; CHECK: cvt.rni.f32.f32
+ %b = call float @llvm.rint.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: rint_float_ftz
+define float @rint_float_ftz(float %a) #1 {
+ ; CHECK: cvt.rni.ftz.f32.f32
+ %b = call float @llvm.rint.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: rint_double
+define double @rint_double(double %a) {
+ ; CHECK: cvt.rni.f64.f64
+ %b = call double @llvm.rint.f64(double %a)
+ ret double %b
+}
+
+; ---- trunc ----
+
+; CHECK-LABEL: trunc_float
+define float @trunc_float(float %a) {
+ ; CHECK: cvt.rzi.f32.f32
+ %b = call float @llvm.trunc.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: trunc_float_ftz
+define float @trunc_float_ftz(float %a) #1 {
+ ; CHECK: cvt.rzi.ftz.f32.f32
+ %b = call float @llvm.trunc.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: trunc_double
+define double @trunc_double(double %a) {
+ ; CHECK: cvt.rzi.f64.f64
+ %b = call double @llvm.trunc.f64(double %a)
+ ret double %b
+}
+
+; ---- abs ----
+
+; CHECK-LABEL: abs_float
+define float @abs_float(float %a) {
+ ; CHECK: abs.f32
+ %b = call float @llvm.fabs.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: abs_float_ftz
+define float @abs_float_ftz(float %a) #1 {
+ ; CHECK: abs.ftz.f32
+ %b = call float @llvm.fabs.f32(float %a)
+ ret float %b
+}
+
+; CHECK-LABEL: abs_double
+define double @abs_double(double %a) {
+ ; CHECK: abs.f64
+ %b = call double @llvm.fabs.f64(double %a)
+ ret double %b
+}
+
+; ---- min ----
+
+; CHECK-LABEL: min_float
+define float @min_float(float %a, float %b) {
+ ; CHECK: min.f32
+ %x = call float @llvm.minnum.f32(float %a, float %b)
+ ret float %x
+}
+
+; CHECK-LABEL: min_imm1
+define float @min_imm1(float %a) {
+ ; CHECK: min.f32
+ %x = call float @llvm.minnum.f32(float %a, float 0.0)
+ ret float %x
+}
+
+; CHECK-LABEL: min_imm2
+define float @min_imm2(float %a) {
+ ; CHECK: min.f32
+ %x = call float @llvm.minnum.f32(float 0.0, float %a)
+ ret float %x
+}
+
+; CHECK-LABEL: min_float_ftz
+define float @min_float_ftz(float %a, float %b) #1 {
+ ; CHECK: min.ftz.f32
+ %x = call float @llvm.minnum.f32(float %a, float %b)
+ ret float %x
+}
+
+; CHECK-LABEL: min_double
+define double @min_double(double %a, double %b) {
+ ; CHECK: min.f64
+ %x = call double @llvm.minnum.f64(double %a, double %b)
+ ret double %x
+}
+
+; ---- max ----
+
+; CHECK-LABEL: max_imm1
+define float @max_imm1(float %a) {
+ ; CHECK: max.f32
+ %x = call float @llvm.maxnum.f32(float %a, float 0.0)
+ ret float %x
+}
+
+; CHECK-LABEL: max_imm2
+define float @max_imm2(float %a) {
+ ; CHECK: max.f32
+ %x = call float @llvm.maxnum.f32(float 0.0, float %a)
+ ret float %x
+}
+
+; CHECK-LABEL: max_float
+define float @max_float(float %a, float %b) {
+ ; CHECK: max.f32
+ %x = call float @llvm.maxnum.f32(float %a, float %b)
+ ret float %x
+}
+
+; CHECK-LABEL: max_float_ftz
+define float @max_float_ftz(float %a, float %b) #1 {
+ ; CHECK: max.ftz.f32
+ %x = call float @llvm.maxnum.f32(float %a, float %b)
+ ret float %x
+}
+
+; CHECK-LABEL: max_double
+define double @max_double(double %a, double %b) {
+ ; CHECK: max.f64
+ %x = call double @llvm.maxnum.f64(double %a, double %b)
+ ret double %x
+}
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { "nvptx-f32ftz" = "true" }