public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] jit: add gcc_jit_type_get_vector
  2017-01-01  0:00   ` Michael Cree
@ 2017-01-01  0:00     ` David Malcolm
  2017-01-01  0:00       ` Michael Cree
  0 siblings, 1 reply; 9+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: Michael Cree; +Cc: jit, gcc-patches, David Malcolm

On Wed, 2017-08-09 at 20:42 +1200, Michael Cree wrote:
> On Mon, Aug 07, 2017 at 10:28:57AM -0400, David Malcolm wrote:
> > On Mon, 2017-08-07 at 20:12 +1200, Michael Cree wrote:
> > 
> > Hi Michael
> > 
> > > I am wondering if libgccjit supports vector types, i.e., can one
> > > attach attribute __vector_size__ to the base types?  There does
> > > not
> > > seem to be any indication of this in the manual.
> > 
> > Currently this isn't supported.
> > 
> > Is this a blocker for you using libgccjit?  
> 
> Yeah, it is.  The idea is to generate image processing operators
> on the fly.  There are opportunities for various optimisations that
> can only be decided on at runtime.
> 
> > What would the ideal API
> > look like? 
> > 
> > Maybe something like:
> > 
> >   extern gcc_jit_type *
> >   gcc_jit_type_get_vector (gcc_jit_type *type, unsigned nunits);
> >  
> > with various requirements (type must be integral/floating point;
> > nunits
> > must be a power of two).
> 
> I suspect that would do the job nicely.
> 
> Cheers
> Michael.

I implemented the above (although I switched the 2nd arg to be
"size_t num_units").

It looks like you may not need to explicitly use builtins to
access machine specific simd intrinsics; for example, on x86_64
when I tried multiplying two of these together for float, with
GCC_JIT_BINARY_OP_MULT, which led to this gimple:

jit_v4f_mult (const vector(4) <float:32> * a, const vector(4) <float:32> * b, vector(4) <float:32> * c)
{
  initial:
  _1 = *a;
  _2 = *b;
  _3 = _1 * _2;
  *c = _3;
  return;
}

on this x86_64 box it compiled to:

	movaps	(%rdi), %xmm0
	mulps	(%rsi), %xmm0
	movaps	%xmm0, (%rdx)
	ret

(i.e. using the "mulps" SIMD instruction).

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu;
takes jit.sum from 9349 passes to 9759.

Committed to trunk as r251018.

gcc/jit/ChangeLog:
	* docs/cp/topics/types.rst (Vector types): New section.
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_8): New tag.
	* docs/topics/types.rst (gcc_jit_context_get_type): Fix typo in
	example.
	(Vector types): New section.
	* docs/_build/texinfo/libgccjit.texi: Regenerate.
	* jit-playback.c (gcc::jit::playback::type::get_vector): New
	method.
	* jit-playback.h (gcc::jit::playback::type::get_vector): New
	method.
	* jit-recording.c: In namespace gcc::jit::recording::
	(type::get_vector): New method.
	(memento_of_get_aligned::write_reproducer): Fix typo
	in leading comment.
	(memento_of_get_vector::replay_into): New method.
	(memento_of_get_vector::make_debug_string): New method.
	(memento_of_get_vector::write_reproducer): New method.
	* jit-recording.h: In namespace gcc::jit::recording::
	(type::get_vector): New
	 method.
	(class memento_of_get_vector): New class.
	* libgccjit++.h (gccjit::type::get_vector): New method.
	* libgccjit.c (gcc_jit_type_get_vector): New public entrypoint.
	* libgccjit.h (LIBGCCJIT_HAVE_gcc_jit_type_get_vector): New
	define.
	(gcc_jit_type_get_vector): New decl.
	* libgccjit.map (LIBGCCJIT_ABI_8): New ABI tag.

gcc/testsuite/ChangeLog:
	* jit.dg/all-non-failing-tests.h: Add note about
	test-vector-types.cc.
	* jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c: New test
	case.
	* jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c:
	New test case.
	* jit.dg/test-vector-types.cc: New test case.
---
 gcc/jit/docs/cp/topics/types.rst                   |  14 ++
 gcc/jit/docs/topics/compatibility.rst              |   7 +
 gcc/jit/docs/topics/types.rst                      |  43 ++++-
 gcc/jit/jit-playback.c                             |  11 ++
 gcc/jit/jit-playback.h                             |   1 +
 gcc/jit/jit-recording.c                            |  56 ++++++-
 gcc/jit/jit-recording.h                            |  26 ++-
 gcc/jit/libgccjit++.h                              |   8 +
 gcc/jit/libgccjit.c                                |  28 ++++
 gcc/jit/libgccjit.h                                |  15 ++
 gcc/jit/libgccjit.map                              |   5 +
 gcc/testsuite/jit.dg/all-non-failing-tests.h       |   2 +
 .../test-error-gcc_jit_type_get_vector-bad-type.c  |  30 ++++
 ...rror-gcc_jit_type_get_vector-non-power-of-two.c |  29 ++++
 gcc/testsuite/jit.dg/test-vector-types.cc          | 185 +++++++++++++++++++++
 15 files changed, 456 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c
 create mode 100644 gcc/testsuite/jit.dg/test-vector-types.cc

diff --git a/gcc/jit/docs/cp/topics/types.rst b/gcc/jit/docs/cp/topics/types.rst
index e85a492..1df896e 100644
--- a/gcc/jit/docs/cp/topics/types.rst
+++ b/gcc/jit/docs/cp/topics/types.rst
@@ -109,6 +109,20 @@ Pointers, `const`, and `volatile`
    Param "loc" is optional.
 
 
+Vector types
+------------
+
+.. function::  gccjit::type gccjit::type::get_vector (size_t num_units)
+
+   Given type "T", get type:
+
+   .. code-block:: c
+
+      T  __attribute__ ((vector_size (sizeof(T) * num_units))
+
+   T must be integral or floating point; num_units must be a power of two.
+
+
 Structures and unions
 ---------------------
 
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 5a13653..1d5fbc2 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -149,3 +149,10 @@ entrypoints:
 -------------------
 ``LIBGCCJIT_ABI_7`` covers the addition of
 :func:`gcc_jit_type_get_aligned`
+
+.. _LIBGCCJIT_ABI_8:
+
+``LIBGCCJIT_ABI_8``
+-------------------
+``LIBGCCJIT_ABI_8`` covers the addition of
+:func:`gcc_jit_type_get_vector`
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 119f10e..c279222 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -35,7 +35,7 @@ Types can be created in several ways:
 
   .. code-block:: c
 
-      gcc_jit_type *int_type = gcc_jit_context_get_type (GCC_JIT_TYPE_INT);
+      gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
 
   See :func:`gcc_jit_context_get_type` for the available types.
 
@@ -136,6 +136,47 @@ Pointers, `const`, and `volatile`
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned
 
+Vector types
+------------
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_get_vector (gcc_jit_type *type, \
+                                        size_t num_units)
+
+   Given type "T", get type:
+
+   .. code-block:: c
+
+      T  __attribute__ ((vector_size (sizeof(T) * num_units))
+
+   T must be integral or floating point; num_units must be a power of two.
+
+   This can be used to construct a vector type in which operations
+   are applied element-wise.  The compiler will automatically
+   use SIMD instructions where possible.  See:
+   https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
+
+   For example, assuming 4-byte ``ints``, then:
+
+   .. code-block:: c
+
+      typedef int v4si __attribute__ ((vector_size (16)));
+
+   can be obtained using:
+
+   .. code-block:: c
+
+      gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+                                                         GCC_JIT_TYPE_INT);
+      gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4);
+
+   This API entrypoint was added in :ref:`LIBGCCJIT_ABI_8`; you can test
+   for its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector
+
 
 Structures and unions
 ---------------------
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 76cc88f..19b6fe2 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -1110,6 +1110,17 @@ get_aligned (size_t alignment_in_bytes) const
   return new type (t_new_type);
 }
 
+/* Construct a playback::type instance (wrapping a tree)
+   for the given vector type.  */
+
+playback::type *
+playback::type::
+get_vector (size_t num_units) const
+{
+  tree t_new_type = build_vector_type (m_inner, num_units);
+  return new type (t_new_type);
+}
+
 /* Construct a playback::lvalue instance (wrapping a tree) for a
    field access.  */
 
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 0a83390..7dc7315 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -392,6 +392,7 @@ public:
   }
 
   type *get_aligned (size_t alignment_in_bytes) const;
+  type *get_vector (size_t num_units) const;
 
 private:
   tree m_inner;
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 723ddb3..ea4ebb1 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -1988,6 +1988,20 @@ recording::type::get_aligned (size_t alignment_in_bytes)
   return result;
 }
 
+/* Given a type, get a vector version of the type.
+
+   Implements the post-error-checking part of
+   gcc_jit_type_get_vector.  */
+
+recording::type *
+recording::type::get_vector (size_t num_units)
+{
+  recording::type *result
+    = new memento_of_get_vector (this, num_units);
+  m_ctxt->record (result);
+  return result;
+}
+
 const char *
 recording::type::access_as_type (reproducer &r)
 {
@@ -2457,7 +2471,7 @@ recording::memento_of_get_aligned::make_debug_string ()
 			      m_alignment_in_bytes);
 }
 
-/* Implementation of recording::memento::write_reproducer for volatile
+/* Implementation of recording::memento::write_reproducer for aligned
    types. */
 
 void
@@ -2471,6 +2485,46 @@ recording::memento_of_get_aligned::write_reproducer (reproducer &r)
 	   m_alignment_in_bytes);
 }
 
+/* The implementation of class gcc::jit::recording::memento_of_get_vector.  */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+   for recording::memento_of_get_vector.  */
+
+void
+recording::memento_of_get_vector::replay_into (replayer *)
+{
+  set_playback_obj
+    (m_other_type->playback_type ()->get_vector (m_num_units));
+}
+
+/* Implementation of recording::memento::make_debug_string for
+   results of get_vector.  */
+
+recording::string *
+recording::memento_of_get_vector::make_debug_string ()
+{
+  return string::from_printf
+    (m_ctxt,
+     "%s  __attribute__((vector_size(sizeof (%s) * %zi)))",
+     m_other_type->get_debug_string (),
+     m_other_type->get_debug_string (),
+     m_num_units);
+}
+
+/* Implementation of recording::memento::write_reproducer for volatile
+   types. */
+
+void
+recording::memento_of_get_vector::write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "type");
+  r.write ("  gcc_jit_type *%s =\n"
+	   "    gcc_jit_type_get_vector (%s, %zi);\n",
+	   id,
+	   r.get_identifier_as_type (m_other_type),
+	   m_num_units);
+}
+
 /* The implementation of class gcc::jit::recording::array_type */
 
 /* Implementation of pure virtual hook recording::type::dereference for
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 5faf35e..248765d 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -474,6 +474,7 @@ public:
   type *get_const ();
   type *get_volatile ();
   type *get_aligned (size_t alignment_in_bytes);
+  type *get_vector (size_t num_units);
 
   /* Get the type obtained when dereferencing this type.
 
@@ -600,8 +601,8 @@ private:
   type *m_other_type;
 };
 
-/* A decorated version of a type, for get_const, get_volatile and
-   get_aligned.  */
+/* A decorated version of a type, for get_const, get_volatile,
+   get_aligned, and get_vector.  */
 
 class decorated_type : public type
 {
@@ -683,6 +684,27 @@ private:
   size_t m_alignment_in_bytes;
 };
 
+/* Result of "gcc_jit_type_get_vector".  */
+class memento_of_get_vector : public decorated_type
+{
+public:
+  memento_of_get_vector (type *other_type, size_t num_units)
+  : decorated_type (other_type),
+    m_num_units (num_units) {}
+
+  /* Strip off the alignment, giving the underlying type.  */
+  type *unqualified () FINAL OVERRIDE { return m_other_type; }
+
+  void replay_into (replayer *) FINAL OVERRIDE;
+
+private:
+  string * make_debug_string () FINAL OVERRIDE;
+  void write_reproducer (reproducer &r) FINAL OVERRIDE;
+
+private:
+  size_t m_num_units;
+};
+
 class array_type : public type
 {
  public:
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index ea277f8..a83ccf6 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -333,6 +333,7 @@ namespace gccjit
     type get_const ();
     type get_volatile ();
     type get_aligned (size_t alignment_in_bytes);
+    type get_vector (size_t num_units);
 
     // Shortcuts for getting values of numeric types:
     rvalue zero ();
@@ -1306,6 +1307,13 @@ type::get_aligned (size_t alignment_in_bytes)
 					 alignment_in_bytes));
 }
 
+inline type
+type::get_vector (size_t num_units)
+{
+  return type (gcc_jit_type_get_vector (get_inner_type (),
+					num_units));
+}
+
 inline rvalue
 type::zero ()
 {
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 9b003e3..6e352c6 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -2994,3 +2994,31 @@ gcc_jit_type_get_aligned (gcc_jit_type *type,
 
   return (gcc_jit_type *)type->get_aligned (alignment_in_bytes);
 }
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::get_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_get_vector (gcc_jit_type *type, size_t num_units)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  gcc::jit::recording::context *ctxt = type->m_ctxt;
+
+  JIT_LOG_FUNC (ctxt->get_logger ());
+
+  RETURN_NULL_IF_FAIL_PRINTF1
+    (type->is_int () || type->is_float (), ctxt, NULL,
+     "type is not integral or floating point: %s",
+     type->get_debug_string ());
+
+  RETURN_NULL_IF_FAIL_PRINTF1
+    (pow2_or_zerop (num_units), ctxt, NULL,
+     "num_units not a power of two: %zi",
+     num_units);
+
+  return (gcc_jit_type *)type->get_vector (num_units);
+}
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 898ee98..b863b07 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1403,6 +1403,21 @@ extern gcc_jit_type *
 gcc_jit_type_get_aligned (gcc_jit_type *type,
 			  size_t alignment_in_bytes);
 
+#define LIBGCCJIT_HAVE_gcc_jit_type_get_vector
+
+/* Given type "T", get type:
+
+     T  __attribute__ ((vector_size (sizeof(T) * num_units))
+
+   T must be integral/floating point; num_units must be a power of two.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_8; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector
+*/
+extern gcc_jit_type *
+gcc_jit_type_get_vector (gcc_jit_type *type, size_t num_units);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 160f4cd..08760e3 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -155,3 +155,8 @@ LIBGCCJIT_ABI_7 {
   global:
     gcc_jit_type_get_aligned;
 } LIBGCCJIT_ABI_6;
+
+LIBGCCJIT_ABI_8 {
+  global:
+    gcc_jit_type_get_vector;
+} LIBGCCJIT_ABI_7;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 58e0c30..4af704a 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -228,6 +228,8 @@
    of gcc_jit_context_set_bool_allow_unreachable_blocks affects the whole
    context.  */
 
+/* test-vector-types.cc: We don't use this, since it's C++.  */
+
 /* test-volatile.c */
 #define create_code create_code_volatile
 #define verify_code verify_code_volatile
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c
new file mode 100644
index 0000000..59aed33
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *void_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+  /* Trigger an API error by passing a bad type.  */
+  (void)gcc_jit_type_get_vector (void_type, 4);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      ("gcc_jit_type_get_vector:"
+		       " type is not integral or floating point: void"));
+}
+
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c
new file mode 100644
index 0000000..aa3bdbd
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c
@@ -0,0 +1,29 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  /* Trigger an API error by passing a bad number of units.  */
+  (void)gcc_jit_type_get_vector (int_type, 7);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      ("gcc_jit_type_get_vector:"
+		       " num_units not a power of two: 7"));
+}
diff --git a/gcc/testsuite/jit.dg/test-vector-types.cc b/gcc/testsuite/jit.dg/test-vector-types.cc
new file mode 100644
index 0000000..3389e04
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-vector-types.cc
@@ -0,0 +1,185 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+typedef int v4si __attribute__ ((vector_size (16)));
+typedef unsigned int v4ui __attribute__ ((vector_size (16)));
+typedef float v4f __attribute__ ((vector_size (16)));
+
+static void
+create_vec_fn (gcc_jit_context *ctxt, const char *fnname,
+	       gcc_jit_type *the_type, enum gcc_jit_binary_op op)
+{
+  /* Create equivalent to:
+
+       static void
+       FNNAME (const T *a, const T *b, T *c)
+       {
+         *c = *a OP *b;
+       }
+
+     where T is "the_type" (e.g. v4si).  */
+
+  gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (the_type);
+
+  gcc_jit_type *const_type = gcc_jit_type_get_const (the_type);
+  gcc_jit_type *ptr_to_const_type = gcc_jit_type_get_pointer (const_type);
+
+  gcc_jit_param *a =
+    gcc_jit_context_new_param (ctxt, NULL, ptr_to_const_type, "a");
+  gcc_jit_param *b =
+    gcc_jit_context_new_param (ctxt, NULL, ptr_to_const_type, "b");
+  gcc_jit_param *c =
+    gcc_jit_context_new_param (ctxt, NULL, ptr_type, "c");
+
+  gcc_jit_type *return_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+  gcc_jit_param *params[3] = {a, b, c};
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  return_type,
+				  fnname,
+				  3, params, 0);
+  gcc_jit_block *initial =
+    gcc_jit_function_new_block (func, "initial");
+
+  /* (*a OP *b) */
+  gcc_jit_rvalue *op_result =
+    gcc_jit_context_new_binary_op (
+      ctxt, NULL,
+      op,
+      the_type,
+      gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (a),
+							    NULL)),
+      gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (b),
+							    NULL)));
+  /* *c = *a OP *b; */
+  gcc_jit_block_add_assignment (
+    initial, NULL,
+    gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (c), NULL),
+    op_result);
+  gcc_jit_block_end_with_void_return (initial, NULL);
+}
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_type *unsigned_type
+    = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
+  gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+  gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4);
+  gcc_jit_type *v4ui_type = gcc_jit_type_get_vector (unsigned_type, 4);
+  gcc_jit_type *v4f_type = gcc_jit_type_get_vector (float_type, 4);
+
+  create_vec_fn (ctxt, "jit_v4si_add",
+		 v4si_type, GCC_JIT_BINARY_OP_PLUS);
+  create_vec_fn (ctxt, "jit_v4si_sub",
+		 v4si_type, GCC_JIT_BINARY_OP_MINUS);
+  create_vec_fn (ctxt, "jit_v4si_mult",
+		 v4si_type, GCC_JIT_BINARY_OP_MULT);
+  create_vec_fn (ctxt, "jit_v4si_div",
+		 v4si_type, GCC_JIT_BINARY_OP_DIVIDE);
+
+  create_vec_fn (ctxt, "jit_v4ui_add",
+		 v4ui_type, GCC_JIT_BINARY_OP_PLUS);
+  create_vec_fn (ctxt, "jit_v4ui_sub",
+		 v4ui_type, GCC_JIT_BINARY_OP_MINUS);
+  create_vec_fn (ctxt, "jit_v4ui_mult",
+		 v4ui_type, GCC_JIT_BINARY_OP_MULT);
+  create_vec_fn (ctxt, "jit_v4ui_div",
+		 v4ui_type, GCC_JIT_BINARY_OP_DIVIDE);
+
+  create_vec_fn (ctxt, "jit_v4f_add",
+		 v4f_type, GCC_JIT_BINARY_OP_PLUS);
+  create_vec_fn (ctxt, "jit_v4f_sub",
+		 v4f_type, GCC_JIT_BINARY_OP_MINUS);
+  create_vec_fn (ctxt, "jit_v4f_mult",
+		 v4f_type, GCC_JIT_BINARY_OP_MULT);
+  create_vec_fn (ctxt, "jit_v4f_div",
+		 v4f_type, GCC_JIT_BINARY_OP_DIVIDE);
+}
+
+template <typename T>
+void
+check_add (const T &a, const T &b, const T &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] + b[i]);
+}
+
+template <typename T>
+void
+check_sub (const T &a, const T &b, const T &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] - b[i]);
+}
+
+template <typename T>
+void
+check_mult (const T &a, const T &b, const T &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] * b[i]);
+}
+
+template <typename T>
+void
+check_div (const T &a, const T &b, const T &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] / b[i]);
+}
+
+template <typename T>
+void
+verify_vec_code (gcc_jit_context *ctxt, gcc_jit_result *result,
+		 const char *fnname,
+		 void (*check_cb) (const T &a, const T &b, const T &c))
+{
+  typedef void (*binop_type) (const T *a, const T *b, T *c);
+  CHECK_NON_NULL (result);
+  binop_type fn =
+    (binop_type)gcc_jit_result_get_code (result, fnname);
+  CHECK_NON_NULL (fn);
+
+  T a, b, c;
+
+  /* Init.  */
+  for (int i = 0; i < 4; i++)
+    {
+      a[i] = i + 5;
+      b[i] = (i + 4) * 3;
+    }
+
+  /* Run jit-compiled code and verify result.  */
+  fn (&a, &b, &c);
+  check_cb (a, b, c);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  verify_vec_code<v4si> (ctxt, result, "jit_v4si_add", check_add);
+  verify_vec_code<v4si> (ctxt, result, "jit_v4si_sub", check_sub);
+  verify_vec_code<v4si> (ctxt, result, "jit_v4si_mult", check_mult);
+  verify_vec_code<v4si> (ctxt, result, "jit_v4si_div", check_div);
+
+  verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_add", check_add);
+  verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_sub", check_sub);
+  verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_mult", check_mult);
+  verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_div", check_div);
+
+  verify_vec_code<v4f> (ctxt, result, "jit_v4f_add", check_add);
+  verify_vec_code<v4f> (ctxt, result, "jit_v4f_sub", check_sub);
+  verify_vec_code<v4f> (ctxt, result, "jit_v4f_mult", check_mult);
+  verify_vec_code<v4f> (ctxt, result, "jit_v4f_div", check_div);
+}
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* does libgccjit support vector types?
@ 2017-01-01  0:00 Michael Cree
  2017-01-01  0:00 ` David Malcolm
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Cree @ 2017-01-01  0:00 UTC (permalink / raw)
  To: jit

