libgccjit: Add vector permutation and vector access operations

Message ID fedb53cc48e2062a25d9ba401f96735f42b0e9c8.camel@zoho.com
State Changes Requested
Delegated to: David Malcolm
Headers
Series libgccjit: Add vector permutation and vector access operations |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Testing passed

Commit Message

Antoni Boucher Nov. 17, 2023, 10:36 p.m. UTC
  Hi.
This patch adds a vector permutation and vector access operations (bug
112602).

This was split from this patch:
https://gcc.gnu.org/pipermail/jit/2023q1/001606.html

Thanks for the review.
  

Comments

David Malcolm Nov. 20, 2023, 11:05 p.m. UTC | #1
On Fri, 2023-11-17 at 17:36 -0500, Antoni Boucher wrote:
> Hi.
> This patch adds a vector permutation and vector access operations
> (bug
> 112602).
> 
> This was split from this patch:
> https://gcc.gnu.org/pipermail/jit/2023q1/001606.html
> 

Thanks for the patch.

Overall, looks good, but 3 minor nitpicks:

[...snip...]

> diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
> index ebede440ee4..a764e3968d1 100644
> --- a/gcc/jit/docs/topics/compatibility.rst
> +++ b/gcc/jit/docs/topics/compatibility.rst
> @@ -378,3 +378,13 @@ alignment of a variable:
>  --------------------
>  ``LIBGCCJIT_ABI_25`` covers the addition of
>  :func:`gcc_jit_type_get_restrict`
> +
> +
> +.. _LIBGCCJIT_ABI_26:
> +
> +``LIBGCCJIT_ABI_26``
> +--------------------
> +``LIBGCCJIT_ABI_26`` covers the addition of functions to manipulate vectors:
> +
> +  * :func:`gcc_jit_context_new_rvalue_vector_perm`
> +  * :func:`gcc_jit_context_new_vector_access`
> diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
> index 42cfee36302..4a45aa13f5c 100644
> --- a/gcc/jit/docs/topics/expressions.rst
> +++ b/gcc/jit/docs/topics/expressions.rst
> @@ -295,6 +295,35 @@ Vector expressions
>  
>        #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
>  
> +.. function:: gcc_jit_rvalue * \
> +              gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt, \
> +                                                      gcc_jit_location *loc, \
> +                                                      gcc_jit_rvalue *elements1, \
> +                                                      gcc_jit_rvalue *elements2, \
> +                                                      gcc_jit_rvalue *mask);
> +
> +   Build a permutation of two vectors.
> +
> +   "elements1" and "elements2" should have the same type.
> +   The length of "mask" and "elements1" should be the same.
> +   The element type of "mask" should be integral.
> +   The size of the element type of "mask" and "elements1" should be the same.
> +
> +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can test for
                                                       ^^
Should be 26

[...snip...]

>  Unary Operations
>  ****************
>  
> @@ -1020,3 +1049,27 @@ Field access is provided separately for both lvalues and rvalues.
>        PTR[INDEX]
>  
>     in C (or, indeed, to ``PTR + INDEX``).
> +
> +.. function:: gcc_jit_lvalue *\
> +              gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,\
> +                                                 gcc_jit_location *loc,\
> +                                                 gcc_jit_rvalue *vector,\
> +                                                 gcc_jit_rvalue *index)
> +
> +   Given an rvalue of vector type ``T __attribute__ ((__vector_size__ (SIZE)))``, get the element `T` at
> +   the given index.
> +
> +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can test for
                                                       ^^

Likewise here.

[...snip...]

