diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index e3dd334e7b098..1517cb8a1ae5d 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -179,3 +179,21 @@ def AArch64 : Target { //===----------------------------------------------------------------------===// include "AArch64PfmCounters.td" + + +//===----------------------------------------------------------------------===// +// GlobalISel patterns +//===----------------------------------------------------------------------===// + +include "AArch64GlobalISelPatterns.td" + +// We want to first hit the instruction patterns. +foreach VT = [nxv2bf16, nxv4bf16, nxv8bf16] in { + // No dedicated instruction, so just clear the sign bit. + def : Pat<(VT (fabs VT:$op)), + (AND_ZI $op, (i64 (logical_imm64_XFORM(i64 0x7fff7fff7fff7fff))))>; + // No dedicated instruction, so just invert the sign bit. + def : Pat<(VT (fneg VT:$op)), + (EOR_ZI $op, (i64 (logical_imm64_XFORM(i64 0x8000800080008000))))>; +} + diff --git a/llvm/lib/Target/AArch64/AArch64GlobalISelPatterns.td b/llvm/lib/Target/AArch64/AArch64GlobalISelPatterns.td new file mode 100644 index 0000000000000..5d1d5816ed4fc --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64GlobalISelPatterns.td @@ -0,0 +1,36 @@ +//===-- AArch64GlobalISelPatterns.td - GlobalISel patterns -*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Selection and combine patterns for GlobalISel. +// +//===----------------------------------------------------------------------===// + + +//unpredicate patterns + + + +// fneg +def : Pat<(nxv2f64 (fneg nxv2f64:$src)), + (FNEG_ZPmZ_D_UNDEF (IMPLICIT_DEF), (PTRUE_D 31), ZPR:$src)>; + +def : Pat<(nxv4f32 (fneg nxv4f32:$src)), + (FNEG_ZPmZ_S_UNDEF (IMPLICIT_DEF), (PTRUE_S 31), ZPR:$src)>; + +def : Pat<(nxv8f16 (fneg nxv8f16:$src)), + (FNEG_ZPmZ_H_UNDEF (IMPLICIT_DEF), (PTRUE_H 31), ZPR:$src)>; + +// fabs +def : Pat<(nxv2f64 (fabs nxv2f64:$src)), + (FABS_ZPmZ_D_UNDEF (IMPLICIT_DEF), (PTRUE_D 31), ZPR:$src)>; + +def : Pat<(nxv4f32 (fabs nxv4f32:$src)), + (FABS_ZPmZ_S_UNDEF (IMPLICIT_DEF), (PTRUE_S 31), ZPR:$src)>; + +def : Pat<(nxv8f16 (fabs nxv8f16:$src)), + (FABS_ZPmZ_H_UNDEF (IMPLICIT_DEF), (PTRUE_H 31), ZPR:$src)>; diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 574432869471a..ecf1cc24e0a50 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -683,15 +683,6 @@ let Predicates = [HasSVEorSME] in { defm NEG_ZPmZ : sve_int_un_pred_arit_bhsd; } - foreach VT = [nxv2bf16, nxv4bf16, nxv8bf16] in { - // No dedicated instruction, so just clear the sign bit. - def : Pat<(VT (fabs VT:$op)), - (AND_ZI $op, (i64 (logical_imm64_XFORM(i64 0x7fff7fff7fff7fff))))>; - // No dedicated instruction, so just invert the sign bit. - def : Pat<(VT (fneg VT:$op)), - (EOR_ZI $op, (i64 (logical_imm64_XFORM(i64 0x8000800080008000))))>; - } - // zext(cmpeq(x, splat(0))) -> cnot(x) def : Pat<(nxv16i8 (zext (nxv16i1 (AArch64setcc_z (nxv16i1 (SVEAllActive):$Pg), nxv16i8:$Op2, (SVEDup0), SETEQ)))), (CNOT_ZPmZ_B $Op2, $Pg, $Op2)>; diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index 619a041c273cd..c7130696a614d 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -279,6 +279,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) getActionDefinitionsBuilder({G_FABS, G_FNEG}) .legalFor({s32, s64, v2s32, v4s32, v2s64}) .legalFor(HasFP16, {s16, v4s16, v8s16}) + .legalFor(HasSVE, {nxv2s64, nxv4s32, nxv8s16}) .scalarizeIf(scalarOrEltWiderThan(0, 64), 0) .lowerIf(scalarOrEltWiderThan(0, 64)) .clampNumElements(0, v4s16, v8s16) diff --git a/llvm/test/CodeGen/AArch64/sve-float.ll b/llvm/test/CodeGen/AArch64/sve-float.ll new file mode 100644 index 0000000000000..665bee964ce8b --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-float.ll @@ -0,0 +1,71 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple aarch64 -mattr=+sve -global-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple aarch64 -mattr=+sve -global-isel -aarch64-enable-gisel-sve=1 | FileCheck %s + +;; fneg +define @fnegnxv2double( %a) { +; CHECK-LABEL: fnegnxv2double: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: fneg z0.d, p0/m, z0.d +; CHECK-NEXT: ret +entry: + %c = fneg %a + ret %c +} + +define @fnegnxv4float( %a) { +; CHECK-LABEL: fnegnxv4float: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: fneg z0.s, p0/m, z0.s +; CHECK-NEXT: ret +entry: + %c = fneg %a + ret %c +} + +define @fnegnxv8half( %a) { +; CHECK-LABEL: fnegnxv8half: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.h +; CHECK-NEXT: fneg z0.h, p0/m, z0.h +; CHECK-NEXT: ret +entry: + %c = fneg %a + ret %c +} + +;; fabs +define @fabsnxv2double( %a) { +; CHECK-LABEL: fabsnxv2double: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: fabs z0.d, p0/m, z0.d +; CHECK-NEXT: ret +entry: + %c = tail call @llvm.fabs.nxv2f64( %a) + ret %c +} + +define @fabsnxv4float( %a) { +; CHECK-LABEL: fabsnxv4float: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: fabs z0.s, p0/m, z0.s +; CHECK-NEXT: ret +entry: + %c = tail call @llvm.fabs.nxv4f32( %a) + ret %c +} + +define @fabsnxv8half( %a) { +; CHECK-LABEL: fabsnxv8half: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.h +; CHECK-NEXT: fabs z0.h, p0/m, z0.h +; CHECK-NEXT: ret +entry: + %c = tail call @llvm.fabs.nxv8f16( %a) + ret %c +}