I am wondering if libgccjit supports vector types, i.e., can one
attach attribute __vector_size__ to the base types?  There does not
seem to be any indication of this in the manual.

I presume using gcc_jit_context_add_command_line_option() one can turn
on code generation for sse/avx/neon/altivec, etc.

And is there a way to access built-in functions such as the machine
specific simd intrinsics?

Cheers
Michael.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: does libgccjit support vector types?
  2017-01-01  0:00 does libgccjit support vector types? Michael Cree
@ 2017-01-01  0:00 ` David Malcolm
  2017-01-01  0:00   ` Michael Cree
  0 siblings, 1 reply; 9+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: Michael Cree, jit

On Mon, 2017-08-07 at 20:12 +1200, Michael Cree wrote:

Hi Michael

> I am wondering if libgccjit supports vector types, i.e., can one
> attach attribute __vector_size__ to the base types?  There does not
> seem to be any indication of this in the manual.

Currently this isn't supported.

[notes to self e.g.:

   typedef int v4si __attribute__ ((vector_size (16)));

is normally handled by C/C++ here:

c-family/c-attribs.c:260:
  { "vector_size",	      1, 1, false, true, false,
			      handle_vector_size_attribute, true },

which ultimately calls:

    new_type = build_vector_type (type, nunits);

    /* Build back pointers if needed.  */
    *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);

(the latter does some support stuff for C++ templates).

Hence the "vector_size" attribute itself isn't supported by libgccjit,
and the underlying build_vector_type call within gcc's internal API
isn't exposed yet via libgccjit.

end of notes to self]

Is this a blocker for you using libgccjit?  What would the ideal API
look like? 

Maybe something like:

  extern gcc_jit_type *
  gcc_jit_type_get_vector (gcc_jit_type *type, unsigned nunits);
 
with various requirements (type must be integral/floating point; nunits
must be a power of two).

> I presume using gcc_jit_context_add_command_line_option() one can
> turn
> on code generation for sse/avx/neon/altivec, etc.

That ought to work, though currently the only usage examples in the
testsuite for this entrypoint are platform-independent (e.g. "-ffast-
math").

> And is there a way to access built-in functions such as the machine
> specific simd intrinsics?

gcc_jit_context_get_builtin_function ought to work, though I don't
think I've tested this particular use-case (as above, the usage
examples in the testsuite are currently all platform-independent).


Hope this is helpful
Dave

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [committed] jit: fix segfault with autovectorization (PR tree-optimization/46805)
  2017-01-01  0:00             ` David Malcolm
@ 2017-01-01  0:00               ` David Malcolm
  0 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: gcc-patches, jit, Michael Cree; +Cc: David Malcolm

On Thu, 2017-08-17 at 11:51 -0400, David Malcolm wrote:
> On Thu, 2017-08-17 at 09:15 +1200, Michael Cree wrote:
> > On Wed, Aug 16, 2017 at 10:01:57AM -0400, David Malcolm wrote:
> > > On Wed, 2017-08-16 at 21:58 +1200, Michael Cree wrote:
> > > > 
> > > > But I have hit a problem which I suspect is a bug in the gcc
> > > > optimiser.
> > > > 
> > > > In the vein of your example above, but working on uint8_t pixel
> > > > data
> > > > and adding saturation, the jit compiler segfaults in the
> > > > optimiser. I
> > > > provide below the gimple produced by the function that causes
> > > > the
> > > > problem (I presume that is more useful than the code calling
> > > > the
> > > > gcc_jit routines), 
> > > 
> > > There's actually a handy entrypoint for generating minimal
> > > reproducers
> > > for such crashes:
> > >   gcc_jit_context_dump_reproducer_to_file
> > > 
> > > https://gcc.gnu.org/onlinedocs/jit/topics/contexts.html#gcc_jit_c
> > > on
> > > text_dump_reproducer_to_file
> > > 
> > > Can you add a call to that to your code (after the context is
> > > fully
> > > populated), and see if the resulting .c file leads to the crash
> > > when
> > > run?  If so, can you post the .c file here please (or attach it
> > > to
> > > bugzilla), and hopefully I can then reproduce it at my end.
> > 
> > Attached.
> > 
> > Cheers
> > Michael.
> 
> Thanks.  I'm able to reproduce the crash using that; am
> investigating.
> 
> Dave

libgccjit ran into its own version of PR tree-optimization/46805 (seen
with the Go frontend); this patch fixes it in the same way.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
Takes jit.sum from 9759 passes to 9769.

Committed to trunk as r251192.

gcc/jit/ChangeLog:
	PR tree-optimization/46805
	* dummy-frontend.c (jit_langhook_parse_file): Handle vector types.

gcc/testsuite/ChangeLog:
	PR tree-optimization/46805
	* jit.dg/all-non-failing-tests.h: Add test-autovectorize.c.
	* jit.dg/test-autovectorize.c: New test case.
---
 gcc/jit/dummy-frontend.c                     |  11 +
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-autovectorize.c    | 375 +++++++++++++++++++++++++++
 3 files changed, 396 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-autovectorize.c

diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
index d7d2172..b217290 100644
--- a/gcc/jit/dummy-frontend.c
+++ b/gcc/jit/dummy-frontend.c
@@ -165,6 +165,17 @@ jit_langhook_parse_file (void)
 static tree
 jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
 {
+  /* Build any vector types here (see PR 46805).  */
+  if (VECTOR_MODE_P (mode))
+    {
+      tree inner;
+
+      inner = jit_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
+      if (inner != NULL_TREE)
+	return build_vector_type_for_mode (inner, mode);
+      return NULL_TREE;
+    }
+
   if (mode == TYPE_MODE (float_type_node))
     return float_type_node;
 
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4af704a..acfcc40 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -50,6 +50,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-autovectorize.c */
+#define create_code create_code_autovectorize
+#define verify_code verify_code_autovectorize
+#include "test-autovectorize.c"
+#undef create_code
+#undef verify_code
+
 /* test-calling-external-function.c */
 #define create_code create_code_calling_external_function
 #define verify_code verify_code_calling_external_function
@@ -267,6 +274,9 @@ const struct testcase testcases[] = {
   {"arrays",
    create_code_arrays,
    verify_code_arrays},
+  {"autovectorize",
+   create_code_autovectorize,
+   verify_code_autovectorize},
   {"calling_external_function",
    create_code_calling_external_function,
    verify_code_calling_external_function},
diff --git a/gcc/testsuite/jit.dg/test-autovectorize.c b/gcc/testsuite/jit.dg/test-autovectorize.c
new file mode 100644
index 0000000..9cfd0b2
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-autovectorize.c
@@ -0,0 +1,375 @@
+#include <libgccjit.h>
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void * user_data)
+{
+  gcc_jit_type *type_void = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+  gcc_jit_type *type_int = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_type *type_unsigned_char = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR);
+  gcc_jit_type *type_void_ptr =
+    gcc_jit_type_get_pointer (type_void);
+  gcc_jit_type *type_void_ptr_ptr =
+    gcc_jit_type_get_pointer (type_void_ptr);
+  gcc_jit_type *type_unsigned_char__ =
+    gcc_jit_type_get_pointer (type_unsigned_char);
+  gcc_jit_field *field_x =
+    gcc_jit_context_new_field (ctxt,
+                               NULL, /* gcc_jit_location *loc */
+                               type_int, /* gcc_jit_type *type, */
+                               "x"); /* const char *name */
+  gcc_jit_field *field_y =
+    gcc_jit_context_new_field (ctxt,
+                               NULL, /* gcc_jit_location *loc */
+                               type_int, /* gcc_jit_type *type, */
+                               "y"); /* const char *name */
+  gcc_jit_struct *struct_struct_ip_coord =
+    gcc_jit_context_new_opaque_struct (ctxt,
+                                       NULL, /* gcc_jit_location *loc */
+                                       "ip_coord"); /* const char *name */
+  gcc_jit_field *fields_fields_0x18dc9d0[2] = {
+    field_x,
+    field_y,
+  };
+  gcc_jit_struct_set_fields (struct_struct_ip_coord, /* gcc_jit_struct *struct_type */
+                             NULL, /* gcc_jit_location *loc */
+                             2, /* int num_fields */
+                             fields_fields_0x18dc9d0); /* gcc_jit_field **fields */
+  gcc_jit_field *field_size =
+    gcc_jit_context_new_field (ctxt,
+                               NULL, /* gcc_jit_location *loc */
+                               gcc_jit_struct_as_type (struct_struct_ip_coord), /* gcc_jit_type *type, */
+                               "size"); /* const char *name */
+  gcc_jit_field *field_imrow =
+    gcc_jit_context_new_field (ctxt,
+                               NULL, /* gcc_jit_location *loc */
+                               type_void_ptr_ptr, /* gcc_jit_type *type, */
+                               "imrow"); /* const char *name */
+  gcc_jit_struct *struct_struct_ip_image =
+    gcc_jit_context_new_opaque_struct (ctxt,
+                                       NULL, /* gcc_jit_location *loc */
+                                       "ip_image"); /* const char *name */
+  gcc_jit_field *fields_fields_0x18dd310[] = {
+    field_size,
+    field_imrow
+  };
+  gcc_jit_struct_set_fields (struct_struct_ip_image, /* gcc_jit_struct *struct_type */
+                             NULL, /* gcc_jit_location *loc */
+                             2, /* int num_fields */
+                             fields_fields_0x18dd310); /* gcc_jit_field **fields */
+  gcc_jit_type *type_struct_ip_image__ =
+    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_struct_ip_image));
+  gcc_jit_param *param_dest =
+    gcc_jit_context_new_param (ctxt,
+                               NULL, /* gcc_jit_location *loc */
+                               type_struct_ip_image__, /*gcc_jit_type *type */
+                               "dest"); /* const char *name */
+  gcc_jit_param *param_src =
+    gcc_jit_context_new_param (ctxt,
+                               NULL, /* gcc_jit_location *loc */
+                               type_struct_ip_image__, /*gcc_jit_type *type */
+                               "src"); /* const char *name */
+  gcc_jit_param *params_for_func_ip_jit_im_add_clip_UBYTE[2] = {
+    param_dest,
+    param_src,
+  };
+  gcc_jit_function *func_ip_jit_im_add_clip_UBYTE =
+    gcc_jit_context_new_function (ctxt, /* gcc_jit_context *ctxt */
+                                  NULL, /* gcc_jit_location *loc */
+                                  GCC_JIT_FUNCTION_EXPORTED, /* enum gcc_jit_function_kind kind */
+                                  type_void, /* gcc_jit_type *return_type */
+                                  "ip_jit_im_add_clip_UBYTE", /* const char *name */
+                                  2, /* int num_params */
+                                  params_for_func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_param **params */
+                                  0); /* int is_variadic */
+  gcc_jit_lvalue *local_rowlen =
+    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */
+                                NULL, /* gcc_jit_location *loc */
+                                type_int, /* gcc_jit_type *type */
+                                "rowlen"); /* const char *name */
+  gcc_jit_lvalue *local_numrows =
+    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */
+                                NULL, /* gcc_jit_location *loc */
+                                type_int, /* gcc_jit_type *type */
+                                "numrows"); /* const char *name */
+  gcc_jit_lvalue *local_j =
+    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */
+                                NULL, /* gcc_jit_location *loc */
+                                type_int, /* gcc_jit_type *type */
+                                "j"); /* const char *name */
+  gcc_jit_lvalue *local_dptr =
+    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */
+                                NULL, /* gcc_jit_location *loc */
+                                type_unsigned_char__, /* gcc_jit_type *type */
+                                "dptr"); /* const char *name */
+  gcc_jit_lvalue *local_sptr =
+    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */
+                                NULL, /* gcc_jit_location *loc */
+                                type_unsigned_char__, /* gcc_jit_type *type */
+                                "sptr"); /* const char *name */
+  gcc_jit_lvalue *local_i =
+    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */
+                                NULL, /* gcc_jit_location *loc */
+                                type_int, /* gcc_jit_type *type */
+                                "i"); /* const char *name */
+  gcc_jit_block *block_F1 =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "F1");
+  gcc_jit_block *block_C1 =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "C1");
+  gcc_jit_block *block_L1 =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "L1");
+  gcc_jit_block *block_C2 =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "C2");
+  gcc_jit_block *block_L2 =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "L2");
+  gcc_jit_block *block_A2 =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "A2");
+  gcc_jit_block *block_A1 =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "A1");
+  gcc_jit_lvalue *lvalue_dest__size=
+    gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_dest), /* gcc_jit_rvalue *ptr */
+                                      NULL, /* gcc_jit_location *loc */
+                                      field_size); /* gcc_jit_field *field */
+  gcc_jit_rvalue *rvalue_dest__size_x = 
+    gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (lvalue_dest__size), /*gcc_jit_rvalue *struct_or_union */
+                                 NULL, /*gcc_jit_location *loc */
+                                 field_x);
+  gcc_jit_block_add_assignment (block_F1, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_rowlen, /* gcc_jit_lvalue *lvalue */
+                                rvalue_dest__size_x); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_rvalue *rvalue_dest__size_y = 
+    gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (lvalue_dest__size), /*gcc_jit_rvalue *struct_or_union */
+                                 NULL, /*gcc_jit_location *loc */
+                                 field_y);
+  gcc_jit_block_add_assignment (block_F1, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_numrows, /* gcc_jit_lvalue *lvalue */
+                                rvalue_dest__size_y); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_rvalue *rvalue__int_0 =
+    gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */
+                                         type_int, /* gcc_jit_type *numeric_type */
+                                         0); /* int value */
+  gcc_jit_block_add_assignment (block_F1, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_j, /* gcc_jit_lvalue *lvalue */
+                                rvalue__int_0); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_block_end_with_jump (block_F1, /*gcc_jit_block *block */
+                               NULL, /* gcc_jit_location *loc */
+                               block_C1); /* gcc_jit_block *target */
+  gcc_jit_rvalue *rvalue_j___numrows =
+    gcc_jit_context_new_comparison (ctxt,
+                                    NULL, /* gcc_jit_location *loc */
+                                    GCC_JIT_COMPARISON_LT, /* enum gcc_jit_comparison op */
+                                    gcc_jit_lvalue_as_rvalue (local_j), /* gcc_jit_rvalue *a */
+                                    gcc_jit_lvalue_as_rvalue (local_numrows)); /* gcc_jit_rvalue *b */
+  gcc_jit_block_end_with_conditional (block_C1, /*gcc_jit_block *block */
+                                      NULL, /* gcc_jit_location *loc */
+                                      rvalue_j___numrows, /* gcc_jit_rvalue *boolval */
+                                      block_L1, /* gcc_jit_block *on_true */
+                                      block_A1); /* gcc_jit_block *on_false */
+  gcc_jit_lvalue *lvalue_dest__imrow=
+    gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_dest), /* gcc_jit_rvalue *ptr */
+                                      NULL, /* gcc_jit_location *loc */
+                                      field_imrow); /* gcc_jit_field *field */
+  gcc_jit_lvalue *lvalue_dest__imrow_j_ = 
+    gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */
+                                      NULL, /*gcc_jit_location *loc */
+                                      gcc_jit_lvalue_as_rvalue (lvalue_dest__imrow), /* gcc_jit_rvalue *ptr */
+                                      gcc_jit_lvalue_as_rvalue (local_j)); /* gcc_jit_rvalue *index */
+  gcc_jit_rvalue *rvalue__unsigned_char___dest__imrow_j_ =
+    gcc_jit_context_new_cast (ctxt,
+                              NULL, /* gcc_jit_location *loc */
+                              gcc_jit_lvalue_as_rvalue (lvalue_dest__imrow_j_), /* gcc_jit_rvalue *rvalue */
+                              type_unsigned_char__); /* gcc_jit_type *type */
+  gcc_jit_block_add_assignment (block_L1, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_dptr, /* gcc_jit_lvalue *lvalue */
+                                rvalue__unsigned_char___dest__imrow_j_); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_lvalue *lvalue_src__imrow=
+    gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_src), /* gcc_jit_rvalue *ptr */
+                                      NULL, /* gcc_jit_location *loc */
+                                      field_imrow); /* gcc_jit_field *field */
+  gcc_jit_lvalue *lvalue_src__imrow_j_ = 
+    gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */
+                                      NULL, /*gcc_jit_location *loc */
+                                      gcc_jit_lvalue_as_rvalue (lvalue_src__imrow), /* gcc_jit_rvalue *ptr */
+                                      gcc_jit_lvalue_as_rvalue (local_j)); /* gcc_jit_rvalue *index */
+  gcc_jit_rvalue *rvalue__unsigned_char___src__imrow_j_ =
+    gcc_jit_context_new_cast (ctxt,
+                              NULL, /* gcc_jit_location *loc */
+                              gcc_jit_lvalue_as_rvalue (lvalue_src__imrow_j_), /* gcc_jit_rvalue *rvalue */
+                              type_unsigned_char__); /* gcc_jit_type *type */
+  gcc_jit_block_add_assignment (block_L1, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_sptr, /* gcc_jit_lvalue *lvalue */
+                                rvalue__unsigned_char___src__imrow_j_); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_rvalue *rvalue__int_0_0x18dd890 =
+    gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */
+                                         type_int, /* gcc_jit_type *numeric_type */
+                                         0); /* int value */
+  gcc_jit_block_add_assignment (block_L1, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_i, /* gcc_jit_lvalue *lvalue */
+                                rvalue__int_0_0x18dd890); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_block_end_with_jump (block_L1, /*gcc_jit_block *block */
+                               NULL, /* gcc_jit_location *loc */
+                               block_C2); /* gcc_jit_block *target */
+  gcc_jit_rvalue *rvalue_i___rowlen =
+    gcc_jit_context_new_comparison (ctxt,
+                                    NULL, /* gcc_jit_location *loc */
+                                    GCC_JIT_COMPARISON_LT, /* enum gcc_jit_comparison op */
+                                    gcc_jit_lvalue_as_rvalue (local_i), /* gcc_jit_rvalue *a */
+                                    gcc_jit_lvalue_as_rvalue (local_rowlen)); /* gcc_jit_rvalue *b */
+  gcc_jit_block_end_with_conditional (block_C2, /*gcc_jit_block *block */
+                                      NULL, /* gcc_jit_location *loc */
+                                      rvalue_i___rowlen, /* gcc_jit_rvalue *boolval */
+                                      block_L2, /* gcc_jit_block *on_true */
+                                      block_A2); /* gcc_jit_block *on_false */
+  gcc_jit_lvalue *dereference__dptr =
+    gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_dptr), /* gcc_jit_rvalue *rvalue */
+                                NULL); /* gcc_jit_location *loc */
+  gcc_jit_lvalue *dereference__sptr =
+    gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_sptr), /* gcc_jit_rvalue *rvalue */
+                                NULL); /* gcc_jit_location *loc */
+  gcc_jit_block *block_p_C1_true =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "p_C1_true");
+  gcc_jit_block *block_p_C1_end =
+    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "p_C1_end");
+  gcc_jit_lvalue *local_ival =
+    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */
+                                NULL, /* gcc_jit_location *loc */
+                                type_int, /* gcc_jit_type *type */
+                                "ival"); /* const char *name */
+  gcc_jit_rvalue *rvalue__int__dptr =
+    gcc_jit_context_new_cast (ctxt,
+                              NULL, /* gcc_jit_location *loc */
+                              gcc_jit_lvalue_as_rvalue (dereference__dptr), /* gcc_jit_rvalue *rvalue */
+                              type_int); /* gcc_jit_type *type */
+  gcc_jit_rvalue *rvalue__int__sptr =
+    gcc_jit_context_new_cast (ctxt,
+                              NULL, /* gcc_jit_location *loc */
+                              gcc_jit_lvalue_as_rvalue (dereference__sptr), /* gcc_jit_rvalue *rvalue */
+                              type_int); /* gcc_jit_type *type */
+  gcc_jit_rvalue *rvalue__int__dptr____int__sptr =
+    gcc_jit_context_new_binary_op (ctxt,
+                                   NULL, /* gcc_jit_location *loc */
+                                   GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */
+                                   type_int, /* gcc_jit_type *result_type */
+                                   rvalue__int__dptr, /* gcc_jit_rvalue *a */
+                                   rvalue__int__sptr); /* gcc_jit_rvalue *b */
+  gcc_jit_block_add_assignment (block_L2, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_ival, /* gcc_jit_lvalue *lvalue */
+                                rvalue__int__dptr____int__sptr); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_rvalue *rvalue__int_255 =
+    gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */
+                                         type_int, /* gcc_jit_type *numeric_type */
+                                         255); /* int value */
+  gcc_jit_rvalue *rvalue_ival____int_255 =
+    gcc_jit_context_new_comparison (ctxt,
+                                    NULL, /* gcc_jit_location *loc */
+                                    GCC_JIT_COMPARISON_GT, /* enum gcc_jit_comparison op */
+                                    gcc_jit_lvalue_as_rvalue (local_ival), /* gcc_jit_rvalue *a */
+                                    rvalue__int_255); /* gcc_jit_rvalue *b */
+  gcc_jit_block_end_with_conditional (block_L2, /*gcc_jit_block *block */
+                                      NULL, /* gcc_jit_location *loc */
+                                      rvalue_ival____int_255, /* gcc_jit_rvalue *boolval */
+                                      block_p_C1_true, /* gcc_jit_block *on_true */
+                                      block_p_C1_end); /* gcc_jit_block *on_false */
+  gcc_jit_block_add_assignment (block_p_C1_true, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_ival, /* gcc_jit_lvalue *lvalue */
+                                rvalue__int_255); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_block_end_with_jump (block_p_C1_true, /*gcc_jit_block *block */
+                               NULL, /* gcc_jit_location *loc */
+                               block_p_C1_end); /* gcc_jit_block *target */
+  gcc_jit_rvalue *rvalue__unsigned_char_ival =
+    gcc_jit_context_new_cast (ctxt,
+                              NULL, /* gcc_jit_location *loc */
+                              gcc_jit_lvalue_as_rvalue (local_ival), /* gcc_jit_rvalue *rvalue */
+                              type_unsigned_char); /* gcc_jit_type *type */
+  gcc_jit_lvalue *dereference__dptr_0x18df2e0 =
+    gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_dptr), /* gcc_jit_rvalue *rvalue */
+                                NULL); /* gcc_jit_location *loc */
+  gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                dereference__dptr_0x18df2e0, /* gcc_jit_lvalue *lvalue */
+                                rvalue__unsigned_char_ival); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_rvalue *rvalue__int_1 =
+    gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */
+                                         type_int, /* gcc_jit_type *numeric_type */
+                                         1); /* int value */
+  gcc_jit_lvalue *lvalue_dptr__int_1_ = 
+    gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */
+                                      NULL, /*gcc_jit_location *loc */
+                                      gcc_jit_lvalue_as_rvalue (local_dptr), /* gcc_jit_rvalue *ptr */
+                                      rvalue__int_1); /* gcc_jit_rvalue *index */
+  gcc_jit_rvalue *address_of__dptr__int_1_ =
+    gcc_jit_lvalue_get_address (lvalue_dptr__int_1_, /* gcc_jit_lvalue *lvalue */
+                                NULL); /* gcc_jit_location *loc */
+  gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_dptr, /* gcc_jit_lvalue *lvalue */
+                                address_of__dptr__int_1_); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_rvalue *rvalue__int_1_0x18df500 =
+    gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */
+                                         type_int, /* gcc_jit_type *numeric_type */
+                                         1); /* int value */
+  gcc_jit_lvalue *lvalue_sptr__int_1_ = 
+    gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */
+                                      NULL, /*gcc_jit_location *loc */
+                                      gcc_jit_lvalue_as_rvalue (local_sptr), /* gcc_jit_rvalue *ptr */
+                                      rvalue__int_1_0x18df500); /* gcc_jit_rvalue *index */
+  gcc_jit_rvalue *address_of__sptr__int_1_ =
+    gcc_jit_lvalue_get_address (lvalue_sptr__int_1_, /* gcc_jit_lvalue *lvalue */
+                                NULL); /* gcc_jit_location *loc */
+  gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_sptr, /* gcc_jit_lvalue *lvalue */
+                                address_of__sptr__int_1_); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_rvalue *rvalue__int_1_0x18df650 =
+    gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */
+                                         type_int, /* gcc_jit_type *numeric_type */
+                                         1); /* int value */
+  gcc_jit_rvalue *rvalue_i____int_1 =
+    gcc_jit_context_new_binary_op (ctxt,
+                                   NULL, /* gcc_jit_location *loc */
+                                   GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */
+                                   type_int, /* gcc_jit_type *result_type */
+                                   gcc_jit_lvalue_as_rvalue (local_i), /* gcc_jit_rvalue *a */
+                                   rvalue__int_1_0x18df650); /* gcc_jit_rvalue *b */
+  gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_i, /* gcc_jit_lvalue *lvalue */
+                                rvalue_i____int_1); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_block_end_with_jump (block_p_C1_end, /*gcc_jit_block *block */
+                               NULL, /* gcc_jit_location *loc */
+                               block_C2); /* gcc_jit_block *target */
+  gcc_jit_rvalue *rvalue__int_1_0x18df7e0 =
+    gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */
+                                         type_int, /* gcc_jit_type *numeric_type */
+                                         1); /* int value */
+  gcc_jit_rvalue *rvalue_j____int_1 =
+    gcc_jit_context_new_binary_op (ctxt,
+                                   NULL, /* gcc_jit_location *loc */
+                                   GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */
+                                   type_int, /* gcc_jit_type *result_type */
+                                   gcc_jit_lvalue_as_rvalue (local_j), /* gcc_jit_rvalue *a */
+                                   rvalue__int_1_0x18df7e0); /* gcc_jit_rvalue *b */
+  gcc_jit_block_add_assignment (block_A2, /*gcc_jit_block *block */
+                                NULL, /* gcc_jit_location *loc */
+                                local_j, /* gcc_jit_lvalue *lvalue */
+                                rvalue_j____int_1); /* gcc_jit_rvalue *rvalue */
+  gcc_jit_block_end_with_jump (block_A2, /*gcc_jit_block *block */
+                               NULL, /* gcc_jit_location *loc */
+                               block_C1); /* gcc_jit_block *target */
+  gcc_jit_block_end_with_void_return (block_A1, /*gcc_jit_block *block */
+                                      NULL); /* gcc_jit_location *loc */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* empty */
+}
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [committed] jit: add gcc_jit_type_get_vector
  2017-01-01  0:00         ` David Malcolm
@ 2017-01-01  0:00           ` Michael Cree
  2017-01-01  0:00             ` David Malcolm
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Cree @ 2017-01-01  0:00 UTC (permalink / raw)
  To: David Malcolm; +Cc: jit

[-- Attachment #1: Type: text/plain, Size: 1064 bytes --]

On Wed, Aug 16, 2017 at 10:01:57AM -0400, David Malcolm wrote:
> On Wed, 2017-08-16 at 21:58 +1200, Michael Cree wrote:
> > 
> > But I have hit a problem which I suspect is a bug in the gcc
> > optimiser.
> > 
> > In the vein of your example above, but working on uint8_t pixel data
> > and adding saturation, the jit compiler segfaults in the optimiser. I
> > provide below the gimple produced by the function that causes the
> > problem (I presume that is more useful than the code calling the
> > gcc_jit routines), 
> 
> There's actually a handy entrypoint for generating minimal reproducers
> for such crashes:
>   gcc_jit_context_dump_reproducer_to_file
> 
> https://gcc.gnu.org/onlinedocs/jit/topics/contexts.html#gcc_jit_context_dump_reproducer_to_file
> 
> Can you add a call to that to your code (after the context is fully
> populated), and see if the resulting .c file leads to the crash when
> run?  If so, can you post the .c file here please (or attach it to
> bugzilla), and hopefully I can then reproduce it at my end.

Attached.

Cheers
Michael.

[-- Attachment #2: ip-jit-reproducer-dump.c --]
[-- Type: text/x-csrc, Size: 42256 bytes --]

/* This code was autogenerated by gcc_jit_context_dump_reproducer_to_file.

   libgccjit (Debian 6.3.0-18) version 6.3.0 20170516 (x86_64-linux-gnu)
  	compiled by GNU C version 6.3.0 20170516, GMP version 6.1.2, MPFR version 3.1.5, MPC version 1.0.3, isl version 0.15
*/
#include <libgccjit.h>

#pragma GCC diagnostic ignored "-Wunused-variable"

static void
set_options (gcc_jit_context *ctxt_0x55a43caf3990);

static void
create_code (gcc_jit_context *ctxt_0x55a43caf3990);

int
main (int argc, const char **argv)
{
  gcc_jit_context *ctxt_0x55a43caf3990;
  gcc_jit_result *result;

  ctxt_0x55a43caf3990 = gcc_jit_context_acquire ();
  set_options (ctxt_0x55a43caf3990);
  create_code (ctxt_0x55a43caf3990);
  result = gcc_jit_context_compile (ctxt_0x55a43caf3990);
  gcc_jit_context_release (ctxt_0x55a43caf3990);
  gcc_jit_result_release (result);
  return 0;
}

static void
set_options (gcc_jit_context *ctxt_0x55a43caf3990)
{
  /* Set options for ctxt_0x55a43caf3990.  */
  /* String options.  */
  gcc_jit_context_set_str_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_STR_OPTION_PROGNAME,
                                  NULL);
  /* Int options.  */
  gcc_jit_context_set_int_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
                                  3);
  /* Boolean options.  */
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_DEBUGINFO,
                                  0);
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
                                  0);
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
                                  0);
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
                                  0);
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
                                  0);
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
                                  0);
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
                                  0);
  gcc_jit_context_set_bool_option (ctxt_0x55a43caf3990,
                                  GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
                                  0);
  gcc_jit_context_set_bool_allow_unreachable_blocks (ctxt_0x55a43caf3990, 0);
  gcc_jit_context_set_bool_use_external_driver (ctxt_0x55a43caf3990, 0);
  /* User-provided command-line options.  */
  gcc_jit_context_add_command_line_option (ctxt_0x55a43caf3990, "-mavx2");
}

static void
create_code (gcc_jit_context *ctxt_0x55a43caf3990)
{
  /* Replay of API calls for ctxt_0x55a43caf3990.  */
  gcc_jit_type *type_void_0x55a43caf3af0 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_VOID);
  gcc_jit_type *type_char_0x55a43caf3b30 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_CHAR);
  gcc_jit_type *type_int_0x55a43caf3b70 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_INT);
  gcc_jit_type *type_unsigned_int_0x55a43caf3bb0 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_UNSIGNED_INT);
  gcc_jit_type *type_float_0x55a43caf3bf0 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_FLOAT);
  gcc_jit_type *type_double_0x55a43caf3c80 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_DOUBLE);
  gcc_jit_type *type_size_t_0x55a43caf3cc0 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_SIZE_T);
  gcc_jit_type *type_unsigned_char_0x55a43caf3d00 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_UNSIGNED_CHAR);
  gcc_jit_type *type_signed_char_0x55a43caf3d40 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_SIGNED_CHAR);
  gcc_jit_type *type_unsigned_short_0x55a43caf3e10 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_UNSIGNED_SHORT);
  gcc_jit_type *type_short_0x55a43caf3e50 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_SHORT);
  gcc_jit_type *type_void___0x55a43caf3e90 =
    gcc_jit_type_get_pointer (type_void_0x55a43caf3af0);
  gcc_jit_type *type_void_____0x55a43caf3ed0 =
    gcc_jit_type_get_pointer (type_void___0x55a43caf3e90);
  gcc_jit_type *type_const_char___0x55a43caf3f10 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_CONST_CHAR_PTR);
  gcc_jit_type *type_unsigned_char___0x55a43caf3f50 =
    gcc_jit_type_get_pointer (type_unsigned_char_0x55a43caf3d00);
  gcc_jit_type *type_unsigned_short___0x55a43caf3f90 =
    gcc_jit_type_get_pointer (type_unsigned_short_0x55a43caf3e10);
  gcc_jit_type *type_short___0x55a43caf3fd0 =
    gcc_jit_type_get_pointer (type_short_0x55a43caf3e50);
  gcc_jit_type *type_unsigned_int___0x55a43caf3d80 =
    gcc_jit_type_get_pointer (type_unsigned_int_0x55a43caf3bb0);
  gcc_jit_type *type_int___0x55a43caf3dc0 =
    gcc_jit_type_get_pointer (type_int_0x55a43caf3b70);
  gcc_jit_type *type_float___0x55a43caf40e0 =
    gcc_jit_type_get_pointer (type_float_0x55a43caf3bf0);
  gcc_jit_type *type_double___0x55a43caf4120 =
    gcc_jit_type_get_pointer (type_double_0x55a43caf3c80);
  gcc_jit_type *array_type_void___2__0x55a43caf3c30 =
    gcc_jit_context_new_array_type (ctxt_0x55a43caf3990,
                                    NULL, /* gcc_jit_location *loc */
                                    type_void___0x55a43caf3e90, /* gcc_jit_type *element_type */
                                    2); /* int num_elements */
  gcc_jit_field *field_r_0x55a43caf41a0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_float_0x55a43caf3bf0, /* gcc_jit_type *type, */
                               "r"); /* const char *name */
  gcc_jit_field *field_i_0x55a43caf4010 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_float_0x55a43caf3bf0, /* gcc_jit_type *type, */
                               "i"); /* const char *name */
  gcc_jit_struct *struct_struct_ip_complex_0x55a43caf4360 =
    gcc_jit_context_new_opaque_struct (ctxt_0x55a43caf3990,
                                       NULL, /* gcc_jit_location *loc */
                                       "ip_complex"); /* const char *name */
  gcc_jit_field *fields_fields_0x55a43caf40a0[2] = {
    field_r_0x55a43caf41a0,
    field_i_0x55a43caf4010,
  };
  gcc_jit_struct_set_fields (struct_struct_ip_complex_0x55a43caf4360, /* gcc_jit_struct *struct_type */
                             NULL, /* gcc_jit_location *loc */
                             2, /* int num_fields */
                             fields_fields_0x55a43caf40a0); /* gcc_jit_field **fields */
  gcc_jit_type *type_struct_ip_complex___0x55a43caf43b0 =
    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_struct_ip_complex_0x55a43caf4360));
  gcc_jit_field *field_r_0x55a43caf4450 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_double_0x55a43caf3c80, /* gcc_jit_type *type, */
                               "r"); /* const char *name */
  gcc_jit_field *field_i_0x55a43caf4500 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_double_0x55a43caf3c80, /* gcc_jit_type *type, */
                               "i"); /* const char *name */
  gcc_jit_struct *struct_struct_ip_dcomplex_0x55a43caf45b0 =
    gcc_jit_context_new_opaque_struct (ctxt_0x55a43caf3990,
                                       NULL, /* gcc_jit_location *loc */
                                       "ip_dcomplex"); /* const char *name */
  gcc_jit_field *fields_fields_0x55a43caf4600[2] = {
    field_r_0x55a43caf4450,
    field_i_0x55a43caf4500,
  };
  gcc_jit_struct_set_fields (struct_struct_ip_dcomplex_0x55a43caf45b0, /* gcc_jit_struct *struct_type */
                             NULL, /* gcc_jit_location *loc */
                             2, /* int num_fields */
                             fields_fields_0x55a43caf4600); /* gcc_jit_field **fields */
  gcc_jit_type *type_struct_ip_dcomplex___0x55a43caf4230 =
    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_struct_ip_dcomplex_0x55a43caf45b0));
  gcc_jit_field *field_r_0x55a43caf42d0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_char_0x55a43caf3d00, /* gcc_jit_type *type, */
                               "r"); /* const char *name */
  gcc_jit_field *field_g_0x55a43caf4850 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_char_0x55a43caf3d00, /* gcc_jit_type *type, */
                               "g"); /* const char *name */
  gcc_jit_field *field_b_0x55a43caf4900 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_char_0x55a43caf3d00, /* gcc_jit_type *type, */
                               "b"); /* const char *name */
  gcc_jit_struct *struct_struct_ip_rgb_0x55a43caf49b0 =
    gcc_jit_context_new_opaque_struct (ctxt_0x55a43caf3990,
                                       NULL, /* gcc_jit_location *loc */
                                       "ip_rgb"); /* const char *name */
  gcc_jit_field *fields_fields_0x55a43caf4a00[3] = {
    field_r_0x55a43caf42d0,
    field_g_0x55a43caf4850,
    field_b_0x55a43caf4900,
  };
  gcc_jit_struct_set_fields (struct_struct_ip_rgb_0x55a43caf49b0, /* gcc_jit_struct *struct_type */
                             NULL, /* gcc_jit_location *loc */
                             3, /* int num_fields */
                             fields_fields_0x55a43caf4a00); /* gcc_jit_field **fields */
  gcc_jit_type *type_struct_ip_rgb___0x55a43caf4a70 =
    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_struct_ip_rgb_0x55a43caf49b0));
  gcc_jit_field *field_r_0x55a43caf4b10 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_short_0x55a43caf3e10, /* gcc_jit_type *type, */
                               "r"); /* const char *name */
  gcc_jit_field *field_g_0x55a43caf4bc0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_short_0x55a43caf3e10, /* gcc_jit_type *type, */
                               "g"); /* const char *name */
  gcc_jit_field *field_b_0x55a43caf4c70 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_short_0x55a43caf3e10, /* gcc_jit_type *type, */
                               "b"); /* const char *name */
  gcc_jit_struct *struct_struct_ip_rgb16_0x55a43caf4670 =
    gcc_jit_context_new_opaque_struct (ctxt_0x55a43caf3990,
                                       NULL, /* gcc_jit_location *loc */
                                       "ip_rgb16"); /* const char *name */
  gcc_jit_field *fields_fields_0x55a43caf46c0[3] = {
    field_r_0x55a43caf4b10,
    field_g_0x55a43caf4bc0,
    field_b_0x55a43caf4c70,
  };
  gcc_jit_struct_set_fields (struct_struct_ip_rgb16_0x55a43caf4670, /* gcc_jit_struct *struct_type */
                             NULL, /* gcc_jit_location *loc */
                             3, /* int num_fields */
                             fields_fields_0x55a43caf46c0); /* gcc_jit_field **fields */
  gcc_jit_type *type_struct_ip_rgb16___0x55a43caf4730 =
    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_struct_ip_rgb16_0x55a43caf4670));
  gcc_jit_field *field_x_0x55a43caf47d0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_int_0x55a43caf3b70, /* gcc_jit_type *type, */
                               "x"); /* const char *name */
  gcc_jit_field *field_y_0x55a43caf5020 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_int_0x55a43caf3b70, /* gcc_jit_type *type, */
                               "y"); /* const char *name */
  gcc_jit_struct *struct_struct_ip_coord_0x55a43caf50d0 =
    gcc_jit_context_new_opaque_struct (ctxt_0x55a43caf3990,
                                       NULL, /* gcc_jit_location *loc */
                                       "ip_coord"); /* const char *name */
  gcc_jit_field *fields_fields_0x55a43caf5170[2] = {
    field_x_0x55a43caf47d0,
    field_y_0x55a43caf5020,
  };
  gcc_jit_struct_set_fields (struct_struct_ip_coord_0x55a43caf50d0, /* gcc_jit_struct *struct_type */
                             NULL, /* gcc_jit_location *loc */
                             2, /* int num_fields */
                             fields_fields_0x55a43caf5170); /* gcc_jit_field **fields */
  gcc_jit_field *field_type_0x55a43caf5210 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_int_0x55a43caf3b70, /* gcc_jit_type *type, */
                               "type"); /* const char *name */
  gcc_jit_field *field_size_0x55a43caf52c0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               gcc_jit_struct_as_type (struct_struct_ip_coord_0x55a43caf50d0), /* gcc_jit_type *type, */
                               "size"); /* const char *name */
  gcc_jit_field *field_row_size_0x55a43caf5370 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_size_t_0x55a43caf3cc0, /* gcc_jit_type *type, */
                               "row_size"); /* const char *name */
  gcc_jit_field *field_status_0x55a43caf5420 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_int_0x55a43caf3bb0, /* gcc_jit_type *type, */
                               "status"); /* const char *name */
  gcc_jit_field *field_palette_0x55a43caf54d0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_struct_ip_rgb___0x55a43caf4a70, /* gcc_jit_type *type, */
                               "palette"); /* const char *name */
  gcc_jit_field *field_imbuff_0x55a43caf5580 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_unsigned_char___0x55a43caf3f50, /* gcc_jit_type *type, */
                               "imbuff"); /* const char *name */
  gcc_jit_field *field_imrow_0x55a43caf5630 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_void_____0x55a43caf3ed0, /* gcc_jit_type *type, */
                               "imrow"); /* const char *name */
  gcc_jit_field *field_num_extra_rows_0x55a43caf56e0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_int_0x55a43caf3b70, /* gcc_jit_type *type, */
                               "num_extra_rows"); /* const char *name */
  gcc_jit_field *field_extra_rows_0x55a43caf4d20 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_void___0x55a43caf3e90, /* gcc_jit_type *type, */
                               "extra_rows"); /* const char *name */
  gcc_jit_field *field_fftw_plans_0x55a43caf4dd0 =
    gcc_jit_context_new_field (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               array_type_void___2__0x55a43caf3c30, /* gcc_jit_type *type, */
                               "fftw_plans"); /* const char *name */
  gcc_jit_struct *struct_struct_ip_image_0x55a43caf4e80 =
    gcc_jit_context_new_opaque_struct (ctxt_0x55a43caf3990,
                                       NULL, /* gcc_jit_location *loc */
                                       "ip_image"); /* const char *name */
  gcc_jit_field *fields_fields_0x55a43caf4ed0[10] = {
    field_type_0x55a43caf5210,
    field_size_0x55a43caf52c0,
    field_row_size_0x55a43caf5370,
    field_status_0x55a43caf5420,
    field_palette_0x55a43caf54d0,
    field_imbuff_0x55a43caf5580,
    field_imrow_0x55a43caf5630,
    field_num_extra_rows_0x55a43caf56e0,
    field_extra_rows_0x55a43caf4d20,
    field_fftw_plans_0x55a43caf4dd0,
  };
  gcc_jit_struct_set_fields (struct_struct_ip_image_0x55a43caf4e80, /* gcc_jit_struct *struct_type */
                             NULL, /* gcc_jit_location *loc */
                             10, /* int num_fields */
                             fields_fields_0x55a43caf4ed0); /* gcc_jit_field **fields */
  gcc_jit_type *type_struct_ip_image___0x55a43caf5c00 =
    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_struct_ip_image_0x55a43caf4e80));
  gcc_jit_param *param_dest_0x55a43caf4f10 =
    gcc_jit_context_new_param (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_struct_ip_image___0x55a43caf5c00, /*gcc_jit_type *type */
                               "dest"); /* const char *name */
  gcc_jit_param *param_src_0x55a43caf5d00 =
    gcc_jit_context_new_param (ctxt_0x55a43caf3990,
                               NULL, /* gcc_jit_location *loc */
                               type_struct_ip_image___0x55a43caf5c00, /*gcc_jit_type *type */
                               "src"); /* const char *name */
  gcc_jit_param *params_for_func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0[2] = {
    param_dest_0x55a43caf4f10,
    param_src_0x55a43caf5d00,
  };
  gcc_jit_function *func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0 =
    gcc_jit_context_new_function (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                  NULL, /* gcc_jit_location *loc */
                                  GCC_JIT_FUNCTION_EXPORTED, /* enum gcc_jit_function_kind kind */
                                  type_void_0x55a43caf3af0, /* gcc_jit_type *return_type */
                                  "ip_jit_im_add_clip_UBYTE", /* const char *name */
                                  2, /* int num_params */
                                  params_for_func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_param **params */
                                  0); /* int is_variadic */
  gcc_jit_lvalue *local_rowlen_0x55a43caf4f60 =
    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_function *func */
                                NULL, /* gcc_jit_location *loc */
                                type_int_0x55a43caf3b70, /* gcc_jit_type *type */
                                "rowlen"); /* const char *name */
  gcc_jit_lvalue *local_numrows_0x55a43caf5f80 =
    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_function *func */
                                NULL, /* gcc_jit_location *loc */
                                type_int_0x55a43caf3b70, /* gcc_jit_type *type */
                                "numrows"); /* const char *name */
  gcc_jit_lvalue *local_j_0x55a43caf6040 =
    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_function *func */
                                NULL, /* gcc_jit_location *loc */
                                type_int_0x55a43caf3b70, /* gcc_jit_type *type */
                                "j"); /* const char *name */
  gcc_jit_lvalue *local_dptr_0x55a43caf6100 =
    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_function *func */
                                NULL, /* gcc_jit_location *loc */
                                type_unsigned_char___0x55a43caf3f50, /* gcc_jit_type *type */
                                "dptr"); /* const char *name */
  gcc_jit_lvalue *local_sptr_0x55a43caf61c0 =
    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_function *func */
                                NULL, /* gcc_jit_location *loc */
                                type_unsigned_char___0x55a43caf3f50, /* gcc_jit_type *type */
                                "sptr"); /* const char *name */
  gcc_jit_lvalue *local_i_0x55a43caf62d0 =
    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_function *func */
                                NULL, /* gcc_jit_location *loc */
                                type_int_0x55a43caf3b70, /* gcc_jit_type *type */
                                "i"); /* const char *name */
  gcc_jit_block *block_F1_0x55a43caf6390 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "F1");
  gcc_jit_block *block_C1_0x55a43caf6440 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "C1");
  gcc_jit_block *block_L1_0x55a43caf64f0 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "L1");
  gcc_jit_block *block_C2_0x55a43caf65a0 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "C2");
  gcc_jit_block *block_L2_0x55a43caf6650 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "L2");
  gcc_jit_block *block_A2_0x55a43caf6750 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "A2");
  gcc_jit_block *block_A1_0x55a43caf6800 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "A1");
  gcc_jit_lvalue *lvalue_dest__size_0x55a43caf6850=
    gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_dest_0x55a43caf4f10), /* gcc_jit_rvalue *ptr */
                                      NULL, /* gcc_jit_location *loc */
                                      field_size_0x55a43caf52c0); /* gcc_jit_field *field */
  gcc_jit_rvalue *rvalue_dest__size_x_0x55a43caf5790 = 
    gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (lvalue_dest__size_0x55a43caf6850), /*gcc_jit_rvalue *struct_or_union */
                                 NULL, /*gcc_jit_location *loc */
                                 field_x_0x55a43caf47d0);
  gcc_jit_block_add_assignment (block_F1_0x55a43caf6390, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_rowlen_0x55a43caf4f60, /* gcc_jit_lvalue *lvalue */
                                rvalue_dest__size_x_0x55a43caf5790); /* gcc_jit_rvalue *rvalue */
  gcc_jit_rvalue *rvalue_dest__size_y_0x55a43caf5840 = 
    gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (lvalue_dest__size_0x55a43caf6850), /*gcc_jit_rvalue *struct_or_union */
                                 NULL, /*gcc_jit_location *loc */
                                 field_y_0x55a43caf5020);
  gcc_jit_block_add_assignment (block_F1_0x55a43caf6390, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_numrows_0x55a43caf5f80, /* gcc_jit_lvalue *lvalue */
                                rvalue_dest__size_y_0x55a43caf5840); /* gcc_jit_rvalue *rvalue */
  gcc_jit_rvalue *rvalue__int_0_0x55a43caf58f0 =
    gcc_jit_context_new_rvalue_from_int (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                         type_int_0x55a43caf3b70, /* gcc_jit_type *numeric_type */
                                         0); /* int value */
  gcc_jit_block_add_assignment (block_F1_0x55a43caf6390, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_j_0x55a43caf6040, /* gcc_jit_lvalue *lvalue */
                                rvalue__int_0_0x55a43caf58f0); /* gcc_jit_rvalue *rvalue */
  gcc_jit_block_end_with_jump (block_F1_0x55a43caf6390, /*gcc_jit_block *block */
                               NULL, /* gcc_jit_location *loc */
                               block_C1_0x55a43caf6440); /* gcc_jit_block *target */
  gcc_jit_type *type_bool_0x55a43caf5a30 = gcc_jit_context_get_type (ctxt_0x55a43caf3990, GCC_JIT_TYPE_BOOL);
  gcc_jit_rvalue *rvalue_j___numrows_0x55a43caf59d0 =
    gcc_jit_context_new_comparison (ctxt_0x55a43caf3990,
                                    NULL, /* gcc_jit_location *loc */
                                    GCC_JIT_COMPARISON_LT, /* enum gcc_jit_comparison op */
                                    gcc_jit_lvalue_as_rvalue (local_j_0x55a43caf6040), /* gcc_jit_rvalue *a */
                                    gcc_jit_lvalue_as_rvalue (local_numrows_0x55a43caf5f80)); /* gcc_jit_rvalue *b */
  gcc_jit_block_end_with_conditional (block_C1_0x55a43caf6440, /*gcc_jit_block *block */
                                      NULL, /* gcc_jit_location *loc */
                                      rvalue_j___numrows_0x55a43caf59d0, /* gcc_jit_rvalue *boolval */
                                      block_L1_0x55a43caf64f0, /* gcc_jit_block *on_true */
                                      block_A1_0x55a43caf6800); /* gcc_jit_block *on_false */
  gcc_jit_lvalue *lvalue_dest__imrow_0x55a43caf5af0=
    gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_dest_0x55a43caf4f10), /* gcc_jit_rvalue *ptr */
                                      NULL, /* gcc_jit_location *loc */
                                      field_imrow_0x55a43caf5630); /* gcc_jit_field *field */
  gcc_jit_lvalue *lvalue_dest__imrow_j__0x55a43caf6e70 = 
    gcc_jit_context_new_array_access (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                      NULL, /*gcc_jit_location *loc */
                                      gcc_jit_lvalue_as_rvalue (lvalue_dest__imrow_0x55a43caf5af0), /* gcc_jit_rvalue *ptr */
                                      gcc_jit_lvalue_as_rvalue (local_j_0x55a43caf6040)); /* gcc_jit_rvalue *index */
  gcc_jit_rvalue *rvalue__unsigned_char___dest__imrow_j__0x55a43caf6ed0 =
    gcc_jit_context_new_cast (ctxt_0x55a43caf3990,
                              NULL, /* gcc_jit_location *loc */
                              gcc_jit_lvalue_as_rvalue (lvalue_dest__imrow_j__0x55a43caf6e70), /* gcc_jit_rvalue *rvalue */
                              type_unsigned_char___0x55a43caf3f50); /* gcc_jit_type *type */
  gcc_jit_block_add_assignment (block_L1_0x55a43caf64f0, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_dptr_0x55a43caf6100, /* gcc_jit_lvalue *lvalue */
                                rvalue__unsigned_char___dest__imrow_j__0x55a43caf6ed0); /* gcc_jit_rvalue *rvalue */
  gcc_jit_lvalue *lvalue_src__imrow_0x55a43caf6fa0=
    gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_src_0x55a43caf5d00), /* gcc_jit_rvalue *ptr */
                                      NULL, /* gcc_jit_location *loc */
                                      field_imrow_0x55a43caf5630); /* gcc_jit_field *field */
  gcc_jit_lvalue *lvalue_src__imrow_j__0x55a43caf7000 = 
    gcc_jit_context_new_array_access (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                      NULL, /*gcc_jit_location *loc */
                                      gcc_jit_lvalue_as_rvalue (lvalue_src__imrow_0x55a43caf6fa0), /* gcc_jit_rvalue *ptr */
                                      gcc_jit_lvalue_as_rvalue (local_j_0x55a43caf6040)); /* gcc_jit_rvalue *index */
  gcc_jit_rvalue *rvalue__unsigned_char___src__imrow_j__0x55a43caf7060 =
    gcc_jit_context_new_cast (ctxt_0x55a43caf3990,
                              NULL, /* gcc_jit_location *loc */
                              gcc_jit_lvalue_as_rvalue (lvalue_src__imrow_j__0x55a43caf7000), /* gcc_jit_rvalue *rvalue */
                              type_unsigned_char___0x55a43caf3f50); /* gcc_jit_type *type */
  gcc_jit_block_add_assignment (block_L1_0x55a43caf64f0, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_sptr_0x55a43caf61c0, /* gcc_jit_lvalue *lvalue */
                                rvalue__unsigned_char___src__imrow_j__0x55a43caf7060); /* gcc_jit_rvalue *rvalue */
  gcc_jit_rvalue *rvalue__int_0_0x55a43caf7100 =
    gcc_jit_context_new_rvalue_from_int (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                         type_int_0x55a43caf3b70, /* gcc_jit_type *numeric_type */
                                         0); /* int value */
  gcc_jit_block_add_assignment (block_L1_0x55a43caf64f0, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_i_0x55a43caf62d0, /* gcc_jit_lvalue *lvalue */
                                rvalue__int_0_0x55a43caf7100); /* gcc_jit_rvalue *rvalue */
  gcc_jit_block_end_with_jump (block_L1_0x55a43caf64f0, /*gcc_jit_block *block */
                               NULL, /* gcc_jit_location *loc */
                               block_C2_0x55a43caf65a0); /* gcc_jit_block *target */
  gcc_jit_rvalue *rvalue_i___rowlen_0x55a43caf71e0 =
    gcc_jit_context_new_comparison (ctxt_0x55a43caf3990,
                                    NULL, /* gcc_jit_location *loc */
                                    GCC_JIT_COMPARISON_LT, /* enum gcc_jit_comparison op */
                                    gcc_jit_lvalue_as_rvalue (local_i_0x55a43caf62d0), /* gcc_jit_rvalue *a */
                                    gcc_jit_lvalue_as_rvalue (local_rowlen_0x55a43caf4f60)); /* gcc_jit_rvalue *b */
  gcc_jit_block_end_with_conditional (block_C2_0x55a43caf65a0, /*gcc_jit_block *block */
                                      NULL, /* gcc_jit_location *loc */
                                      rvalue_i___rowlen_0x55a43caf71e0, /* gcc_jit_rvalue *boolval */
                                      block_L2_0x55a43caf6650, /* gcc_jit_block *on_true */
                                      block_A2_0x55a43caf6750); /* gcc_jit_block *on_false */
  gcc_jit_lvalue *dereference__dptr_0x55a43caf72c0 =
    gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_dptr_0x55a43caf6100), /* gcc_jit_rvalue *rvalue */
                                NULL); /* gcc_jit_location *loc */
  gcc_jit_lvalue *dereference__sptr_0x55a43caf7310 =
    gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_sptr_0x55a43caf61c0), /* gcc_jit_rvalue *rvalue */
                                NULL); /* gcc_jit_location *loc */
  gcc_jit_block *block_p_C1_true_0x55a43caf73a0 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "p_C1_true");
  gcc_jit_block *block_p_C1_end_0x55a43caf7450 =
    gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, "p_C1_end");
  gcc_jit_lvalue *local_ival_0x55a43caf7590 =
    gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE_0x55a43caf5dc0, /* gcc_jit_function *func */
                                NULL, /* gcc_jit_location *loc */
                                type_int_0x55a43caf3b70, /* gcc_jit_type *type */
                                "ival"); /* const char *name */
  gcc_jit_rvalue *rvalue__int__dptr_0x55a43caf66a0 =
    gcc_jit_context_new_cast (ctxt_0x55a43caf3990,
                              NULL, /* gcc_jit_location *loc */
                              gcc_jit_lvalue_as_rvalue (dereference__dptr_0x55a43caf72c0), /* gcc_jit_rvalue *rvalue */
                              type_int_0x55a43caf3b70); /* gcc_jit_type *type */
  gcc_jit_rvalue *rvalue__int__sptr_0x55a43caf75f0 =
    gcc_jit_context_new_cast (ctxt_0x55a43caf3990,
                              NULL, /* gcc_jit_location *loc */
                              gcc_jit_lvalue_as_rvalue (dereference__sptr_0x55a43caf7310), /* gcc_jit_rvalue *rvalue */
                              type_int_0x55a43caf3b70); /* gcc_jit_type *type */
  gcc_jit_rvalue *rvalue__int__dptr____int__sptr_0x55a43caf7640 =
    gcc_jit_context_new_binary_op (ctxt_0x55a43caf3990,
                                   NULL, /* gcc_jit_location *loc */
                                   GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */
                                   type_int_0x55a43caf3b70, /* gcc_jit_type *result_type */
                                   rvalue__int__dptr_0x55a43caf66a0, /* gcc_jit_rvalue *a */
                                   rvalue__int__sptr_0x55a43caf75f0); /* gcc_jit_rvalue *b */
  gcc_jit_block_add_assignment (block_L2_0x55a43caf6650, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_ival_0x55a43caf7590, /* gcc_jit_lvalue *lvalue */
                                rvalue__int__dptr____int__sptr_0x55a43caf7640); /* gcc_jit_rvalue *rvalue */
  gcc_jit_rvalue *rvalue__int_255_0x55a43caf7720 =
    gcc_jit_context_new_rvalue_from_int (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                         type_int_0x55a43caf3b70, /* gcc_jit_type *numeric_type */
                                         255); /* int value */
  gcc_jit_rvalue *rvalue_ival____int_255_0x55a43caf7770 =
    gcc_jit_context_new_comparison (ctxt_0x55a43caf3990,
                                    NULL, /* gcc_jit_location *loc */
                                    GCC_JIT_COMPARISON_GT, /* enum gcc_jit_comparison op */
                                    gcc_jit_lvalue_as_rvalue (local_ival_0x55a43caf7590), /* gcc_jit_rvalue *a */
                                    rvalue__int_255_0x55a43caf7720); /* gcc_jit_rvalue *b */
  gcc_jit_block_end_with_conditional (block_L2_0x55a43caf6650, /*gcc_jit_block *block */
                                      NULL, /* gcc_jit_location *loc */
                                      rvalue_ival____int_255_0x55a43caf7770, /* gcc_jit_rvalue *boolval */
                                      block_p_C1_true_0x55a43caf73a0, /* gcc_jit_block *on_true */
                                      block_p_C1_end_0x55a43caf7450); /* gcc_jit_block *on_false */
  gcc_jit_block_add_assignment (block_p_C1_true_0x55a43caf73a0, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_ival_0x55a43caf7590, /* gcc_jit_lvalue *lvalue */
                                rvalue__int_255_0x55a43caf7720); /* gcc_jit_rvalue *rvalue */
  gcc_jit_block_end_with_jump (block_p_C1_true_0x55a43caf73a0, /*gcc_jit_block *block */
                               NULL, /* gcc_jit_location *loc */
                               block_p_C1_end_0x55a43caf7450); /* gcc_jit_block *target */
  gcc_jit_rvalue *rvalue__unsigned_char_ival_0x55a43caf78e0 =
    gcc_jit_context_new_cast (ctxt_0x55a43caf3990,
                              NULL, /* gcc_jit_location *loc */
                              gcc_jit_lvalue_as_rvalue (local_ival_0x55a43caf7590), /* gcc_jit_rvalue *rvalue */
                              type_unsigned_char_0x55a43caf3d00); /* gcc_jit_type *type */
  gcc_jit_lvalue *dereference__dptr_0x55a43caf7930 =
    gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_dptr_0x55a43caf6100), /* gcc_jit_rvalue *rvalue */
                                NULL); /* gcc_jit_location *loc */
  gcc_jit_block_add_assignment (block_p_C1_end_0x55a43caf7450, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                dereference__dptr_0x55a43caf7930, /* gcc_jit_lvalue *lvalue */
                                rvalue__unsigned_char_ival_0x55a43caf78e0); /* gcc_jit_rvalue *rvalue */
  gcc_jit_rvalue *rvalue__int_1_0x55a43caf7a00 =
    gcc_jit_context_new_rvalue_from_int (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                         type_int_0x55a43caf3b70, /* gcc_jit_type *numeric_type */
                                         1); /* int value */
  gcc_jit_lvalue *lvalue_dptr__int_1__0x55a43caf7a50 = 
    gcc_jit_context_new_array_access (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                      NULL, /*gcc_jit_location *loc */
                                      gcc_jit_lvalue_as_rvalue (local_dptr_0x55a43caf6100), /* gcc_jit_rvalue *ptr */
                                      rvalue__int_1_0x55a43caf7a00); /* gcc_jit_rvalue *index */
  gcc_jit_rvalue *address_of__dptr__int_1__0x55a43caf7ab0 =
    gcc_jit_lvalue_get_address (lvalue_dptr__int_1__0x55a43caf7a50, /* gcc_jit_lvalue *lvalue */
                                NULL); /* gcc_jit_location *loc */
  gcc_jit_block_add_assignment (block_p_C1_end_0x55a43caf7450, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_dptr_0x55a43caf6100, /* gcc_jit_lvalue *lvalue */
                                address_of__dptr__int_1__0x55a43caf7ab0); /* gcc_jit_rvalue *rvalue */
  gcc_jit_rvalue *rvalue__int_1_0x55a43caf7b50 =
    gcc_jit_context_new_rvalue_from_int (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                         type_int_0x55a43caf3b70, /* gcc_jit_type *numeric_type */
                                         1); /* int value */
  gcc_jit_lvalue *lvalue_sptr__int_1__0x55a43caf7ba0 = 
    gcc_jit_context_new_array_access (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                      NULL, /*gcc_jit_location *loc */
                                      gcc_jit_lvalue_as_rvalue (local_sptr_0x55a43caf61c0), /* gcc_jit_rvalue *ptr */
                                      rvalue__int_1_0x55a43caf7b50); /* gcc_jit_rvalue *index */
  gcc_jit_rvalue *address_of__sptr__int_1__0x55a43caf7c00 =
    gcc_jit_lvalue_get_address (lvalue_sptr__int_1__0x55a43caf7ba0, /* gcc_jit_lvalue *lvalue */
                                NULL); /* gcc_jit_location *loc */
  gcc_jit_block_add_assignment (block_p_C1_end_0x55a43caf7450, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_sptr_0x55a43caf61c0, /* gcc_jit_lvalue *lvalue */
                                address_of__sptr__int_1__0x55a43caf7c00); /* gcc_jit_rvalue *rvalue */
  gcc_jit_rvalue *rvalue__int_1_0x55a43caf7ca0 =
    gcc_jit_context_new_rvalue_from_int (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                         type_int_0x55a43caf3b70, /* gcc_jit_type *numeric_type */
                                         1); /* int value */
  gcc_jit_rvalue *rvalue_i____int_1_0x55a43caf7cf0 =
    gcc_jit_context_new_binary_op (ctxt_0x55a43caf3990,
                                   NULL, /* gcc_jit_location *loc */
                                   GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */
                                   type_int_0x55a43caf3b70, /* gcc_jit_type *result_type */
                                   gcc_jit_lvalue_as_rvalue (local_i_0x55a43caf62d0), /* gcc_jit_rvalue *a */
                                   rvalue__int_1_0x55a43caf7ca0); /* gcc_jit_rvalue *b */
  gcc_jit_block_add_assignment (block_p_C1_end_0x55a43caf7450, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_i_0x55a43caf62d0, /* gcc_jit_lvalue *lvalue */
                                rvalue_i____int_1_0x55a43caf7cf0); /* gcc_jit_rvalue *rvalue */
  gcc_jit_block_end_with_jump (block_p_C1_end_0x55a43caf7450, /*gcc_jit_block *block */
                               NULL, /* gcc_jit_location *loc */
                               block_C2_0x55a43caf65a0); /* gcc_jit_block *target */
  gcc_jit_rvalue *rvalue__int_1_0x55a43caf7e30 =
    gcc_jit_context_new_rvalue_from_int (ctxt_0x55a43caf3990, /* gcc_jit_context *ctxt */
                                         type_int_0x55a43caf3b70, /* gcc_jit_type *numeric_type */
                                         1); /* int value */
  gcc_jit_rvalue *rvalue_j____int_1_0x55a43caf7e80 =
    gcc_jit_context_new_binary_op (ctxt_0x55a43caf3990,
                                   NULL, /* gcc_jit_location *loc */
                                   GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */
                                   type_int_0x55a43caf3b70, /* gcc_jit_type *result_type */
                                   gcc_jit_lvalue_as_rvalue (local_j_0x55a43caf6040), /* gcc_jit_rvalue *a */
                                   rvalue__int_1_0x55a43caf7e30); /* gcc_jit_rvalue *b */
  gcc_jit_block_add_assignment (block_A2_0x55a43caf6750, /*gcc_jit_block *block */
                                NULL, /* gcc_jit_location *loc */
                                local_j_0x55a43caf6040, /* gcc_jit_lvalue *lvalue */
                                rvalue_j____int_1_0x55a43caf7e80); /* gcc_jit_rvalue *rvalue */
  gcc_jit_block_end_with_jump (block_A2_0x55a43caf6750, /*gcc_jit_block *block */
                               NULL, /* gcc_jit_location *loc */
                               block_C1_0x55a43caf6440); /* gcc_jit_block *target */
  gcc_jit_block_end_with_void_return (block_A1_0x55a43caf6800, /*gcc_jit_block *block */
                                      NULL); /* gcc_jit_location *loc */
}

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [committed] jit: add gcc_jit_type_get_vector
  2017-01-01  0:00       ` Michael Cree