> @@ -4071,6 +4107,79 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
>       (gcc::jit::recording::rvalue **)elements);
>  }
>  
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::context::new_rvalue_vector_perm method, in
> +   jit-recording.cc.  */
> +
> +gcc_jit_rvalue *
> +gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
> +					gcc_jit_location *loc,
> +					gcc_jit_rvalue *elements1,
> +					gcc_jit_rvalue *elements2,
> +					gcc_jit_rvalue *mask)
> +{
> +  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
> +  JIT_LOG_FUNC (ctxt->get_logger ());
> +
> +  /* LOC can be NULL.  */

...but "elements1", "elements2", and "mask" must not be NULL, as
they're dereferenced below.  So this is going to need something like
the following (untested):

  RETURN_NULL_IF_FAIL (elements1, ctxt, loc, "NULL elements1");
  RETURN_NULL_IF_FAIL (elements2, ctxt, loc, "NULL elements2");
  RETURN_NULL_IF_FAIL (mask, ctxt, loc, "NULL mask");

[...snip...]

OK with those fixed.

Thanks
Dave
  
Antoni Boucher Nov. 30, 2023, 10:16 p.m. UTC | #2
All of these are fixed in this new patch.
Thanks for the review.

On Mon, 2023-11-20 at 18:05 -0500, David Malcolm wrote:
> On Fri, 2023-11-17 at 17:36 -0500, Antoni Boucher wrote:
> > Hi.
> > This patch adds a vector permutation and vector access operations
> > (bug
> > 112602).
> > 
> > This was split from this patch:
> > https://gcc.gnu.org/pipermail/jit/2023q1/001606.html
> > 
> 
> Thanks for the patch.
> 
> Overall, looks good, but 3 minor nitpicks:
> 
> [...snip...]
> 
> > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > b/gcc/jit/docs/topics/compatibility.rst
> > index ebede440ee4..a764e3968d1 100644
> > --- a/gcc/jit/docs/topics/compatibility.rst
> > +++ b/gcc/jit/docs/topics/compatibility.rst
> > @@ -378,3 +378,13 @@ alignment of a variable:
> >  --------------------
> >  ``LIBGCCJIT_ABI_25`` covers the addition of
> >  :func:`gcc_jit_type_get_restrict`
> > +
> > +
> > +.. _LIBGCCJIT_ABI_26:
> > +
> > +``LIBGCCJIT_ABI_26``
> > +--------------------
> > +``LIBGCCJIT_ABI_26`` covers the addition of functions to
> > manipulate vectors:
> > +
> > +  * :func:`gcc_jit_context_new_rvalue_vector_perm`
> > +  * :func:`gcc_jit_context_new_vector_access`
> > diff --git a/gcc/jit/docs/topics/expressions.rst
> > b/gcc/jit/docs/topics/expressions.rst
> > index 42cfee36302..4a45aa13f5c 100644
> > --- a/gcc/jit/docs/topics/expressions.rst
> > +++ b/gcc/jit/docs/topics/expressions.rst
> > @@ -295,6 +295,35 @@ Vector expressions
> >  
> >        #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
> >  
> > +.. function:: gcc_jit_rvalue * \
> > +              gcc_jit_context_new_rvalue_vector_perm
> > (gcc_jit_context *ctxt, \
> > +                                                     
> > gcc_jit_location *loc, \
> > +                                                     
> > gcc_jit_rvalue *elements1, \
> > +                                                     
> > gcc_jit_rvalue *elements2, \
> > +                                                     
> > gcc_jit_rvalue *mask);
> > +
> > +   Build a permutation of two vectors.
> > +
> > +   "elements1" and "elements2" should have the same type.
> > +   The length of "mask" and "elements1" should be the same.
> > +   The element type of "mask" should be integral.
> > +   The size of the element type of "mask" and "elements1" should
> > be the same.
> > +
> > +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can
> > test for
>                                                        ^^
> Should be 26
> 
> [...snip...]
> 
> >  Unary Operations
> >  ****************
> >  
> > @@ -1020,3 +1049,27 @@ Field access is provided separately for both
> > lvalues and rvalues.
> >        PTR[INDEX]
> >  
> >     in C (or, indeed, to ``PTR + INDEX``).
> > +
> > +.. function:: gcc_jit_lvalue *\
> > +              gcc_jit_context_new_vector_access (gcc_jit_context
> > *ctxt,\
> > +                                                 gcc_jit_location
> > *loc,\
> > +                                                 gcc_jit_rvalue
> > *vector,\
> > +                                                 gcc_jit_rvalue
> > *index)
> > +
> > +   Given an rvalue of vector type ``T __attribute__
> > ((__vector_size__ (SIZE)))``, get the element `T` at
> > +   the given index.
> > +
> > +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can
> > test for
>                                                        ^^
> 
> Likewise here.
> 
> [...snip...]
> 
> > @@ -4071,6 +4107,79 @@ gcc_jit_context_new_rvalue_from_vector
> > (gcc_jit_context *ctxt,
> >       (gcc::jit::recording::rvalue **)elements);
> >  }
> >  
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::context::new_rvalue_vector_perm method, in
> > +   jit-recording.cc.  */
> > +
> > +gcc_jit_rvalue *
> > +gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
> > +					gcc_jit_location *loc,
> > +					gcc_jit_rvalue *elements1,
> > +					gcc_jit_rvalue *elements2,
> > +					gcc_jit_rvalue *mask)
> > +{
> > +  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
> > +  JIT_LOG_FUNC (ctxt->get_logger ());
> > +
> > +  /* LOC can be NULL.  */
> 
> ...but "elements1", "elements2", and "mask" must not be NULL, as
> they're dereferenced below.  So this is going to need something like
> the following (untested):
> 
>   RETURN_NULL_IF_FAIL (elements1, ctxt, loc, "NULL elements1");
>   RETURN_NULL_IF_FAIL (elements2, ctxt, loc, "NULL elements2");
>   RETURN_NULL_IF_FAIL (mask, ctxt, loc, "NULL mask");
> 
> [...snip...]
> 
> OK with those fixed.
> 
> Thanks
> Dave
>
  
Antoni Boucher Jan. 19, 2024, 8:21 p.m. UTC | #3
David: Ping.

On Thu, 2023-11-30 at 17:16 -0500, Antoni Boucher wrote:
> All of these are fixed in this new patch.
> Thanks for the review.
> 
> On Mon, 2023-11-20 at 18:05 -0500, David Malcolm wrote:
> > On Fri, 2023-11-17 at 17:36 -0500, Antoni Boucher wrote:
> > > Hi.
> > > This patch adds a vector permutation and vector access operations
> > > (bug
> > > 112602).
> > > 
> > > This was split from this patch:
> > > https://gcc.gnu.org/pipermail/jit/2023q1/001606.html
> > > 
> > 
> > Thanks for the patch.
> > 
> > Overall, looks good, but 3 minor nitpicks:
> > 
> > [...snip...]
> > 
> > > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > > b/gcc/jit/docs/topics/compatibility.rst
> > > index ebede440ee4..a764e3968d1 100644
> > > --- a/gcc/jit/docs/topics/compatibility.rst
> > > +++ b/gcc/jit/docs/topics/compatibility.rst
> > > @@ -378,3 +378,13 @@ alignment of a variable:
> > >  --------------------
> > >  ``LIBGCCJIT_ABI_25`` covers the addition of
> > >  :func:`gcc_jit_type_get_restrict`
> > > +
> > > +
> > > +.. _LIBGCCJIT_ABI_26:
> > > +
> > > +``LIBGCCJIT_ABI_26``
> > > +--------------------
> > > +``LIBGCCJIT_ABI_26`` covers the addition of functions to
> > > manipulate vectors:
> > > +
> > > +  * :func:`gcc_jit_context_new_rvalue_vector_perm`
> > > +  * :func:`gcc_jit_context_new_vector_access`
> > > diff --git a/gcc/jit/docs/topics/expressions.rst
> > > b/gcc/jit/docs/topics/expressions.rst
> > > index 42cfee36302..4a45aa13f5c 100644
> > > --- a/gcc/jit/docs/topics/expressions.rst
> > > +++ b/gcc/jit/docs/topics/expressions.rst
> > > @@ -295,6 +295,35 @@ Vector expressions
> > >  
> > >        #ifdef
> > > LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
> > >  
> > > +.. function:: gcc_jit_rvalue * \
> > > +              gcc_jit_context_new_rvalue_vector_perm
> > > (gcc_jit_context *ctxt, \
> > > +                                                     
> > > gcc_jit_location *loc, \
> > > +                                                     
> > > gcc_jit_rvalue *elements1, \
> > > +                                                     
> > > gcc_jit_rvalue *elements2, \
> > > +                                                     
> > > gcc_jit_rvalue *mask);
> > > +
> > > +   Build a permutation of two vectors.
> > > +
> > > +   "elements1" and "elements2" should have the same type.
> > > +   The length of "mask" and "elements1" should be the same.
> > > +   The element type of "mask" should be integral.
> > > +   The size of the element type of "mask" and "elements1" should
> > > be the same.
> > > +
> > > +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can
> > > test for
> >                                                        ^^
> > Should be 26
> > 
> > [...snip...]
> > 
> > >  Unary Operations
> > >  ****************
> > >  
> > > @@ -1020,3 +1049,27 @@ Field access is provided separately for
> > > both
> > > lvalues and rvalues.
> > >        PTR[INDEX]
> > >  
> > >     in C (or, indeed, to ``PTR + INDEX``).
> > > +
> > > +.. function:: gcc_jit_lvalue *\
> > > +              gcc_jit_context_new_vector_access (gcc_jit_context
> > > *ctxt,\
> > > +                                                
> > > gcc_jit_location
> > > *loc,\
> > > +                                                 gcc_jit_rvalue
> > > *vector,\
> > > +                                                 gcc_jit_rvalue
> > > *index)
> > > +
> > > +   Given an rvalue of vector type ``T __attribute__
> > > ((__vector_size__ (SIZE)))``, get the element `T` at
> > > +   the given index.
> > > +
> > > +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can
> > > test for
> >                                                        ^^
> > 
> > Likewise here.
> > 
> > [...snip...]
> > 
> > > @@ -4071,6 +4107,79 @@ gcc_jit_context_new_rvalue_from_vector
> > > (gcc_jit_context *ctxt,
> > >       (gcc::jit::recording::rvalue **)elements);
> > >  }
> > >  
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::context::new_rvalue_vector_perm method,
> > > in
> > > +   jit-recording.cc.  */
> > > +
> > > +gcc_jit_rvalue *
> > > +gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
> > > +					gcc_jit_location *loc,
> > > +					gcc_jit_rvalue
> > > *elements1,
> > > +					gcc_jit_rvalue
> > > *elements2,
> > > +					gcc_jit_rvalue *mask)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
> > > +  JIT_LOG_FUNC (ctxt->get_logger ());
> > > +
> > > +  /* LOC can be NULL.  */
> > 
> > ...but "elements1", "elements2", and "mask" must not be NULL, as
> > they're dereferenced below.  So this is going to need something
> > like
> > the following (untested):
> > 
> >   RETURN_NULL_IF_FAIL (elements1, ctxt, loc, "NULL elements1");
> >   RETURN_NULL_IF_FAIL (elements2, ctxt, loc, "NULL elements2");
> >   RETURN_NULL_IF_FAIL (mask, ctxt, loc, "NULL mask");
> > 
> > [...snip...]
> > 
> > OK with those fixed.
> > 
> > Thanks
> > Dave
> > 
>
  
