[llvm] [SelectionDAG] Allow lowering CTPOP into a libcall (PR #99752)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 21 03:00:16 PDT 2024
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/99752
>From bb8a735facb710a07601d3bc9c45316f0de9d68d Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sat, 20 Jul 2024 13:11:56 +0300
Subject: [PATCH 1/2] [SelectionDAG] Allow lowering CTPOP into a libcall
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.
---
llvm/include/llvm/IR/RuntimeLibcalls.def | 3 ++
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 38 +++++++++----------
2 files changed, 20 insertions(+), 21 deletions(-)
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..bfae5671d8b77 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,16 @@ 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
>From 437a0e5d0e6f3688bc9d7de13a412bb234d7f574 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 21 Jul 2024 12:53:02 +0300
Subject: [PATCH 2/2] [ARM] Lower 32-bit CTPOP to a libcall
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 5 +-
llvm/lib/Target/ARM/ARMISelLowering.cpp | 2 +-
llvm/test/CodeGen/ARM/popcnt.ll | 70 +++---------------
llvm/test/CodeGen/Thumb2/mve-ctpop.ll | 74 +++++++------------
4 files changed, 40 insertions(+), 111 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 140c97ccd90ba..a273fafd3f4d6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9127,8 +9127,9 @@ SDValue TargetLowering::expandCTTZ(SDNode *Node, SelectionDAG &DAG) const {
!isOperationLegalOrCustomOrPromote(ISD::XOR, VT)))
return SDValue();
- // Emit Table Lookup if ISD::CTLZ and ISD::CTPOP are not legal.
- if (!VT.isVector() && isOperationExpand(ISD::CTPOP, VT) &&
+ // Emit Table Lookup if ISD::CTPOP used in the fallback path below is going
+ // to be expanded or converted to a libcall.
+ if (!VT.isVector() && !isOperationLegalOrCustomOrPromote(ISD::CTPOP, VT) &&
!isOperationLegal(ISD::CTLZ, VT))
if (SDValue V = CTTZTableLookup(Node, DAG, dl, VT, Op, NumBitsPerElt))
return V;
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 2683b5741d459..2c0fd20e76d60 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1204,7 +1204,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ROTR, VT, Expand);
}
setOperationAction(ISD::CTTZ, MVT::i32, Custom);
- setOperationAction(ISD::CTPOP, MVT::i32, Expand);
+ setOperationAction(ISD::CTPOP, MVT::i32, LibCall);
if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, LibCall);
diff --git a/llvm/test/CodeGen/ARM/popcnt.ll b/llvm/test/CodeGen/ARM/popcnt.ll
index edcae5e141e73..d3d66d6d52979 100644
--- a/llvm/test/CodeGen/ARM/popcnt.ll
+++ b/llvm/test/CodeGen/ARM/popcnt.ll
@@ -324,30 +324,7 @@ define i32 @ctpop16(i16 %x) nounwind readnone {
define i32 @ctpop32(i32 %x) nounwind readnone {
; CHECK-LABEL: ctpop32:
; CHECK: @ %bb.0:
-; CHECK-NEXT: ldr r1, .LCPI22_0
-; CHECK-NEXT: ldr r2, .LCPI22_3
-; CHECK-NEXT: and r1, r1, r0, lsr #1
-; CHECK-NEXT: ldr r12, .LCPI22_1
-; CHECK-NEXT: sub r0, r0, r1
-; CHECK-NEXT: ldr r3, .LCPI22_2
-; CHECK-NEXT: and r1, r0, r2
-; CHECK-NEXT: and r0, r2, r0, lsr #2
-; CHECK-NEXT: add r0, r1, r0
-; CHECK-NEXT: add r0, r0, r0, lsr #4
-; CHECK-NEXT: and r0, r0, r12
-; CHECK-NEXT: mul r1, r0, r3
-; CHECK-NEXT: lsr r0, r1, #24
-; CHECK-NEXT: mov pc, lr
-; CHECK-NEXT: .p2align 2
-; CHECK-NEXT: @ %bb.1:
-; CHECK-NEXT: .LCPI22_0:
-; CHECK-NEXT: .long 1431655765 @ 0x55555555
-; CHECK-NEXT: .LCPI22_1:
-; CHECK-NEXT: .long 252645135 @ 0xf0f0f0f
-; CHECK-NEXT: .LCPI22_2:
-; CHECK-NEXT: .long 16843009 @ 0x1010101
-; CHECK-NEXT: .LCPI22_3:
-; CHECK-NEXT: .long 858993459 @ 0x33333333
+; CHECK-NEXT: b __popcountsi2
%count = tail call i32 @llvm.ctpop.i32(i32 %x)
ret i32 %count
}
@@ -355,42 +332,17 @@ define i32 @ctpop32(i32 %x) nounwind readnone {
define i32 @ctpop64(i64 %x) nounwind readnone {
; CHECK-LABEL: ctpop64:
; CHECK: @ %bb.0:
-; CHECK-NEXT: .save {r4, lr}
-; CHECK-NEXT: push {r4, lr}
-; CHECK-NEXT: ldr r2, .LCPI23_0
-; CHECK-NEXT: ldr r3, .LCPI23_3
-; CHECK-NEXT: and r4, r2, r0, lsr #1
-; CHECK-NEXT: and r2, r2, r1, lsr #1
-; CHECK-NEXT: sub r0, r0, r4
-; CHECK-NEXT: sub r1, r1, r2
-; CHECK-NEXT: and r4, r0, r3
-; CHECK-NEXT: and r2, r1, r3
-; CHECK-NEXT: and r0, r3, r0, lsr #2
-; CHECK-NEXT: and r1, r3, r1, lsr #2
-; CHECK-NEXT: add r0, r4, r0
-; CHECK-NEXT: ldr lr, .LCPI23_1
-; CHECK-NEXT: add r1, r2, r1
-; CHECK-NEXT: ldr r12, .LCPI23_2
-; CHECK-NEXT: add r0, r0, r0, lsr #4
-; CHECK-NEXT: and r0, r0, lr
-; CHECK-NEXT: add r1, r1, r1, lsr #4
-; CHECK-NEXT: mul r2, r0, r12
-; CHECK-NEXT: and r0, r1, lr
-; CHECK-NEXT: mul r1, r0, r12
-; CHECK-NEXT: lsr r0, r2, #24
-; CHECK-NEXT: add r0, r0, r1, lsr #24
-; CHECK-NEXT: pop {r4, lr}
+; CHECK-NEXT: .save {r4, r5, r11, lr}
+; CHECK-NEXT: push {r4, r5, r11, lr}
+; CHECK-NEXT: mov r4, r0
+; CHECK-NEXT: mov r0, r1
+; CHECK-NEXT: bl __popcountsi2
+; CHECK-NEXT: mov r5, r0
+; CHECK-NEXT: mov r0, r4
+; CHECK-NEXT: bl __popcountsi2
+; CHECK-NEXT: add r0, r0, r5
+; CHECK-NEXT: pop {r4, r5, r11, lr}
; CHECK-NEXT: mov pc, lr
-; CHECK-NEXT: .p2align 2
-; CHECK-NEXT: @ %bb.1:
-; CHECK-NEXT: .LCPI23_0:
-; CHECK-NEXT: .long 1431655765 @ 0x55555555
-; CHECK-NEXT: .LCPI23_1:
-; CHECK-NEXT: .long 252645135 @ 0xf0f0f0f
-; CHECK-NEXT: .LCPI23_2:
-; CHECK-NEXT: .long 16843009 @ 0x1010101
-; CHECK-NEXT: .LCPI23_3:
-; CHECK-NEXT: .long 858993459 @ 0x33333333
%count = tail call i64 @llvm.ctpop.i64(i64 %x)
%conv = trunc i64 %count to i32
ret i32 %conv
diff --git a/llvm/test/CodeGen/Thumb2/mve-ctpop.ll b/llvm/test/CodeGen/Thumb2/mve-ctpop.ll
index 724bd4f7963b8..dcba42db886ae 100644
--- a/llvm/test/CodeGen/Thumb2/mve-ctpop.ll
+++ b/llvm/test/CodeGen/Thumb2/mve-ctpop.ll
@@ -1,58 +1,34 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; NOTE: Assertions have been autoenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK
define arm_aapcs_vfpcc <2 x i64> @ctpop_2i64_t(<2 x i64> %src){
; CHECK-LABEL: ctpop_2i64_t:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: .save {r4, r5, r7, lr}
-; CHECK-NEXT: push {r4, r5, r7, lr}
-; CHECK-NEXT: vmov r1, r2, d1
-; CHECK-NEXT: mov.w lr, #1431655765
-; CHECK-NEXT: vmov r3, r4, d0
-; CHECK-NEXT: mov.w r12, #858993459
-; CHECK-NEXT: vldr s1, .LCPI0_0
-; CHECK-NEXT: vmov.f32 s3, s1
-; CHECK-NEXT: and.w r0, lr, r2, lsr #1
-; CHECK-NEXT: subs r0, r2, r0
-; CHECK-NEXT: and.w r2, r12, r0, lsr #2
-; CHECK-NEXT: bic r0, r0, #-858993460
-; CHECK-NEXT: add r0, r2
-; CHECK-NEXT: and.w r2, lr, r1, lsr #1
-; CHECK-NEXT: subs r1, r1, r2
-; CHECK-NEXT: add.w r0, r0, r0, lsr #4
-; CHECK-NEXT: and.w r2, r12, r1, lsr #2
-; CHECK-NEXT: bic r1, r1, #-858993460
-; CHECK-NEXT: add r1, r2
-; CHECK-NEXT: and.w r2, lr, r3, lsr #1
-; CHECK-NEXT: subs r2, r3, r2
-; CHECK-NEXT: bic r5, r0, #-252645136
-; CHECK-NEXT: add.w r1, r1, r1, lsr #4
-; CHECK-NEXT: mov.w r0, #16843009
-; CHECK-NEXT: and.w r3, r12, r2, lsr #2
-; CHECK-NEXT: bic r2, r2, #-858993460
-; CHECK-NEXT: add r2, r3
-; CHECK-NEXT: and.w r3, lr, r4, lsr #1
-; CHECK-NEXT: subs r3, r4, r3
-; CHECK-NEXT: bic r1, r1, #-252645136
-; CHECK-NEXT: add.w r2, r2, r2, lsr #4
-; CHECK-NEXT: muls r5, r0, r5
-; CHECK-NEXT: and.w r4, r12, r3, lsr #2
-; CHECK-NEXT: bic r3, r3, #-858993460
-; CHECK-NEXT: bic r2, r2, #-252645136
-; CHECK-NEXT: add r3, r4
-; CHECK-NEXT: muls r1, r0, r1
-; CHECK-NEXT: add.w r3, r3, r3, lsr #4
-; CHECK-NEXT: muls r2, r0, r2
-; CHECK-NEXT: bic r3, r3, #-252645136
-; CHECK-NEXT: muls r0, r3, r0
-; CHECK-NEXT: lsrs r1, r1, #24
-; CHECK-NEXT: add.w r1, r1, r5, lsr #24
-; CHECK-NEXT: lsrs r2, r2, #24
-; CHECK-NEXT: vmov s2, r1
-; CHECK-NEXT: add.w r0, r2, r0, lsr #24
-; CHECK-NEXT: vmov s0, r0
-; CHECK-NEXT: pop {r4, r5, r7, pc}
+; CHECK-NEXT: .save {r4, r5, r6, lr}
+; CHECK-NEXT: push {r4, r5, r6, lr}
+; CHECK-NEXT: .vsave {d8, d9}
+; CHECK-NEXT: vpush {d8, d9}
+; CHECK-NEXT: vmov q4, q0
+; CHECK-NEXT: vmov r4, r0, d9
+; CHECK-NEXT: bl __popcountsi2
+; CHECK-NEXT: mov r5, r0
+; CHECK-NEXT: mov r0, r4
+; CHECK-NEXT: bl __popcountsi2
+; CHECK-NEXT: vmov r4, r1, d8
+; CHECK-NEXT: adds r6, r0, r5
+; CHECK-NEXT: vldr s17, .LCPI0_0
+; CHECK-NEXT: mov r0, r1
+; CHECK-NEXT: bl __popcountsi2
+; CHECK-NEXT: mov r5, r0
+; CHECK-NEXT: mov r0, r4
+; CHECK-NEXT: vmov s18, r6
+; CHECK-NEXT: bl __popcountsi2
+; CHECK-NEXT: add r0, r5
+; CHECK-NEXT: vmov.f32 s19, s17
+; CHECK-NEXT: vmov s16, r0
+; CHECK-NEXT: vmov q0, q4
+; CHECK-NEXT: vpop {d8, d9}
+; CHECK-NEXT: pop {r4, r5, r6, pc}
; CHECK-NEXT: .p2align 2
; CHECK-NEXT: @ %bb.1:
; CHECK-NEXT: .LCPI0_0:
More information about the llvm-commits
mailing list