@ 2017-01-01  0:00         ` David Malcolm
  2017-01-01  0:00           ` Michael Cree
  0 siblings, 1 reply; 9+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: Michael Cree; +Cc: jit

On Wed, 2017-08-16 at 21:58 +1200, Michael Cree wrote:
> On Wed, Aug 09, 2017 at 09:01:13PM -0400, David Malcolm wrote:
> > On Wed, 2017-08-09 at 20:42 +1200, Michael Cree wrote:
> > > On Mon, Aug 07, 2017 at 10:28:57AM -0400, David Malcolm wrote:
> > > > What would the ideal API
> > > > look like? 
> > > > 
> > > > Maybe something like:
> > > > 
> > > >   extern gcc_jit_type *
> > > >   gcc_jit_type_get_vector (gcc_jit_type *type, unsigned
> > > > nunits);
> > > >  
> > > > with various requirements (type must be integral/floating
> > > > point;
> > > > nunits
> > > > must be a power of two).
> > > 
> > > I suspect that would do the job nicely.
> > 
> > I implemented the above (although I switched the 2nd arg to be
> > "size_t num_units").
> 
> Thanks!  I haven't been able to try the vector type yet; current
> gcc trunk which I just pulled failed to build.
> 
> But I have started work using gcc 6.4 and 7.1 libgccjit (without
> the vector type) and have a problem noted below.  But first:
> 
> > It looks like you may not need to explicitly use builtins to
> > access machine specific simd intrinsics; for example, on x86_64
> > when I tried multiplying two of these together for float, with
> > GCC_JIT_BINARY_OP_MULT, which led to this gimple:
> > 
> > jit_v4f_mult (const vector(4) <float:32> * a, const vector(4)
> > <float:32> * b, vector(4) <float:32> * c)
> > {
> >   initial:
> >   _1 = *a;
> >   _2 = *b;
> >   _3 = _1 * _2;
> >   *c = _3;
> >   return;
> > }
> > 
> > on this x86_64 box it compiled to:
> > 
> > 	movaps	(%rdi), %xmm0
> > 	mulps	(%rsi), %xmm0
> > 	movaps	%xmm0, (%rdx)
> > 	ret
> > 
> > (i.e. using the "mulps" SIMD instruction).
> 
> Yep, compiling with optimisation set to -O3 will enable the
> vectorisation optimisations.  I normally compile with -O2;
> historically
> I have found -O3 as likely to impair performance as to improve
> performance (so I tend not to use -O3) but maybe that has changed in
> recent decades ;-)
> 
> The vectorisation optimisations are not clever enough to well
> optimise
> more complicated image processing filters so accessing the builtins
> will
> be necessary. 
> 
> But I have hit a problem which I suspect is a bug in the gcc
> optimiser.
> 
> In the vein of your example above, but working on uint8_t pixel data
> and adding saturation, the jit compiler segfaults in the optimiser. I
> provide below the gimple produced by the function that causes the
> problem (I presume that is more useful than the code calling the
> gcc_jit routines), 