Antoni Boucher Feb. 17, 2024, 4:54 p.m. UTC | #4
David: Ping.

On Fri, 2024-01-19 at 15:21 -0500, Antoni Boucher wrote:
> David: Ping.
> 
> On Thu, 2023-11-30 at 17:16 -0500, Antoni Boucher wrote:
> > All of these are fixed in this new patch.
> > Thanks for the review.
> > 
> > On Mon, 2023-11-20 at 18:05 -0500, David Malcolm wrote:
> > > On Fri, 2023-11-17 at 17:36 -0500, Antoni Boucher wrote:
> > > > Hi.
> > > > This patch adds a vector permutation and vector access
> > > > operations
> > > > (bug
> > > > 112602).
> > > > 
> > > > This was split from this patch:
> > > > https://gcc.gnu.org/pipermail/jit/2023q1/001606.html
> > > > 
> > > 
> > > Thanks for the patch.
> > > 
> > > Overall, looks good, but 3 minor nitpicks:
> > > 
> > > [...snip...]
> > > 
> > > > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > > > b/gcc/jit/docs/topics/compatibility.rst
> > > > index ebede440ee4..a764e3968d1 100644
> > > > --- a/gcc/jit/docs/topics/compatibility.rst
> > > > +++ b/gcc/jit/docs/topics/compatibility.rst
> > > > @@ -378,3 +378,13 @@ alignment of a variable:
> > > >  --------------------
> > > >  ``LIBGCCJIT_ABI_25`` covers the addition of
> > > >  :func:`gcc_jit_type_get_restrict`
> > > > +
> > > > +
> > > > +.. _LIBGCCJIT_ABI_26:
> > > > +
> > > > +``LIBGCCJIT_ABI_26``
> > > > +--------------------
> > > > +``LIBGCCJIT_ABI_26`` covers the addition of functions to
> > > > manipulate vectors:
> > > > +
> > > > +  * :func:`gcc_jit_context_new_rvalue_vector_perm`
> > > > +  * :func:`gcc_jit_context_new_vector_access`
> > > > diff --git a/gcc/jit/docs/topics/expressions.rst
> > > > b/gcc/jit/docs/topics/expressions.rst
> > > > index 42cfee36302..4a45aa13f5c 100644
> > > > --- a/gcc/jit/docs/topics/expressions.rst
> > > > +++ b/gcc/jit/docs/topics/expressions.rst
> > > > @@ -295,6 +295,35 @@ Vector expressions
> > > >  
> > > >        #ifdef
> > > > LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
> > > >  
> > > > +.. function:: gcc_jit_rvalue * \
> > > > +              gcc_jit_context_new_rvalue_vector_perm
> > > > (gcc_jit_context *ctxt, \
> > > > +                                                     
> > > > gcc_jit_location *loc, \
> > > > +                                                     
> > > > gcc_jit_rvalue *elements1, \
> > > > +                                                     
> > > > gcc_jit_rvalue *elements2, \
> > > > +                                                     
> > > > gcc_jit_rvalue *mask);
> > > > +
> > > > +   Build a permutation of two vectors.
> > > > +
> > > > +   "elements1" and "elements2" should have the same type.
> > > > +   The length of "mask" and "elements1" should be the same.
> > > > +   The element type of "mask" should be integral.
> > > > +   The size of the element type of "mask" and "elements1"
> > > > should
> > > > be the same.
> > > > +
> > > > +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you
> > > > can
> > > > test for
> > >                                                        ^^
> > > Should be 26
> > > 
> > > [...snip...]
> > > 
> > > >  Unary Operations
> > > >  ****************
> > > >  
> > > > @@ -1020,3 +1049,27 @@ Field access is provided separately for
> > > > both
> > > > lvalues and rvalues.
> > > >        PTR[INDEX]
> > > >  
> > > >     in C (or, indeed, to ``PTR + INDEX``).
> > > > +
> > > > +.. function:: gcc_jit_lvalue *\
> > > > +              gcc_jit_context_new_vector_access
> > > > (gcc_jit_context
> > > > *ctxt,\
> > > > +                                                
> > > > gcc_jit_location
> > > > *loc,\
> > > > +                                                
> > > > gcc_jit_rvalue
> > > > *vector,\
> > > > +                                                
> > > > gcc_jit_rvalue
> > > > *index)
> > > > +
> > > > +   Given an rvalue of vector type ``T __attribute__
> > > > ((__vector_size__ (SIZE)))``, get the element `T` at
> > > > +   the given index.
> > > > +
> > > > +   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you
> > > > can
> > > > test for
> > >                                                        ^^
> > > 
> > > Likewise here.
> > > 
> > > [...snip...]
> > > 
> > > > @@ -4071,6 +4107,79 @@ gcc_jit_context_new_rvalue_from_vector
> > > > (gcc_jit_context *ctxt,
> > > >       (gcc::jit::recording::rvalue **)elements);
> > > >  }
> > > >  
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::context::new_rvalue_vector_perm
> > > > method,
> > > > in
> > > > +   jit-recording.cc.  */
> > > > +
> > > > +gcc_jit_rvalue *
> > > > +gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
> > > > +					gcc_jit_location *loc,
> > > > +					gcc_jit_rvalue
> > > > *elements1,
> > > > +					gcc_jit_rvalue
> > > > *elements2,
> > > > +					gcc_jit_rvalue *mask)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
> > > > +  JIT_LOG_FUNC (ctxt->get_logger ());
> > > > +
> > > > +  /* LOC can be NULL.  */
> > > 
> > > ...but "elements1", "elements2", and "mask" must not be NULL, as
> > > they're dereferenced below.  So this is going to need something
> > > like
> > > the following (untested):
> > > 
> > >   RETURN_NULL_IF_FAIL (elements1, ctxt, loc, "NULL elements1");
> > >   RETURN_NULL_IF_FAIL (elements2, ctxt, loc, "NULL elements2");
> > >   RETURN_NULL_IF_FAIL (mask, ctxt, loc, "NULL mask");
> > > 
> > > [...snip...]
> > > 
> > > OK with those fixed.
> > > 
> > > Thanks
> > > Dave
> > > 
> > 
>
  

