1#include <stdlib.h> 2#include <stdio.h> 3#include <string.h> 4 5#include "libgccjit.h" 6 7#include "harness.h" 8 9void 10create_code (gcc_jit_context *ctxt, void *user_data) 11{ 12 /* Let's try to inject the equivalent of: 13 14 double 15 my_dot_product (int n, double *a, double *b) 16 { 17 double result = 0.; 18 for (int i = 0; i < n; i++) 19 result += a[i] * b[i]; 20 return result 21 } 22 23 and see what the optimizer can do. */ 24 gcc_jit_type *val_type = 25 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); 26 gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (val_type); 27 gcc_jit_type *int_type = 28 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 29 30 gcc_jit_type *return_type = val_type; 31 gcc_jit_param *param_n = 32 gcc_jit_context_new_param (ctxt, NULL, int_type, "n"); 33 gcc_jit_param *param_a = 34 gcc_jit_context_new_param (ctxt, NULL, ptr_type, "a"); 35 gcc_jit_param *param_b = 36 gcc_jit_context_new_param (ctxt, NULL, ptr_type, "b"); 37 gcc_jit_param *params[3] = {param_n, param_a, param_b}; 38 gcc_jit_function *func = 39 gcc_jit_context_new_function (ctxt, NULL, 40 GCC_JIT_FUNCTION_EXPORTED, 41 return_type, 42 "my_dot_product", 43 3, params, 0); 44 45 gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial"); 46 gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test"); 47 gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body"); 48 gcc_jit_block *final = gcc_jit_function_new_block (func, "final"); 49 50 /* Build: "double result = 0.;" */ 51 gcc_jit_lvalue *result = 52 gcc_jit_function_new_local (func, NULL, val_type, "result"); 53 54 gcc_jit_block_add_assignment (initial, NULL, 55 result, gcc_jit_context_zero (ctxt, val_type)); 56 57 /* Build: "for (int i = 0; i < n; i++)" */ 58 gcc_jit_lvalue *i = 59 gcc_jit_function_new_local (func, NULL, int_type, "i"); 60 gcc_jit_block_add_assignment (initial, NULL, 61 i, gcc_jit_context_zero (ctxt, int_type)); 62 63 gcc_jit_block_end_with_jump (initial, NULL, loop_test); 64 65 gcc_jit_block_end_with_conditional ( 66 loop_test, NULL, 67 68 /* (i < n) */ 69 gcc_jit_context_new_comparison ( 70 ctxt, NULL, 71 GCC_JIT_COMPARISON_LT, 72 gcc_jit_lvalue_as_rvalue (i), 73 gcc_jit_param_as_rvalue (param_n)), 74 75 loop_body, 76 final); 77 78 /* Build: "result += a[i] * b[i];" */ 79 gcc_jit_block_add_assignment_op ( 80 loop_body, NULL, 81 result, 82 GCC_JIT_BINARY_OP_PLUS, 83 gcc_jit_context_new_binary_op ( 84 ctxt, NULL, 85 GCC_JIT_BINARY_OP_MULT, 86 val_type, 87 gcc_jit_lvalue_as_rvalue ( 88 gcc_jit_context_new_array_access ( 89 ctxt, NULL, 90 gcc_jit_param_as_rvalue (param_a), 91 gcc_jit_lvalue_as_rvalue (i))), 92 gcc_jit_lvalue_as_rvalue ( 93 gcc_jit_context_new_array_access ( 94 ctxt, NULL, 95 gcc_jit_param_as_rvalue (param_b), 96 gcc_jit_lvalue_as_rvalue (i))))); 97 98 /* Build: "i++" */ 99 gcc_jit_block_add_assignment_op ( 100 loop_body, NULL, 101 i, 102 GCC_JIT_BINARY_OP_PLUS, 103 gcc_jit_context_one (ctxt, int_type)); 104 105 gcc_jit_block_end_with_jump (loop_body, NULL, loop_test); 106 107 /* Build: "return result;" */ 108 gcc_jit_block_end_with_return ( 109 final, 110 NULL, 111 gcc_jit_lvalue_as_rvalue (result)); 112} 113 114void 115verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) 116{ 117 typedef double (*my_dot_product_fn_type) (int n, double *a, double *b); 118 CHECK_NON_NULL (result); 119 120 my_dot_product_fn_type my_dot_product = 121 (my_dot_product_fn_type)gcc_jit_result_get_code (result, 122 "my_dot_product"); 123 CHECK_NON_NULL (my_dot_product); 124 double test_array[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}; 125 double val = my_dot_product (10, test_array, test_array); 126 note ("my_dot_product returned: %f", val); 127 CHECK_VALUE (val, 385.0); 128} 129 130