diff mbox

[02/02] PR jit/64166: Add API entrypoint gcc_jit_context_enable_dump

Message ID 1417730619-14800-2-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm Dec. 4, 2014, 10:03 p.m. UTC
This is the JIT-specific part of the patch for PR jit/64166.

Implement a way to get at dumpfiles from JIT testcases.

Use it from test-sum-of-squares.c to provide a simple selftest of the
dumping functionality, and use it from test-functions.c to add
verification of the fix for PR jit/64020.

gcc/jit/ChangeLog:
	PR jit/64166
	* docs/topics/contexts.rst (Debugging): Add description of
	gcc_jit_context_enable_dump.
	* jit-playback.c: Include context.h
	(class auto_argvec): New class
	(auto_argvec::~auto_argvec): New function.
	(gcc::jit::playback::context::compile): Convert fake_args to be
	an auto_argvec, so that it can contain dynamically-allocated
	strings.   Construct a vec of all requested dumps, and pass it to
	make_fake_args.  Extract requested dumps between the calls to
	toplev::main and toplev::finalize.
	(gcc::jit::playback::context::make_fake_args): Convert param
	"argvec" to be a vec <char *>, and gain a "requested_dumps"
	param.  Convert to dynamically-allocated arg strings by converting
	ADD_ARG to take a copy of the arg, and add ADD_ARG_TAKE_OWNERSHIP
	for args that are already a copy.  Add args for all requested dumps.
	(gcc::jit::playback::context::extract_any_requested_dumps): New
	function.
	(gcc::jit::playback::context::read_dump_file): New function.
	* jit-playback.h (gcc::jit::playback::context::make_fake_args):
	Convert param "argvec" to be a vec <char *>, and gain a
	"requested_dumps" param.
	(gcc::jit::playback::context::extract_any_requested_dumps): New
	function.
	(gcc::jit::playback::context::read_dump_file): New function.
	* jit-recording.c (gcc::jit::recording::context::enable_dump): New
	function.
	(gcc::jit::recording::context::get_all_requested_dumps): New
	function.
	* jit-recording.h (gcc::jit::recording::requested_dump): New
	struct.
	(gcc::jit::recording::context::enable_dump): New function.
	(gcc::jit::recording::context::get_all_requested_dumps): New
	function.
	(gcc::jit::recording::context::m_requested_dumps): New field.
	* libgccjit.c (gcc_jit_context_enable_dump): New API entrypoint.
	* libgccjit.h (gcc_jit_context_enable_dump): New API entrypoint.
	* libgccjit.map (gcc_jit_context_enable_dump): New API entrypoint.

gcc/testsuite/ChangeLog:
	PR jit/64166
	PR jit/64020
	* jit.dg/harness.h (CHECK_STRING_CONTAINS): New macro.
	(check_string_contains): New function.
	* jit.dg/test-error-unrecognized-dump.c: New file.
	* jit.dg/test-functions.c (trig_sincos_dump): New variable.
	(trig_statistics_dump): New variable.
	(create_test_of_builtin_trig): Enable dumping of "sincos" and
	"statistics" into "trig_sincos_dump" and "trig_statistics_dump".
	(verify_test_of_builtin_trig): Verify the sincos and statistics
	dumps.
	* jit.dg/test-sum-of-squares.c (dump_vrp1): New variable.
	(create_code): Enable dumping of "tree-vrp1" into dump_vrp1.
	(verify_code): Verify the tree-vrp1 dump.
---
 gcc/jit/docs/topics/contexts.rst                   |  47 +++++++
 gcc/jit/jit-playback.c                             | 141 ++++++++++++++++++++-
 gcc/jit/jit-playback.h                             |  12 +-
 gcc/jit/jit-recording.c                            |  34 +++++
 gcc/jit/jit-recording.h                            |  17 +++
 gcc/jit/libgccjit.c                                |  18 +++
 gcc/jit/libgccjit.h                                |  34 +++++
 gcc/jit/libgccjit.map                              |   1 +
 gcc/testsuite/jit.dg/harness.h                     |  33 +++++
 .../jit.dg/test-error-unrecognized-dump.c          |  27 ++++
 gcc/testsuite/jit.dg/test-functions.c              |  27 ++++
 gcc/testsuite/jit.dg/test-sum-of-squares.c         |  16 +++
 12 files changed, 400 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-error-unrecognized-dump.c
