(root)/
gcc-13.2.0/
gcc/
testsuite/
jit.dg/
test-nested-loops.c
       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
      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
     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  }