diff mbox series

x86: Allow TImode offsettable memory only with 8-bit constant

Message ID 20240412224212.940737-1-hjl.tools@gmail.com
State New
Headers show
Series x86: Allow TImode offsettable memory only with 8-bit constant | expand

Commit Message

H.J. Lu April 12, 2024, 10:42 p.m. UTC
The x86 instruction size limit is 15 bytes.  If a NDD instruction has
a segment prefix byte, a 4-byte opcode prefix, a MODRM byte, a SIB byte,
a 4-byte displacement and a 4-byte immediate, adding an address size
prefix will exceed the size limit.  Change TImode ADD, AND, OR and XOR
to allow offsettable memory only with 8-bit signed integer constant,
which is encoded with a 1-byte immediate, if the address size prefix
is used.

gcc/

	PR target/114696
	* config/i386/i386.md (isa): Add apx_ndd_64.
	(enabled): Likewise.
	(*add<dwi>3_doubleword): Change rjO to r,ro,jO with 8-bit
	signed integer constant and enable jO only for apx_ndd_64.
	(*add<dwi>3_doubleword_cc_overflow_1): Likewise.
	(*and<dwi>3_doubleword): Likewise.
	(*<code><dwi>3_doubleword): Likewise.

gcc/testsuite/

	PR target/114696
	* gcc.target/i386/apx-ndd-x32-2a.c: New test.
	* gcc.target/i386/apx-ndd-x32-2b.c: Likewise.
	* gcc.target/i386/apx-ndd-x32-2c.c: Likewise.
	* gcc.target/i386/apx-ndd-x32-2d.c: Likewise.
---
 gcc/config/i386/i386.md                       | 36 ++++++++++---------
 .../gcc.target/i386/apx-ndd-x32-2a.c          | 13 +++++++
 .../gcc.target/i386/apx-ndd-x32-2b.c          |  6 ++++
 .../gcc.target/i386/apx-ndd-x32-2c.c          |  6 ++++
 .../gcc.target/i386/apx-ndd-x32-2d.c          |  6 ++++
 5 files changed, 50 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c
 create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c
 create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c

Comments

Hongtao Liu April 15, 2024, 1:25 a.m. UTC | #1
On Sat, Apr 13, 2024 at 6:42 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> The x86 instruction size limit is 15 bytes.  If a NDD instruction has
> a segment prefix byte, a 4-byte opcode prefix, a MODRM byte, a SIB byte,
> a 4-byte displacement and a 4-byte immediate, adding an address size
> prefix will exceed the size limit.  Change TImode ADD, AND, OR and XOR
> to allow offsettable memory only with 8-bit signed integer constant,
> which is encoded with a 1-byte immediate, if the address size prefix
> is used.
Ok.
>
> gcc/
>
>         PR target/114696
>         * config/i386/i386.md (isa): Add apx_ndd_64.
>         (enabled): Likewise.
>         (*add<dwi>3_doubleword): Change rjO to r,ro,jO with 8-bit
>         signed integer constant and enable jO only for apx_ndd_64.
>         (*add<dwi>3_doubleword_cc_overflow_1): Likewise.
>         (*and<dwi>3_doubleword): Likewise.
>         (*<code><dwi>3_doubleword): Likewise.
>
> gcc/testsuite/
>
>         PR target/114696
>         * gcc.target/i386/apx-ndd-x32-2a.c: New test.
>         * gcc.target/i386/apx-ndd-x32-2b.c: Likewise.
>         * gcc.target/i386/apx-ndd-x32-2c.c: Likewise.
>         * gcc.target/i386/apx-ndd-x32-2d.c: Likewise.
> ---
>  gcc/config/i386/i386.md                       | 36 ++++++++++---------
>  .../gcc.target/i386/apx-ndd-x32-2a.c          | 13 +++++++
>  .../gcc.target/i386/apx-ndd-x32-2b.c          |  6 ++++
>  .../gcc.target/i386/apx-ndd-x32-2c.c          |  6 ++++
>  .../gcc.target/i386/apx-ndd-x32-2d.c          |  6 ++++
>  5 files changed, 50 insertions(+), 17 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c
>
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index d4ce3809e6d..adab1ef9e04 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -568,7 +568,7 @@ (define_attr "unit" "integer,i387,sse,mmx,unknown"
>
>  ;; Used to control the "enabled" attribute on a per-instruction basis.
>  (define_attr "isa" "base,x64,nox64,x64_sse2,x64_sse4,x64_sse4_noavx,
> -                   x64_avx,x64_avx512bw,x64_avx512dq,apx_ndd,
> +                   x64_avx,x64_avx512bw,x64_avx512dq,apx_ndd,apx_ndd_64,
>                     sse_noavx,sse2,sse2_noavx,sse3,sse3_noavx,sse4,sse4_noavx,
>                     avx,noavx,avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,avx512f_512,
>                     noavx512f,avx512bw,avx512bw_512,noavx512bw,avx512dq,
> @@ -968,6 +968,8 @@ (define_attr "enabled" ""
>            (symbol_ref "TARGET_VPCLMULQDQ && TARGET_AVX512VL")
>          (eq_attr "isa" "apx_ndd")
>            (symbol_ref "TARGET_APX_NDD")
> +        (eq_attr "isa" "apx_ndd_64")
> +          (symbol_ref "TARGET_APX_NDD && Pmode == DImode")
>          (eq_attr "isa" "vaes_avx512vl")
>            (symbol_ref "TARGET_VAES && TARGET_AVX512VL")
>
> @@ -6302,10 +6304,10 @@ (define_expand "add<mode>3"
>  })
>
>  (define_insn_and_split "*add<dwi>3_doubleword"
> -  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
> +  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
>         (plus:<DWI>
> -         (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
> -         (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,r")))
> +         (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
> +         (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,r")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)"
>    "#"
> @@ -6344,7 +6346,7 @@ (define_insn_and_split "*add<dwi>3_doubleword"
>        DONE;
>      }
>  }
> -[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
> +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
>
>  (define_insn_and_split "*add<dwi>3_doubleword_zext"
>    [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o,&r,&r")
> @@ -9515,10 +9517,10 @@ (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
>    [(set (reg:CCC FLAGS_REG)
>         (compare:CCC
>           (plus:<DWI>
> -           (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
> -           (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o"))
> +           (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
> +           (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,o"))
>           (match_dup 1)))
> -   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
> +   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
>         (plus:<DWI> (match_dup 1) (match_dup 2)))]
>    "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)"
>    "#"
> @@ -9560,7 +9562,7 @@ (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
>    else
>      operands[6] = gen_rtx_ZERO_EXTEND (<DWI>mode, operands[5]);
>  }
> -[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
> +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
>
>  ;; x == 0 with zero flag test can be done also as x < 1U with carry flag
>  ;; test, where the latter is preferrable if we have some carry consuming
> @@ -11704,10 +11706,10 @@ (define_expand "and<mode>3"
>  })
>
>  (define_insn_and_split "*and<dwi>3_doubleword"
> -  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
> +  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
>         (and:<DWI>
> -        (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
> -        (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o")))
> +        (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
> +        (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,o")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (AND, <DWI>mode, operands, TARGET_APX_NDD)"
>    "#"
> @@ -11744,7 +11746,7 @@ (define_insn_and_split "*and<dwi>3_doubleword"
>
>    DONE;
>  }
> -[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
> +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
>
>  (define_insn "*anddi_1"
>    [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,r,?k")
> @@ -12694,10 +12696,10 @@ (define_expand "<code><mode>3"
>  })
>
>  (define_insn_and_split "*<code><dwi>3_doubleword"
> -  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
> +  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
>         (any_or:<DWI>
> -        (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
> -        (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o")))
> +        (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
> +        (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,o")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (<CODE>, <DWI>mode, operands, TARGET_APX_NDD)"
>    "#"
> @@ -12750,7 +12752,7 @@ (define_insn_and_split "*<code><dwi>3_doubleword"
>
>    DONE;
>  }
> -[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
> +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
>
>  (define_insn "*<code><mode>_1"
>    [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,r,?k")
> diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c
> new file mode 100644
> index 00000000000..6f7edb224a3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c
> @@ -0,0 +1,13 @@
> +/* PR target/114696 */
> +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-mapxf -O0 -mx32" } */
> +
> +_Thread_local unsigned _BitInt(65) a;
> +_BitInt(129) b;
> +
> +void
> +foo (void)
> +{
> +  a += b;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c
> new file mode 100644
> index 00000000000..8f53d5c10c9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c
> @@ -0,0 +1,6 @@
> +/* PR target/114696 */
> +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-mapxf -O2 -mx32" } */
> +
> +#include "apx-ndd-x32-2a.c"
> diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c
> new file mode 100644
> index 00000000000..0485833e813
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c
> @@ -0,0 +1,6 @@
> +/* PR target/114696 */
> +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-mapxf -O0 -mx32 -maddress-mode=long" } */
> +
> +#include "apx-ndd-x32-2a.c"
> diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c
> new file mode 100644
> index 00000000000..ec62d373684
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c
> @@ -0,0 +1,6 @@
> +/* PR target/114696 */
> +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-mapxf -O2 -mx32 -maddress-mode=long" } */
> +
> +#include "apx-ndd-x32-2a.c"
> --
> 2.44.0
>
diff mbox series

Patch

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d4ce3809e6d..adab1ef9e04 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -568,7 +568,7 @@  (define_attr "unit" "integer,i387,sse,mmx,unknown"
 
 ;; Used to control the "enabled" attribute on a per-instruction basis.
 (define_attr "isa" "base,x64,nox64,x64_sse2,x64_sse4,x64_sse4_noavx,
-		    x64_avx,x64_avx512bw,x64_avx512dq,apx_ndd,
+		    x64_avx,x64_avx512bw,x64_avx512dq,apx_ndd,apx_ndd_64,
 		    sse_noavx,sse2,sse2_noavx,sse3,sse3_noavx,sse4,sse4_noavx,
 		    avx,noavx,avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,avx512f_512,
 		    noavx512f,avx512bw,avx512bw_512,noavx512bw,avx512dq,
@@ -968,6 +968,8 @@  (define_attr "enabled" ""
 	   (symbol_ref "TARGET_VPCLMULQDQ && TARGET_AVX512VL")
 	 (eq_attr "isa" "apx_ndd")
 	   (symbol_ref "TARGET_APX_NDD")
+	 (eq_attr "isa" "apx_ndd_64")
+	   (symbol_ref "TARGET_APX_NDD && Pmode == DImode")
 	 (eq_attr "isa" "vaes_avx512vl")
 	   (symbol_ref "TARGET_VAES && TARGET_AVX512VL")
 
@@ -6302,10 +6304,10 @@  (define_expand "add<mode>3"
 })
 
 (define_insn_and_split "*add<dwi>3_doubleword"
-  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
+  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
 	(plus:<DWI>
-	  (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
-	  (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,r")))
+	  (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
+	  (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,r")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)"
   "#"
@@ -6344,7 +6346,7 @@  (define_insn_and_split "*add<dwi>3_doubleword"
       DONE;
     }
 }
-[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
+[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
 
 (define_insn_and_split "*add<dwi>3_doubleword_zext"
   [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o,&r,&r")
@@ -9515,10 +9517,10 @@  (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
   [(set (reg:CCC FLAGS_REG)
 	(compare:CCC
 	  (plus:<DWI>
-	    (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
-	    (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o"))
+	    (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
+	    (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,o"))
 	  (match_dup 1)))
-   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
+   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
 	(plus:<DWI> (match_dup 1) (match_dup 2)))]
   "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)"
   "#"
@@ -9560,7 +9562,7 @@  (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
   else
     operands[6] = gen_rtx_ZERO_EXTEND (<DWI>mode, operands[5]);
 }
-[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
+[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
 
 ;; x == 0 with zero flag test can be done also as x < 1U with carry flag
 ;; test, where the latter is preferrable if we have some carry consuming
@@ -11704,10 +11706,10 @@  (define_expand "and<mode>3"
 })
 
 (define_insn_and_split "*and<dwi>3_doubleword"
-  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
+  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
 	(and:<DWI>
-	 (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
-	 (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o")))
+	 (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
+	 (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,o")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (AND, <DWI>mode, operands, TARGET_APX_NDD)"
   "#"
@@ -11744,7 +11746,7 @@  (define_insn_and_split "*and<dwi>3_doubleword"
 
   DONE;
 }
-[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
+[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
 
 (define_insn "*anddi_1"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,r,?k")
@@ -12694,10 +12696,10 @@  (define_expand "<code><mode>3"
 })
 
 (define_insn_and_split "*<code><dwi>3_doubleword"
-  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r")
+  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r,&r,&r")
 	(any_or:<DWI>
-	 (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r")
-	 (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o")))
+	 (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r,ro,jO,r")
+	 (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,K,<di>,o")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (<CODE>, <DWI>mode, operands, TARGET_APX_NDD)"
   "#"
@@ -12750,7 +12752,7 @@  (define_insn_and_split "*<code><dwi>3_doubleword"
 
   DONE;
 }
-[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")])
+[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")])
 
 (define_insn "*<code><mode>_1"
   [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,r,?k")
diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c
new file mode 100644
index 00000000000..6f7edb224a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2a.c
@@ -0,0 +1,13 @@ 
+/* PR target/114696 */
+/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-mapxf -O0 -mx32" } */
+
+_Thread_local unsigned _BitInt(65) a;
+_BitInt(129) b;
+
+void
+foo (void)
+{
+  a += b;
+}
diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c
new file mode 100644
index 00000000000..8f53d5c10c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2b.c
@@ -0,0 +1,6 @@ 
+/* PR target/114696 */
+/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-mapxf -O2 -mx32" } */
+
+#include "apx-ndd-x32-2a.c"
diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c
new file mode 100644
index 00000000000..0485833e813
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2c.c
@@ -0,0 +1,6 @@ 
+/* PR target/114696 */
+/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-mapxf -O0 -mx32 -maddress-mode=long" } */
+
+#include "apx-ndd-x32-2a.c"
diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c
new file mode 100644
index 00000000000..ec62d373684
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-2d.c
@@ -0,0 +1,6 @@ 
+/* PR target/114696 */
+/* { dg-do assemble { target { apxf && { ! ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-mapxf -O2 -mx32 -maddress-mode=long" } */
+
+#include "apx-ndd-x32-2a.c"