There's actually a handy entrypoint for generating minimal reproducers
for such crashes:
  gcc_jit_context_dump_reproducer_to_file

https://gcc.gnu.org/onlinedocs/jit/topics/contexts.html#gcc_jit_context_dump_reproducer_to_file

Can you add a call to that to your code (after the context is fully
populated), and see if the resulting .c file leads to the crash when
run?  If so, can you post the .c file here please (or attach it to
bugzilla), and hopefully I can then reproduce it at my end.

> and a backtrace from the jit compiler.  This example
> is from Debian gcc 6.3.0-18 (but it also happens with gcc 7.1;
> unfortunately my build of gcc from the trunk failed).  Should I file
> a
> bug report, and if so, against what component?

Yes please.  There's a "jit" component.

> For the below I have set optimisation level to -O3 (to get
> vectorisation) and specified -mavx2 as a compiler arg.  (BTW, the
> same
> segfault also occurs when compiling for Arm and Arm64.  Also if I set
> optimisation level to -O2 the example compiles and runs correctly.)
> 
> The offending function I implement in the JIT is essentially:
> 
> ip_jit_im_add_clip_UBYTE (struct ip_image * dest, struct ip_image *
> src)
> {
>     int rowlen = dest->size.x;
>     int numrows = dest->size.y;
>     for (int j=0; j<numrows; j++) {
>         uint8_t *sptr, *dptr;
>         dptr = (uint8_t *)dest->imrow[j];
>         sptr = (uint8_t *)src->imrow[j];
>         for (int i=0; i<rowlen; i++) {
>             int ival = (int)*dptr + (int)*sptr;
>             if (ival > UINT8_MAX)
>                 ival = UINT8_MAX;
>             *dptr = (uint8_t)ival;
>             sptr++; dptr++;
>         }
>     }
> }
> 
> 
> The gimple produced is:
> 
> ip_jit_im_add_clip_UBYTE (struct ip_image * dest, struct ip_image *
> src)
> {
>   void * * D.370;
>   sizetype D.371;
>   sizetype D.372;
>   void * * D.373;
>   void * * D.374;
>   void * * D.375;
>   unsigned char D.376;
>   signed int D.377;
>   unsigned char D.378;
>   signed int D.379;
>   unsigned char D.380;
>   sizetype D.381;
>   signed int ival;
>   signed int i;
>   unsigned char * sptr;
>   unsigned char * dptr;
>   signed int j;
>   signed int numrows;
>   signed int rowlen;
> 
>   F1:
>   rowlen = dest->size.x;
>   numrows = dest->size.y;
>   j = 0;
>   goto C1;
>   C1:
>   if (j < numrows) goto L1; else goto A1;
>   L1:
>   D.370 = dest->imrow;
>   D.371 = (sizetype) j;
>   D.372 = D.371 * 8;
>   D.373 = D.370 + D.372;
>   dptr = *D.373;
>   D.374 = src->imrow;
>   D.371 = (sizetype) j;
>   D.372 = D.371 * 8;
>   D.375 = D.374 + D.372;
>   sptr = *D.375;
>   i = 0;
>   goto C2;
>   C2:
>   if (i < rowlen) goto L2; else goto A2;
>   L2:
>   D.376 = *dptr;
>   D.377 = (signed int) D.376;
>   D.378 = *sptr;
>   D.379 = (signed int) D.378;
>   ival = D.377 + D.379;
>   if (ival > 255) goto p_C1_true; else goto p_C1_end;
>   A2:
>   j = j + 1;
>   goto C1;
>   A1:
>   return;
>   p_C1_true:
>   ival = 255;
>   goto p_C1_end;
>   p_C1_end:
>   D.380 = (unsigned char) ival;
>   *dptr = D.380;
>   D.381 = 1;
>   dptr = dptr + D.381;
>   D.381 = 1;
>   sptr = sptr + D.381;
>   i = i + 1;
>   goto C2;
> }
> 
> 
> And the optimiser segfaults while compiling the above with:
> 
> Program received signal SIGSEGV, Segmentation fault.
> optab_for_tree_code (code=code@entry=VEC_UNPACK_LO_EXPR, type=type@en
> try=0x0, 
>     subtype=subtype@entry=optab_default) at ../../src/gcc/optabs-
> tree.c:190
> 190	../../src/gcc/optabs-tree.c: No such file or directory.
> (gdb) bt
> #0  optab_for_tree_code (code=code@entry=VEC_UNPACK_LO_EXPR, type=typ
> e@entry=0x0, 
>     subtype=subtype@entry=optab_default) at ../../src/gcc/optabs-
> tree.c:190
> #1  0x00007ffff6148593 in supportable_widening_operation (code=code@e
> ntry=NOP_EXPR, 
>     stmt=stmt@entry=0x7ffff3d170f0, vectype_out=vectype_out@entry=0x7
> ffff3d32f18, 
>     vectype_in=0x7ffff3cf3f18, code1=code1@entry=0x7fffffffd804, 
>     code2=code2@entry=0x7fffffffd808, multi_step_cvt=0x7fffffffd814, 
>     interm_types=0x7fffffffd850) at ../../src/gcc/tree-vect-
> stmts.c:9037
> #2  0x00007ffff614c2e5 in vectorizable_conversion (stmt=stmt@entry=0x
> 7ffff3d170f0, 
>     gsi=gsi@entry=0x0, vec_stmt=vec_stmt@entry=0x0, slp_node=slp_node
> @entry=0x0)
>     at ../../src/gcc/tree-vect-stmts.c:3803
> #3  0x00007ffff6159d25 in vect_analyze_stmt (stmt=stmt@entry=0x7ffff3
> d170f0, 
>     need_to_vectorize=need_to_vectorize@entry=0x7fffffffd978, node=no
> de@entry=0x0)
>     at ../../src/gcc/tree-vect-stmts.c:8135
> #4  0x00007ffff616830b in vect_analyze_loop_operations
> (loop_vinfo=0x555555e80660, 
>     loop_vinfo=0x555555e80660) at ../../src/gcc/tree-vect-loop.c:1727
> #5  vect_analyze_loop_2 (fatal=<synthetic pointer>: <optimized out>,
> loop_vinfo=0x555555e80660)
>     at ../../src/gcc/tree-vect-loop.c:2015
> #6  vect_analyze_loop (loop=loop@entry=0x7ffff3d02ee0) at
> ../../src/gcc/tree-vect-loop.c:2268
> #7  0x00007ffff617a37f in vectorize_loops () at ../../src/gcc/tree-
> vectorizer.c:532
> #8  0x00007ffff5eec80a in execute_one_pass (pass=pass@entry=0x555555c
> 335c0)
>     at ../../src/gcc/passes.c:2336
> #9  0x00007ffff5eecdd8 in execute_pass_list_1 (pass=0x555555c335c0)
>     at ../../src/gcc/passes.c:2420
> #10 0x00007ffff5eecdea in execute_pass_list_1 (pass=0x555555c32e30)
>     at ../../src/gcc/passes.c:2421
> #11 0x00007ffff5eecdea in execute_pass_list_1 (pass=0x555555c31c90)
>     at ../../src/gcc/passes.c:2421
> #12 0x00007ffff5eece3d in execute_pass_list (fn=<optimized out>,
> pass=<optimized out>)
>     at ../../src/gcc/passes.c:2431
> #13 0x00007ffff5c7c4b3 in cgraph_node::expand (this=0x7ffff3d132e0)
>     at ../../src/gcc/cgraphunit.c:1990
> #14 0x00007ffff5c7db6f in expand_all_functions () at
> ../../src/gcc/cgraphunit.c:2126
> #15 symbol_table::compile (this=0x7ffff3cd30a8) at
> ../../src/gcc/cgraphunit.c:2482
> #16 0x00007ffff5c7f53a in symbol_table::finalize_compilation_unit
> (this=0x7ffff3cd30a8)
>     at ../../src/gcc/cgraphunit.c:2572
> #17 0x00007ffff5fa227a in compile_file () at
> ../../src/gcc/toplev.c:488
> #18 0x00007ffff5bdb207 in do_compile () at
> ../../src/gcc/toplev.c:2011
> #19 toplev::main (this=this@entry=0x7fffffffdd4e, argc=<optimized
> out>, argv=<optimized out>)
>     at ../../src/gcc/toplev.c:2119
> #20 0x00007ffff5bfd066 in gcc::jit::playback::context::compile (this=
> this@entry=0x7fffffffdda0)
>     at ../../src/gcc/jit/jit-playback.c:1789
> #21 0x00007ffff5bf3bf9 in gcc::jit::recording::context::compile (this
> =this@entry=0x555555bb8990)
>     at ../../src/gcc/jit/jit-recording.c:1241
> #22 0x00007ffff5be9649 in gcc_jit_context_compile
> (ctxt=0x555555bb8990)
>     at ../../src/gcc/jit/libgccjit.c:2677
> #23 0x00005555555703c7 in ip_init_jit () at jit.c:615
> #24 0x0000555555568c6f in im_add (dest=0x5555559b3530,
> src=0x5555558b0eb0, flag=0)
>     at arith.c:750
> #25 0x000055555556364e in run_libip_operator (flag=0,
> s=0x5555558b0eb0, d=0x5555559b3530, op=0)
>     at arith-test.c:228
> #26 im_op_ii_check (op=0, type=3, size=..., flag=<optimized out>,
> source=<optimized out>)
>     at arith-test.c:334
> #27 0x000055555556428f in run_im_ii_tests (operator=0, size=...,
> chk_flag=114)
>     at arith-test.c:488
> #28 0x000055555555ef34 in main (argc=<optimized out>, argv=<optimized
> out>) at arith-test.c:601
> 
> Cheers
> Michael.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [committed] jit: add gcc_jit_type_get_vector
  2017-01-01  0:00           ` Michael Cree
@ 2017-01-01  0:00             ` David Malcolm
  2017-01-01  0:00               ` [committed] jit: fix segfault with autovectorization (PR tree-optimization/46805) David Malcolm
  0 siblings, 1 reply; 9+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: Michael Cree; +Cc: jit

On Thu, 2017-08-17 at 09:15 +1200, Michael Cree wrote:
> On Wed, Aug 16, 2017 at 10:01:57AM -0400, David Malcolm wrote:
> > On Wed, 2017-08-16 at 21:58 +1200, Michael Cree wrote:
> > > 
> > > But I have hit a problem which I suspect is a bug in the gcc
> > > optimiser.
> > > 
> > > In the vein of your example above, but working on uint8_t pixel
> > > data
> > > and adding saturation, the jit compiler segfaults in the
> > > optimiser. I
> > > provide below the gimple produced by the function that causes the
> > > problem (I presume that is more useful than the code calling the
> > > gcc_jit routines), 
> > 
> > There's actually a handy entrypoint for generating minimal
> > reproducers
> > for such crashes:
> >   gcc_jit_context_dump_reproducer_to_file
> > 
> > https://gcc.gnu.org/onlinedocs/jit/topics/contexts.html#gcc_jit_con
> > text_dump_reproducer_to_file
> > 
> > Can you add a call to that to your code (after the context is fully
> > populated), and see if the resulting .c file leads to the crash
> > when
> > run?  If so, can you post the .c file here please (or attach it to
> > bugzilla), and hopefully I can then reproduce it at my end.
> 
> Attached.
> 
> Cheers
> Michael.

Thanks.  I'm able to reproduce the crash using that; am investigating.

Dave

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: does libgccjit support vector types?
  2017-01-01  0:00 ` David Malcolm
