Skip to content

[SDag][ARM][RISCV] Allow lowering CTPOP into a libcall #99752

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

Merged
merged 9 commits into from
Aug 2, 2024

Conversation

s-barannikov
Copy link
Contributor

@s-barannikov s-barannikov commented Jul 20, 2024

The main change is adding CTPOP to RuntimeLibcalls.def to allow
targets to use LibCall action for CTPOP. DAG legalizers are changed
accordingly.

@llvmbot llvmbot added llvm:SelectionDAG SelectionDAGISel as well llvm:ir labels Jul 20, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 20, 2024

@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-backend-loongarch
@llvm/pr-subscribers-llvm-analysis
@llvm/pr-subscribers-backend-arm
@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-llvm-selectiondag

Author: Sergei Barannikov (s-barannikov)

Changes

Some in-tree targets (e.g. ARM) could benefit from this lowering, at least in opt-size mode, but I don't know if the libcall is available in their libgcc, so no tests.


Full diff: https://github.com/llvm/llvm-project/pull/99752.diff

2 Files Affected:

  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.def (+3)
  • (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (+21-21)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def
index 89aaf6d1ad83f..3dd75622b8e43 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -85,6 +85,9 @@ HANDLE_LIBCALL(NEG_I64, "__negdi2")
 HANDLE_LIBCALL(CTLZ_I32, "__clzsi2")
 HANDLE_LIBCALL(CTLZ_I64, "__clzdi2")
 HANDLE_LIBCALL(CTLZ_I128, "__clzti2")
+HANDLE_LIBCALL(CTPOP_I32, "__popcountsi2")
+HANDLE_LIBCALL(CTPOP_I64, "__popcountdi2")
+HANDLE_LIBCALL(CTPOP_I128, "__popcountti2")
 
 // Floating-point
 HANDLE_LIBCALL(ADD_F32, "__addsf3")
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 9f515739ee048..c0141cfc533b7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -140,12 +140,9 @@ class SelectionDAGLegalize {
                        RTLIB::Libcall Call_F128,
                        RTLIB::Libcall Call_PPCF128,
                        SmallVectorImpl<SDValue> &Results);
-  SDValue ExpandIntLibCall(SDNode *Node, bool isSigned,
-                           RTLIB::Libcall Call_I8,
-                           RTLIB::Libcall Call_I16,
-                           RTLIB::Libcall Call_I32,
-                           RTLIB::Libcall Call_I64,
-                           RTLIB::Libcall Call_I128);
+  SDValue ExpandIntLibCall(SDNode *Node, bool IsSigned, RTLIB::Libcall Call_I8,
+                           RTLIB::Libcall Call_I16, RTLIB::Libcall Call_I32,
+                           RTLIB::Libcall Call_I64, RTLIB::Libcall Call_I128);
   void ExpandArgFPLibCall(SDNode *Node,
                           RTLIB::Libcall Call_F32, RTLIB::Libcall Call_F64,
                           RTLIB::Libcall Call_F80, RTLIB::Libcall Call_F128,
@@ -2209,7 +2206,7 @@ void SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node,
   ExpandFPLibCall(Node, LC, Results);
 }
 
-SDValue SelectionDAGLegalize::ExpandIntLibCall(SDNode* Node, bool isSigned,
+SDValue SelectionDAGLegalize::ExpandIntLibCall(SDNode *Node, bool IsSigned,
                                                RTLIB::Libcall Call_I8,
                                                RTLIB::Libcall Call_I16,
                                                RTLIB::Libcall Call_I32,
@@ -2224,7 +2221,9 @@ SDValue SelectionDAGLegalize::ExpandIntLibCall(SDNode* Node, bool isSigned,
   case MVT::i64:  LC = Call_I64; break;
   case MVT::i128: LC = Call_I128; break;
   }
-  return ExpandLibCall(LC, Node, isSigned).first;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL &&
+         "LibCall explicitly requested, but not available");
+  return ExpandLibCall(LC, Node, IsSigned).first;
 }
 
 /// Expand the node to a libcall based on first argument type (for instance
@@ -4980,19 +4979,20 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
                                        RTLIB::MUL_I64, RTLIB::MUL_I128));
     break;
   case ISD::CTLZ_ZERO_UNDEF:
