Coder Social home page Coder Social logo

ir's People

Contributors

arnaud-lb avatar danog avatar devnexen avatar dktapps avatar dstogov avatar iluuu1994 avatar javiereguiluz avatar jserv avatar nielsdos avatar sebastianbergmann avatar stkeke avatar weltling avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ir's Issues

IR build failed with "-O0" but succeeded with "-O2" option

The IR function below failed to compile with -O0 option, but okay with -O2 option.

Failed IR program

tony@Win11Z790I:~/ir$ cat t.ir
{
        uintptr_t c_1 = 0;
        bool c_2 = 0;
        bool c_3 = 1;
        int32_t c_4 = 1;
        int32_t c_5 = 2;
        l_1 = START(l_20);
        bool d_2 = PARAM(l_1, "cond", 0);
        bool d_3 = COPY(c_4);
        l_4 = END(l_1);
        l_5 = LOOP_BEGIN(l_4, l_18);
        int32_t d_6 = PHI(l_5, d_3, d_15);
        bool d_7 = NE(d_6, c_4);
        l_8 = IF(l_5, d_7);
        l_9 = IF_TRUE(l_8);
        int32_t d_10 = COPY(c_5);
        l_11 = END(l_9);
        l_12 = IF_FALSE(l_8);
        l_13 = END(l_12);
        l_14 = MERGE(l_11, l_13);
        int32_t d_15 = PHI(l_14, d_10, d_6);
        l_16 = IF(l_14, d_2);
        l_17 = IF_TRUE(l_16);
        l_18 = LOOP_END(l_17);
        l_19 = IF_FALSE(l_16);
        l_20 = RETURN(l_19, d_15);
}

tony@Win11Z790I:~/ir$ ~/ir/ir t.ir  -O0 --save 
ir_base[6].ops[2] (3) type is incompatible with result type (1 != 10)
ir: ir_check.c:347: ir_check: Assertion `ok' failed.
Aborted

tony@Win11Z790I:~/ir$ ~/ir/ir t.ir  -O2 --save 
{
        uintptr_t c_1 = 0;
        bool c_2 = 0;
        bool c_3 = 1;
        int32_t c_4 = 1;
        l_1 = START(l_9);
        bool d_2 = PARAM(l_1, "cond", 0);
        l_3 = END(l_1);
        l_4 = LOOP_BEGIN(l_3, l_7);
        l_5 = IF(l_4, d_2);
        l_6 = IF_TRUE(l_5);
        l_7 = LOOP_END(l_6);
        l_8 = IF_FALSE(l_5);
        l_9 = RETURN(l_8, c_4);
}

DO NOT USE for Reproduce

This is the good -O2 dump --- sorry for paste wrong program in first report.

tony@Win11Z790I:~/ir$ cat t.ir
{
        uintptr_t c_1 = 0;
        bool c_2 = 0;
        bool c_3 = 1;
        int32_t c_4 = 1;
        l_1 = START(l_9);
        bool d_2 = PARAM(l_1, "cond", 0);
        l_3 = END(l_1);
        l_4 = LOOP_BEGIN(l_3, l_7);
        l_5 = IF(l_4, d_2);
        l_6 = IF_TRUE(l_5);
        l_7 = LOOP_END(l_6);
        l_8 = IF_FALSE(l_5);
        l_9 = RETURN(l_8, c_4);
}
tony@Win11Z790I:~/ir$ ./ir -O0 t.ir --save
ir_base[6].ops[2] (3) type is incompatible with result type (1 != 10)
ir: ir_check.c:347: ir_check: Assertion `ok' failed.
Aborted

tony@Win11Z790I:~/ir$ ./ir -O2 t.ir --save
{
        uintptr_t c_1 = 0;
        bool c_2 = 0;
        bool c_3 = 1;
        int32_t c_4 = 1;
        l_1 = START(l_9);
        bool d_2 = PARAM(l_1, "cond", 0);
        l_3 = END(l_1);
        l_4 = LOOP_BEGIN(l_3, l_7);
        l_5 = IF(l_4, d_2);
        l_6 = IF_TRUE(l_5);
        l_7 = LOOP_END(l_6);
        l_8 = IF_FALSE(l_5);
        l_9 = RETURN(l_8, c_4);
}

