-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[AArch64][GlobalISel] Extend scalar lrint legalization. #88360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-aarch64 Author: David Green (davemgreen) ChangesThis extends the legalization of lrint, adding libcall support for fp128. The old vector legal types were removed as they were not being properly handled (vector lrint is a fairly new concept as far as I understand). They can be re-added properly in a followup. Full diff: https://github.com/llvm/llvm-project/pull/88360.diff 7 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 95c6a359e52ec6..bd5f0685dca7ad 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -472,6 +472,8 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
RTLIBCASE(NEARBYINT_F);
case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
RTLIBCASE(ROUNDEVEN_F);
+ case TargetOpcode::G_INTRINSIC_LRINT:
+ RTLIBCASE(LRINT_F);
}
llvm_unreachable("Unknown libcall function");
}
@@ -1059,6 +1061,26 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
return Status;
break;
}
+ case TargetOpcode::G_INTRINSIC_LRINT: {
+ LLT LLTy = MRI.getType(MI.getOperand(1).getReg());
+ unsigned Size = LLTy.getSizeInBits();
+ Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
+ Type *ITy = IntegerType::get(
+ Ctx, MRI.getType(MI.getOperand(0).getReg()).getSizeInBits());
+ if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
+ LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
+ return UnableToLegalize;
+ }
+ auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
+ SmallVector<CallLowering::ArgInfo, 2> Args;
+ Args.push_back({MI.getOperand(1).getReg(), HLTy, 0});
+ LegalizeResult Status =
+ createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ITy, 0},
+ Args, LocObserver, &MI);
+ if (Status != Legalized)
+ return Status;
+ break;
+ }
case TargetOpcode::G_FPOWI: {
LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
unsigned Size = LLTy.getSizeInBits();
@@ -2639,6 +2661,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
case TargetOpcode::G_FPTOSI:
case TargetOpcode::G_FPTOUI:
+ case TargetOpcode::G_INTRINSIC_LRINT:
case TargetOpcode::G_IS_FPCLASS:
Observer.changingInstr(MI);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 96ded69905f7cc..661ea151d1a0ce 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -263,23 +263,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.scalarize(0);
getActionDefinitionsBuilder(G_INTRINSIC_LRINT)
- // If we don't have full FP16 support, then scalarize the elements of
- // vectors containing fp16 types.
- .fewerElementsIf(
- [=, &ST](const LegalityQuery &Query) {
- const auto &Ty = Query.Types[0];
- return Ty.isVector() && Ty.getElementType() == s16 &&
- !ST.hasFullFP16();
- },
- [=](const LegalityQuery &Query) { return std::make_pair(0, s16); })
- // If we don't have full FP16 support, then widen s16 to s32 if we
- // encounter it.
- .widenScalarIf(
- [=, &ST](const LegalityQuery &Query) {
- return Query.Types[0] == s16 && !ST.hasFullFP16();
- },
- [=](const LegalityQuery &Query) { return std::make_pair(0, s32); })
- .legalFor({s16, s32, s64, v2s32, v4s32, v2s64, v2s16, v4s16, v8s16});
+ .legalFor({{s64, MinFPScalar}, {s64, s32}, {s64, s64}})
+ .libcallFor({{s64, s128}})
+ .minScalarOrElt(1, MinFPScalar);
getActionDefinitionsBuilder(
{G_FCOS, G_FSIN, G_FPOW, G_FLOG, G_FLOG2, G_FLOG10,
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index 58d000b6b2a9e1..d39de770eaf16e 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -829,6 +829,7 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
}
case TargetOpcode::G_FPTOSI:
case TargetOpcode::G_FPTOUI:
+ case TargetOpcode::G_INTRINSIC_LRINT:
if (MRI.getType(MI.getOperand(0).getReg()).isVector())
break;
OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 200e9d19d58d25..0793f3983c8e57 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -154,8 +154,8 @@
# 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_INTRINSIC_LRINT (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. the first uncovered type index: 2, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_INTRINSIC_ROUNDEVEN (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
diff --git a/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll b/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
index 7557ceac1212f7..6771a862c386fd 100644
--- a/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
+++ b/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
@@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK-NOFP16
; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK-FP16
+; RUN: llc < %s -mtriple=aarch64 -global-isel | FileCheck %s --check-prefixes=CHECK-NOFP16
+; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 -global-isel | FileCheck %s --check-prefixes=CHECK-FP16
define i16 @testmhhs(half %x) {
; CHECK-NOFP16-LABEL: testmhhs:
diff --git a/llvm/test/CodeGen/AArch64/lrint-conv.ll b/llvm/test/CodeGen/AArch64/lrint-conv.ll
index b61d6f04b400e0..60393b4f18d9d0 100644
--- a/llvm/test/CodeGen/AArch64/lrint-conv.ll
+++ b/llvm/test/CodeGen/AArch64/lrint-conv.ll
@@ -1,9 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
-; RUN: llc < %s -mtriple=aarch64 -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-
-; CHECK-GI: warning: Instruction selection used fallback path for testmswl
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for testmsll
+; RUN: llc < %s -mtriple=aarch64 -global-isel | FileCheck %s
define i32 @testmsws(float %x) {
; CHECK-LABEL: testmsws:
diff --git a/llvm/test/CodeGen/AArch64/vector-lrint.ll b/llvm/test/CodeGen/AArch64/vector-lrint.ll
index b7fcd11ba8d164..db85b23428216a 100644
--- a/llvm/test/CodeGen/AArch64/vector-lrint.ll
+++ b/llvm/test/CodeGen/AArch64/vector-lrint.ll
@@ -2,8 +2,7 @@
; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK,CHECK-SD
; RUN: llc < %s -mtriple=aarch64 -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-; CHECK-GI: warning: Instruction selection used fallback path for lrint_v1f16
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v2f16
+; CHECK-GI: warning: Instruction selection used fallback path for lrint_v2f16
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v4f16
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v8f16
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v16i64_v16f16
|
@llvm/pr-subscribers-llvm-globalisel Author: David Green (davemgreen) ChangesThis extends the legalization of lrint, adding libcall support for fp128. The old vector legal types were removed as they were not being properly handled (vector lrint is a fairly new concept as far as I understand). They can be re-added properly in a followup. Full diff: https://github.com/llvm/llvm-project/pull/88360.diff 7 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 95c6a359e52ec6..bd5f0685dca7ad 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -472,6 +472,8 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
RTLIBCASE(NEARBYINT_F);
case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
RTLIBCASE(ROUNDEVEN_F);
+ case TargetOpcode::G_INTRINSIC_LRINT:
+ RTLIBCASE(LRINT_F);
}
llvm_unreachable("Unknown libcall function");
}
@@ -1059,6 +1061,26 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
return Status;
break;
}
+ case TargetOpcode::G_INTRINSIC_LRINT: {
+ LLT LLTy = MRI.getType(MI.getOperand(1).getReg());
+ unsigned Size = LLTy.getSizeInBits();
+ Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
+ Type *ITy = IntegerType::get(
+ Ctx, MRI.getType(MI.getOperand(0).getReg()).getSizeInBits());
+ if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
+ LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
+ return UnableToLegalize;
+ }
+ auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
+ SmallVector<CallLowering::ArgInfo, 2> Args;
+ Args.push_back({MI.getOperand(1).getReg(), HLTy, 0});
+ LegalizeResult Status =
+ createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ITy, 0},
+ Args, LocObserver, &MI);
+ if (Status != Legalized)
+ return Status;
+ break;
+ }
case TargetOpcode::G_FPOWI: {
LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
unsigned Size = LLTy.getSizeInBits();
@@ -2639,6 +2661,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
case TargetOpcode::G_FPTOSI:
case TargetOpcode::G_FPTOUI:
+ case TargetOpcode::G_INTRINSIC_LRINT:
case TargetOpcode::G_IS_FPCLASS:
Observer.changingInstr(MI);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 96ded69905f7cc..661ea151d1a0ce 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -263,23 +263,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.scalarize(0);
getActionDefinitionsBuilder(G_INTRINSIC_LRINT)
- // If we don't have full FP16 support, then scalarize the elements of
- // vectors containing fp16 types.
- .fewerElementsIf(
- [=, &ST](const LegalityQuery &Query) {
- const auto &Ty = Query.Types[0];
- return Ty.isVector() && Ty.getElementType() == s16 &&
- !ST.hasFullFP16();
- },
- [=](const LegalityQuery &Query) { return std::make_pair(0, s16); })
- // If we don't have full FP16 support, then widen s16 to s32 if we
- // encounter it.
- .widenScalarIf(
- [=, &ST](const LegalityQuery &Query) {
- return Query.Types[0] == s16 && !ST.hasFullFP16();
- },
- [=](const LegalityQuery &Query) { return std::make_pair(0, s32); })
- .legalFor({s16, s32, s64, v2s32, v4s32, v2s64, v2s16, v4s16, v8s16});
+ .legalFor({{s64, MinFPScalar}, {s64, s32}, {s64, s64}})
+ .libcallFor({{s64, s128}})
+ .minScalarOrElt(1, MinFPScalar);
getActionDefinitionsBuilder(
{G_FCOS, G_FSIN, G_FPOW, G_FLOG, G_FLOG2, G_FLOG10,
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index 58d000b6b2a9e1..d39de770eaf16e 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -829,6 +829,7 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
}
case TargetOpcode::G_FPTOSI:
case TargetOpcode::G_FPTOUI:
+ case TargetOpcode::G_INTRINSIC_LRINT:
if (MRI.getType(MI.getOperand(0).getReg()).isVector())
break;
OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 200e9d19d58d25..0793f3983c8e57 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -154,8 +154,8 @@
# 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_INTRINSIC_LRINT (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. the first uncovered type index: 2, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_INTRINSIC_ROUNDEVEN (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
diff --git a/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll b/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
index 7557ceac1212f7..6771a862c386fd 100644
--- a/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
+++ b/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
@@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK-NOFP16
; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK-FP16
+; RUN: llc < %s -mtriple=aarch64 -global-isel | FileCheck %s --check-prefixes=CHECK-NOFP16
+; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 -global-isel | FileCheck %s --check-prefixes=CHECK-FP16
define i16 @testmhhs(half %x) {
; CHECK-NOFP16-LABEL: testmhhs:
diff --git a/llvm/test/CodeGen/AArch64/lrint-conv.ll b/llvm/test/CodeGen/AArch64/lrint-conv.ll
index b61d6f04b400e0..60393b4f18d9d0 100644
--- a/llvm/test/CodeGen/AArch64/lrint-conv.ll
+++ b/llvm/test/CodeGen/AArch64/lrint-conv.ll
@@ -1,9 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
-; RUN: llc < %s -mtriple=aarch64 -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-
-; CHECK-GI: warning: Instruction selection used fallback path for testmswl
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for testmsll
+; RUN: llc < %s -mtriple=aarch64 -global-isel | FileCheck %s
define i32 @testmsws(float %x) {
; CHECK-LABEL: testmsws:
diff --git a/llvm/test/CodeGen/AArch64/vector-lrint.ll b/llvm/test/CodeGen/AArch64/vector-lrint.ll
index b7fcd11ba8d164..db85b23428216a 100644
--- a/llvm/test/CodeGen/AArch64/vector-lrint.ll
+++ b/llvm/test/CodeGen/AArch64/vector-lrint.ll
@@ -2,8 +2,7 @@
; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK,CHECK-SD
; RUN: llc < %s -mtriple=aarch64 -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-; CHECK-GI: warning: Instruction selection used fallback path for lrint_v1f16
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v2f16
+; CHECK-GI: warning: Instruction selection used fallback path for lrint_v2f16
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v4f16
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v8f16
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lrint_v16i64_v16f16
|
SmallVector<CallLowering::ArgInfo, 2> Args; | ||
Args.push_back({MI.getOperand(1).getReg(), HLTy, 0}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can do this in the initializer. Also don't need 2 size list for 1 element?
if (Status != Legalized) | ||
return Status; | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Erase the instruction and directly return? I don't know why the other cases here are mostly making you look to the end of the function to do the basic return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM, thanks. I don't mind changing the others too if you think it's a good idea.
This extends the legalization of lrint, adding libcall support for fp128. The old vector legal types were removed as they were not being properly handled (vector lrint is a fairly new concept as far as I understand). They can be re-added properly in a followup.
This extends the legalization of lrint, adding libcall support for fp128. The old vector legal types were removed as they were not being properly handled (vector lrint is a fairly new concept as far as I understand). They can be re-added properly in a followup.
This extends the legalization of lrint, adding libcall support for fp128. The old vector legal types were removed as they were not being properly handled (vector lrint is a fairly new concept as far as I understand). They can be re-added properly in a followup.
This extends the legalization of lrint, adding libcall support for fp128. The old vector legal types were removed as they were not being properly handled (vector lrint is a fairly new concept as far as I understand). They can be re-added properly in a followup.