Skip to content

improved cdmemset() #21509

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 1 commit into from
Jul 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion compiler/src/dmd/backend/arm/cod1.d
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@
getf2,
lttf2,
letf2,

memset,
}

private
Expand Down Expand Up @@ -1455,6 +1455,14 @@
case CLIB_A.gttf2: declare("__gttf2"); break;
case CLIB_A.getf2: declare("__getf2"); break;

case CLIB_A.memset:

Check warning on line 1458 in compiler/src/dmd/backend/arm/cod1.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod1.d#L1458

Added line #L1458 was not covered by tests
{
string name = "memset";
s = symboly(name, mask(0));
cinfo.retregs = mask(0);
break;

Check warning on line 1463 in compiler/src/dmd/backend/arm/cod1.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod1.d#L1460-L1463

Added lines #L1460 - L1463 were not covered by tests
}

default:
assert(0);
}
Expand Down
135 changes: 41 additions & 94 deletions compiler/src/dmd/backend/arm/cod2.d
Original file line number Diff line number Diff line change
Expand Up @@ -1185,39 +1185,22 @@
return;
}

bool valueIsConst = false;
targ_size_t value;
if (evalue.Eoper == OPconst)
if (enumbytes.Eoper == OPconst ||
evalue.Eoper == OPstrpar) // happens if evalue is a struct of 0 size

Check warning on line 1189 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1188-L1189

Added lines #L1188 - L1189 were not covered by tests
{
value = el_tolong(evalue) & 0xFF;
value |= value << 8;
value |= value << 16;
value |= value << 32;
valueIsConst = true;
}
else if (evalue.Eoper == OPstrpar) // happens if evalue is a struct of 0 size
{
value = 0;
valueIsConst = true;
}
else
value = 0xDEADBEEF; // stop annoying false positives that value is not inited

// Get nbytes into CX
regm_t nbytesregs = 0;
if (enumbytes.Eoper != OPconst)
{
nbytesregs = cgstate.allregs & ~pretregs;
// Get nbytes into nbytesreg
regm_t nbytesregs = cgstate.allregs & ~pretregs;

Check warning on line 1192 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1192

Added line #L1192 was not covered by tests
if (!nbytesregs)
nbytesregs = cgstate.allregs;
codelem(cgstate,cdb,enumbytes,nbytesregs,false);
}

// Get value into valuereg
regm_t valueregs;
reg_t valuereg;
if (valueIsConst)
{
ulong value = evalue.Eoper == OPstrpar ? 0 : el_tolong(evalue) & 0xFF;
value |= value << 8;
value |= value << 16;
value |= value << 32;

Check warning on line 1200 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1197-L1200

Added lines #L1197 - L1200 were not covered by tests

regm_t valueregs;
reg_t valuereg;

Check warning on line 1203 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1202-L1203

Added lines #L1202 - L1203 were not covered by tests
if (value == 0)
{
valueregs = 0;
Expand All @@ -1228,43 +1211,31 @@
valueregs = cgstate.allregs & ~(pretregs | nbytesregs);
if (!valueregs)
valueregs = cgstate.allregs & ~nbytesregs;
regwithvalue(cdb, valueregs, value, 64);
valuereg = regwithvalue(cdb, valueregs, value, 64);
valueregs = mask(valuereg);

Check warning on line 1215 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1214-L1215

Added lines #L1214 - L1215 were not covered by tests
getregs(cdb, valueregs);
valuereg = findreg(valueregs);
cgstate.regimmed_set(valuereg, value);
}
freenode(evalue);
}
else
{
scodelem(cgstate,cdb,evalue,valueregs,nbytesregs,false);

valuereg = findreg(valueregs);
getregs(cdb,valueregs);

regm_t regm = cgstate.allregs & ~(valueregs | nbytesregs);
const r = regwithvalue(cdb,regm,cast(targ_size_t)0x01010101_01010101,64); // MOV r,0x01010101_01010101
cdb.gen2(0x0FAF,modregrmx(3,valuereg,r)); // IMUL valuereg,r
}
freenode(e2);
freenode(e2);

Check warning on line 1222 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1222

Added line #L1222 was not covered by tests

// Get destination into dstreg
regm_t dstregs = cgstate.allregs & ~(nbytesregs | valueregs);
scodelem(cgstate,cdb,e.E1,dstregs,nbytesregs | valueregs,false);
reg_t dstreg = findreg(dstregs);
// Get destination into dstreg
regm_t dstregs = cgstate.allregs & ~(nbytesregs | valueregs);
scodelem(cgstate,cdb,e.E1,dstregs,nbytesregs | valueregs,false);
reg_t dstreg = findreg(dstregs);

Check warning on line 1227 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1225-L1227

Added lines #L1225 - L1227 were not covered by tests

regm_t retregs;
if (pretregs) // if need return value
{
retregs = pretregs & ~(nbytesregs | valueregs | dstregs);
if (!retregs)
retregs = cgstate.allregs & ~(nbytesregs | valueregs | dstregs);
reg_t retreg = allocreg(cdb,retregs,TYnptr);
genmovreg(cdb,retreg,dstreg); // MOV retreg,dstreg
}
regm_t retregs;
if (pretregs) // if need return value

Check warning on line 1230 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1229-L1230

Added lines #L1229 - L1230 were not covered by tests
{
retregs = pretregs & ~(nbytesregs | valueregs | dstregs);
if (!retregs)
retregs = cgstate.allregs & ~(nbytesregs | valueregs | dstregs);
reg_t retreg = allocreg(cdb,retregs,TYnptr);
genmovreg(cdb,retreg,dstreg); // MOV retreg,dstreg

Check warning on line 1236 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1232-L1236

Added lines #L1232 - L1236 were not covered by tests
}

if (enumbytes.Eoper == OPconst)
{
uint numbytes = cast(uint)el_tolong(enumbytes);
if (const n = numbytes & ~(REGSIZE - 1))
{
Expand Down Expand Up @@ -1292,50 +1263,26 @@
return;
}

// TODO AArch64

getregs(cdb,mDI | mCX);

/* MOV sreg,ECX
SHR ECX,n
REP
STOSD/Q

ADC ECX,ECX
REP
STOSD

MOV ECX,sreg
AND ECX,3
REP
STOSB
/* ptr => x0
* value => w1
* num => x2
*/
regm_t regs = cgstate.allregs & (pretregs ? ~(mAX|mBX|mCX|mDI) : ~(mAX|mCX|mDI));
const sreg = allocreg(cdb,regs,TYint);
genregs(cdb,0x89,CX,sreg); // MOV sreg,ECX (32 bits only)

const n = I64 ? 3 : 2;
cdb.genc2(0xC1, modregrm(3,5,CX), n); // SHR ECX,n
// Get nbytes into x2
regm_t nbytesregs = mask(2);
codelem(cgstate,cdb,enumbytes,nbytesregs,false);

Check warning on line 1273 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1272-L1273

Added lines #L1272 - L1273 were not covered by tests

cdb.gen1(0xF3); // REP
cdb.gen1(STOS); // STOSD/Q
if (I64)
code_orrex(cdb.last(), REX_W);
// Get value into w1
regm_t valueregs = mask(1);
scodelem(cgstate,cdb,evalue,valueregs,nbytesregs,false);

Check warning on line 1277 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1276-L1277

Added lines #L1276 - L1277 were not covered by tests

if (I64)
{
cdb.gen2(0x11,modregrm(3,CX,CX)); // ADC ECX,ECX
cdb.gen1(0xF3); // REP
cdb.gen1(STOS); // STOSD
}
freenode(e2);

Check warning on line 1279 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1279

Added line #L1279 was not covered by tests

genregs(cdb,0x89,sreg,CX); // MOV ECX,sreg (32 bits only)
cdb.genc2(0x81, modregrm(3,4,CX), 3); // AND ECX,3
cdb.gen1(0xF3); // REP
cdb.gen1(STOSB); // STOSB
// Get destination into x0
regm_t dstregs = mask(0);
scodelem(cgstate,cdb,e.E1,dstregs,nbytesregs | valueregs,false);

Check warning on line 1283 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1282-L1283

Added lines #L1282 - L1283 were not covered by tests

cgstate.regimmed_set(CX, 0); // CX is now 0
fixresult(cdb,e,mES|mBX,pretregs);
callclib(cdb,null,CLIB_A.memset,pretregs,0); // memset(void* ptr, int value, size_t num)

Check warning on line 1285 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1285

Added line #L1285 was not covered by tests
}

/***********************************************
Expand Down
Loading