doc: Add examples directory

The idea behind this is to create a collection of a code snippets that can be used for both education purposes and later for embedding into documentation.

ir-test: Move away from diff tool dependency

The availability of the console tool can be not guaranteed. A diff implementation can be put into the test tool directly, thus eliminating the dependency on the external tooling. It is thinkable to implement a simplified diff algorithm or include a class with a compatible license, that implements the diff functionality.

Weird loop behavior with -O2 optimization

I am still quite native to IR construction APIs and programming, so my IR function to implement a for loop could be fundamentally wrong! Please advise.

my IR function

void gen_myfunc(ir_ctx *ctx)
{
	ir_START();
	ir_ref cnt = ir_PARAM(IR_I32, "loop_count", 1);

	ir_ref init_idx = ir_CONST_I32(1);
	ir_ref init_total = ir_CONST_I32(0);

	/* loop begin */
	ir_ref loop = ir_LOOP_BEGIN(ir_END());

	ir_ref phi_idx = ir_PHI_2(init_idx, IR_UNUSED);
	ir_ref phi_total = ir_PHI_2(init_total, IR_UNUSED);

	ir_ref if1 = ir_IF(ir_LE(phi_idx, cnt));
	ir_IF_TRUE(if1);
		ir_ref phi_idx_2 = ir_ADD_I32(phi_idx, ir_CONST_I32(1));
		ir_ref ret = ir_ADD_I32(phi_total, phi_idx);
		ir_ref loop_end = ir_LOOP_END(); /* loop end */
	ir_IF_FALSE(if1); /* loop exit */
		ir_RETURN(ret);
	ir_MERGE_SET_OP(loop, 2, loop_end);
	ir_PHI_SET_OP(phi_idx, 2, phi_idx_2);
	ir_PHI_SET_OP(phi_total, 2, ret);
}

After ir_jit_compile() with O2, ir_ref ret = ir_ADD_I32(phi_total, phi_idx); unexpectedly (at least to me) moved between LE and IF (expect to be placed after IF_TRUE: do addition only when idx<=loop_count); hence, do one more addition than expected.

image

bindings: Implement C++ frontend

Based on ir.h, ir_test.h and ir_test.c example implementation, develop a C++ wrapper for the IR functionality. Yet it is to be started in a simple manner to make the C++ code as simple as possible, while keeping in mind to prospectively modernize for the C++11 and onwards.

ir-test: Parallelize test runs

Make tests executing concurrently can speed-up the test runs and thus save developer and pipeline time. This will especially become relevant with the growing number of tests. An implementation might be simplest done through the utilization of std::async APIs but needs to be thought well so then possible exceptions can be caught in a safe way.

[ir-test]: no 'diff' on Windows, use 'fc.exe'

When running ir-test.exe with --show-diff on Windows, 'no diff error' happens.
Let's use 'fc.exe' instead.

# 001.irt is specially changed to make test FAIL.
PS C:\Users\Tony\ir> .\win32\build_x86-windows\ir-test.exe --show-diff .\tests\001.irt
FAIL: 001: add function [.\tests\001.irt]    
'diff' is not recognized as an internal or external command,
operable program or batch file.

amd64: Use CPUID to automatically enable features

Certain features can be enabled automatically, based on the data advertised through CPUID. There needs to be a framework to

  • Retrieve the processor capabilities
  • Provide API to consuming parts within IR to self modify the generated code depending on processor features

The feature enablement can be done an the library level or provided to the consumer for further decision.

Some IR tests still fail on MacOS/AArch64

Hi @dstogov,

I noticed that you had fixed the ir_add_veneer() assertion failure in 1671b3d. After your fix, there is no more assertion failure, but below IR tests still fail on MacOS/AArch64.

