Skip to content

Commit

Permalink
improve join compute pass -> better strcpy code gen
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-s168 committed Oct 22, 2024
1 parent 2d076dd commit eb31bed
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 37 deletions.
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

: ${CFLAGS:="-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-comment -Wno-format -Wno-sign-compare -Wno-char-subscripts -Wno-implicit-fallthrough -Wno-missing-braces -Werror"}
: ${CFLAGS:="-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-comment -Wno-format -Wno-sign-compare -Wno-char-subscripts -Wno-implicit-fallthrough -Wno-missing-braces -Werror -g -glldb"}

if [ -z $EMPATH ]; then
: ${CC:=clang}
Expand Down
7 changes: 7 additions & 0 deletions ir/builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ void vx_IrBlock_addOp(vx_IrBlock *block,
vx_IrBlock_deepTraverse(new->parent, add_op__trav, &data);
}

vx_IrOp *vx_IrBlock_addOpAtBeginBuilding(vx_IrBlock *block) {
vx_IrOp *new = fastalloc(sizeof(vx_IrOp));
new->next = block->first;
block->first = new;
return new;
}

/** WARNING: DON'T REF VARS IN OP THAT ARE NOT ALREADY INDEXED ROOT */
vx_IrOp *vx_IrBlock_addOpBuilding(vx_IrBlock *block) {
vx_IrOp *new = fastalloc(sizeof(vx_IrOp));
Expand Down
42 changes: 42 additions & 0 deletions ir/ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@
#include <stdlib.h>


bool vx_IrValue_eq(vx_IrValue a, vx_IrValue b)
{
if (a.type != b.type)
return false;

switch (a.type)
{
case VX_IR_VAL_IMM_INT:
return a.imm_int == b.imm_int;

case VX_IR_VAL_IMM_FLT:
return a.imm_flt == b.imm_flt;

case VX_IR_VAL_VAR:
return a.var == b.var;

case VX_IR_VAL_UNINIT:
return true;

case VX_IR_VAL_BLOCKREF:
return a.block == b.block;

case VX_IR_VAL_BLOCK:
return a.block == b.block;

case VX_IR_VAL_TYPE:
return a.ty == b.ty;

case VX_IR_VAL_ID:
return a.id == b.id;
}
}

vx_IrOp *vx_IrBlock_tail(vx_IrBlock *block) {
vx_IrOp *op = block->first;
while (op && op->next) {
Expand Down Expand Up @@ -278,6 +311,15 @@ vx_IrTypeRef vx_IrBlock_type(vx_IrBlock* block) {
return (vx_IrTypeRef) { .ptr = type, .shouldFree = true };
}

void vx_IrOp_updateParent(vx_IrOp* op, vx_IrBlock* to)
{
op->parent = to;
FOR_INPUTS(op, inp, ({
if (inp.type == VX_IR_VAL_BLOCK)
inp.block->parent = to;
}));
}

#include "opt.h"
#include "../cg/x86_stupid/cg.h"

Expand Down
4 changes: 4 additions & 0 deletions ir/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ typedef struct {
};
} vx_IrValue;

bool vx_IrValue_eq(vx_IrValue a, vx_IrValue b);

#define VX_IR_VALUE_IMM_INT(varin) ((vx_IrValue) { .type = VX_IR_VAL_IMM_INT, .imm_int = varin })
#define VX_IR_VALUE_IMM_FLT(varin) ((vx_IrValue) { .type = VX_IR_VAL_IMM_FLT, .imm_flt = varin })
#define VX_IR_VALUE_VAR(varin) ((vx_IrValue) { .type = VX_IR_VAL_VAR, .var = varin })
Expand Down Expand Up @@ -286,6 +288,7 @@ void vx_IrBlock_addIn(vx_IrBlock *block, vx_IrVar var, vx_IrType *type);
void vx_IrBlock_addOp(vx_IrBlock *block, const vx_IrOp *op);
/** WARNING: DON'T REF VARS IN OP THAT ARE NOT ALREADY INDEXED ROOT */
vx_IrOp *vx_IrBlock_addOpBuilding(vx_IrBlock *block);
vx_IrOp *vx_IrBlock_addOpAtBeginBuilding(vx_IrBlock *block);
vx_IrOp *vx_IrBlock_insertOpBuildingAfter(vx_IrOp *after);
void vx_IrBlock_addAllOp(vx_IrBlock *dest, const vx_IrBlock *src);
void vx_IrBlock_addOut(vx_IrBlock *block, vx_IrVar out);
Expand Down Expand Up @@ -472,6 +475,7 @@ bool vx_IrOp_isTail(vx_IrOp *op);
bool vx_IrOp_after(vx_IrOp *op, vx_IrOp *after);
bool vx_IrOp_followingNoEffect(vx_IrOp* op);
vx_IrOp* vx_IrOp_nextWithEffect(vx_IrOp* op);
void vx_IrOp_updateParent(vx_IrOp* op, vx_IrBlock* to);

typedef bool (*vx_IrOpFilter)(vx_IrOp* op, void* userdata);

Expand Down
4 changes: 2 additions & 2 deletions ir/ops.cdef
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ enum_entry_prefix "VX_IR_OP_"
endsFlow true
hasEffect true
volatile false
sideEffect false
sideEffect true
;

entry BREAK args "states.."
Expand All @@ -582,7 +582,7 @@ enum_entry_prefix "VX_IR_OP_"
endsFlow true
hasEffect true
volatile false
sideEffect false
sideEffect true
;

entry RETURN args "returns.."
Expand Down
23 changes: 15 additions & 8 deletions ir/opt.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ vx_OptConfig vx_g_optconfig = {
.if_eval = true,
};

static void RecCallInOut(void (*fn)(vx_IrBlock*), vx_IrBlock* block)
{
for (vx_IrOp *op = block->first; op; op = op->next) {
FOR_INPUTS(op, input, ({
if (input.type == VX_IR_VAL_BLOCK)
RecCallInOut(fn, input.block);
}));
}

fn(block);
}

static void opt_pre(vx_IrBlock *block) {
// place immediates into params
vx_opt_inline_vars(block);
Expand Down Expand Up @@ -53,14 +65,9 @@ void opt(vx_IrBlock *block) {

void opt_preLower(vx_IrBlock *block)
{
for (vx_IrOp *op = block->first; op; op = op->next) {
FOR_INPUTS(op, input, ({
if (input.type == VX_IR_VAL_BLOCK)
opt_preLower(input.block);
}));
}

opt_pre(block);
RecCallInOut(opt_pre, block);
RecCallInOut(vx_opt_join_compute, block);
RecCallInOut(opt_pre, block);
}

void opt_ll(vx_IrBlock *block) {
Expand Down
79 changes: 70 additions & 9 deletions ir/opt/join_compute.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,85 @@
#include <assert.h>
#include <string.h>

static bool eq(vx_IrOp* a, vx_IrOp* b)
{
if (!( a->id == b->id
&& a->args_len == b->args_len
&& a->params_len == b->params_len
&& a->outs_len == b->outs_len
))
return false;

for (size_t i = 0; i < a->params_len; i ++) {
if (a->params[i].name != b->params[i].name)
return false;
if (!vx_IrValue_eq(a->params[i].val, b->params[i].val))
return false;
}

for (size_t i = 0; i < a->args_len; i ++)
if (!vx_IrValue_eq(a->args[i], b->args[i]))
return false;

return true;
}

static vx_IrOp* findMatchingOutBefore(vx_IrBlock* block, vx_IrOp* before, vx_IrOp* cmp, bool stepIn, bool stepOut)
{
for (vx_IrOp* op = block->first; op && op != before; op = op->next)
{
if (eq(op, cmp))
return op;

if (stepIn) {
FOR_INPUTS(op, inp, ({
if (inp.type == VX_IR_VAL_BLOCK) {
vx_IrOp* m = findMatchingOutBefore(inp.block, NULL, cmp, /*stepIn=*/true, /*stepOut=*/false);
if (m)
return m;
}
}));
}
}

if (stepOut && block->parent)
{
vx_IrOp* m = findMatchingOutBefore(block->parent, block->parent_op, cmp, /*stepIn=*/false, /*stepOut=*/true);
if (m)
return m;
}

return NULL;
}

/**
* Find identical computations and join them
*/
void vx_opt_join_compute(vx_IrBlock *block)
{
for (vx_IrOp *op = block->first; op; op = op->next) {
for (vx_IrOp *prev = block->first; prev != op; prev = prev->next) {
if (prev->id != op->id || vx_IrOp_isVolatile(op) || prev->params_len != op->params_len || prev->outs_len == 0)
continue;
if (vx_IrOp_isVolatile(op) || vx_IrOp_hasSideEffect(op))
continue;

if (memcmp(prev->params, op->params, sizeof(vx_IrNamedValue) * op->params_len) != 0)
continue;
vx_IrOp* m = findMatchingOutBefore(block, op, op, true, true);
assert(m != op);
if (m == NULL)
continue;

op->id = VX_IR_OP_IMM;
vx_IrOp_removeParams(op);
vx_IrOp_addParam_s(op, VX_IR_NAME_VALUE, (vx_IrValue) { .type = VX_IR_VAL_VAR, .var = prev->outs[0].var });
vx_IrOp* pred = vx_IrOp_predecessor(op);

break;
vx_IrOp* last = pred;
for (size_t i = 0; i < op->outs_len; i ++) {
vx_IrOp* new = (pred == NULL)
? vx_IrBlock_addOpAtBeginBuilding(block)
: vx_IrBlock_insertOpBuildingAfter(pred);

vx_IrOp_init(new, VX_IR_OP_IMM, block);
vx_IrOp_addParam_s(new, VX_IR_NAME_VALUE, VX_IR_VALUE_VAR(m->outs[i].var));
vx_IrOp_addOut(new, op->outs[i].var, op->outs[i].type);
last = new;
}

last->next = op->next;
}
}
4 changes: 3 additions & 1 deletion ir/transform/lower_loops.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ void vx_IrBlock_llir_preLower_loops(vx_IrBlock *block)
vx_IrOp* ifOp = vx_IrBlock_addOpBuilding(newBody);
vx_IrOp_init(ifOp, VX_IR_OP_IF, newBody);

body->parent = ifOp->parent;
vx_IrOp_addParam_s(ifOp, VX_IR_NAME_COND, VX_IR_VALUE_BLK(cond));

body->parent = ifOp->parent;
vx_IrOp_addParam_s(ifOp, VX_IR_NAME_COND_THEN, VX_IR_VALUE_BLK(body));

{
vx_IrBlock* els = vx_IrBlock_initHeap(newBody, ifOp);
vx_IrBlock* els = vx_IrBlock_initHeap(ifOp->parent, ifOp);

vx_IrOp* brk = vx_IrBlock_addOpBuilding(els);
vx_IrOp_init(brk, VX_IR_OP_BREAK, els);
Expand Down
3 changes: 3 additions & 0 deletions ir/transform/ssair_llir_lower.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ void vx_IrBlock_llir_preLower_ifs(vx_IrBlock *block)
*cond = VX_IR_VALUE_VAR(condbl->outs[0]);

if (condbl->first) {
for (vx_IrOp* i = condbl->first; i; i = i->next)
vx_IrOp_updateParent(i, block);

vx_IrOp* pred = vx_IrOp_predecessor(op);
if (pred)
pred->next = condbl->first;
Expand Down
23 changes: 7 additions & 16 deletions ir/verify_common.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <stdlib.h>

#include "ir.h"
Expand Down Expand Up @@ -32,9 +33,6 @@ static bool analyze_if(vx_Errors *dest,
if (vcond == NULL) {
vx_error_param_missing(dest, "cond");
err = true;
} else if (vcond->type != VX_IR_VAL_BLOCK) {
vx_error_param_type(dest, "block");
err = true;
}

const vx_IrValue *vthen = vx_IrOp_param(op, VX_IR_NAME_COND_THEN);
Expand All @@ -56,18 +54,9 @@ static bool analyze_if(vx_Errors *dest,
}

if (!err) {
vx_IrBlock *bcond = vcond->block;
vx_IrBlock *bthen = vthen->block;
vx_IrBlock *belse = velse->block;

if (bcond->outs_len != 1) {
vx_Error error = {
.error = "If block is missing a condition",
.additional = "If block is missing a condition! Example: `cond=(){ ^ 1 }`"
};
vx_Errors_add(dest, &error);
}

if (!(bthen->outs_len == belse->outs_len && bthen->outs_len == op->outs_len)) {
vx_Error error = {
.error = "If block invalid outputs",
Expand Down Expand Up @@ -122,9 +111,11 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) {

for (vx_IrOp *op = block->first; op; op = op->next) {
if (op->parent != block) {
char buf[256];
sprintf(buf, "OP (%s) has different parent", vx_IrOpType__entries[op->id].debug.a);
const vx_Error error = {
.error = "Invalid parent",
.additional = "OP has different parent"
.additional = strdup(buf)
};
vx_Errors_add(dest, &error);
}
Expand Down Expand Up @@ -159,11 +150,11 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) {
case VX_IR_OP_COND: {
size_t label = vx_IrOp_param(op, VX_IR_NAME_ID)->id;
if (label >= root->as_root.labels_len || root->as_root.labels[label].decl == NULL) {
static char buf[256];
char buf[256];
sprintf(buf, "Label %%%zu is never declared!", label);
vx_Error error = {
.error = "Undeclared label",
.additional = buf
.additional = strdup(buf)
};
vx_Errors_add(dest, &error);
}
Expand Down Expand Up @@ -202,7 +193,7 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) {
sprintf(buf, "Variable %%%zu is never declared!", var);
vx_Error error = {
.error = "Undeclared variable",
.additional = buf
.additional = strdup(buf)
};
vx_Errors_add(dest, &error);
}
Expand Down

0 comments on commit eb31bed

Please sign in to comment.