diff mbox

Patch

diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst
index c3f8c52..d03ccf4 100644
--- a/gcc/jit/docs/topics/contexts.rst
+++ b/gcc/jit/docs/topics/contexts.rst
@@ -152,6 +152,53 @@  Debugging
    :macro:`GCC_JIT_BOOL_OPTION_DEBUGINFO` to allow stepping through the
    code in a debugger.
 
+.. function:: void\
+              gcc_jit_context_enable_dump (gcc_jit_context *ctxt,\
+                                           const char *dumpname, \
+                                           char **out_ptr)
+
+   Enable the dumping of a specific set of internal state from the
+   compilation, capturing the result in-memory as a buffer.
+
+   Parameter "dumpname" corresponds to the equivalent gcc command-line
+   option, without the "-fdump-" prefix.
+   For example, to get the equivalent of :option:`-fdump-tree-vrp1`,
+   supply ``"tree-vrp1"``:
+
+   .. code-block:: c
+
+      static char *dump_vrp1;
+
+      void
+      create_code (gcc_jit_context *ctxt)
+      {
+         gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1);
+         /* (other API calls omitted for brevity) */
+      }
+
+   The context directly stores the dumpname as a ``(const char *)``, so
+   the passed string must outlive the context.
+
+   :func:`gcc_jit_context_compile` will capture the dump as a
+   dynamically-allocated buffer, writing it to ``*out_ptr``.
+
+   The caller becomes responsible for calling:
+
+   .. code-block:: c
+
+      free (*out_ptr)
+
+   each time that :func:`gcc_jit_context_compile` is called.
+   ``*out_ptr`` will be written to, either with the address of a buffer,
+   or with ``NULL`` if an error occurred.
+
+   .. warning::
+
+      This API entrypoint is likely to be less stable than the others.
+      In particular, both the precise dumpnames, and the format and content
+      of the dumps are subject to change.
+
+      It exists primarily for writing the library's own test suite.
 
 Options
 -------
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index ecdae80..cf50fb3 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -47,6 +47,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "gcc-driver-name.h"
 #include "attribs.h"
+#include "context.h"
 
 #include "jit-common.h"
 #include "jit-playback.h"
@@ -1552,6 +1553,26 @@  make_tempdir_path_template ()
   return result;
 }
 
+/* A subclass of auto_vec <char *> that frees all of its elements on
+   deletion.  */
+
+class auto_argvec : public auto_vec <char *>
+{
+ public:
+  ~auto_argvec ();
+};
+
+/* auto_argvec's dtor, freeing all contained strings, automatically
+   chaining up to ~auto_vec <char *>, which frees the internal buffer.  */
+
+auto_argvec::~auto_argvec ()
+{
+  int i;
+  char *str;
+  FOR_EACH_VEC_ELT (*this, i, str)
+    free (str);
+}
+
 /* Compile a playback::context:
 
    - Use the context's options to cconstruct command-line options, and
@@ -1594,14 +1615,25 @@  compile ()
   if (!ctxt_progname)
     ctxt_progname = "libgccjit.so";
 
-  auto_vec <const char *> fake_args;
-  make_fake_args (&fake_args, ctxt_progname);
+  auto_vec <recording::requested_dump> requested_dumps;
+  m_recording_ctxt->get_all_requested_dumps (&requested_dumps);
+
+  auto_argvec fake_args;
+  make_fake_args (&fake_args, ctxt_progname, &requested_dumps);
   if (errors_occurred ())
     return NULL;
 
+  /* This runs the compiler.  */
   toplev toplev (false);
   toplev.main (fake_args.length (),
 	       const_cast <char **> (fake_args.address ()));
+
+  /* Extracting dumps makes use of the gcc::dump_manager, hence we
+     need to do it between toplev::main (which creates the dump manager)
+     and toplev::finalize (which deletes it).  */
+  extract_any_requested_dumps (&requested_dumps);
+
+  /* Clean up the compiler.  */
   toplev.finalize ();
 
   active_playback_ctxt = NULL;
