diff --git a/gcc/Makefile.in b/gcc/Makefile.in index bb6197a8eb377c5caa0aa332398a9eaed010dfd1..6315462aae645392f84d0f11f62ee13030ab8e3e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1734,13 +1734,13 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \ pretty-print.o intl.o \ sbitmap.o \ vec.o input.o hash-table.o ggc-none.o memory-block.o \ - selftest.o selftest-diagnostic.o sort.o + ai4c-infer.o selftest.o selftest-diagnostic.o sort.o # Objects in libcommon-target.a, used by drivers and by the core # compiler and containing target-dependent code. OBJS-libcommon-target = $(common_out_object_file) prefix.o \ opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o \ - hash-table.o file-find.o spellcheck.o selftest.o opt-suggestions.o + hash-table.o file-find.o spellcheck.o ai4c-infer.o selftest.o opt-suggestions.o # This lists all host objects for the front ends. ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS)) @@ -2256,7 +2256,7 @@ gcc-nm.cc: gcc-ar.cc cp $^ $@ COLLECT2_OBJS = collect2.o collect2-aix.o vec.o ggc-none.o \ - collect-utils.o file-find.o hash-table.o selftest.o + collect-utils.o file-find.o hash-table.o ai4c-infer.o selftest.o COLLECT2_LIBS = @COLLECT2_LIBS@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) # Don't try modifying collect2 (aka ld) in place--it might be linking this. @@ -3720,6 +3720,8 @@ install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype # Install the compiler executables built during cross compilation. install-common: native lang.install-common installdirs + rm -f $(DESTDIR)$(libexecdir)/onnx.fdata + cp $(srcdir)/onnx.fdata $(DESTDIR)$(libexecsubdir)/onnx.fdata for file in $(COMPILERS); do \ if [ -f $$file ] ; then \ rm -f $(DESTDIR)$(libexecsubdir)/$$file; \ diff --git a/gcc/ai4c-infer.cc b/gcc/ai4c-infer.cc new file mode 100644 index 0000000000000000000000000000000000000000..4fa7c47708efa1be5bf7cdbf81c1f80ed762409b --- /dev/null +++ b/gcc/ai4c-infer.cc @@ -0,0 +1,402 @@ +/* TODO + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ai4c-infer.h" +#include "config.h" +#include "system.h" + +#ifndef _cbmc_ +#define __CPROVER_assume(...) do {} while (0) +#endif + +#define M_OPTION_SIZE 7 +#define M_MODE_SIZE 6 + +#define CATS_STRINGS_ROW 12 +#define CATS_STRINGS_COL 65 +#define OFFSET_ROW 6 +#define SCALE_ROW 6 +#define UNITY_ROW 1 +#define COEFFICIENT_ROW 18 +#define COEFFICIENT_COL 100 +#define COEFFICIENT1_ROW 100 +#define COEFFICIENT1_COL 1 +#define INTERCEPTS_ROW 100 +#define INTERCEPTS1_ROW 1 + +/* Model info. */ +static int64_t argv_hw1[argc_hw1]; +static char native_tune[128]; + +static char cats_strings[CATS_STRINGS_ROW][CATS_STRINGS_COL]; +static float offset[OFFSET_ROW]; +static float scale[SCALE_ROW]; +static float unity[UNITY_ROW]; +static float coefficient[COEFFICIENT_ROW][COEFFICIENT_COL]; +static float coefficient1[COEFFICIENT1_ROW][COEFFICIENT1_COL]; +static float intercepts[INTERCEPTS_ROW]; +static float intercepts1[INTERCEPTS1_ROW]; + +/* Model result。 */ +int64_t initialize_decision; +int64_t optmize_result; + +void +set_initialize_decision () + { + initialize_decision = 1; + } +void +set_native_tune (const char *info) +{ + if (info) + { + strcpy(native_tune, info); + return; + } + return; +} + +void +set_cache_info (int index, int cache_value) +{ + argv_hw1[index] = cache_value; +} + +void +fill_node (char *file_name) +{ + + FILE *file = fopen (file_name, "rb"); + + if (!file) + { + perror ("Can not open file."); + fclose (file); + return; + } + + // parse cats_strings + for (int i = 0; i < CATS_STRINGS_ROW; i++) + { + fread (cats_strings[i], sizeof (char), CATS_STRINGS_COL - 1, file); + cats_strings[i][64] = '\0'; + } + + fread (offset, sizeof (float), OFFSET_ROW, file); + fread (scale, sizeof (float), SCALE_ROW, file); + fread (coefficient, sizeof (float), COEFFICIENT_ROW * COEFFICIENT_COL, file); + fread (coefficient1, sizeof (float), COEFFICIENT1_ROW * COEFFICIENT1_COL, file); + fread (intercepts, sizeof (float), INTERCEPTS_ROW, file); + fread (intercepts1, sizeof (float), INTERCEPTS1_ROW, file); + fread (unity, sizeof (float), UNITY_ROW, file); + fclose (file); + return; +} + +static void +matmul (const float *lhs, const float *rhs, int m, int k, int n, float *out) +{ + for (int i = 0; i < m; i++) + { + for (int j = 0; j < n; j++) + { + out[i * n + j] = 0.0f; + for (int p = 0; p < k; p++) + { + out[i * n + j] += lhs[i * k + p] * rhs[p * n + j]; + } + } + } +} + +static void +add (const float *lhs, const float *rhs, int length, float *out) +{ + for (int i = 0; i < length; i++) + { + out[i] = lhs[i] + rhs[i]; + } +} + +static void +sub (const float *lhs, const float *rhs, int length, float *out) +{ + for (int i = 0; i < length; i++) + { + out[i] = lhs[i] - rhs[i]; + } +} + +static void +sigmoid (const float *in, int length, float *out) +{ + for (int i = 0; i < length; i++) + { + out[i] = 1.0f / (1.0f + expf (-in[i])); + } +} + +static void +relu (const float *data, int length, float *out) +{ + for (int i = 0; i < length; i++) + { + if (data[i] < 0) + { + out[i] = 0; + } + else + { + out[i] = data[i]; + } + } +} + +static void +line_concat (const float *in, int in_size, float *out, int out_size) +{ + for (int i = 0; i < in_size; i++) + { + out[out_size + i] = in[i]; + } +} + +static void +one_hot_encoder (const char *in, const char (*cats)[65], float *out, + int out_size) +{ + for (int i = 0; i < out_size; i++) + { + if (i < out_size && strcmp (cats[i], in) == 0) + { + out[i] = 1.0f; + } + else + { + out[i] = 0.0f; + } + } +} + +static void +imputer (const int64_t *in, int size, float *out) +{ + for (int i = 0; i < size; i++) + { + out[i] = in[i] * 1.0f; + } +} + +static void +scaler (const float *in, const float *offset, const float *scale, int size, float *out) +{ + for (int i = 0; i < size; i++) + { + out[i] = (in[i] - offset[i]) * scale[i]; + } +} + +static int +argmax (const float *in, int in_size) +{ + int out_idx = 0; + for (int i = 0; i < in_size; i++) + { + if (in[i] > in[out_idx]) + { + out_idx = 1; + } + } + return out_idx; +} + +static void +preprocess (int argc1, const char *argv1, int argc2, int64_t *argv2, int64_t *in_modes) +{ + int default_int_val= 0; + for (int i = 0; i < argc2; i++) + { + if (i < argc2) + { + in_modes[i] = argv2[i]; + } + else + { + in_modes[i] = default_int_val; + } + } +} + +static int +graph_infer (int argc, const char *argv, int argc2, int64_t *argv2) +{ + + const char *file_name = getenv ("COLLECT_LTO_WRAPPER"); + char native_file [512]; + if (file_name) + { + const char *onnx_fdata = "onnx.fdata"; + strncpy(native_file, file_name, sizeof(native_file) - 1); + native_file[sizeof(native_file) - 1] = '\0'; + + char *last_slash = strrchr(native_file, '/'); + if (last_slash) + strcpy(last_slash + 1, onnx_fdata); + } + + if (access(native_file, F_OK) == 0) + { + fill_node (native_file); + } + else + { + return 0; + } + + static int64_t in_modes[M_MODE_SIZE]; + + preprocess (argc, argv, argc2, argv2, in_modes); + + const int concat_out_size = 18; + float concat_result[concat_out_size]; + const int encoder_out_size = 12; + int concat_size = 0; + float encoder_out[encoder_out_size]; + + one_hot_encoder (argv, cats_strings, encoder_out, encoder_out_size); + + line_concat (encoder_out, encoder_out_size, concat_result, concat_size); + concat_size += encoder_out_size; + + float variable[M_MODE_SIZE]; + imputer (in_modes, M_MODE_SIZE, variable); + + float variable1[M_MODE_SIZE]; + scaler (variable, offset, scale, M_MODE_SIZE, variable1); + float transformed_column[concat_out_size + M_MODE_SIZE]; + line_concat (variable1, M_MODE_SIZE, transformed_column, 0); + line_concat (concat_result, concat_out_size, transformed_column, 6); + + const int m = 1, k = 18, n = 100; + float mul_result[n]; + matmul (transformed_column, coefficient[0], m, k, n, mul_result); + + float add_result[n]; + add (mul_result, intercepts, n, add_result); + + float next_activations[n]; + relu (add_result, n, next_activations); + + const int m2 = 1, k2 = 100, n2 = 1; + float mul_result1 [n2]; + matmul (next_activations, coefficient1[0], m2, k2, n2, mul_result1); + + float add_result1[n2]; + add (mul_result1, intercepts1, n2, add_result1); + + float out_activations_result[n2]; + sigmoid (add_result1, n2, out_activations_result); + + float negative_class_proba[n2]; + sub (unity, out_activations_result, n2, negative_class_proba); + const int prob_size = n2 + n2; + float probabilities[prob_size]; + line_concat (negative_class_proba, n2, probabilities, 0); + line_concat (out_activations_result, n2, probabilities, n2); + + int argmax_output = argmax (probabilities, prob_size); + return argmax_output; +} + +void execute_sha256(const char *input, char *output, size_t output_size) +{ + char command[256]; + snprintf (command, sizeof(command), "echo -n \"%s\" | sha256sum", input); + + FILE *pipe = popen (command, "r"); + if (pipe == NULL) + { + perror ("Failed to run command."); + } + + if (fgets (output, output_size, pipe) != NULL) + { + size_t length = strlen (output); + if (length > 0 && (output[length - 1] == '\n' || output[length - 1] == ' ')) + { + output[length] = '\0'; + } + + char *space_pos = strchr (output, ' '); + if (space_pos != NULL) + { + *space_pos = '\0'; + } + } + pclose (pipe); +} + +int +get_optimize_decision () +{ + if (initialize_decision == 1) + { + return optmize_result; + } + if (native_tune && (strstr (native_tune, "mcpu=hip09") != NULL + || strstr (native_tune, "mcpu=tsv110") != NULL )) + { + char hash[65]; + char input[64]; + const char *prefix = "="; + const char *start = strstr(native_tune, prefix); + if (start) + { + start += strlen(prefix); + const char *end = strchr(start, '+'); + if (!end) + { + end = native_tune + strlen(native_tune); + } + size_t len = end - start; + if (len >= sizeof(input)) len = sizeof(input)- 1; + strncpy(input, start, len); + input[len] = '\0'; + } + else + { + input[0] = '\0'; + } + execute_sha256(input, hash, sizeof(hash)); + optmize_result = graph_infer (1, hash, argc_hw1, argv_hw1); + set_initialize_decision (); + if (optmize_result == 1) + setenv ("AI_GUIDED", "1", 1); + } + return optmize_result; +} \ No newline at end of file diff --git a/gcc/ai4c-infer.h b/gcc/ai4c-infer.h new file mode 100644 index 0000000000000000000000000000000000000000..218b2a1510b338a0b9727f3590d25650c9afa685 --- /dev/null +++ b/gcc/ai4c-infer.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2008-2022 Free Software Foundation, Inc. + Contributed by Zhenyu Zhao (zhaozhenyu17@huawei.com). + +This file is part of GCC. +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef AI4C_INFER +#define AI4C_INFER + +extern int64_t initialize_decision; +extern int64_t optmize_result; +const int64_t argc_hw1 = 6; + +extern int get_optimize_decision (); +extern void set_cache_info (int index, int cache_value); +extern void set_native_tune (const char *info); +extern void set_initialize_decision (); +#endif /* AI4C_INFERH*/ \ No newline at end of file diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 08a43541ebdac51c066155aae234b83d8bb15151..05e1cc1d8b29528a66eadb339c9a7a468fa4b6cd 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -18857,6 +18857,7 @@ static void reset_machine_option (struct gcc_options *opts) { if (!(opts->x_optimize_maximum) + || opts->x_aarch64_cpu_string == NULL || strstr (opts->x_aarch64_tune_string, "hip09") == NULL) { return; diff --git a/gcc/gcc.cc b/gcc/gcc.cc index 32e45adc26486788cf6dc89f47390fb1485f26a8..d8957384633d51d0bf8f6d7d4d67af377e5daf6c 100644 --- a/gcc/gcc.cc +++ b/gcc/gcc.cc @@ -5798,6 +5798,9 @@ do_self_spec (const char *spec) do_spec_2 (spec, NULL); do_spec_1 (" ", 0, NULL); + const char* tune_native = eval_spec_function ("local_cpu_detect", "cpu", ""); + setenv ("TUNE", tune_native, 1); + /* Mark % 0 /* Only enable in lto or whole_program. */ - && (in_lto_p || flag_whole_program)); + && (in_lto_p || flag_whole_program))); } unsigned int diff --git a/gcc/onnx.fdata b/gcc/onnx.fdata new file mode 100644 index 0000000000000000000000000000000000000000..3c8610e7f8822e1603ad0ebce5842f5289ab2c73 Binary files /dev/null and b/gcc/onnx.fdata differ diff --git a/gcc/opts-global.cc b/gcc/opts-global.cc index a18c76940f971d8ff60ffacaa43ae1e8d41f1ed5..ba91617881b5a695e88e5611dd678235c04b0bac 100644 --- a/gcc/opts-global.cc +++ b/gcc/opts-global.cc @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "asan.h" #include "file-prefix-map.h" /* add_*_prefix_map() */ +#include "ai4c-infer.h" typedef const char *const_char_p; /* For DEF_VEC_P. */ @@ -304,6 +305,15 @@ decode_options (struct gcc_options *opts, struct gcc_options *opts_set, location_t loc, diagnostic_context *dc, void (*target_option_override_hook) (void)) { + set_cache_info (0, global_options.x_param_simultaneous_prefetches); + set_cache_info (1, global_options.x_param_l1_cache_size); + set_cache_info (2, global_options.x_param_l1_cache_line_size); + set_cache_info (3, global_options.x_param_l2_cache_size); + set_cache_info (4, global_options.x_param_prefetch_latency); + set_cache_info (5, global_options.x_param_ipa_prefetch_distance_factor); + const char *tune_native = getenv ("TUNE"); + set_native_tune (tune_native); + struct cl_option_handlers handlers; unsigned int lang_mask;