* [PATCH 1/2] lpm: load tbl24 entries up front in scalar lookupx4
2026-10-05 6:30 [PATCH 0/2] lpm: use scalar lookupx4 on RISC-V Sun Yuechi
@ 2026-10-05 6:30 ` Sun Yuechi
2026-10-05 6:30 ` [PATCH 2/2] lpm: use scalar lookupx4 on RISC-V Sun Yuechi
1 sibling, 0 replies; 3+ messages in thread
From: Sun Yuechi @ 2026-10-05 6:30 UTC (permalink / raw)
To: Bruce Richardson, Vladimir Medvedkin; +Cc: dev, Sun Yuechi
Read the four tbl24 entries before resolving any of them, as the SSE
and NEON versions do. On an in-order core the cache misses then
overlap instead of being served one after another.
Signed-off-by: Sun Yuechi <sunyuechi@iscas.ac.cn>
---
lib/lpm/rte_lpm_scalar.h | 40 +++++++++++++++++++++++++++++-----------
1 file changed, 29 insertions(+), 11 deletions(-)
diff --git a/lib/lpm/rte_lpm_scalar.h b/lib/lpm/rte_lpm_scalar.h
index df4f83fa48..9ad25838fd 100644
--- a/lib/lpm/rte_lpm_scalar.h
+++ b/lib/lpm/rte_lpm_scalar.h
@@ -13,22 +13,40 @@
extern "C" {
#endif
+static inline uint32_t
+__rte_lpm_lookupx4_hop(const struct rte_lpm *lpm, uint32_t tbl_entry,
+ uint32_t ip, uint32_t defv)
+{
+ if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+ RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+ const uint32_t *tbl8 = (const uint32_t *)lpm->tbl8;
+
+ tbl_entry = tbl8[(uint8_t)ip + (tbl_entry & 0x00FFFFFF) *
+ RTE_LPM_TBL8_GROUP_NUM_ENTRIES];
+ }
+
+ return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ?
+ (tbl_entry & 0x00FFFFFF) : defv;
+}
+
static inline void
rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
uint32_t defv)
{
rte_xmm_t xip = { .x = ip };
- uint32_t nh;
- int ret;
-
- ret = rte_lpm_lookup(lpm, xip.u32[0], &nh);
- hop[0] = (ret == 0) ? nh : defv;
- ret = rte_lpm_lookup(lpm, xip.u32[1], &nh);
- hop[1] = (ret == 0) ? nh : defv;
- ret = rte_lpm_lookup(lpm, xip.u32[2], &nh);
- hop[2] = (ret == 0) ? nh : defv;
- ret = rte_lpm_lookup(lpm, xip.u32[3], &nh);
- hop[3] = (ret == 0) ? nh : defv;
+ const uint32_t *tbl24 = (const uint32_t *)lpm->tbl24;
+ uint32_t tbl0, tbl1, tbl2, tbl3;
+
+ /* Issue the four tbl24 loads before any entry is examined. */
+ tbl0 = tbl24[xip.u32[0] >> 8];
+ tbl1 = tbl24[xip.u32[1] >> 8];
+ tbl2 = tbl24[xip.u32[2] >> 8];
+ tbl3 = tbl24[xip.u32[3] >> 8];
+
+ hop[0] = __rte_lpm_lookupx4_hop(lpm, tbl0, xip.u32[0], defv);
+ hop[1] = __rte_lpm_lookupx4_hop(lpm, tbl1, xip.u32[1], defv);
+ hop[2] = __rte_lpm_lookupx4_hop(lpm, tbl2, xip.u32[2], defv);
+ hop[3] = __rte_lpm_lookupx4_hop(lpm, tbl3, xip.u32[3], defv);
}
#ifdef __cplusplus
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 2/2] lpm: use scalar lookupx4 on RISC-V
2026-10-05 6:30 [PATCH 0/2] lpm: use scalar lookupx4 on RISC-V Sun Yuechi
2026-10-05 6:30 ` [PATCH 1/2] lpm: load tbl24 entries up front in scalar lookupx4 Sun Yuechi
@ 2026-10-05 6:30 ` Sun Yuechi
1 sibling, 0 replies; 3+ messages in thread
From: Sun Yuechi @ 2026-10-05 6:30 UTC (permalink / raw)
To: Bruce Richardson, Vladimir Medvedkin; +Cc: dev, Sun Yuechi
The RVV lookupx4 loads tbl24 with scalar code and always issues a
masked gather for tbl8. With the previous patch the scalar version is
faster on every core tried, so remove the RVV one.
Signed-off-by: Sun Yuechi <sunyuechi@iscas.ac.cn>
---
lib/lpm/meson.build | 1 -
lib/lpm/rte_lpm.h | 2 --
lib/lpm/rte_lpm_rvv.h | 59 -------------------------------------------
3 files changed, 62 deletions(-)
delete mode 100644 lib/lpm/rte_lpm_rvv.h
diff --git a/lib/lpm/meson.build b/lib/lpm/meson.build
index c4522eaf0c..cff8fed473 100644
--- a/lib/lpm/meson.build
+++ b/lib/lpm/meson.build
@@ -11,7 +11,6 @@ indirect_headers += files(
'rte_lpm_scalar.h',
'rte_lpm_sse.h',
'rte_lpm_sve.h',
- 'rte_lpm_rvv.h',
)
deps += ['hash']
deps += ['rcu']
diff --git a/lib/lpm/rte_lpm.h b/lib/lpm/rte_lpm.h
index 38a061513f..bcd3da9706 100644
--- a/lib/lpm/rte_lpm.h
+++ b/lib/lpm/rte_lpm.h
@@ -421,8 +421,6 @@ rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
#include "rte_lpm_altivec.h"
#elif defined(RTE_ARCH_X86)
#include "rte_lpm_sse.h"
-#elif defined(RTE_ARCH_RISCV) && defined(RTE_RISCV_FEATURE_V)
-#include "rte_lpm_rvv.h"
#else
#include "rte_lpm_scalar.h"
#endif
diff --git a/lib/lpm/rte_lpm_rvv.h b/lib/lpm/rte_lpm_rvv.h
deleted file mode 100644
index 0d3dc91055..0000000000
--- a/lib/lpm/rte_lpm_rvv.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright (c) 2025 Institute of Software Chinese Academy of Sciences (ISCAS).
- */
-
-#ifndef _RTE_LPM_RVV_H_
-#define _RTE_LPM_RVV_H_
-
-#include <rte_vect.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define RTE_LPM_LOOKUP_SUCCESS 0x01000000
-#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03000000
-
-static inline void rte_lpm_lookupx4(
- const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4], uint32_t defv)
-{
- size_t vl = 4;
-
- const uint32_t *tbl24_p = (const uint32_t *)lpm->tbl24;
- uint32_t tbl_entries[4] = {
- tbl24_p[((uint32_t)ip[0]) >> 8],
- tbl24_p[((uint32_t)ip[1]) >> 8],
- tbl24_p[((uint32_t)ip[2]) >> 8],
- tbl24_p[((uint32_t)ip[3]) >> 8],
- };
- vuint32m1_t vtbl_entry = __riscv_vle32_v_u32m1(tbl_entries, vl);
-
- vbool32_t mask = __riscv_vmseq_vx_u32m1_b32(
- __riscv_vand_vx_u32m1(vtbl_entry, RTE_LPM_VALID_EXT_ENTRY_BITMASK, vl),
- RTE_LPM_VALID_EXT_ENTRY_BITMASK, vl);
-
- vuint32m1_t vtbl8_index = __riscv_vsll_vx_u32m1(
- __riscv_vadd_vv_u32m1(
- __riscv_vsll_vx_u32m1(__riscv_vand_vx_u32m1(vtbl_entry, 0x00FFFFFF, vl), 8, vl),
- __riscv_vand_vx_u32m1(
- __riscv_vle32_v_u32m1((const uint32_t *)&ip, vl), 0x000000FF, vl),
- vl),
- 2, vl);
-
- vtbl_entry = __riscv_vluxei32_v_u32m1_mu(
- mask, vtbl_entry, (const uint32_t *)(lpm->tbl8), vtbl8_index, vl);
-
- vuint32m1_t vnext_hop = __riscv_vand_vx_u32m1(vtbl_entry, 0x00FFFFFF, vl);
- mask = __riscv_vmseq_vx_u32m1_b32(
- __riscv_vand_vx_u32m1(vtbl_entry, RTE_LPM_LOOKUP_SUCCESS, vl), 0, vl);
-
- vnext_hop = __riscv_vmerge_vxm_u32m1(vnext_hop, defv, mask, vl);
-
- __riscv_vse32_v_u32m1(hop, vnext_hop, vl);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RTE_LPM_RVV_H_ */
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread