Skip to content

Commit

Permalink
add duplicate function merging to nucode backend
Browse files Browse the repository at this point in the history
  • Loading branch information
totalspectrum committed Jan 7, 2024
1 parent e7e24c2 commit 5f2b1a4
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 16 deletions.
8 changes: 0 additions & 8 deletions backends/asm/optimize_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -5809,14 +5809,6 @@ HashIR(SHA256_CTX *ctx, IR *ir, Function *f)

static FunctionList *funchash[256];

static FunctionList *
NewFunctionList(Function *f)
{
FunctionList *entry = (FunctionList *)calloc(1, sizeof(FunctionList));
entry->func = f;
return entry;
}

void
HashFuncIRL(Function *f)
{
Expand Down
1 change: 1 addition & 0 deletions backends/asm/outasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define OUTASM_H

#include "instr.h"
#include "becommon.h"
#include "util/sha256.h"

// functions for producing local identifiers
Expand Down
13 changes: 11 additions & 2 deletions backends/becommon.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Spin to C/C++ translator
* Copyright 2011-2023 Total Spectrum Software Inc.
* Copyright 2021-2022 Ada Gottensträter
* Copyright 2011-2024 Total Spectrum Software Inc.
* Copyright 2021-2024 Ada Gottensträter
* +--------------------------------------------------------------------
* ¦ TERMS OF USE: MIT License
* +--------------------------------------------------------------------
Expand Down Expand Up @@ -690,3 +690,12 @@ int DecomposeBits(unsigned val, int *shifts)
}
return r;
}

FunctionList *
NewFunctionList(Function *f)
{
FunctionList *entry = (FunctionList *)calloc(1, sizeof(FunctionList));
entry->func = f;
return entry;
}

3 changes: 3 additions & 0 deletions backends/becommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,7 @@ static inline bool isPowerOf2(uint32_t x)
// shifts[2] to initial shift
int DecomposeBits(unsigned val, int *shifts);

// allocate a FunctionList entry
FunctionList *NewFunctionList(Function *f);

#endif /* BACKEND_COMMON_H */
84 changes: 80 additions & 4 deletions backends/nucode/outnu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2353,7 +2353,7 @@ static int NuConvertFunctions(void *vptr, Module *P) {
}

static int NuOptimizeFunction(Function *pf, NuIrList *irl) {
// for now, do nothing
// for now, do very little
int change;
int all_changes = 0;
unsigned flags = pf->optimize_flags;
Expand Down Expand Up @@ -2383,15 +2383,25 @@ static int NuRevisitFunctions(void *vptr, Module *P) {
Function *pf;
NuIrList **global_ptr = (NuIrList **)vptr;
NuIrList *globalList = *global_ptr;
bool isDup;

current = P;

for (pf = P->functions; pf; pf = pf->next) {
// optimize function
irl = &FunData(pf)->irl;
NuOptimizeFunction(pf, irl);
// thread into global list
irl->nextList = globalList;
globalList = irl;
if (pf->optimize_flags & OPT_MERGE_DUPLICATES) {
// see if it matches any other function
isDup = NuHashFunc(pf);
} else {
isDup = false;
}
if (!isDup) {
// thread into global list
irl->nextList = globalList;
globalList = irl;
}
}

current = save;
Expand Down Expand Up @@ -2426,6 +2436,13 @@ static int NuCompileObject(void *vptr, Module *P) {
flexbuf_delete(&datBuf);
}
for (pf = P->functions; pf; pf = pf->next) {
FunctionList *fl;
if (FunData(pf)->isRemoved) continue;
for (fl = FunData(pf)->funcdups; fl; fl = fl->next) {
Function *f2 = fl->func;
flexbuf_printf(fb, "'--- Function: %s\n", f2->name);
NuOutputLabelNL(fb, FunData(f2)->entryLabel);
}
flexbuf_printf(fb, "'--- Function: %s\n", pf->name);
NuOutputIrList(fb, &FunData(pf)->irl);
if (FunData(pf)->dataLabel) {
Expand All @@ -2436,6 +2453,64 @@ static int NuCompileObject(void *vptr, Module *P) {
return 1;
}

//
// hashing function
// returns true if function is found to be a duplicate of another one,
// otherwise false
//
static FunctionList *buckets[256];

bool NuHashFunc(Function *f) {
static int unique_func_count = 0;
SHA256_CTX ctx;
FunctionList *fl;

if (!(f->optimize_flags & OPT_MERGE_DUPLICATES)) {
++unique_func_count;
memcpy(FunData(f)->hash, &unique_func_count, sizeof(unique_func_count));
return false;
}
NuIrList *irl = &FunData(f)->irl;
NuIr *ir;

sha256_init(&ctx);
for (ir = irl->head; ir; ir = ir->next) {
sha256_update(&ctx, (unsigned char *)&ir->op, sizeof(ir->op));
}
sha256_final(&ctx, FunData(f)->hash);

fl = buckets[FunData(f)->hash[0]];
if (!fl) {
buckets[FunData(f)->hash[0]] = NewFunctionList(f);
return false;
}
for(;;) {
Function *f2 = fl->func;
if (FunData(f2)) {
if (memcmp(FunData(f2)->hash, FunData(f)->hash, SHA256_BLOCK_SIZE) == 0) {
FunData(f)->isRemoved = true;
// make sure we keep f2
f2->used_as_ptr |= f->used_as_ptr;
f2->cog_task |= f->cog_task;
f2->callSites += f->callSites;

FunctionList *entry = NewFunctionList(f);
entry->next = FunData(f2)->funcdups;
FunData(f2)->funcdups = entry;
FunData(f)->isRemoved = true;
return true;
}
}
if (!fl->next) {
fl->next = NewFunctionList(f);
break;
}
fl = fl->next;
}

return false;
}

#ifdef NEVER
static void NuAddHeap(ByteOutputBuffer *bob, Module*P) {
Symbol *sym = LookupSymbolInTable(&systemModule->objsyms, "__heap_base");
Expand Down Expand Up @@ -2548,3 +2623,4 @@ void OutputNuCode(const char *asmFileName, Module *P)
current = saveCurrent;
curfunc = saveFunc;
}

6 changes: 4 additions & 2 deletions backends/nucode/outnu.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ typedef struct {
NuIrList irl;
NuIrLabel *entryLabel;
NuIrLabel *dataLabel;
Flexbuf dataBuf; // inline data for the function
Flexbuf dataBuf; // inline data for the function
FunctionList *funcdups; // functions that are aliases to this one
bool isRemoved; // flag, if set function is a duplicate of something else
unsigned char hash[SHA256_BLOCK_SIZE];
} NuFunData;

Expand All @@ -35,7 +37,7 @@ NuIrOpcode NuInvertCondition(NuIrOpcode op);
NuIrOpcode NuReverseDirCondition(NuIrOpcode op);
void NuDeleteIr(NuIrList *irl, NuIr *ir);
void NuIrInsertBefore(NuIrList *irl, NuIr *anchor, NuIr *newitem);
void NuFuncHash(Function *f);
bool NuHashFunc(Function *f);

/* ultimate output function */
void OutputNuCode(const char *fname, Module *P);
Expand Down

0 comments on commit 5f2b1a4

Please sign in to comment.