[llvm] 0748f42 - [AArch64][GlobalISel] Legalize 128-bit types for FABS (#104753)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 3 04:47:31 PDT 2024
Author: Him188
Date: 2024-09-03T12:47:26+01:00
New Revision: 0748f4227cd6a4a32b155d4bb9ad3f07e1b54bfe
URL: https://github.com/llvm/llvm-project/commit/0748f4227cd6a4a32b155d4bb9ad3f07e1b54bfe
DIFF: https://github.com/llvm/llvm-project/commit/0748f4227cd6a4a32b155d4bb9ad3f07e1b54bfe.diff
LOG: [AArch64][GlobalISel] Legalize 128-bit types for FABS (#104753)
This patch adds a common lower action for `G_FABS`, which generates `and
x8, x8, #0x7fffffffffffffff` to reset the sign bit. The action does not
support vectors since `G_AND` does not support fp128.
This approach is different than what SDAG is doing. SDAG stores the
value onto stack, clears the sign bit in the most significant byte, and
loads the value back into register. This involves multiple memory ops
and sounds slower.
Added:
llvm/test/CodeGen/AArch64/fabs-fp128.ll
Modified:
llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 0b2cd299bde12a..afd68250f5ca6e 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -437,6 +437,7 @@ class LegalizerHelper {
LegalizeResult lowerAbsToAddXor(MachineInstr &MI);
LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI);
LegalizeResult lowerAbsToCNeg(MachineInstr &MI);
+ LegalizeResult lowerFAbs(MachineInstr &MI);
LegalizeResult lowerVectorReduction(MachineInstr &MI);
LegalizeResult lowerMemcpyInline(MachineInstr &MI);
LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0);
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index f818c4e1426ce1..3640b77ff4068c 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4255,6 +4255,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
return lowerShlSat(MI);
case G_ABS:
return lowerAbsToAddXor(MI);
+ case G_FABS:
+ return lowerFAbs(MI);
case G_SELECT:
return lowerSelect(MI);
case G_IS_FPCLASS:
@@ -8761,6 +8763,22 @@ LegalizerHelper::lowerAbsToCNeg(MachineInstr &MI) {
return Legalized;
}
+LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
+ Register SrcReg = MI.getOperand(1).getReg();
+ Register DstReg = MI.getOperand(0).getReg();
+
+ LLT Ty = MRI.getType(DstReg);
+
+ // Reset sign bit
+ MIRBuilder.buildAnd(
+ DstReg, SrcReg,
+ MIRBuilder.buildConstant(
+ Ty, APInt::getSignedMaxValue(Ty.getScalarSizeInBits())));
+
+ MI.eraseFromParent();
+ return Legalized;
+}
+
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerVectorReduction(MachineInstr &MI) {
Register SrcReg = MI.getOperand(1).getReg();
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 7eaf6a84bd204f..db5cd1d32d73d0 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -242,9 +242,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.widenScalarToNextPow2(0);
getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FNEG,
- G_FABS, G_FSQRT, G_FMAXNUM, G_FMINNUM,
- G_FMAXIMUM, G_FMINIMUM, G_FCEIL, G_FFLOOR,
- G_FRINT, G_FNEARBYINT, G_INTRINSIC_TRUNC,
+ G_FSQRT, G_FMAXNUM, G_FMINNUM, G_FMAXIMUM,
+ G_FMINIMUM, G_FCEIL, G_FFLOOR, G_FRINT,
+ G_FNEARBYINT, G_INTRINSIC_TRUNC,
G_INTRINSIC_ROUND, G_INTRINSIC_ROUNDEVEN})
.legalFor({MinFPScalar, s32, s64, v2s32, v4s32, v2s64})
.legalIf([=](const LegalityQuery &Query) {
@@ -258,6 +258,20 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.clampNumElements(0, v2s64, v2s64)
.moreElementsToNextPow2(0);
+ getActionDefinitionsBuilder(G_FABS)
+ .legalFor({MinFPScalar, s32, s64, v2s32, v4s32, v2s64})
+ .legalIf([=](const LegalityQuery &Query) {
+ const auto &Ty = Query.Types[0];
+ return (Ty == v8s16 || Ty == v4s16) && HasFP16;
+ })
+ .scalarizeIf(scalarOrEltWiderThan(0, 64), 0)
+ .lowerIf(scalarOrEltWiderThan(0, 64))
+ .minScalarOrElt(0, MinFPScalar)
+ .clampNumElements(0, v4s16, v8s16)
+ .clampNumElements(0, v2s32, v4s32)
+ .clampNumElements(0, v2s64, v2s64)
+ .moreElementsToNextPow2(0);
+
getActionDefinitionsBuilder(G_FREM)
.libcallFor({s32, s64})
.minScalar(0, s32)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 87a415b45cca9a..b3b85090d11251 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -1,3 +1,4 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
# RUN: llc -mtriple=aarch64-- -run-pass=legalizer %s \
# RUN: -mcpu=cortex-a75 -o - 2>&1 | FileCheck %s --check-prefixes=CHECK
@@ -538,7 +539,6 @@
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_FABS (opcode {{[0-9]+}}): 1 type index, 0 imm indices
-# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_FCOPYSIGN (opcode {{[0-9]+}}): 2 type indices
diff --git a/llvm/test/CodeGen/AArch64/fabs-fp128.ll b/llvm/test/CodeGen/AArch64/fabs-fp128.ll
new file mode 100644
index 00000000000000..903aa8adf70851
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/fabs-fp128.ll
@@ -0,0 +1,170 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -global-isel=0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -global-isel=1 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+define fp128 @fabs_f128(fp128 %a) {
+; CHECK-SD-LABEL: fabs_f128:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: str q0, [sp, #-16]!
+; CHECK-SD-NEXT: .cfi_def_cfa_offset 16
+; CHECK-SD-NEXT: ldrb w8, [sp, #15]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #15]
+; CHECK-SD-NEXT: ldr q0, [sp], #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fabs_f128:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov x8, v0.d[1]
+; CHECK-GI-NEXT: mov v0.d[0], v0.d[0]
+; CHECK-GI-NEXT: and x8, x8, #0x7fffffffffffffff
+; CHECK-GI-NEXT: mov v0.d[1], x8
+; CHECK-GI-NEXT: ret
+entry:
+ %c = call fp128 @llvm.fabs.f128(fp128 %a)
+ ret fp128 %c
+}
+
+define <1 x fp128> @fabs_v1f128(<1 x fp128> %a) {
+; CHECK-SD-LABEL: fabs_v1f128:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: str q0, [sp, #-16]!
+; CHECK-SD-NEXT: .cfi_def_cfa_offset 16
+; CHECK-SD-NEXT: ldrb w8, [sp, #15]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #15]
+; CHECK-SD-NEXT: ldr q0, [sp], #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fabs_v1f128:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov x8, v0.d[1]
+; CHECK-GI-NEXT: mov v0.d[0], v0.d[0]
+; CHECK-GI-NEXT: and x8, x8, #0x7fffffffffffffff
+; CHECK-GI-NEXT: mov v0.d[1], x8
+; CHECK-GI-NEXT: ret
+entry:
+ %c = call <1 x fp128> @llvm.fabs.v1f128(<1 x fp128> %a)
+ ret <1 x fp128> %c
+}
+
+define <2 x fp128> @fabs_v2f128(<2 x fp128> %a) {
+; CHECK-SD-LABEL: fabs_v2f128:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: stp q0, q1, [sp, #-32]!
+; CHECK-SD-NEXT: .cfi_def_cfa_offset 32
+; CHECK-SD-NEXT: ldrb w8, [sp, #15]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #15]
+; CHECK-SD-NEXT: ldrb w8, [sp, #31]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #31]
+; CHECK-SD-NEXT: ldp q0, q1, [sp], #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fabs_v2f128:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov x8, v0.d[1]
+; CHECK-GI-NEXT: mov x9, v1.d[1]
+; CHECK-GI-NEXT: mov v0.d[0], v0.d[0]
+; CHECK-GI-NEXT: mov v1.d[0], v1.d[0]
+; CHECK-GI-NEXT: and x8, x8, #0x7fffffffffffffff
+; CHECK-GI-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-GI-NEXT: mov v0.d[1], x8
+; CHECK-GI-NEXT: mov v1.d[1], x9
+; CHECK-GI-NEXT: ret
+entry:
+ %c = call <2 x fp128> @llvm.fabs.v2f128(<2 x fp128> %a)
+ ret <2 x fp128> %c
+}
+
+define <3 x fp128> @fabs_v3f128(<3 x fp128> %a) {
+; CHECK-SD-LABEL: fabs_v3f128:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: stp q0, q1, [sp, #-48]!
+; CHECK-SD-NEXT: .cfi_def_cfa_offset 48
+; CHECK-SD-NEXT: ldrb w8, [sp, #15]
+; CHECK-SD-NEXT: str q2, [sp, #32]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #15]
+; CHECK-SD-NEXT: ldrb w8, [sp, #31]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #31]
+; CHECK-SD-NEXT: ldrb w8, [sp, #47]
+; CHECK-SD-NEXT: ldp q0, q1, [sp]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #47]
+; CHECK-SD-NEXT: ldr q2, [sp, #32]
+; CHECK-SD-NEXT: add sp, sp, #48
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fabs_v3f128:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov x8, v0.d[1]
+; CHECK-GI-NEXT: mov x9, v1.d[1]
+; CHECK-GI-NEXT: mov x10, v2.d[1]
+; CHECK-GI-NEXT: mov v0.d[0], v0.d[0]
+; CHECK-GI-NEXT: mov v1.d[0], v1.d[0]
+; CHECK-GI-NEXT: mov v2.d[0], v2.d[0]
+; CHECK-GI-NEXT: and x8, x8, #0x7fffffffffffffff
+; CHECK-GI-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-GI-NEXT: and x10, x10, #0x7fffffffffffffff
+; CHECK-GI-NEXT: mov v0.d[1], x8
+; CHECK-GI-NEXT: mov v1.d[1], x9
+; CHECK-GI-NEXT: mov v2.d[1], x10
+; CHECK-GI-NEXT: ret
+entry:
+ %c = call <3 x fp128> @llvm.fabs.v3f128(<3 x fp128> %a)
+ ret <3 x fp128> %c
+}
+
+define <4 x fp128> @fabs_v4f128(<4 x fp128> %a) {
+; CHECK-SD-LABEL: fabs_v4f128:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: stp q0, q1, [sp, #-64]!
+; CHECK-SD-NEXT: .cfi_def_cfa_offset 64
+; CHECK-SD-NEXT: ldrb w8, [sp, #15]
+; CHECK-SD-NEXT: stp q2, q3, [sp, #32]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #15]
+; CHECK-SD-NEXT: ldrb w8, [sp, #31]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #31]
+; CHECK-SD-NEXT: ldrb w8, [sp, #47]
+; CHECK-SD-NEXT: ldp q0, q1, [sp]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #47]
+; CHECK-SD-NEXT: ldrb w8, [sp, #63]
+; CHECK-SD-NEXT: and w8, w8, #0x7f
+; CHECK-SD-NEXT: strb w8, [sp, #63]
+; CHECK-SD-NEXT: ldp q2, q3, [sp, #32]
+; CHECK-SD-NEXT: add sp, sp, #64
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fabs_v4f128:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov x8, v0.d[1]
+; CHECK-GI-NEXT: mov v7.d[0], v0.d[0]
+; CHECK-GI-NEXT: mov x9, v1.d[1]
+; CHECK-GI-NEXT: mov x10, v2.d[1]
+; CHECK-GI-NEXT: mov x11, v3.d[1]
+; CHECK-GI-NEXT: mov v1.d[0], v1.d[0]
+; CHECK-GI-NEXT: mov v2.d[0], v2.d[0]
+; CHECK-GI-NEXT: mov v3.d[0], v3.d[0]
+; CHECK-GI-NEXT: and x8, x8, #0x7fffffffffffffff
+; CHECK-GI-NEXT: mov v7.d[1], x8
+; CHECK-GI-NEXT: and x8, x9, #0x7fffffffffffffff
+; CHECK-GI-NEXT: and x9, x10, #0x7fffffffffffffff
+; CHECK-GI-NEXT: and x10, x11, #0x7fffffffffffffff
+; CHECK-GI-NEXT: mov v1.d[1], x8
+; CHECK-GI-NEXT: mov v2.d[1], x9
+; CHECK-GI-NEXT: mov v3.d[1], x10
+; CHECK-GI-NEXT: mov v0.16b, v7.16b
+; CHECK-GI-NEXT: ret
+entry:
+ %c = call <4 x fp128> @llvm.fabs.v4f128(<4 x fp128> %a)
+ ret <4 x fp128> %c
+}
+
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
More information about the llvm-commits
mailing list