ir/ir_test.c

223 lines
5.2 KiB
C
Raw Permalink Normal View History

2022-11-08 09:32:46 +01:00
/*
* IR - Lightweight JIT Compilation Framework
* (Mandelbrot example)
* Copyright (C) 2022 Zend by Perforce.
* Authors: Dmitry Stogov <dmitry@php.net>
*/
2022-04-05 23:19:23 +02:00
#include "ir.h"
2023-02-10 11:34:46 +01:00
#include "ir_builder.h"
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
# include "ir_x86.h"
#endif
2022-04-27 13:47:52 +02:00
#include <stdlib.h>
2022-05-27 12:18:04 +02:00
#include <string.h>
2023-02-28 13:35:31 +01:00
#ifndef _WIN32
# include <sys/time.h>
#endif
2022-04-05 23:19:23 +02:00
#define BAILOUT 16
#define MAX_ITERATIONS 1000
void gen_mandelbrot(ir_ctx *ctx)
{
2023-02-10 11:34:46 +01:00
ir_START();
ir_ref x = ir_PARAM(IR_DOUBLE, "x", 1);
ir_ref y = ir_PARAM(IR_DOUBLE, "y", 2);
ir_ref cr = ir_SUB_D(y, ir_CONST_DOUBLE(0.5));
ir_ref ci = ir_COPY_D(x);
ir_ref zi = ir_COPY_D(ir_CONST_DOUBLE(0.0));
ir_ref zr = ir_COPY_D(ir_CONST_DOUBLE(0.0));
ir_ref i = ir_COPY_D(ir_CONST_I32(0));
ir_ref loop = ir_LOOP_BEGIN(ir_END());
ir_ref zi_1 = ir_PHI_2(zi, IR_UNUSED);
ir_ref zr_1 = ir_PHI_2(zr, IR_UNUSED);
ir_ref i_1 = ir_PHI_2(i, IR_UNUSED);
ir_ref i_2 = ir_ADD_I32(i_1, ir_CONST_I32(1));
ir_ref temp = ir_MUL_D(zr_1, zi_1);
ir_ref zr2 = ir_MUL_D(zr_1, zr_1);
ir_ref zi2 = ir_MUL_D(zi_1, zi_1);
ir_ref zr_2 = ir_ADD_D(ir_SUB_D(zr2, zi2), cr);
ir_ref zi_2 = ir_ADD_D(ir_ADD_D(temp, temp), ci);
ir_ref if_1 = ir_IF(ir_GT(ir_ADD_D(zi2, zr2), ir_CONST_DOUBLE(16.0)));
ir_IF_TRUE(if_1);
ir_RETURN(i_2);
ir_IF_FALSE(if_1);
ir_ref if_2 = ir_IF(ir_GT(i_2, ir_CONST_I32(1000)));
ir_IF_TRUE(if_2);
ir_RETURN(ir_CONST_I32(0));
ir_IF_FALSE(if_2);
ir_ref loop_end = ir_LOOP_END();
2023-02-10 11:34:46 +01:00
/* close loop */
2023-02-13 18:55:54 +01:00
ir_MERGE_SET_OP(loop, 2, loop_end);
ir_PHI_SET_OP(zi_1, 2, zi_2);
ir_PHI_SET_OP(zr_1, 2, zr_2);
ir_PHI_SET_OP(i_1, 2, i_2);
2022-04-05 23:19:23 +02:00
}
typedef int (*mandelbrot_t)(double, double);
void run(mandelbrot_t mandelbrot)
{
2023-02-28 13:35:31 +01:00
#ifndef _WIN32
2022-04-05 23:19:23 +02:00
struct timeval aTv;
gettimeofday(&aTv, NULL);
long init_time = aTv.tv_sec;
long init_usec = aTv.tv_usec;
2023-02-28 13:35:31 +01:00
#endif
2022-04-05 23:19:23 +02:00
int x,y;
for (y = -39; y < 39; y++) {
printf("\n");
for (x = -39; x < 39; x++) {
int i = mandelbrot(x/40.0, y/40.0);
if (i==0)
printf("*");
else
printf(" ");
}
}
printf ("\n");
2023-02-28 13:35:31 +01:00
#ifndef _WIN32
2022-04-05 23:19:23 +02:00
gettimeofday(&aTv,NULL);
double query_time = (aTv.tv_sec - init_time) + (double)(aTv.tv_usec - init_usec)/1000000.0;
printf ("C Elapsed %0.3f\n", query_time);
2023-02-28 13:35:31 +01:00
#endif
2022-04-05 23:19:23 +02:00
}
int main(int argc, char **argv)
2022-04-05 23:19:23 +02:00
{
ir_ctx ctx;
FILE *f;
int i;
int opt_level = 2;
uint32_t flags = 0;
uint32_t mflags = 0;
uint64_t debug_regset = 0xffffffffffffffff;
2022-05-27 12:18:04 +02:00
ir_consistency_check();
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-' && argv[i][1] == 'O' && strlen(argv[i]) == 3) {
if (argv[i][2] == '0') {
opt_level = 0;
} else if (argv[i][2] == '1') {
opt_level = 1;
} else if (argv[i][2] == '2') {
opt_level = 2;
} else {
/* pass */
}
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
} else if (strcmp(argv[i], "-mavx") == 0) {
mflags |= IR_X86_AVX;
#endif
2022-05-17 21:37:13 +02:00
} else if (strcmp(argv[i], "-muse-fp") == 0) {
flags |= IR_USE_FRAME_POINTER;
2022-04-27 13:47:52 +02:00
#ifdef IR_DEBUG
} else if (strcmp(argv[i], "--debug-sccp") == 0) {
flags |= IR_DEBUG_SCCP;
2022-04-27 13:47:52 +02:00
} else if (strcmp(argv[i], "--debug-gcm") == 0) {
flags |= IR_DEBUG_GCM;
} else if (strcmp(argv[i], "--debug-schedule") == 0) {
flags |= IR_DEBUG_SCHEDULE;
2022-04-27 13:47:52 +02:00
} else if (strcmp(argv[i], "--debug-ra") == 0) {
flags |= IR_DEBUG_RA;
#endif
2022-04-27 13:47:52 +02:00
} else if (strcmp(argv[i], "--debug-regset") == 0) {
if (i + 1 == argc || argv[i + 1][0] == '-') {
fprintf(stderr, "ERROR: Invalid usage' (use --help)\n");
return 1;
}
2022-05-31 23:34:45 +02:00
debug_regset = strtoull(argv[i + 1], NULL, 0);
2022-04-27 13:47:52 +02:00
i++;
} else {
/* pass*/
}
}
2022-04-05 23:19:23 +02:00
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
uint32_t cpuinfo = ir_cpuinfo();
if (!(cpuinfo & IR_X86_SSE2)) {
fprintf(stderr, "ERROR: incompatible CPU (SSE2 is not supported)\n");
return 1;
}
if ((mflags & IR_X86_AVX) & !(cpuinfo & IR_X86_AVX)) {
fprintf(stderr, "ERROR: -mAVX is not compatible with CPU (AVX is not supported)\n");
return 1;
}
#endif
flags |= IR_FUNCTION;
if (opt_level > 0) {
flags |= IR_OPT_FOLDING | IR_OPT_CFG | IR_OPT_CODEGEN;
}
ir_init(&ctx, flags, 256, 1024);
ctx.mflags = mflags;
ctx.fixed_regset = ~debug_regset;
2022-09-08 09:50:07 +02:00
gen_mandelbrot(&ctx);
// ir_save(&ctx, stderr);
2022-04-05 23:19:23 +02:00
ir_build_def_use_lists(&ctx);
if (opt_level > 1) {
ir_sccp(&ctx);
}
2022-04-05 23:19:23 +02:00
ir_build_cfg(&ctx);
if (opt_level > 0) {
ir_build_dominators_tree(&ctx);
ir_find_loops(&ctx);
ir_gcm(&ctx);
ir_schedule(&ctx);
}
2022-04-05 23:19:23 +02:00
ir_match(&ctx);
ir_assign_virtual_registers(&ctx);
if (opt_level > 0) {
ir_compute_live_ranges(&ctx);
ir_coalesce(&ctx);
ir_reg_alloc(&ctx);
ir_schedule_blocks(&ctx);
} else {
ir_compute_dessa_moves(&ctx);
}
2022-04-05 23:19:23 +02:00
2022-09-08 09:50:07 +02:00
ir_truncate(&ctx);
// ir_dump(&ctx, stderr);
ir_save(&ctx, stderr);
ir_dump_live_ranges(&ctx, stderr);
f = fopen("ir.dot", "w+");
ir_dump_dot(&ctx, f);
fclose(f);
2022-04-05 23:19:23 +02:00
size_t size;
2022-05-27 12:18:04 +02:00
void *entry = ir_emit_code(&ctx, &size);
2022-04-05 23:19:23 +02:00
if (entry) {
ir_disasm("test", entry, size, 0, &ctx, stderr);
2022-04-05 23:19:23 +02:00
2023-02-28 13:35:31 +01:00
#ifndef _WIN32
2022-04-05 23:19:23 +02:00
ir_perf_map_register("test", entry, size);
ir_perf_jitdump_open();
ir_perf_jitdump_register("test", entry, size);
ir_mem_unprotect(entry, 4096);
ir_gdb_register("test", entry, size, sizeof(void*), 0);
2022-04-05 23:19:23 +02:00
ir_mem_protect(entry, 4096);
2023-02-28 13:35:31 +01:00
#endif
2022-04-05 23:19:23 +02:00
run((mandelbrot_t)entry);
2023-02-28 13:35:31 +01:00
#ifndef _WIN32
2022-04-05 23:19:23 +02:00
ir_perf_jitdump_close();
2023-02-28 13:35:31 +01:00
#endif
2022-04-05 23:19:23 +02:00
}
ir_free(&ctx);
return 0;
}