1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "libgccjit.h"
6
7 #include "harness.h"
8
9 void
create_code(gcc_jit_context * ctxt,void * user_data)10 create_code (gcc_jit_context *ctxt, void *user_data)
11 {
12 /* Let's try to inject the equivalent of:
13
14 double
15 test_nested_loops (int n, double *a, double *b)
16 {
17 double result = 0.;
18 for (int i = 0; i < n; i++)
19 for (int j = 0; j < n; j++)
20 result += a[i] * b[j];
21 return result
22 }
23 */
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 "test_nested_loops",
43 3, params, 0);
44
45 /* Create locals. */
46 gcc_jit_lvalue *result =
47 gcc_jit_function_new_local (func, NULL, val_type, "result");
48 gcc_jit_lvalue *i =
49 gcc_jit_function_new_local (func, NULL, int_type, "i");
50 gcc_jit_lvalue *j =
51 gcc_jit_function_new_local (func, NULL, int_type, "j");
52
53 /* Create basic blocks. */
54 gcc_jit_block *b_entry =
55 gcc_jit_function_new_block (func, "b_entry");
56 gcc_jit_block *b_outer_loop_cond =
57 gcc_jit_function_new_block (func, "b_outer_loop_cond");
58 gcc_jit_block *b_outer_loop_head =
59 gcc_jit_function_new_block (func, "b_outer_loop_head");
60 gcc_jit_block *b_outer_loop_tail =
61 gcc_jit_function_new_block (func, "b_outer_loop_tail");
62 gcc_jit_block *b_inner_loop_cond =
63 gcc_jit_function_new_block (func, "b_inner_loop_cond");
64 gcc_jit_block *b_inner_loop_body =
65 gcc_jit_function_new_block (func, "b_inner_loop_body");
66 gcc_jit_block *b_exit =
67 gcc_jit_function_new_block (func, "b_exit");
68
69
70 /* Populate b_entry. */
71
72 /* "result = 0.;" */
73 gcc_jit_block_add_assignment (
74 b_entry, NULL,
75 result,
76 gcc_jit_context_zero (ctxt, val_type));
77 /* "i = 0;" */
78 gcc_jit_block_add_assignment (
79 b_entry, NULL,
80 i,
81 gcc_jit_context_zero (ctxt, int_type));
82 gcc_jit_block_end_with_jump (b_entry, NULL, b_outer_loop_cond);
83
84 /* Populate b_outer_loop_cond. */
85 gcc_jit_block_end_with_conditional (
86 b_outer_loop_cond,
87 NULL,
88 /* (i < n) */
89 gcc_jit_context_new_comparison (
90 ctxt, NULL,
91 GCC_JIT_COMPARISON_LT,
92 gcc_jit_lvalue_as_rvalue (i),
93 gcc_jit_param_as_rvalue (param_n)),
94 b_outer_loop_head,
95 b_exit);
96
97 /* Populate b_outer_loop_head. */
98 /* j = 0; */
99 gcc_jit_block_add_assignment (
100 b_outer_loop_head, NULL,
101 j,
102 gcc_jit_context_zero (ctxt, int_type));
103 gcc_jit_block_end_with_jump (b_outer_loop_head, NULL, b_inner_loop_cond);
104
105 /* Populate b_inner_loop_cond. */
106 gcc_jit_block_end_with_conditional (
107 b_inner_loop_cond,
108 NULL,
109 /* (j < n) */
110 gcc_jit_context_new_comparison (
111 ctxt, NULL,
112 GCC_JIT_COMPARISON_LT,
113 gcc_jit_lvalue_as_rvalue (j),
114 gcc_jit_param_as_rvalue (param_n)),
115 b_inner_loop_body,
116 b_outer_loop_tail);
117
118 /* Populate b_inner_loop_body. */
119 /* "result += a[i] * b[j];" */
120 gcc_jit_block_add_assignment_op (
121 b_inner_loop_body, NULL,
122 result,
123 GCC_JIT_BINARY_OP_PLUS,
124 gcc_jit_context_new_binary_op (
125 ctxt, NULL,
126 GCC_JIT_BINARY_OP_MULT,
127 val_type,
128 gcc_jit_lvalue_as_rvalue (
129 gcc_jit_context_new_array_access(
130 ctxt, NULL,
131 gcc_jit_param_as_rvalue (param_a),
132 gcc_jit_lvalue_as_rvalue (i))),
133 gcc_jit_lvalue_as_rvalue (
134 gcc_jit_context_new_array_access(
135 ctxt, NULL,
136 gcc_jit_param_as_rvalue (param_b),
137 gcc_jit_lvalue_as_rvalue (j)))));
138 /* "j++" */
139 gcc_jit_block_add_assignment_op (
140 b_inner_loop_body, NULL,
141 j,
142 GCC_JIT_BINARY_OP_PLUS,
143 gcc_jit_context_one (ctxt, int_type));
144
145 gcc_jit_block_end_with_jump (b_inner_loop_body, NULL, b_inner_loop_cond);
146
147 /* Populate b_outer_loop_tail. */
148 /* "i++" */
149 gcc_jit_block_add_assignment_op (
150 b_outer_loop_tail, NULL,
151 i,
152 GCC_JIT_BINARY_OP_PLUS,
153 gcc_jit_context_one (ctxt, int_type));
154 gcc_jit_block_end_with_jump (b_outer_loop_tail, NULL, b_outer_loop_cond);
155
156 /* Populate b_exit. */
157 /* "return result;" */
158 gcc_jit_block_end_with_return (
159 b_exit,
160 NULL,
161 gcc_jit_lvalue_as_rvalue (result));
162 }
163
164 void
verify_code(gcc_jit_context * ctxt,gcc_jit_result * result)165 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
166 {
167 typedef double (*test_nested_loops_fn_type) (int n, double *a, double *b);
168 CHECK_NON_NULL (result);
169
170 test_nested_loops_fn_type test_nested_loops =
171 (test_nested_loops_fn_type)gcc_jit_result_get_code (result,
172 "test_nested_loops");
173 CHECK_NON_NULL (test_nested_loops);
174 double test_a[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
175 double test_b[] = {5., 6., 7., 8., 9., 10., 1., 2., 3., 4.};
176 double val = test_nested_loops (10, test_a, test_b);
177 note ("test_nested_loops returned: %f", val);
178 CHECK_VALUE (val, 3025.0);
179 }
180