From 1314859a8085a6cc4604532f054e92d0aa7890d0 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Tue, 11 Jul 2023 15:36:43 -0400 Subject: [PATCH] clmul-based pext emulation --- src/singeli/src/slash.singeli | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/singeli/src/slash.singeli b/src/singeli/src/slash.singeli index ce2473b6..ecffa66c 100644 --- a/src/singeli/src/slash.singeli +++ b/src/singeli/src/slash.singeli @@ -2,6 +2,12 @@ include './base' if (hasarch{'BMI2'}) { include './bmi2' } +if (hasarch{'PCLMUL'}) { + include './sse' # PCLMUL implies SSE4.2 + def clmul{a:T, b:T, imm & w128i{T}} = emit{T, '_mm_clmulepi64_si128', a, b, imm} +} else { + def clmul{...x} = assert{'clmul not supported', show{...x}} +} include 'util/tup' def storeu{p:T, i, v:eltype{T} & *u64==T} = emit{void, 'storeu_u64', p+i, v} @@ -102,4 +108,23 @@ fn pext{T}(x:T, m:T) { fold{|, b&s, each{gr, g*slice{iota{cdiv{w,g}},1}}} } +fn pext{T & hasarch{'PCLMUL'} & T==u64}(xs:T, ms:T) { + def num = lb{width{T}} + def V = [2]T + m := V**ms + x := V**xs & m + d := ~m << 1 # One bit of the position difference at x + c := V**(1<<64-1) + @unroll (i to num) { + def sh = 1 << i + def shift_at{v, s} = { v = (v&~s) | (v&s)>>sh } + p := clmul{d, c, 0} # xor-scan + d = d &~ p # Remove even bits + p &= m + shift_at{m, p} + shift_at{x, p} + } + extract{x, 0} +} + export{'si_pext_u64', pext{u64}}