Patch

From 25b386334f22845d7ba1b60658730373eb6ddbb3 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Fri, 17 Nov 2023 17:23:28 -0500
Subject: [PATCH] libgccjit: Add vector permutation and vector access
 operations

gcc/jit/ChangeLog:
	PR jit/112602
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): New ABI tag.
	* docs/topics/expressions.rst: Document
	gcc_jit_context_new_rvalue_vector_perm and
	gcc_jit_context_new_vector_access.
	* jit-playback.cc (playback::context::new_rvalue_vector_perm,
	common_mark_addressable_vec,
	gnu_vector_type_p,
	lvalue_p,
	convert_vector_to_array_for_subscript,
	new_vector_access): new functions.
	* jit-playback.h (new_rvalue_vector_perm, new_vector_access):
	New functions.
	* jit-recording.cc (recording::context::new_rvalue_vector_perm,
	recording::context::new_vector_access,
	memento_of_new_rvalue_vector_perm,
	recording::memento_of_new_rvalue_vector_perm::replay_into,
	recording::memento_of_new_rvalue_vector_perm::visit_children,
	recording::memento_of_new_rvalue_vector_perm::make_debug_string,
	recording::memento_of_new_rvalue_vector_perm::write_reproducer,
	recording::vector_access::replay_into,
	recording::vector_access::visit_children,
	recording::vector_access::make_debug_string,
	recording::vector_access::write_reproducer): New methods.
	* jit-recording.h (class memento_of_new_rvalue_vector_perm,
	class vector_access): New classes.
	* libgccjit.cc (gcc_jit_context_new_vector_access,
	gcc_jit_context_new_rvalue_vector_perm): New functions.
	* libgccjit.h (gcc_jit_context_new_rvalue_vector_perm,
	gcc_jit_context_new_vector_access): New functions.
	* libgccjit.map: New functions.

gcc/testsuite/ChangeLog:
	PR jit/112602
	* jit.dg/all-non-failing-tests.h: New test test-vector-perm.c.
	* jit.dg/test-vector-perm.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  10 ++
 gcc/jit/docs/topics/expressions.rst          |  53 ++++++
 gcc/jit/jit-playback.cc                      | 150 ++++++++++++++++
 gcc/jit/jit-playback.h                       |  11 ++
 gcc/jit/jit-recording.cc                     | 169 +++++++++++++++++++
 gcc/jit/jit-recording.h                      |  72 ++++++++
 gcc/jit/libgccjit.cc                         | 109 ++++++++++++
 gcc/jit/libgccjit.h                          |  29 ++++
 gcc/jit/libgccjit.map                        |   6 +
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  12 +-
 gcc/testsuite/jit.dg/test-vector-perm.c      |  96 +++++++++++
 11 files changed, 716 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-vector-perm.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index ebede440ee4..a764e3968d1 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -378,3 +378,13 @@  alignment of a variable:
 --------------------
 ``LIBGCCJIT_ABI_25`` covers the addition of
 :func:`gcc_jit_type_get_restrict`
+
+
+.. _LIBGCCJIT_ABI_26:
+
+``LIBGCCJIT_ABI_26``
+--------------------
+``LIBGCCJIT_ABI_26`` covers the addition of functions to manipulate vectors:
+
+  * :func:`gcc_jit_context_new_rvalue_vector_perm`
+  * :func:`gcc_jit_context_new_vector_access`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 42cfee36302..4a45aa13f5c 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -295,6 +295,35 @@  Vector expressions
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
 
+.. function:: gcc_jit_rvalue * \
+              gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt, \
+                                                      gcc_jit_location *loc, \
+                                                      gcc_jit_rvalue *elements1, \
+                                                      gcc_jit_rvalue *elements2, \
+                                                      gcc_jit_rvalue *mask);
+
+   Build a permutation of two vectors.
+
+   "elements1" and "elements2" should have the same type.
+   The length of "mask" and "elements1" should be the same.
+   The element type of "mask" should be integral.
+   The size of the element type of "mask" and "elements1" should be the same.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+
+    Analogous to:
+
+    .. code-block:: c
+
+       __builtin_shuffle (elements1, elements2, mask)
+
+    in C.
+
 Unary Operations
 ****************
 