@@ -1645,10 +1677,12 @@  compile ()
 
 void
 playback::context::
-make_fake_args (auto_vec <const char *> *argvec,
-		const char *ctxt_progname)
+make_fake_args (vec <char *> *argvec,
+		const char *ctxt_progname,
+		vec <recording::requested_dump> *requested_dumps)
 {
-#define ADD_ARG(arg) argvec->safe_push (arg)
+#define ADD_ARG(arg) argvec->safe_push (xstrdup (arg))
+#define ADD_ARG_TAKE_OWNERSHIP(arg) argvec->safe_push (arg)
 
   ADD_ARG (ctxt_progname);
   ADD_ARG (m_path_c_file);
@@ -1707,7 +1741,104 @@  make_fake_args (auto_vec <const char *> *argvec,
       ADD_ARG ("-fdump-rtl-all");
       ADD_ARG ("-fdump-ipa-all");
     }
+
+  /* Add "-fdump-" options for any calls to
+     gcc_jit_context_enable_dump.  */
+  {
+    int i;
+    recording::requested_dump *d;
+    FOR_EACH_VEC_ELT (*requested_dumps, i, d)
+      {
+	char *arg = concat ("-fdump-", d->m_dumpname, NULL);
+	ADD_ARG_TAKE_OWNERSHIP (arg);
+      }
+  }
+
 #undef ADD_ARG
+#undef ADD_ARG_TAKE_OWNERSHIP
+}
+
+/* The second half of the implementation of gcc_jit_context_enable_dump.
+   Iterate through the requested dumps, reading the underlying files
+   into heap-allocated buffers, writing pointers to the buffers into
+   the char ** pointers provided by client code.
+   Client code is responsible for calling free on the results.  */
+
+void
+playback::context::
+extract_any_requested_dumps (vec <recording::requested_dump> *requested_dumps)
+{
+  int i;
+  recording::requested_dump *d;
+  FOR_EACH_VEC_ELT (*requested_dumps, i, d)
+    {
+      dump_file_info *dfi;
+      char *filename;
+      char *content;
+
+      dfi = g->get_dumps ()->get_dump_file_info_by_switch (d->m_dumpname);
+      if (!dfi)
+	{
+	  add_error (NULL, "unrecognized dump: %s", d->m_dumpname);
+	  continue;
+	}
+
+      filename = g->get_dumps ()->get_dump_file_name (dfi);
+      content = read_dump_file (filename);
+      *(d->m_out_ptr) = content;
+      free (filename);
+    }
+}
+
+/* Helper function for playback::context::extract_any_requested_dumps
+   (itself for use in implementation of gcc_jit_context_enable_dump).
+
+   Attempt to read the complete file at the given path, returning the
+   bytes found there as a buffer.
+   The caller is responsible for calling free on the result.
+   Errors will be reported on the context, and lead to NULL being
+   returned; an out-of-memory error will terminate the process.  */
+
+char *
+playback::context::read_dump_file (const char *path)
+{
+  char *result = NULL;
+  size_t total_sz = 0;
+  char buf[4096];
+  size_t sz;
+  FILE *f_in;
+
+  f_in = fopen (path, "r");
+  if (!f_in)
+    {
+      add_error (NULL, "unable to open %s for reading", path);
+      return NULL;
+    }
+
+  while ( (sz = fread (buf, 1, sizeof (buf), f_in)) )
+    {
+      size_t old_total_sz = total_sz;
+      total_sz += sz;
+      result = reinterpret_cast <char *> (xrealloc (result, total_sz + 1));
+      memcpy (result + old_total_sz, buf, sz);
+    }
+
+  if (!feof (f_in))
+    {
+      add_error (NULL, "error reading from %s", path);
+      free (result);
+      return NULL;
+    }
+
+  fclose (f_in);
+
+  if (result)
+    {
+      result[total_sz] = '\0';
+      return result;
+    }
+  else
+    return xstrdup ("");
 }
 
 /* Part of playback::context::compile ().
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 02f08ba..b2b983a 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -236,8 +236,16 @@  private:
   /* Functions for implementing "compile".  */
 
   void