001: Argument Passing [./tests/debug.aarch64/args_001.irt]
002: Argument Passing [./tests/debug.aarch64/args_002.irt]
Simple CALL -O0 [./tests/debug.aarch64/call-O0.irt]
Simple CALL [./tests/debug.aarch64/call.irt]
CALL with parallel argument passing [./tests/debug.aarch64/call2.irt]
Simple CALL with ALLOCA [./tests/debug.aarch64/call_alloca.irt]
Simple CALL with VADDR [./tests/debug.aarch64/call_vaddr.irt]
003: Parameter Loading and argument passing [./tests/debug.aarch64/params_003.irt]
Fib [./tests/debug.aarch64/regset-fib.irt]
Fib2 [./tests/debug.aarch64/regset-fib2.irt]
FibI [./tests/debug.aarch64/regset-fibi.irt]
Simple CALL [./tests/debug.aarch64/tailcall_001.irt]
FibI [./tests/fibi_min.irt]
CTLZ 001: [./tests/run/ctlz_001.irt]
CTPOP 001: [./tests/run/ctpop_001.irt]
CTTZ 001: [./tests/run/cttz_001.irt]
Floating Point number comparison (001: CMP edge cases) [./tests/run/fcmp_001.irt]
Floating Point number comparison (002: CMP+COND edge cases) [./tests/run/fcmp_002.irt]
VA_ARG 001: va_arg(int) [./tests/run/vaarg_001.irt]
VA_ARG 002: va_arg(double) [./tests/run/vaarg_002.irt]
VA_ARG 003: va_arg(float) [./tests/run/vaarg_003.irt]
VA_ARG 004: va_arg() expanded on AArch64 [./tests/run/vaarg_004_aarch64.irt]

The failures are caused by the difference between .exp and .out, for example ./tests/debug.aarch64/call.irt

call.out