-    switch (Node->getSimpleValueType(0).SimpleTy) {
-    default:
-      llvm_unreachable("LibCall explicitly requested, but not available");
-    case MVT::i32:
-      Results.push_back(ExpandLibCall(RTLIB::CTLZ_I32, Node, false).first);
-      break;
-    case MVT::i64:
-      Results.push_back(ExpandLibCall(RTLIB::CTLZ_I64, Node, false).first);
-      break;
-    case MVT::i128:
-      Results.push_back(ExpandLibCall(RTLIB::CTLZ_I128, Node, false).first);
-      break;
-    }
+    Results.push_back(ExpandIntLibCall(Node, /*IsSigned=*/false,
+                                       RTLIB::UNKNOWN_LIBCALL,
+                                       RTLIB::UNKNOWN_LIBCALL,
+                                       RTLIB::CTLZ_I32,
+                                       RTLIB::CTLZ_I64,
+                                       RTLIB::CTLZ_I128));
+    break;
+  case ISD::CTPOP:
+    Results.push_back(ExpandIntLibCall(Node, /*IsSigned=*/false,
+                                       RTLIB::UNKNOWN_LIBCALL,
+                                       RTLIB::UNKNOWN_LIBCALL,
+                                       RTLIB::CTPOP_I32,
+                                       RTLIB::CTPOP_I64,
+                                       RTLIB::CTPOP_I128));
     break;
   case ISD::RESET_FPENV: {
     // It is legalized to call 'fesetenv(FE_DFL_ENV)'. On most targets

Copy link

github-actions bot commented Jul 20, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Some in-tree targets (e.g. ARM) could benefit from this lowering,
at least in opt-size mode, but I don't know if the libcall
is available in their libgcc, so no tests.
@tschuett
Copy link

Dead code?

@arsenm
Copy link
Contributor

arsenm commented Jul 21, 2024

but I don't know if the libcall is available in their libgcc

Should be easy to find out?

@s-barannikov
Copy link
Contributor Author

but I don't know if the libcall is available in their libgcc

Should be easy to find out?

Right. It appears it is available and gcc uses it for __builtin_popcount[l,ll] even when optimizing for speed (-Ofast).
There is no 128-bit version though.
I'll update the PR.

@s-barannikov s-barannikov marked this pull request as draft July 21, 2024 10:12
@s-barannikov s-barannikov requested a review from RKSimon July 21, 2024 12:28
@s-barannikov s-barannikov changed the title [SelectionDAG] Allow lowering CTPOP into a libcall [SDag][ARM][RISCV] Lower 64-bit CTPOP into a libcall Jul 21, 2024
@s-barannikov s-barannikov marked this pull request as ready for review July 21, 2024 12:51
@s-barannikov s-barannikov changed the title [SDag][ARM][RISCV] Lower 64-bit CTPOP into a libcall [SDag][ARM][RISCV] Allow lowering CTPOP into a libcall Jul 21, 2024
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: sext.w a0, a0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__popcountsi2 should be returning a sign extended result right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, this is probably a bug specific to rv64-legal-i32 which is still experimental.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried setting IsSExt to true in MakeLibCallOptions, but that changed nothing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears 32-bit libcall is not available in 64-bit libgcc. I reverted to Expand action for rv64-legal-i32.

@s-barannikov
Copy link
Contributor Author

ping

Comment on lines +143 to +145
SDValue ExpandIntLibCall(SDNode *Node, bool IsSigned, RTLIB::Libcall Call_I8,
RTLIB::Libcall Call_I16, RTLIB::Libcall Call_I32,
RTLIB::Libcall Call_I64, RTLIB::Libcall Call_I128);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a lot of unrelated format changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed isSigned -> IsSigned while I was here, clang-format insisted that I reformat this code fragment.
Do I need to revert these changes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, didn't notice the capital letter change. I don't think it's necessary to change then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can precommit this unrelated change

@s-barannikov
Copy link
Contributor Author

@topperc
Please take a look. Are RISC-V changes OK?

@topperc
Copy link
Collaborator

topperc commented Aug 1, 2024

@topperc Please take a look. Are RISC-V changes OK?

RISC-V changes look ok.

@s-barannikov s-barannikov merged commit 92e18ff into llvm:main Aug 2, 2024
7 checks passed
@s-barannikov
Copy link
Contributor Author

s-barannikov commented Aug 2, 2024

This is likely causing armv7/v8 stage2 build failures (other changes don't look related):
https://lab.llvm.org/buildbot/#/builders/135/builds/554
https://lab.llvm.org/buildbot/#/builders/122/builds/389
https://lab.llvm.org/buildbot/#/builders/79/builds/552

I don't have an ARM machine handy to investigate, so I'll just revert the ARM changes and see if it helps.

@DavidSpickett
Copy link
Collaborator

@antmox should be able to help you figure it out, he's maintaining the bots this week.

@s-barannikov
Copy link
Contributor Author

@antmox Could you please take a look? I've already reverted the changes, but I'd like to reland them if they're not the reason of the failures.

@s-barannikov
Copy link
Contributor Author

The reversal made the bots green.

I think I understood what the issue is. All popcount libcalls returns int, but ISD::CTPOP returns the type of the argument, which can be larger. In type legalizer I need to pass the correct return type to makeLibCall and sign-extend the result afterwards.

I'll revert the rest of the patch because the issue should affect RISC-V as well.

@s-barannikov s-barannikov deleted the popcount-libcall branch August 2, 2024 19:31
s-barannikov added a commit that referenced this pull request Aug 2, 2024
@s-barannikov s-barannikov restored the popcount-libcall branch August 2, 2024 19:45
s-barannikov added a commit that referenced this pull request Aug 2, 2024
@s-barannikov s-barannikov deleted the popcount-libcall branch August 3, 2024 03:51
s-barannikov added a commit to s-barannikov/llvm-project that referenced this pull request Aug 3, 2024
The main change is adding CTPOP to `RuntimeLibcalls.def` to allow
targets to use LibCall action for CTPOP. DAG legalizers are changed
accordingly.
s-barannikov added a commit that referenced this pull request Apr 23, 2025
This is a reland of #99752 with the bug fixed (see test diff in the
third commit in this PR).
All `popcount` libcalls return `int`, but `ISD::CTPOP` returns the type
of the argument, which can be wider than `int`. The fix is to make DAG
legalizer pass the correct return type to `makeLibCall` and sign-extend
the result afterwards.

Original commit message:
The main change is adding CTPOP to `RuntimeLibcalls.def` to allow
targets to use LibCall action for CTPOP. DAG legalizers are changed
accordingly.

Pull Request: #101786
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
This is a reland of llvm#99752 with the bug fixed (see test diff in the
third commit in this PR).
All `popcount` libcalls return `int`, but `ISD::CTPOP` returns the type
of the argument, which can be wider than `int`. The fix is to make DAG
legalizer pass the correct return type to `makeLibCall` and sign-extend
the result afterwards.