-  make_fake_args (auto_vec <const char *> *argvec,
-		  const char *ctxt_progname);
+  make_fake_args (vec <char *> *argvec,
+		  const char *ctxt_progname,
+		  vec <recording::requested_dump> *requested_dumps);
+
+  void
+  extract_any_requested_dumps
+    (vec <recording::requested_dump> *requested_dumps);
+
+  char *
+  read_dump_file (const char *path);
 
   void
   convert_to_dso (const char *ctxt_progname);
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 82ec399..74fd111 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -868,6 +868,27 @@  recording::context::set_bool_option (enum gcc_jit_bool_option opt,
   m_bool_options[opt] = value ? true : false;
 }
 
+/* Add the given dumpname/out_ptr pair to this context's list of requested
+   dumps.
+
+   Implements the post-error-checking part of
+   gcc_jit_context_enable_dump.  */
+
+void
+recording::context::enable_dump (const char *dumpname,
+				 char **out_ptr)
+{
+  requested_dump d;
+  gcc_assert (dumpname);
+  gcc_assert (out_ptr);
+
+  d.m_dumpname = dumpname;
+  d.m_out_ptr = out_ptr;
+  *out_ptr = NULL;
+  m_requested_dumps.safe_push (d);
+}
+
+
 /* This mutex guards gcc::jit::recording::context::compile, so that only
    one thread can be accessing the bulk of GCC's state at once.  */
 
@@ -1026,6 +1047,19 @@  recording::context::dump_to_file (const char *path, bool update_locations)
     }
 }
 
+/* Copy the requested dumps within this context and all ancestors into
+   OUT. */
+
+void
+recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
+{
+  if (m_parent_ctxt)
+    m_parent_ctxt->get_all_requested_dumps (out);
+
+  out->reserve (m_requested_dumps.length ());
+  out->splice (m_requested_dumps);
+}
+
 /* This is a pre-compilation check for the context (and any parents).
 
    Detect errors within the context, adding errors if any are found.  */
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 31fb304..d2f5ffb 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -45,6 +45,13 @@  playback_string (string *str);
 playback::block *
 playback_block (block *b);
 
+/* A recording of a call to gcc_jit_context_enable_dump.  */
+struct requested_dump
+{
+  const char *m_dumpname;
+  char **m_out_ptr;
+};
+
 /* A JIT-compilation context.  */
 class context
 {
@@ -191,6 +198,10 @@  public:
   set_bool_option (enum gcc_jit_bool_option opt,
 		   int value);
 
+  void
+  enable_dump (const char *dumpname,
+	       char **out_ptr);
+
   const char *
   get_str_option (enum gcc_jit_str_option opt) const
   {
@@ -235,6 +246,9 @@  public:
 
   void dump_to_file (const char *path, bool update_locations);
 
+  void
+  get_all_requested_dumps (vec <recording::requested_dump> *out);
+
 private:
   void validate ();
 
@@ -250,6 +264,9 @@  private:
   int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
   bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS];
 
+  /* Dumpfiles that were requested via gcc_jit_context_enable_dump.  */
+  auto_vec<requested_dump> m_requested_dumps;
+
   /* Recorded API usage.  */
   auto_vec<memento *> m_mementos;
 
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 42769e8..0f50c43 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -2004,6 +2004,24 @@  gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
+   gcc::jit::recording::context::enable_dump method in
+   jit-recording.c.  */
+
+void
+gcc_jit_context_enable_dump (gcc_jit_context *ctxt,
+			     const char *dumpname,
+			     char **out_ptr)
+{
+  RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+  RETURN_IF_FAIL (dumpname, ctxt, NULL, "NULL dumpname");
+  RETURN_IF_FAIL (out_ptr, ctxt, NULL, "NULL out_ptr");
+
+  ctxt->enable_dump (dumpname, out_ptr);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
    gcc::jit::recording::context::compile method in
    jit-recording.c.  */
 
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index ed6390e..71628e0 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -985,6 +985,40 @@  gcc_jit_block_end_with_void_return (gcc_jit_block *block,
 extern gcc_jit_context *
 gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt);
 
+/**********************************************************************
+ Implementation support.
+ **********************************************************************/
+
+/* Enable the dumping of a specific set of internal state from the
+   compilation, capturing the result in-memory as a buffer.
+
+   Parameter "dumpname" corresponds to the equivalent gcc command-line
+   option, without the "-fdump-" prefix.
+   For example, to get the equivalent of "-fdump-tree-vrp1", supply
+   "tree-vrp1".
+   The context directly stores the dumpname as a (const char *), so the
+   passed string must outlive the context.
+
+   gcc_jit_context_compile will capture the dump as a
+   dynamically-allocated buffer, writing it to ``*out_ptr``.
+
+   The caller becomes responsible for calling
+      free (*out_ptr)
+   each time that gcc_jit_context_compile is called.  *out_ptr will be
+   written to, either with the address of a buffer, or with NULL if an
+   error occurred.
+
+   This API entrypoint is likely to be less stable than the others.
+   In particular, both the precise dumpnames, and the format and content
+   of the dumps are subject to change.
+
+   It exists primarily for writing the library's own test suite.  */
+
+extern void
+gcc_jit_context_enable_dump (gcc_jit_context *ctxt,
+			     const char *dumpname,
+			     char **out_ptr);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index d4ba7b6..0375e77 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -33,6 +33,7 @@ 
     gcc_jit_context_acquire;
     gcc_jit_context_compile;
     gcc_jit_context_dump_to_file;
+    gcc_jit_context_enable_dump;
     gcc_jit_context_get_builtin_function;
     gcc_jit_context_get_first_error;
     gcc_jit_context_get_type;
diff --git a/gcc/testsuite/jit.dg/harness.h b/gcc/testsuite/jit.dg/harness.h
index a30b66e..1493c6f 100644
--- a/gcc/testsuite/jit.dg/harness.h
+++ b/gcc/testsuite/jit.dg/harness.h
@@ -84,6 +84,9 @@  static char test[1024];
 #define CHECK_STRING_STARTS_WITH(ACTUAL, EXPECTED_PREFIX) \
   check_string_starts_with ((ACTUAL), (EXPECTED_PREFIX));
 
+#define CHECK_STRING_CONTAINS(ACTUAL, EXPECTED_SUBSTRING) \
+  check_string_contains (#ACTUAL, (ACTUAL), (EXPECTED_SUBSTRING));
+
 #define CHECK(COND) \
   do {					\
     if (COND)				\
@@ -110,6 +113,11 @@  extern void
 check_string_starts_with (const char *actual,
 			  const char *expected_prefix);
 
+extern void
+check_string_contains (const char *name,
+		       const char *actual,
+		       const char *expected_substring);
+
 /* Implement framework needed for turning the testcase hooks into an
    executable.  test-combination.c and test-threads.c each combine multiple
    testcases into larger testcases, so we have COMBINED_TEST as a way of
@@ -168,6 +176,31 @@  check_string_starts_with (const char *actual,
 	test, actual, expected_prefix);
 }
 
+void
+check_string_contains (const char *name,
+		       const char *actual,
+		       const char *expected_substring)
+{
+  if (!actual)
+    {
+      fail ("%s: %s: actual: NULL does not contain expected substring: \"%s\"",
+	    test, name, expected_substring);
+      fprintf (stderr, "incorrect value\n");
+      abort ();
+    }
+
+  if (!strstr (actual, expected_substring))
+    {
+      fail ("%s: %s: actual: \"%s\" did not contain expected substring: \"%s\"",
+	    test, name, actual, expected_substring);
+      fprintf (stderr, "incorrect value\n");
+      abort ();
+    }
+
+  pass ("%s: %s: found substring: \"%s\"",
+	test, name, expected_substring);
+}
+
 static void set_options (gcc_jit_context *ctxt, const char *argv0)
 {
   /* Set up options.  */
diff --git a/gcc/testsuite/jit.dg/test-error-unrecognized-dump.c b/gcc/testsuite/jit.dg/test-error-unrecognized-dump.c
new file mode 100644
index 0000000..0b73360
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-unrecognized-dump.c
@@ -0,0 +1,27 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+static char *dump;
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_context_enable_dump (ctxt,
+			       "not-a-valid-dump-switch",
+			       &dump);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "unrecognized dump: not-a-valid-dump-switch");
+}
+
diff --git a/gcc/testsuite/jit.dg/test-functions.c b/gcc/testsuite/jit.dg/test-functions.c
index 3d03ada..45c24d6 100644
--- a/gcc/testsuite/jit.dg/test-functions.c
+++ b/gcc/testsuite/jit.dg/test-functions.c
@@ -167,6 +167,9 @@  create_test_of_builtin_strcmp (gcc_jit_context *ctxt)
   gcc_jit_block_end_with_return (initial, NULL, call);
 }
 
+static char *trig_sincos_dump;
+static char *trig_statistics_dump;
+
 static void
 create_test_of_builtin_trig (gcc_jit_context *ctxt)
 {
@@ -178,6 +181,14 @@  create_test_of_builtin_trig (gcc_jit_context *ctxt)
        }
        (in theory, optimizable to sin (2 * theta))
   */
+
+  gcc_jit_context_enable_dump (ctxt,
+			       "tree-sincos",
+			       &trig_sincos_dump);
+  gcc_jit_context_enable_dump (ctxt,
+			       "statistics",
+			       &trig_statistics_dump);
+
   gcc_jit_type *double_t =
     gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
 
@@ -266,6 +277,22 @@  verify_test_of_builtin_trig (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_2      ),  0.0);
   CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_4 * 3.0), -1.0);
   CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI        ),  0.0);