main:
	stp x29, x30, [sp, #-0x10]!
	mov x29, sp
	adr x0, .L1
	movz w1, #0x2a
	movz x17, #0x9f54
	movk x17, #0x8d06, lsl #16
	movk x17, #0x1, lsl #32
	blr x17
	ldp x29, x30, [sp], #0x10
	ret
.rodata
.L1:
	.db 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x25, 0x64, 0x21, 0x0a, 0x00, 0x00

hello 1799882064!

exit code = 18

call.exp

main:
	stp x29, x30, [sp, #-0x10]!
	mov x29, sp
	adr x0, .L1
	movz w1, #0x2a
	bl printf
	ldp x29, x30, [sp], #0x10
	ret
.rodata
	.db 0x1f, 0x20, 0x03, 0xd5
.L1:
	.db 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x25, 0x64, 0x21, 0x0a, 0x00, 0x00

hello 42!

exit code = 10

It looks that the issues are still related to calling convention differences between Linux/AArch64 and MacOS/AArch64. Perhaps you are still working on some complete fixes for this. But I'd like to add this issue here to track this.

doc: Add code and API documentation

The public library API needs to be documented for the end consumer. It is thinkable to approach this using code inline documentation and then generate a readable format using tools like doxygen or similar. The exact method on how to implement this is to be evaluated and discussed closer, to achieve the best result.

ir-test: Improve console argument parsing

Currently there's a simple parsing there, by looping the argv array and checking for a present string. There needs to be a full featured console argument parsing for this tool.

[HELP] Simple if-else IR program compile failure

I wrote a simple C function (see gen_ir() section below) using IR construction APIs (I'm not sure my programming is correct) and I can dump out this function by 'ir_save()' but ir will fail with -O0 with the error message different with #32 and #33.
-O2 will make if-else disappear after optimization.

tony@Win11Z790I:~/ir/examples/c$ ~/ir/ir -O0 002_if.ir -S
ir: ./ir_x86.dasc:3653: ir_emit_cmp_int_common: Assertion `0' failed.
Aborted

Generated IR

{
        uintptr_t c_1 = 0;
        bool c_2 = 0;
        bool c_3 = 1;
        int32_t c_4 = 1;
        int32_t c_5 = 4;
        l_1 = START(l_9);
        bool d_2 = LT(c_4, c_5);
        l_3 = IF(l_1, d_2);
        l_4 = IF_TRUE(l_3);
        l_5 = END(l_4);
        l_6 = IF_FALSE(l_3);
        l_7 = END(l_6);
        l_8 = MERGE(l_5, l_7);
        l_9 = RETURN(l_8, c_5);
}

image

gen_ir() in C

/* ctx: used by IR construction API defined in ir_builder.h
 * Note: must be named as 'ctx'
 */
void gen_ir(ir_ctx* ctx)
{
    ir_ref c_4 = ir_CONST_I32(1);
    ir_ref c_5 = ir_CONST_I32(4);

    ir_START(); /* Mark function start */

    ir_ref d_10 = ir_LT(c_4, c_5);

    ir_ref end_inputs = IR_UNUSED;
    ir_ref if1 = ir_IF(d_10);
    ir_IF_TRUE(if1);
    ir_END_list(end_inputs);

    ir_IF_FALSE(if1);
    ir_END_list(end_inputs);

    ir_MERGE_list(end_inputs);
    ir_RETURN(c_5);
}

Full C program

/*
This example shows a basic program framework of how to use IR.
*/

/* IR public APIs and target platform*/
#include "ir.h"
#include "ir_builder.h"

#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
# include "ir_x86.h"
#endif /* IR_TARGET_X86 || IR_TARGET_X64 */

#include <stdio.h>

/* ctx: used by IR construction API defined in ir_builder.h
 * Note: must be named as 'ctx'
 */
void gen_ir(ir_ctx* ctx)
{
    ir_ref c_4 = ir_CONST_I32(1);
    ir_ref c_5 = ir_CONST_I32(4);

    ir_START(); /* Mark function start */

    ir_ref d_10 = ir_LT(c_4, c_5);

    ir_ref end_inputs = IR_UNUSED;
    ir_ref if1 = ir_IF(d_10);
    ir_IF_TRUE(if1);
    ir_END_list(end_inputs);

    ir_IF_FALSE(if1);
    ir_END_list(end_inputs);

    ir_MERGE_list(end_inputs);
    ir_RETURN(c_5);
}

int ir_compile_and_run_func(ir_ctx *ctx, int opt_level)
{
    gen_ir(ctx);
    puts("Before ...");
    ir_save(ctx, stderr);
    FILE* f = fopen("002_if.dot", "w+");
    ir_dump_dot(ctx, f);
    fclose(f);

	if (opt_level > 0 || (ctx->flags & (IR_GEN_NATIVE|IR_GEN_C))) {
		ir_build_def_use_lists(ctx);
	}

	ir_check(ctx);

	/* Global Optimization */
	if (opt_level > 1) {
		ir_sccp(ctx);
	}

	if (opt_level > 0 || (ctx->flags & (IR_GEN_NATIVE|IR_GEN_C))) {
		ir_build_cfg(ctx);
	}

	/* Schedule */
	if (opt_level > 0) {
		ir_build_dominators_tree(ctx);
		ir_find_loops(ctx);
		ir_gcm(ctx);
		ir_schedule(ctx);
	}

	if (ctx->flags & IR_GEN_NATIVE) {
		ir_match(ctx);
	}

	if (opt_level > 0) {
		ir_assign_virtual_registers(ctx);
		ir_compute_live_ranges(ctx);
		ir_coalesce(ctx);

		if (ctx->flags & IR_GEN_NATIVE) {
			ir_reg_alloc(ctx);
		}

		ir_schedule_blocks(ctx);
	} else if (ctx->flags & (IR_GEN_NATIVE|IR_GEN_C)) {
		ir_assign_virtual_registers(ctx);
		ir_compute_dessa_moves(ctx);
	}

	ir_check(ctx);

    puts("After ...\n");
    ir_save(ctx, stderr);
    /* generate native code and return function entry pointer */
    typedef void (*ir_func_t)(void);
    size_t size;
    ir_func_t entry = (ir_func_t) ir_emit_code(ctx, &size);

    if(entry) {
        entry();
    }

	return 1;
}

int main(void)
{
    ir_ctx ctx;
    /* generate a function */
    uint32_t flags = IR_FUNCTION | IR_GEN_NATIVE | IR_GEN_C;
    ir_consistency_check();
    /* 256: constants limit; 1024: instructions limit */
    ir_init(&ctx, flags, 256, 1024);
    ir_compile_and_run_func(&ctx, 2);
    ir_free(&ctx);
    return 0;
}

tests: Implement fuzz tests

This would include choosing an appropriate test framework, generating the test data and adding the test cases.

IR program failed to compile with "-O0" "-S" options

tony@Win11Z790I:~/ir/tests/debug$ cat ./dce_001.ir
{
        uintptr_t c_1 = 0;
        bool c_2 = 0;
        bool c_3 = 1;
        int32_t c_4 = 10;
        int32_t c_5 = 2;
        int32_t c_6 = 1;
        int32_t c_7 = 0;
        l_1 = START(l_14);
        int32_t d_2 = PARAM(l_1, "x", 0);
        l_3 = END(l_1);
        l_4 = LOOP_BEGIN(l_3, l_12);
        int32_t d_5 = PHI(l_4, c_7, d_7);
        int32_t d_6 = ADD(d_2, c_6);
        int32_t d_7 = ADD(d_6, d_5);
        int32_t d_8 = MUL(d_7, c_5);
        int32_t xxx = DIV(d_8, c_4);
        bool d_9 = LT(d_7, c_4);
        l_10 = IF(l_4, d_9);
        l_11 = IF_TRUE(l_10);
        l_12 = LOOP_END(l_11);
        l_13 = IF_FALSE(l_10);
        l_14 = RETURN(l_13, d_8);
}

# failed with -O0 option
tony@Win11Z790I:~/ir/tests/debug$ ~/ir/ir -O0 ./dce_001.ir -S
ir: ./ir_x86.dasc:3173: ir_emit_mul_div_mod: Assertion `def_reg != -1' failed.
Aborted

# succeeded with -O2 option
tony@Win11Z790I:~/ir/tests/debug$ ~/ir/ir -O2 ./dce_001.ir -S
test:
        leal 1(%rdi), %eax
        xorl %ecx, %ecx
.L1:
        addl %eax, %ecx
        cmpl $0xa, %ecx
        jl .L1
        leal (%rcx, %rcx), %eax
        retq

ir_emit_c() dumping misses BB label

A simple switch-case IR function and ir_emit_c() dumping is missing BB2 (or maybe BB1) .

Erroneous ir_emit_c() dumping

int32_t test(int32_t num)
{
        int32_t d_1 = num;
        int32_t d_2;
        int32_t d_3;
        int32_t d_4;
        int32_t d_5;
        d_2 = d_1 % 3;
        d_3 = d_1 * 3;
        d_4 = d_1 + 1;
        d_5 = d_1 - 2;
        switch (d_2) {
                case 0: goto bb2;
                case 1: goto bb4;
                case 2: goto bb3;
                default: goto bb3;
        }
        d_5 = d_3;
bb3:
        return d_5;
bb4:
        d_5 = d_4;
        goto bb3;
}

IR function

void gen_myfunc(ir_ctx *ctx)
{
	ir_ref divisor = ir_CONST_I32(3);
	ir_ref rem0 = ir_CONST_I32(0);
	ir_ref rem1 = ir_CONST_I32(1);
	ir_ref rem2 = ir_CONST_I32(2);

	ir_START();
	ir_ref num = ir_PARAM(IR_I32, "num", 1);
	ir_ref rets[4], ends[4];
	ir_ref remainder = ir_MOD_I32(num, divisor);

	ir_ref s = ir_SWITCH(remainder);
	ir_CASE_VAL(s, rem0);
		rets[0] = ir_MUL_I32(num, ir_CONST_I32(3));
		ends[0] = ir_END();
	ir_CASE_VAL(s, rem1);
		rets[1] = ir_ADD_I32(num, ir_CONST_I32(1));
		ends[1] = ir_END();
	ir_CASE_VAL(s, rem2);
		rets[2] = ir_SUB_I32(num, ir_CONST_I32(2));
		ends[2] = ir_END();
	ir_CASE_DEFAULT(s);
		rets[3] = rets[2];
		ends[3] = ir_END();

	ir_MERGE_N(4, ends);
	ir_ref ret = ir_PHI_N(4, rets);

	ir_RETURN(ret);
}

Equivalent C code for IR function

 int32_t myfunc(int32_t num) {
	int remainder = num % 3;
        switch (remainder)
        {
        case 0:  num = num * 3;   break;
        case 1:  num = num + 1;  break;
        case 2:  // fall through
        default: num = num - 2; break;
        }
        return num;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.