Original commit message:
The main change is adding CTPOP to `RuntimeLibcalls.def` to allow
targets to use LibCall action for CTPOP. DAG legalizers are changed
accordingly.

Pull Request: llvm#101786
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
This is a reland of llvm#99752 with the bug fixed (see test diff in the
third commit in this PR).
All `popcount` libcalls return `int`, but `ISD::CTPOP` returns the type
of the argument, which can be wider than `int`. The fix is to make DAG
legalizer pass the correct return type to `makeLibCall` and sign-extend
the result afterwards.

Original commit message:
The main change is adding CTPOP to `RuntimeLibcalls.def` to allow
targets to use LibCall action for CTPOP. DAG legalizers are changed
accordingly.

Pull Request: llvm#101786
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
This is a reland of llvm#99752 with the bug fixed (see test diff in the
third commit in this PR).
All `popcount` libcalls return `int`, but `ISD::CTPOP` returns the type
of the argument, which can be wider than `int`. The fix is to make DAG
legalizer pass the correct return type to `makeLibCall` and sign-extend
the result afterwards.

Original commit message:
The main change is adding CTPOP to `RuntimeLibcalls.def` to allow
targets to use LibCall action for CTPOP. DAG legalizers are changed
accordingly.

Pull Request: llvm#101786
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants