diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -159,6 +159,9 @@ BUILTIN(__builtin_ppc_minfe, "LdLdLdLd.", "t") BUILTIN(__builtin_ppc_minfl, "dddd.", "t") BUILTIN(__builtin_ppc_minfs, "ffff.", "t") +// Floating Negative Absolute Value +BUILTIN(__builtin_ppc_fnabs, "dd", "") +BUILTIN(__builtin_ppc_fnabss, "ff", "") BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n") diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -252,6 +252,8 @@ Builder.defineMacro("__test_data_class", "__builtin_ppc_test_data_class"); Builder.defineMacro("__swdiv", "__builtin_ppc_swdiv"); Builder.defineMacro("__swdivs", "__builtin_ppc_swdivs"); + Builder.defineMacro("__fnabs", "__builtin_ppc_fnabs"); + Builder.defineMacro("__fnabss", "__builtin_ppc_fnabss"); Builder.defineMacro("__builtin_maxfe", "__builtin_ppc_maxfe"); Builder.defineMacro("__builtin_maxfl", "__builtin_ppc_maxfl"); Builder.defineMacro("__builtin_maxfs", "__builtin_ppc_maxfs"); diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-fnabs.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-fnabs.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-fnabs.c @@ -0,0 +1,36 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu \ +// RUN: -emit-llvm %s -target-cpu pwr8 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -target-cpu pwr8 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu \ +// RUN: -emit-llvm %s -target-cpu pwr7 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -target-cpu pwr7 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu \ +// RUN: -emit-llvm %s -target-cpu pwr6 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu \ +// RUN: -emit-llvm %s -target-cpu pwr6 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -target-cpu pwr6 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -target-cpu pwr6 -o - | FileCheck %s + +extern float f; +extern double d; + +// CHECK-LABEL: @test_fnabs( +// CHECK: [[TMP0:%.*]] = load double, ptr @d +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.ppc.fnabs(double [[TMP0]]) +// CHECK-NEXT: ret double [[TMP1]] +double test_fnabs() { + return __fnabs (d); +} + +// CHECK-LABEL: @test_fnabss( +// CHECK: [[TMP0:%.*]] = load float, ptr @f +// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ppc.fnabss(float [[TMP0]]) +// CHECK-NEXT: ret float [[TMP1]] +float test_fnabss() { + return __fnabss (f); +} diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -1801,6 +1801,12 @@ def int_ppc_test_data_class_f : Intrinsic<[llvm_i32_ty], [llvm_float_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; + def int_ppc_fnabs + : GCCBuiltin<"__builtin_ppc_fnabs">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fnabss + : GCCBuiltin<"__builtin_ppc_fnabss">, + Intrinsic <[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; def int_ppc_convert_f128_to_ppcf128 : Intrinsic<[llvm_ppcf128_ty], [llvm_f128_ty], [IntrNoMem]>; diff --git a/llvm/lib/Target/PowerPC/P10InstrResources.td b/llvm/lib/Target/PowerPC/P10InstrResources.td --- a/llvm/lib/Target/PowerPC/P10InstrResources.td +++ b/llvm/lib/Target/PowerPC/P10InstrResources.td @@ -956,7 +956,7 @@ WAIT, XSABSDP, XSABSQP, - XSNABSDP, + XSNABSDP, XSNABSDPs, XSNABSQP, XSNEGDP, XSNEGQP, diff --git a/llvm/lib/Target/PowerPC/P9InstrResources.td b/llvm/lib/Target/PowerPC/P9InstrResources.td --- a/llvm/lib/Target/PowerPC/P9InstrResources.td +++ b/llvm/lib/Target/PowerPC/P9InstrResources.td @@ -156,6 +156,7 @@ MCRF, MCRXRX, XSNABSDP, + XSNABSDPs, XSXEXPDP, XSABSDP, XSNEGDP, diff --git a/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def b/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def --- a/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def +++ b/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def @@ -434,6 +434,7 @@ XSMINDP, XSMINJDP, XSNABSDP, + XSNABSDPs, XSNABSQP, XSNEGDP, XSNEGQP, @@ -978,6 +979,7 @@ XSMINDP, XSMINJDP, XSNABSDP, + XSNABSDPs, XSNABSQP, XSNEGDP, XSNEGQP, diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -3240,6 +3240,8 @@ def : Pat<(int_ppc_fnmadds f32:$A, f32:$B, f32:$C), (FNMADDS $A, $B, $C)>; def : Pat<(int_ppc_fre f64:$A), (FRE $A)>; def : Pat<(int_ppc_fres f32:$A), (FRES $A)>; +def : Pat<(int_ppc_fnabs f64:$A), (FNABSD $A)>; +def : Pat<(int_ppc_fnabss f32:$A), (FNABSS $A)>; include "PPCInstrAltivec.td" include "PPCInstrSPE.td" diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td --- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td +++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td @@ -703,6 +703,11 @@ (outs vsfrc:$XT), (ins vsfrc:$XB), "xsnabsdp $XT, $XB", IIC_VecFP, [(set f64:$XT, (fneg (fabs f64:$XB)))]>; + let isCodeGenOnly = 1 in + def XSNABSDPs : XX2Form<60, 361, + (outs vssrc:$XT), (ins vssrc:$XB), + "xsnabsdp $XT, $XB", IIC_VecFP, + [(set f32:$XT, (fneg (fabs f32:$XB)))]>; def XSNEGDP : XX2Form<60, 377, (outs vsfrc:$XT), (ins vsfrc:$XB), "xsnegdp $XT, $XB", IIC_VecFP, @@ -2871,6 +2876,8 @@ def : Pat<(int_ppc_fnmadd f64:$A, f64:$B, f64:$C), (XSNMADDMDP $A, $B, $C)>; def : Pat<(int_ppc_fre f64:$A), (XSREDP $A)>; def : Pat<(int_ppc_frsqrte vsfrc:$XB), (XSRSQRTEDP $XB)>; +def : Pat<(int_ppc_fnabs f64:$A), (XSNABSDP $A)>; +def : Pat<(int_ppc_fnabss f32:$A), (XSNABSDPs $A)>; // XXMRG[LH]W is a direct replacement for VMRG[LH]W respectively. // Prefer the VSX form for greater register range. diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-fnabs.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-fnabs.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-fnabs.ll @@ -0,0 +1,79 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr8 < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-DEFAULT +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr8 < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-DEFAULT +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix -mcpu=pwr8 \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names < %s | FileCheck %s \ +; RUN: --check-prefix=CHECK-DEFAULT +; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix -mcpu=pwr8 < %s \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names | FileCheck %s \ +; RUN: --check-prefix=CHECK-DEFAULT +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix -mcpu=pwr7 \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names < %s | FileCheck %s \ +; RUN: --check-prefix=CHECK-DEFAULT +; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix -mcpu=pwr7 \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names < %s | FileCheck %s \ +; RUN: --check-prefix=CHECK-DEFAULT + +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr6 < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-NOVSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr6 < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-NOVSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr6 < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-NOVSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr6 < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-NOVSX + +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr8 \ +; RUN: -mattr=-vsx < %s | FileCheck %s --check-prefix=CHECK-NOVSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr8 \ +; RUN: -mattr=-vsx < %s | FileCheck %s --check-prefix=CHECK-NOVSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr8 \ +; RUN: -mattr=-vsx < %s | FileCheck %s --check-prefix=CHECK-NOVSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names -mcpu=pwr8 \ +; RUN: -mattr=-vsx < %s | FileCheck %s --check-prefix=CHECK-NOVSX + +declare double @llvm.ppc.fnabs(double) +declare float @llvm.ppc.fnabss(float) + +define double @test_fnabs2(double %d) { +; CHECK-DEFAULT-LABEL: test_fnabs2: +; CHECK-DEFAULT: # %bb.0: # %entry +; CHECK-DEFAULT-NEXT: xsnabsdp f1, f1 +; CHECK-DEFAULT-NEXT: blr +; +; CHECK-NOVSX-LABEL: test_fnabs2: +; CHECK-NOVSX: # %bb.0: # %entry +; CHECK-NOVSX-NEXT: fnabs f1, f1 +; CHECK-NOVSX-NEXT: blr +entry: + %0 = tail call double @llvm.ppc.fnabs(double %d) + ret double %0 +} + +define float @test_fnabss(float %f) { +; CHECK-DEFAULT-LABEL: test_fnabss: +; CHECK-DEFAULT: # %bb.0: # %entry +; CHECK-DEFAULT-NEXT: xsnabsdp f1, f1 +; CHECK-DEFAULT-NEXT: blr +; +; CHECK-NOVSX-LABEL: test_fnabss: +; CHECK-NOVSX: # %bb.0: # %entry +; CHECK-NOVSX-NEXT: fnabs f1, f1 +; CHECK-NOVSX-NEXT: blr +entry: + %0 = tail call float @llvm.ppc.fnabss(float %f) + ret float %0 +} +