@@ -1020,3 +1049,27 @@  Field access is provided separately for both lvalues and rvalues.
       PTR[INDEX]
 
    in C (or, indeed, to ``PTR + INDEX``).
+
+.. function:: gcc_jit_lvalue *\
+              gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,\
+                                                 gcc_jit_location *loc,\
+                                                 gcc_jit_rvalue *vector,\
+                                                 gcc_jit_rvalue *index)
+
+   Given an rvalue of vector type ``T __attribute__ ((__vector_size__ (SIZE)))``, get the element `T` at
+   the given index.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+
+   Analogous to:
+
+   .. code-block:: c
+
+      VECTOR[INDEX]
+
+   in C.
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 18cc4da25b8..1aba0fb4a28 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -1011,6 +1011,26 @@  playback::context::new_rvalue_from_vector (location *,
   return new rvalue (this, t_ctor);
 }
 
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+   vector perm.  */
+
+playback::rvalue *
+playback::context::new_rvalue_vector_perm (location *loc,
+					   rvalue* elements1,
+					   rvalue* elements2,
+					   rvalue* mask)
+{
+  tree t_elements1 = elements1->as_tree ();
+  tree t_elements2 = elements2->as_tree ();
+  tree t_mask = mask->as_tree ();
+
+  tree t_vector_perm = build3 (VEC_PERM_EXPR, TREE_TYPE (t_elements1),
+			       t_elements1, t_elements2, t_mask);
+  if (loc)
+    set_tree_location (t_vector_perm, loc);
+  return new rvalue (this, t_vector_perm);
+}
+
 /* Coerce a tree expression into a boolean tree expression.  */
 
 tree
@@ -1527,6 +1547,136 @@  new_array_access (location *loc,
     }
 }
 
+/* The following functions come from c-common.h.  */
+/* Like c_mark_addressable but don't check register qualifier.  */
+void
+common_mark_addressable_vec (tree t)
+{
+  while (handled_component_p (t) || TREE_CODE (t) == C_MAYBE_CONST_EXPR)
+    {
+      t = TREE_OPERAND (t, 0);
+    }
+  if (!VAR_P (t)
+      && TREE_CODE (t) != PARM_DECL
+      && TREE_CODE (t) != COMPOUND_LITERAL_EXPR
+      && TREE_CODE (t) != TARGET_EXPR)
+    return;
+  if (!VAR_P (t) || !DECL_HARD_REGISTER (t))
+    TREE_ADDRESSABLE (t) = 1;
+  if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR)
+    TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (t)) = 1;
+  else if (TREE_CODE (t) == TARGET_EXPR)
+    TREE_ADDRESSABLE (TARGET_EXPR_SLOT (t)) = 1;
+}
+
+/* Return true if TYPE is a vector type that should be subject to the GNU
+   vector extensions (as opposed to a vector type that is used only for
+   the purposes of defining target-specific built-in functions).  */
+
+inline bool
+gnu_vector_type_p (const_tree type)
+{
+  return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type);
+}
+
+/* Return nonzero if REF is an lvalue valid for this language.
+   Lvalues can be assigned, unless their type has TYPE_READONLY.
+   Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
+
+bool
+lvalue_p (const_tree ref)
+{
+  const enum tree_code code = TREE_CODE (ref);
+
+  switch (code)
+    {
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case COMPONENT_REF:
+      return lvalue_p (TREE_OPERAND (ref, 0));
+
+    case C_MAYBE_CONST_EXPR:
+      return lvalue_p (TREE_OPERAND (ref, 1));
+
+    case COMPOUND_LITERAL_EXPR:
+    case STRING_CST:
+      return true;
+
+    case MEM_REF:
+    case TARGET_MEM_REF:
+      /* MEM_REFs can appear from -fgimple parsing or folding, so allow them
+	 here as well.  */
+    case INDIRECT_REF:
+    case ARRAY_REF:
+    case VAR_DECL:
+    case PARM_DECL:
+    case RESULT_DECL:
+    case ERROR_MARK:
+      return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
+	      && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
+
+    case BIND_EXPR:
+      return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
+
+    default:
+      return false;
+    }
+}
+
+bool
+convert_vector_to_array_for_subscript (tree *vecp)
+{
+  bool ret = false;
+  if (gnu_vector_type_p (TREE_TYPE (*vecp)))
+    {
+      tree type = TREE_TYPE (*vecp);
+
+      ret = !lvalue_p (*vecp);
+
+      /* We are building an ARRAY_REF so mark the vector as addressable
+	to not run into the gimplifiers premature setting of DECL_GIMPLE_REG_P
+	 for function parameters.  */
+      /* NOTE: that was the missing piece for making vector access work with
+	optimizations enabled.  */
+      common_mark_addressable_vec (*vecp);
+
+      *vecp = build1 (VIEW_CONVERT_EXPR,
+		      build_array_type_nelts (TREE_TYPE (type),
+					      TYPE_VECTOR_SUBPARTS (type)),
+		      *vecp);
+    }
+  return ret;
+}
+
+/* Construct a playback::lvalue instance (wrapping a tree) for a
+   vector access.  */
+
+playback::lvalue *
+playback::context::
+new_vector_access (location *loc,
+		   rvalue *vector,
+		   rvalue *index)
+{
+  gcc_assert (vector);
+  gcc_assert (index);
+
+  /* For comparison, see:
+       c/c-typeck.cc: build_array_ref
+  */
+
+  tree t_vector = vector->as_tree ();
+  bool non_lvalue = convert_vector_to_array_for_subscript (&t_vector);
+  tree type = TREE_TYPE (TREE_TYPE (t_vector));
+  tree t_result = build4 (ARRAY_REF, type, t_vector, index->as_tree (),
+			  NULL_TREE, NULL_TREE);
+  if (non_lvalue)
+    t_result = non_lvalue (t_result);
+
+  if (loc)
+    set_tree_location (t_result, loc);
+  return new lvalue (this, t_result);
+}
+
 /* Construct a tree for a field access.  */
 
 tree
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index f9e29d0baec..a2d99331dbe 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -147,6 +147,12 @@  public:
 			  type *type,
 			  const auto_vec<rvalue *> &elements);
 
+  rvalue *
+  new_rvalue_vector_perm (location *loc,
+			  rvalue* elements1,
+			  rvalue* elements2,
+			  rvalue* mask);
+
   rvalue *
   new_unary_op (location *loc,
 		enum gcc_jit_unary_op op,
@@ -191,6 +197,11 @@  public:
 		    rvalue *ptr,
 		    rvalue *index);
 
+  lvalue *
+  new_vector_access (location *loc,
+		     rvalue *vector,
+		     rvalue *index);
+
   void
   set_str_option (enum gcc_jit_str_option opt,
 		  const char *value);
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 9b5b8005ebe..cf1319ec3bb 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -1108,6 +1108,19 @@  recording::context::new_rvalue_from_vector (location *loc,
   return result;
 }
 
+recording::rvalue *
+recording::context::new_rvalue_vector_perm (location *loc,
+			  rvalue *elements1,
+			  rvalue *elements2,
+			  rvalue *mask)
+{
+  recording::rvalue *result
+    = new memento_of_new_rvalue_vector_perm (this, loc, elements1, elements2,
+					     mask);
+  record (result);
+  return result;
+}
+
 recording::rvalue *
 recording::context::new_ctor (recording::location *loc,
 			      recording::type *type,
@@ -1309,6 +1322,22 @@  recording::context::new_array_access (recording::location *loc,
   return result;
 }
 
+/* Create a recording::vector_access instance and add it to this context's list
+   of mementos.
+
+   Implements the post-error-checking part of
+   gcc_jit_context_new_vector_access.  */
+
+recording::lvalue *
+recording::context::new_vector_access (recording::location *loc,
+				      recording::rvalue *vector,
+				      recording::rvalue *index)
+{
+  recording::lvalue *result = new vector_access (this, loc, vector, index);
+  record (result);
+  return result;
+}
+
 /* Create a recording::case_ instance and add it to this context's list
    of mementos.
 
@@ -5437,6 +5466,90 @@  recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
 	   elements_id);
 }
 
+/* The implementation of class
+   gcc::jit::recording::memento_of_new_rvalue_vector_perm.  */
+
+/* The constructor for
+   gcc::jit::recording::memento_of_new_rvalue_vector_perm.  */
+
+recording::memento_of_new_rvalue_vector_perm::
+memento_of_new_rvalue_vector_perm (context *ctxt,
+				   location *loc,
+				   rvalue *elements1,
+				   rvalue *elements2,
+				   rvalue *mask)
+: rvalue (ctxt, loc, elements1->get_type ()),
+  m_elements1 (elements1),
+  m_elements2 (elements2),
+  m_mask (mask)
+{
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+   for recording::memento_of_new_rvalue_vector_perm.  */
+
+void
+recording::memento_of_new_rvalue_vector_perm::replay_into (replayer *r)
+{
+  playback::rvalue *playback_elements1 = m_elements1->playback_rvalue ();
+  playback::rvalue *playback_elements2 = m_elements2->playback_rvalue ();
+  playback::rvalue *playback_mask = m_mask->playback_rvalue ();
+
+  set_playback_obj (r->new_rvalue_vector_perm (playback_location (r, m_loc),
+		    playback_elements1,
+		    playback_elements2,
+		    playback_mask));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+   for recording::memento_of_new_rvalue_from_vector.  */
+
+    void
+recording::memento_of_new_rvalue_vector_perm::visit_children (rvalue_visitor *v)
+{
+  v->visit (m_elements1);
+  v->visit (m_elements2);
+  v->visit (m_mask);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+   vectors.  */
+
+    recording::string *
+recording::memento_of_new_rvalue_vector_perm::make_debug_string ()
+{
+    /* Now build a string.  */
+    string *result = string::from_printf (m_ctxt,
+		"shufflevector (%s, %s, %s)",
+		m_elements1->get_debug_string (),
+		m_elements2->get_debug_string (),
+		m_mask->get_debug_string ());
+
+    return result;
+
+}
+
+/* Implementation of recording::memento::write_reproducer for
+   vectors.  */
+
+    void
+recording::memento_of_new_rvalue_vector_perm::write_reproducer (reproducer &r)
+{
+    const char *id = r.make_identifier (this, "vector");
+  r.write ("  gcc_jit_rvalue *%s =\n"
+	   "    gcc_jit_context_new_rvalue_vector_perm (%s, /* gcc_jit_context *ctxt */\n"
+	   "                                            %s, /* gcc_jit_location *loc */\n"
+	   "                                            %s, /* gcc_jit_rvalue **elements1*/\n"
+	   "                                            %s, /* gcc_jit_rvalue **elements2*/\n"
+	   "                                            %s); /* gcc_jit_rvalue **mask*/\n",
+	   id,
+	   r.get_identifier (get_context ()),
+	   r.get_identifier (m_loc),
+	   r.get_identifier_as_rvalue (m_elements1),
+	   r.get_identifier_as_rvalue (m_elements2),
+	   r.get_identifier_as_rvalue (m_mask));
+}
+
 void
 recording::ctor::visit_children (rvalue_visitor *v)
 {
@@ -6307,6 +6420,62 @@  recording::array_access::write_reproducer (reproducer &r)
 	   r.get_identifier_as_rvalue (m_index));
 }
 
+/* The implementation of class gcc::jit::recording::vector_access.  */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+   for recording::vector_access.  */
+
+void
+recording::vector_access::replay_into (replayer *r)
+{
+  set_playback_obj (
+    r->new_vector_access (playback_location (r, m_loc),
+			  m_vector->playback_rvalue (),
+			  m_index->playback_rvalue ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+   for recording::vector_access.  */
+
+void
+recording::vector_access::visit_children (rvalue_visitor *v)
+{
+  v->visit (m_vector);
+  v->visit (m_index);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+   array accesses.  */
+
+recording::string *
+recording::vector_access::make_debug_string ()
+{
+  enum precedence prec = get_precedence ();
+  return string::from_printf (m_ctxt,
+			      "%s[%s]",
+			      m_vector->get_debug_string_parens (prec),
+			      m_index->get_debug_string_parens (prec));
+}
+
+/* Implementation of recording::memento::write_reproducer for
+   vector_access.  */
+
+void
+recording::vector_access::write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "lvalue");
+  r.write ("  gcc_jit_lvalue *%s = \n"
+	   "    gcc_jit_context_new_vector_access (%s, /* gcc_jit_context *ctxt */\n"
+	   "                                       %s, /*gcc_jit_location *loc */\n"
+	   "                                       %s, /* gcc_jit_rvalue *vector */\n"
+	   "                                       %s); /* gcc_jit_rvalue *index */\n",
+	   id,
+	   r.get_identifier (get_context ()),
+	   r.get_identifier (m_loc),
+	   r.get_identifier_as_rvalue (m_vector),
+	   r.get_identifier_as_rvalue (m_index));
+}
+
 /* The implementation of class gcc::jit::recording::access_field_of_lvalue.  */
 
 /* Implementation of pure virtual hook recording::memento::replay_into
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 4a8082991fb..8669fdeb4a2 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -173,6 +173,12 @@  public:
 			  vector_type *type,
 			  rvalue **elements);
 
+  rvalue *
+  new_rvalue_vector_perm (location *loc,
+			  rvalue *elements1,
+			  rvalue *elements2,
+			  rvalue *mask);
+
   rvalue *
   new_unary_op (location *loc,
 		enum gcc_jit_unary_op op,
@@ -215,6 +221,11 @@  public:
 		    rvalue *ptr,
 		    rvalue *index);
 
+  lvalue *
+  new_vector_access (location *loc,
+		     rvalue *vector,
+		     rvalue *index);
+
   case_ *
   new_case (rvalue *min_value,
 	    rvalue *max_value,
@@ -810,6 +821,10 @@  public:
 
   void replay_into (replayer *) final override;
 
+  vector_type *dyn_cast_vector_type () final override {
+    return m_other_type->dyn_cast_vector_type ();
+  }
+
 private:
   string * make_debug_string () final override;
   void write_reproducer (reproducer &r) final override;
@@ -1625,6 +1640,33 @@  private:
   auto_vec<rvalue *> m_elements;
 };
 
+class memento_of_new_rvalue_vector_perm : public rvalue
+{
+public:
+  memento_of_new_rvalue_vector_perm (context *ctxt,
+				     location *loc,
+				     rvalue *elements1,
+				     rvalue *elements2,
+				     rvalue *mask);
+
+  void replay_into (replayer *r) final override;
+
+  void visit_children (rvalue_visitor *) final override;
+
+private:
+  string * make_debug_string () final override;
+  void write_reproducer (reproducer &r) final override;
+  enum precedence get_precedence () const final override
+  {
+    return PRECEDENCE_PRIMARY;
+  }
+
+private:
+  rvalue *m_elements1;
+  rvalue *m_elements2;
+  rvalue *m_mask;
+};
+
 class ctor : public rvalue
 {
 public:
@@ -1907,6 +1949,36 @@  private:
   rvalue *m_index;
 };
 
+class vector_access : public lvalue
+{
+public:
+  vector_access (context *ctxt,
+		 location *loc,
+		 rvalue *vector,
+		 rvalue *index)
+  : lvalue (ctxt, loc, vector->get_type ()->dyn_cast_vector_type ()
+			     ->get_element_type ()),
+    m_vector (vector),
+    m_index (index)
+  {}
+
+  void replay_into (replayer *r) final override;
+
+  void visit_children (rvalue_visitor *v) final override;
+
+private:
+  string * make_debug_string () final override;
+  void write_reproducer (reproducer &r) final override;
+  enum precedence get_precedence () const final override
+  {
+    return PRECEDENCE_POSTFIX;
+  }
+
+private:
+  rvalue *m_vector;
+  rvalue *m_index;
+};
+
 class access_field_of_lvalue : public lvalue
 {
 public:
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 0451b4df7f9..3123e6075ec 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -2437,6 +2437,9 @@  gcc_jit_context_new_cast (gcc_jit_context *ctxt,
   /* LOC can be NULL.  */
   RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
   RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->dyn_cast_vector_type ();
+  RETURN_NULL_IF_FAIL (vector_type == NULL, ctxt, loc,
+		       "cannot cast vector types");
   RETURN_NULL_IF_FAIL_PRINTF3 (
     is_valid_cast (rvalue->get_type (), type),
     ctxt, loc,
@@ -2503,6 +2506,39 @@  gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
   return (gcc_jit_lvalue *)ctxt->new_array_access (loc, ptr, index);
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::context::new_vector_access method in
+   jit-recording.cc.  */
+
+extern gcc_jit_lvalue *
+gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,
+				   gcc_jit_location *loc,
+				   gcc_jit_rvalue *vector,
+				   gcc_jit_rvalue *index)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  /* LOC can be NULL.  */
+  RETURN_NULL_IF_FAIL (vector, ctxt, loc, "NULL vector");
+  RETURN_NULL_IF_FAIL (index, ctxt, loc, "NULL index");
+  RETURN_NULL_IF_FAIL_PRINTF2 (
+    vector->get_type ()->dyn_cast_vector_type (),
+    ctxt, loc,
+    "vector: %s (type: %s) is not a vector",
+    vector->get_debug_string (),
+    vector->get_type ()->get_debug_string ());
+  RETURN_NULL_IF_FAIL_PRINTF2 (
+    index->get_type ()->is_numeric (),
+    ctxt, loc,
+    "index: %s (type: %s) is not of numeric type",
+    index->get_debug_string (),
+    index->get_type ()->get_debug_string ());
+
+  return (gcc_jit_lvalue *)ctxt->new_vector_access (loc, vector, index);
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -4071,6 +4107,79 @@  gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
      (gcc::jit::recording::rvalue **)elements);
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::context::new_rvalue_vector_perm method, in
+   jit-recording.cc.  */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
+					gcc_jit_location *loc,
+					gcc_jit_rvalue *elements1,
+					gcc_jit_rvalue *elements2,
+					gcc_jit_rvalue *mask)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+
+  /* LOC can be NULL.  */
+
+  gcc::jit::recording::type *elements1_type = elements1->get_type ();
+  gcc::jit::recording::type *elements2_type = elements2->get_type ();
+  RETURN_NULL_IF_FAIL_PRINTF4 (
+    compatible_types (elements1->get_type ()->unqualified (),
+		      elements2->get_type ()->unqualified ()),
+    ctxt, loc,
+    "mismatching types for vector perm:"
+    " elements1: %s (type: %s) elements2: %s (type: %s)",
+    elements1->get_debug_string (),
+    elements1_type->get_debug_string (),
+    elements2->get_debug_string (),
+    elements2_type->get_debug_string ());
+
+  gcc::jit::recording::type *mask_type = mask->get_type ();
+  gcc::jit::recording::vector_type *mask_vector_type =
+    mask_type->dyn_cast_vector_type ();
+  gcc::jit::recording::vector_type *elements1_vector_type =
+    elements1_type->dyn_cast_vector_type ();
+
+  size_t mask_len = mask_vector_type->get_num_units ();
+  size_t elements1_len = elements1_vector_type->get_num_units ();
+
+  RETURN_NULL_IF_FAIL_PRINTF2 (
+    mask_len == elements1_len,
+    ctxt, loc,
+    "mismatching length for mask:"
+    " elements1 length: %ld mask length: %ld",
+    mask_len,
+    elements1_len);
+
+  gcc::jit::recording::type *mask_element_type =
+    mask_vector_type->get_element_type ();
+
+  RETURN_NULL_IF_FAIL (
+    mask_element_type->is_int (),
+    ctxt, loc,
+    "elements of mask must be of an integer type");
+
+  gcc::jit::recording::type *elements1_element_type =
+    elements1_vector_type->get_element_type ();
+  size_t mask_element_size = mask_element_type->get_size ();
+  size_t elements1_element_size = elements1_element_type->get_size ();
+
+  RETURN_NULL_IF_FAIL_PRINTF2 (
+    mask_element_size == elements1_element_size,
+    ctxt, loc,
+    "mismatching size for mask element type:"
+    " elements1 element type: %ld mask element type: %ld",
+    mask_element_size,
+    elements1_element_size);
+
+  return (gcc_jit_rvalue *)ctxt->new_rvalue_vector_perm (loc, elements1,
+							 elements2, mask);
+}
+
 /* A mutex around the cached state in parse_basever.
    Ideally this would be within parse_basever, but the mutex is only needed
    by libgccjit.  */
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 749f6c24177..3a8af99a994 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1301,6 +1301,35 @@  gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
 				  gcc_jit_rvalue *ptr,
 				  gcc_jit_rvalue *index);
 
+/* Build a permutation vector rvalue from an 3 arrays of elements.
+
+   "vec_type" should be a vector type, created using gcc_jit_type_get_vector.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_26; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+*/
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
+					gcc_jit_location *loc,
+					gcc_jit_rvalue *elements1,
+					gcc_jit_rvalue *elements2,
+					gcc_jit_rvalue *mask);
+
+#define LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+
+/* Get the element at INDEX in VECTOR.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_26; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+*/
+extern gcc_jit_lvalue *
+gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,
+				   gcc_jit_location *loc,
+				   gcc_jit_rvalue *vector,
+				   gcc_jit_rvalue *index);
+
 /* Field access is provided separately for both lvalues and rvalues.  */
 
 /* Accessing a field of an lvalue of struct type, analogous to:
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 8b90a0e2ff3..510c9386d7a 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -276,3 +276,9 @@  LIBGCCJIT_ABI_25 {
   global:
     gcc_jit_type_get_restrict;
 } LIBGCCJIT_ABI_24;
+
+LIBGCCJIT_ABI_26 {
+  global:
+    gcc_jit_context_new_vector_access;
+    gcc_jit_context_new_rvalue_vector_perm;
+} LIBGCCJIT_ABI_25;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index e762563f9bd..8dbb582df61 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -377,6 +377,13 @@ 
 #undef create_code
 #undef verify_code
 
+/* test-vector-perm.c */
+#define create_code create_code_vector_perm
+#define verify_code verify_code_vector_perm
+#include "test-vector-perm.c"
+#undef create_code
+#undef verify_code
+
 /* Now expose the individual testcases as instances of this struct.  */
 
 struct testcase
@@ -529,7 +536,10 @@  const struct testcase testcases[] = {
    verify_code_version},
   {"volatile",
    create_code_volatile,
-   verify_code_volatile}
+   verify_code_volatile},
+  {"vector_perm",
+   create_code_vector_perm,
+   verify_code_vector_perm},
 };
 
 const int num_testcases = (sizeof (testcases) / sizeof (testcases[0]));
diff --git a/gcc/testsuite/jit.dg/test-vector-perm.c b/gcc/testsuite/jit.dg/test-vector-perm.c
new file mode 100644
index 00000000000..7cf193b1ef3
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-vector-perm.c
@@ -0,0 +1,96 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+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 *v4si =
+    gcc_jit_type_get_vector (int_type, 4);
+
+  gcc_jit_function *func_vector =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  int_type,
+				  "vector",
+				  0, NULL,
+				  0);
+
+  gcc_jit_rvalue *elements[4]
+    = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 3),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 4),
+    };
+
+  gcc_jit_rvalue *vector
+    = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, elements);
+
+  gcc_jit_rvalue *index
+    = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2);
+
+  gcc_jit_block *block_a = gcc_jit_function_new_block (func_vector, NULL);
+  gcc_jit_lvalue *value
+    = gcc_jit_context_new_vector_access (ctxt, NULL, vector, index);
+  gcc_jit_block_end_with_return (block_a, NULL, gcc_jit_lvalue_as_rvalue (value));
+
+  gcc_jit_function *func_vector_perm =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  v4si,
+				  "vector_perm",
+				  0, NULL,
+				  0);
+
+  gcc_jit_rvalue *elements2[4]
+    = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 5),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 6),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 7),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 8),
+    };
+
+  gcc_jit_rvalue *vector2
+    = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, elements2);
+
+  gcc_jit_rvalue *mask_values[4]
+    = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 7),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 3),
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0),
+    };
+
+  gcc_jit_rvalue *mask
+    = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, mask_values);
+
+  gcc_jit_block *block_b = gcc_jit_function_new_block (func_vector_perm, NULL);
+  gcc_jit_rvalue *result = gcc_jit_context_new_rvalue_vector_perm (ctxt, NULL, vector, vector2, mask);
+  gcc_jit_block_end_with_return (block_b, NULL, result);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_NON_NULL (result);
+
+  typedef int (*vector) ();
+  vector fn = (vector)gcc_jit_result_get_code (result, "vector");
+  CHECK_NON_NULL (fn);
+
+  int vector_access = fn ();
+  CHECK_VALUE (vector_access, 3);
+
+  typedef v4si (*vector_perm) ();
+  vector_perm perm_fn = (vector_perm)gcc_jit_result_get_code (result, "vector_perm");
+  CHECK_NON_NULL (perm_fn);
+
+  v4si vector_perm_res = perm_fn ();
+  v4si expected_vec = { 8, 3, 4, 1 };
+  CHECK_VECTOR_VALUE (4, vector_perm_res, expected_vec);
+}
-- 
2.42.1