+
+  /* PR jit/64020:
+     The "sincos" pass merges sin/cos calls into the cexpi builtin.
+     Verify that a dump of the "sincos" pass was provided, and that it
+     shows a call to the cexpi builtin on a SSA name of "theta".  */
+  CHECK_NON_NULL (trig_sincos_dump);
+  CHECK_STRING_CONTAINS (trig_sincos_dump, " = __builtin_cexpi (theta_");
+  free (trig_sincos_dump);
+
+  /* Similarly, verify that the statistics dump was provided, and that
+     it shows the sincos optimization.  */
+  CHECK_NON_NULL (trig_statistics_dump);
+  CHECK_STRING_CONTAINS (
+    trig_statistics_dump,
+    "sincos \"sincos statements inserted\" \"test_of_builtin_trig\" 1");
+  free (trig_statistics_dump);
 }
 
 static void
diff --git a/gcc/testsuite/jit.dg/test-sum-of-squares.c b/gcc/testsuite/jit.dg/test-sum-of-squares.c
index d6fdcf6..46fd5c2 100644
--- a/gcc/testsuite/jit.dg/test-sum-of-squares.c
+++ b/gcc/testsuite/jit.dg/test-sum-of-squares.c
@@ -6,6 +6,8 @@ 
 
 #include "harness.h"
 
+static char *dump_vrp1;
+
 void
 create_code (gcc_jit_context *ctxt, void *user_data)
 {
@@ -22,6 +24,8 @@  create_code (gcc_jit_context *ctxt, void *user_data)
       }
       return sum;
    */
+  gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1);
+
   gcc_jit_type *the_type =
     gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
   gcc_jit_type *return_type = the_type;
@@ -123,4 +127,16 @@  verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   int val = loop_test (10);
   note ("loop_test returned: %d", val);
   CHECK_VALUE (val, 285);
+
+  CHECK_NON_NULL (dump_vrp1);
+  /* PR jit/64166
+     An example of using gcc_jit_context_enable_dump to verify a property
+     of the compile.
+
+     In this case, verify that vrp is able to deduce the
+     bounds of the iteration variable. Specifically, verify that some
+     variable is known to be in the range negative infinity to some
+     expression based on param "n" (actually n-1).  */
+  CHECK_STRING_CONTAINS (dump_vrp1, ": [-INF, n_");
+  free (dump_vrp1);
 }