test-nested-loops.c 5.2 KB

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