Skip to content

Commit

Permalink
implement cdpopcnt for AArch64 (#20787)
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright authored Jan 27, 2025
1 parent b289b6a commit 2ca7960
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 44 deletions.
63 changes: 22 additions & 41 deletions compiler/src/dmd/backend/arm/cod4.d
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,6 @@ void cdmsw(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
// cdbtst
// cdbt
// cdbscan
// cdpopcnt

/************************
* OPpopcnt operator
Expand All @@ -1922,51 +1921,33 @@ void cdpopcnt(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
return;
}

/*
fmov d31, x0 9e67001f
cnt v31.8b, v31.8b 0e205bff
addv b31, v31.8b 132603e0
//umov w0, v0.b[0]
fmov w0,s31 1e2603e0
*/
if (e) assert(0);
const tyml = tybasic(e.E1.Ety);

const sz = _tysize[tyml];
assert(sz == 2 || sz == 4 || (sz == 8 && I64)); // no byte op

code cs = void;
if ((e.E1.Eoper == OPind && !e.E1.Ecount) || e.E1.Eoper == OPvar)
{
getlvalue(cdb, cs, e.E1, 0, RM.load); // get addressing mode
}
else
assert(sz == 8); // popcnt only operates on 64 bits
if (tyfloating(tyml))
{
regm_t retregs = cgstate.allregs;
codelem(cgstate,cdb,e.E1, retregs, false);
const reg = findreg(retregs);
cs.Irm = modregrm(3,0,reg & 7);
cs.Iflags = 0;
cs.Irex = 0;
if (reg & 8)
cs.Irex |= REX_B;
assert(0);
}

regm_t retregs = pretregs & cgstate.allregs;
if (!retregs)
retregs = cgstate.allregs;
const reg = allocreg(cdb,retregs, e.Ety);

cs.Iop = POPCNT; // POPCNT reg,EA
code_newreg(&cs, reg);
if (sz == SHORTSIZE)
cs.Iflags |= CFopsize;
if (pretregs & mPSW)
cs.Iflags |= CFpsw;
cdb.gen(&cs);
if (sz == 8)
code_orrex(cdb.last(), REX_W);
pretregs &= mBP | ALLREGS; // flags already set
const posregs = cgstate.allregs;
regm_t retregs1 = posregs;
codelem(cgstate,cdb,e.E1,retregs1,false);

regm_t retregs = pretregs & cg.allregs;
if (retregs == 0) /* if no return regs speced */
/* (like if wanted flags only) */
retregs = ALLREGS & posregs; // give us some
reg_t Rd = allocreg(cdb, retregs, tyml); // destination register

const R1 = findreg(retregs1); // source register

regm_t vregs = ALLREGS; // floating point register
reg_t Vx = allocreg(cdb, vregs, TYdouble);

cdb.gen1(INSTR.fmov_float_gen(1,1,0,7,R1,Vx)); // FMOV Dx,X1
cdb.gen1(INSTR.cnt_advsimd(0,0,Vx,Vx)); // CNT Vx.8b,Vx.8b
cdb.gen1(INSTR.addv_advsimd(0,0,Vx,Vx)); // ADDV Bx,Vx.8b
cdb.gen1(INSTR.fmov_float_gen(0,0,0,6,Vx,Rd)); // FMOV Wd,Sx

fixresult(cdb,e,retregs,pretregs);
}
Expand Down
9 changes: 7 additions & 2 deletions compiler/src/dmd/backend/arm/disasmarm.d
Original file line number Diff line number Diff line change
Expand Up @@ -1815,8 +1815,8 @@ void disassemble(uint c) @trusted
if (U == 0 && size == 0 && opcode == 0x05) // https://www.scs.stanford.edu/~zyedidia/arm64/cnt_advsimd.html
{
p1 = "cnt"; // cnt <Vd>.<T>, <Vn>.<T>
p2 = vregString(rbuf[0 .. 7], Rd, Q);
p3 = vregString(rbuf[8 .. 14], Rn, Q);
p2 = vregString(rbuf[0 .. 7], Q, Rd);
p3 = vregString(rbuf[8 .. 14], Q, Rn);
//printf("p2: %.*s p3: %.*s\n", cast(int)p2.length, p2.ptr, cast(int)p3.length, p3.ptr);
}
else if (U == 0 && (size & 2) && opcode == 0x1B) // https://www.scs.stanford.edu/~zyedidia/arm64/fcvtzs_advsimd_int.html
Expand Down Expand Up @@ -1945,6 +1945,11 @@ void disassemble(uint c) @trusted
p2 = regString(sf,Rd);
p3 = fregString(rbuf[4 .. 8],"sd h"[ftype],Rn);
}
else if (sf == 1 && ftype == 1 && rmode == 0 && opcode == 7)
{
p2 = fregString(rbuf[4 .. 8],"sd h"[ftype],Rd);
p3 = regString(sf,Rn);
}
}
}
else
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dmd/target.d
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ extern (C++) struct Target
extern (C++) void _init(ref const Param params)
{
// isX86_64 and cpu are initialized in parseCommandLine
isX86 = !isX86_64;
//printf("isX86_64 %d isAArch64 %d\n", isX86_64, isAArch64);
isX86 = !isX86_64 && !isAArch64;
assert(isX86 + isX86_64 + isAArch64 == 1); // there can be only one

this.params = &params;
Expand Down
5 changes: 5 additions & 0 deletions druntime/src/core/bitop.d
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,11 @@ private int softPopcnt(N)(N x) pure
return cast(int) x;
}

version (DigitalMars) version (AArch64)
{
int _popcnt(ulong x) pure;
}

version (DigitalMars) version (AnyX86)
{
/**
Expand Down

0 comments on commit 2ca7960

Please sign in to comment.