@ 2017-01-01  0:00   ` Michael Cree
  2017-01-01  0:00     ` [committed] jit: add gcc_jit_type_get_vector David Malcolm
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Cree @ 2017-01-01  0:00 UTC (permalink / raw)
  To: David Malcolm; +Cc: jit

On Mon, Aug 07, 2017 at 10:28:57AM -0400, David Malcolm wrote:
> On Mon, 2017-08-07 at 20:12 +1200, Michael Cree wrote:
> 
> Hi Michael
> 
> > I am wondering if libgccjit supports vector types, i.e., can one
> > attach attribute __vector_size__ to the base types?  There does not
> > seem to be any indication of this in the manual.
> 
> Currently this isn't supported.
> 
> Is this a blocker for you using libgccjit?  

Yeah, it is.  The idea is to generate image processing operators
on the fly.  There are opportunities for various optimisations that
can only be decided on at runtime.

> What would the ideal API
> look like? 
> 
> Maybe something like:
> 
>   extern gcc_jit_type *
>   gcc_jit_type_get_vector (gcc_jit_type *type, unsigned nunits);
>  
> with various requirements (type must be integral/floating point; nunits
> must be a power of two).

I suspect that would do the job nicely.

Cheers
Michael.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [committed] jit: add gcc_jit_type_get_vector
  2017-01-01  0:00     ` [committed] jit: add gcc_jit_type_get_vector David Malcolm
@ 2017-01-01  0:00       ` Michael Cree
  2017-01-01  0:00         ` David Malcolm
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Cree @ 2017-01-01  0:00 UTC (permalink / raw)
  To: David Malcolm; +Cc: jit

On Wed, Aug 09, 2017 at 09:01:13PM -0400, David Malcolm wrote:
> On Wed, 2017-08-09 at 20:42 +1200, Michael Cree wrote:
> > On Mon, Aug 07, 2017 at 10:28:57AM -0400, David Malcolm wrote:
> > > What would the ideal API
> > > look like? 
> > > 
> > > Maybe something like:
> > > 
> > >   extern gcc_jit_type *
> > >   gcc_jit_type_get_vector (gcc_jit_type *type, unsigned nunits);
> > >  
> > > with various requirements (type must be integral/floating point;
> > > nunits
> > > must be a power of two).
> > 
> > I suspect that would do the job nicely.
> 
> I implemented the above (although I switched the 2nd arg to be
> "size_t num_units").

Thanks!  I haven't been able to try the vector type yet; current
gcc trunk which I just pulled failed to build.

But I have started work using gcc 6.4 and 7.1 libgccjit (without
the vector type) and have a problem noted below.  But first:

> It looks like you may not need to explicitly use builtins to
> access machine specific simd intrinsics; for example, on x86_64
> when I tried multiplying two of these together for float, with
> GCC_JIT_BINARY_OP_MULT, which led to this gimple:
> 
> jit_v4f_mult (const vector(4) <float:32> * a, const vector(4) <float:32> * b, vector(4) <float:32> * c)
> {
>   initial:
>   _1 = *a;
>   _2 = *b;
>   _3 = _1 * _2;
>   *c = _3;
>   return;
> }
> 
> on this x86_64 box it compiled to:
> 
> 	movaps	(%rdi), %xmm0
> 	mulps	(%rsi), %xmm0
> 	movaps	%xmm0, (%rdx)
> 	ret
> 
> (i.e. using the "mulps" SIMD instruction).

Yep, compiling with optimisation set to -O3 will enable the
vectorisation optimisations.  I normally compile with -O2; historically
I have found -O3 as likely to impair performance as to improve
performance (so I tend not to use -O3) but maybe that has changed in
recent decades ;-)

The vectorisation optimisations are not clever enough to well optimise
more complicated image processing filters so accessing the builtins will
be necessary. 

But I have hit a problem which I suspect is a bug in the gcc optimiser.

In the vein of your example above, but working on uint8_t pixel data
and adding saturation, the jit compiler segfaults in the optimiser. I
provide below the gimple produced by the function that causes the
problem (I presume that is more useful than the code calling the
gcc_jit routines), and a backtrace from the jit compiler.  This example
is from Debian gcc 6.3.0-18 (but it also happens with gcc 7.1;
unfortunately my build of gcc from the trunk failed).  Should I file a
bug report, and if so, against what component?

For the below I have set optimisation level to -O3 (to get
vectorisation) and specified -mavx2 as a compiler arg.  (BTW, the same
segfault also occurs when compiling for Arm and Arm64.  Also if I set
optimisation level to -O2 the example compiles and runs correctly.)

The offending function I implement in the JIT is essentially:

ip_jit_im_add_clip_UBYTE (struct ip_image * dest, struct ip_image * src)
{
    int rowlen = dest->size.x;
    int numrows = dest->size.y;
    for (int j=0; j<numrows; j++) {
        uint8_t *sptr, *dptr;
        dptr = (uint8_t *)dest->imrow[j];
        sptr = (uint8_t *)src->imrow[j];
        for (int i=0; i<rowlen; i++) {
            int ival = (int)*dptr + (int)*sptr;
            if (ival > UINT8_MAX)
                ival = UINT8_MAX;
            *dptr = (uint8_t)ival;
            sptr++; dptr++;
        }
    }
}


The gimple produced is:

ip_jit_im_add_clip_UBYTE (struct ip_image * dest, struct ip_image * src)
{
  void * * D.370;
  sizetype D.371;
  sizetype D.372;
  void * * D.373;
  void * * D.374;
  void * * D.375;
  unsigned char D.376;
  signed int D.377;
  unsigned char D.378;
  signed int D.379;
  unsigned char D.380;
  sizetype D.381;
  signed int ival;
  signed int i;
  unsigned char * sptr;
  unsigned char * dptr;
  signed int j;
  signed int numrows;
  signed int rowlen;

  F1:
  rowlen = dest->size.x;
  numrows = dest->size.y;
  j = 0;
  goto C1;
  C1:
  if (j < numrows) goto L1; else goto A1;
  L1:
  D.370 = dest->imrow;
  D.371 = (sizetype) j;
  D.372 = D.371 * 8;
  D.373 = D.370 + D.372;
  dptr = *D.373;
  D.374 = src->imrow;
  D.371 = (sizetype) j;
  D.372 = D.371 * 8;
  D.375 = D.374 + D.372;
  sptr = *D.375;
  i = 0;
  goto C2;
  C2:
  if (i < rowlen) goto L2; else goto A2;
  L2:
  D.376 = *dptr;
  D.377 = (signed int) D.376;
  D.378 = *sptr;
  D.379 = (signed int) D.378;
  ival = D.377 + D.379;
  if (ival > 255) goto p_C1_true; else goto p_C1_end;
  A2:
  j = j + 1;
  goto C1;
  A1:
  return;
  p_C1_true:
  ival = 255;
  goto p_C1_end;
  p_C1_end:
  D.380 = (unsigned char) ival;
  *dptr = D.380;
  D.381 = 1;
  dptr = dptr + D.381;
  D.381 = 1;
  sptr = sptr + D.381;
  i = i + 1;
  goto C2;
}


And the optimiser segfaults while compiling the above with:

Program received signal SIGSEGV, Segmentation fault.
optab_for_tree_code (code=code@entry=VEC_UNPACK_LO_EXPR, type=type@entry=0x0, 
    subtype=subtype@entry=optab_default) at ../../src/gcc/optabs-tree.c:190
190	../../src/gcc/optabs-tree.c: No such file or directory.
(gdb) bt
#0  optab_for_tree_code (code=code@entry=VEC_UNPACK_LO_EXPR, type=type@entry=0x0, 
    subtype=subtype@entry=optab_default) at ../../src/gcc/optabs-tree.c:190
#1  0x00007ffff6148593 in supportable_widening_operation (code=code@entry=NOP_EXPR, 
    stmt=stmt@entry=0x7ffff3d170f0, vectype_out=vectype_out@entry=0x7ffff3d32f18, 
    vectype_in=0x7ffff3cf3f18, code1=code1@entry=0x7fffffffd804, 
    code2=code2@entry=0x7fffffffd808, multi_step_cvt=0x7fffffffd814, 
    interm_types=0x7fffffffd850) at ../../src/gcc/tree-vect-stmts.c:9037
#2  0x00007ffff614c2e5 in vectorizable_conversion (stmt=stmt@entry=0x7ffff3d170f0, 
    gsi=gsi@entry=0x0, vec_stmt=vec_stmt@entry=0x0, slp_node=slp_node@entry=0x0)
    at ../../src/gcc/tree-vect-stmts.c:3803
#3  0x00007ffff6159d25 in vect_analyze_stmt (stmt=stmt@entry=0x7ffff3d170f0, 
    need_to_vectorize=need_to_vectorize@entry=0x7fffffffd978, node=node@entry=0x0)
    at ../../src/gcc/tree-vect-stmts.c:8135
#4  0x00007ffff616830b in vect_analyze_loop_operations (loop_vinfo=0x555555e80660, 
    loop_vinfo=0x555555e80660) at ../../src/gcc/tree-vect-loop.c:1727
#5  vect_analyze_loop_2 (fatal=<synthetic pointer>: <optimized out>, loop_vinfo=0x555555e80660)
    at ../../src/gcc/tree-vect-loop.c:2015
#6  vect_analyze_loop (loop=loop@entry=0x7ffff3d02ee0) at ../../src/gcc/tree-vect-loop.c:2268
#7  0x00007ffff617a37f in vectorize_loops () at ../../src/gcc/tree-vectorizer.c:532
#8  0x00007ffff5eec80a in execute_one_pass (pass=pass@entry=0x555555c335c0)
    at ../../src/gcc/passes.c:2336
#9  0x00007ffff5eecdd8 in execute_pass_list_1 (pass=0x555555c335c0)
    at ../../src/gcc/passes.c:2420
#10 0x00007ffff5eecdea in execute_pass_list_1 (pass=0x555555c32e30)
    at ../../src/gcc/passes.c:2421
#11 0x00007ffff5eecdea in execute_pass_list_1 (pass=0x555555c31c90)
    at ../../src/gcc/passes.c:2421
#12 0x00007ffff5eece3d in execute_pass_list (fn=<optimized out>, pass=<optimized out>)
    at ../../src/gcc/passes.c:2431
#13 0x00007ffff5c7c4b3 in cgraph_node::expand (this=0x7ffff3d132e0)
    at ../../src/gcc/cgraphunit.c:1990
#14 0x00007ffff5c7db6f in expand_all_functions () at ../../src/gcc/cgraphunit.c:2126
#15 symbol_table::compile (this=0x7ffff3cd30a8) at ../../src/gcc/cgraphunit.c:2482
#16 0x00007ffff5c7f53a in symbol_table::finalize_compilation_unit (this=0x7ffff3cd30a8)
    at ../../src/gcc/cgraphunit.c:2572
#17 0x00007ffff5fa227a in compile_file () at ../../src/gcc/toplev.c:488
#18 0x00007ffff5bdb207 in do_compile () at ../../src/gcc/toplev.c:2011
#19 toplev::main (this=this@entry=0x7fffffffdd4e, argc=<optimized out>, argv=<optimized out>)
    at ../../src/gcc/toplev.c:2119
#20 0x00007ffff5bfd066 in gcc::jit::playback::context::compile (this=this@entry=0x7fffffffdda0)
    at ../../src/gcc/jit/jit-playback.c:1789
#21 0x00007ffff5bf3bf9 in gcc::jit::recording::context::compile (this=this@entry=0x555555bb8990)
    at ../../src/gcc/jit/jit-recording.c:1241
#22 0x00007ffff5be9649 in gcc_jit_context_compile (ctxt=0x555555bb8990)
    at ../../src/gcc/jit/libgccjit.c:2677
#23 0x00005555555703c7 in ip_init_jit () at jit.c:615
#24 0x0000555555568c6f in im_add (dest=0x5555559b3530, src=0x5555558b0eb0, flag=0)
    at arith.c:750
#25 0x000055555556364e in run_libip_operator (flag=0, s=0x5555558b0eb0, d=0x5555559b3530, op=0)
    at arith-test.c:228
#26 im_op_ii_check (op=0, type=3, size=..., flag=<optimized out>, source=<optimized out>)
    at arith-test.c:334
#27 0x000055555556428f in run_im_ii_tests (operator=0, size=..., chk_flag=114)
    at arith-test.c:488
#28 0x000055555555ef34 in main (argc=<optimized out>, argv=<optimized out>) at arith-test.c:601

Cheers
Michael.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-08-19  0:01 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-01  0:00 does libgccjit support vector types? Michael Cree
2017-01-01  0:00 ` David Malcolm
2017-01-01  0:00   ` Michael Cree
2017-01-01  0:00     ` [committed] jit: add gcc_jit_type_get_vector David Malcolm
2017-01-01  0:00       ` Michael Cree
2017-01-01  0:00         ` David Malcolm
2017-01-01  0:00           ` Michael Cree
2017-01-01  0:00             ` David Malcolm
2017-01-01  0:00               ` [committed] jit: fix segfault with autovectorization (PR tree-optimization/46805) David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).