public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/morello)] convert.c: Add logic for widening conversions of capabilities
@ 2022-11-16 13:44 Alex Coplan
0 siblings, 0 replies; 2+ messages in thread
From: Alex Coplan @ 2022-11-16 13:44 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:c69da8925365a04afdcc222e98235e8b7459756d
commit c69da8925365a04afdcc222e98235e8b7459756d
Author: Victor Do Nascimento <Victor.DoNascimento@arm.com>
Date: Wed Nov 16 13:41:56 2022 +0000
convert.c: Add logic for widening conversions of capabilities
This patch provides a pathway for conversion of capabilities to
__int128 types, extending extracted capability values according to the
underlying capability type.
As a direct conversion from capability to __int128 would imply the
exposure of capability metadata, an indirect conversion path via
noncapability_type is provided, dropping capability metadata prior to
converting to the final integer type.
Further logic is also added to prevent the folding of the resulting
2-step conversion back to the original expression during optimization.
Pointers are sign extended to follow GCC's existing
implementation-defined choice for the result of converting a pointer
to a wider integer type, while __intcap values are extended in
accordance with their signedness.
This fixes an ICE seen in libstdc++
25_algorithms/{fill|generate}_n/87982_neg.cc tests.
gcc/ChangeLog:
* gcc/convert.c (convert_to_integer_1): add capability ->
__int128 conversion logic.
* gcc/match.pd: Prevent folding of metadata-exposing widening
conversions for capabilities.
gcc/testsuite/ChangeLog:
* g++.target/aarch64/morello/int128-conv-semantics.C: New.
* gcc.target/aarch64/morello/int128-conv-semantics.c: Likewise.
Diff:
---
gcc/convert.c | 42 ++++++++++---
gcc/match.pd | 4 +-
.../aarch64/morello/int128-conv-semantics.C | 73 ++++++++++++++++++++++
.../aarch64/morello/int128-conv-semantics.c | 72 +++++++++++++++++++++
4 files changed, 180 insertions(+), 11 deletions(-)
diff --git a/gcc/convert.c b/gcc/convert.c
index e076be027f4..8bcb58489d0 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -514,6 +514,8 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
unsigned int outprec = element_precision (type);
location_t loc = EXPR_LOCATION (expr);
+ gcc_assert (!capability_type_p (type));
+
/* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can
be. Consider `enum E = { a, b = (enum E) 3 };'. */
if (!COMPLETE_TYPE_P (type))
@@ -688,17 +690,37 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
&& !TREE_OVERFLOW (tree_strip_any_location_wrapper (expr)))
return build_int_cst (type, 0);
- /* Convert to an unsigned integer of the correct width first, and from
- there widen/truncate to the required type. Some targets support the
- coexistence of multiple valid pointer sizes, so fetch the one we need
+ /* Convert to integer of the correct width first, and from there
+ widen/truncate to the required type. In the case of intcap
+ values, the signedness of the intermediate type mirrors that
+ of the original intcap type. In the case of capabilities,
+ GCC's implementation-defined behavior of sign-extending
+ pointers is preserved. Some targets support the coexistence
+ of multiple valid pointer sizes, so fetch the one we need
from the type. */
- if (!dofold)
- return build1 (CONVERT_EXPR, type, expr);
- expr = fold_build1 (CONVERT_EXPR,
- lang_hooks.types.type_for_size
- (TYPE_NONCAP_PRECISION (intype), 0),
- expr);
- return fold_convert (type, expr);
+ {
+ int unsigned_p = INTCAP_TYPE_P (intype) ? TYPE_UNSIGNED (intype) : 0;
+ if (!dofold)
+ {
+ /* Enable conversion from capability and __intcap to __int128
+ via initial conversion to (unsigned) long int. */
+ if (capability_type_p (intype)
+ && INTEGRAL_TYPE_P (type)
+ && outprec > TYPE_NONCAP_PRECISION (intype))
+ {
+ expr = build1 (CONVERT_EXPR,
+ lang_hooks.types.type_for_size
+ (TYPE_NONCAP_PRECISION (intype), unsigned_p),
+ expr);
+ }
+ return build1 (CONVERT_EXPR, type, expr);
+ }
+ expr = fold_build1 (CONVERT_EXPR,
+ lang_hooks.types.type_for_size
+ (TYPE_NONCAP_PRECISION (intype), unsigned_p),
+ expr);
+ return fold_convert (type, expr);
+ }
case INTEGER_TYPE:
case ENUMERAL_TYPE:
diff --git a/gcc/match.pd b/gcc/match.pd
index fa196c23ba9..07640ffe0a9 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3188,6 +3188,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(with
{
tree inside_type = TREE_TYPE (@0);
+ bool inside_iscap = capability_type_p (inside_type);
tree inter_type = TREE_TYPE (@1);
int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type);
@@ -3262,7 +3263,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& ((inter_unsignedp && inter_prec > inside_prec)
== (final_unsignedp && final_prec > inter_prec))
&& ! (inside_ptr && inter_prec != final_prec)
- && ! (final_ptr && inside_prec != inter_prec))
+ && ! (final_ptr && inside_prec != inter_prec)
+ && ! (inside_iscap && final_prec > inside_prec))
(ocvt @0))
/* A truncation to an unsigned type (a zero-extension) should be
diff --git a/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C b/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C
new file mode 100644
index 00000000000..f464f4cb5ac
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C
@@ -0,0 +1,73 @@
+/* Check that __int128 conversion semantics are implemented
+ correctly in the front and middle-end. */
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps=obj -fdump-tree-original -fpermissive" } */
+/* { dg-final { check-function-bodies "**" "" { {-O[123s]} } } } */
+/* { dg-require-effective-target cheri_capability_pure } */
+/* { dg-skip-if "" { *-*-* } { -fuse-linker-plugin } } */
+
+/*
+** _Z18uintcap_to_uint128u11__uintcap_t:
+** mov x1, 0
+** ret
+*/
+unsigned __int128 uintcap_to_uint128(unsigned __intcap a1)
+{
+ return a1;
+}
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128 unsigned\) \(long unsigned int\) a1;} 1 "original" } } */
+
+/*
+** _Z17intcap_to_uint128u10__intcap_t:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 intcap_to_uint128(__intcap a2)
+{
+ return a2;
+}
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128 unsigned\) \(long int\) a2;} 1 "original" } } */
+
+/*
+** _Z14ptr_to_uint128Pi:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 ptr_to_uint128(int *a3)
+{
+ return a3; /* { dg-warning \[-fpermissive\] } */
+}
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128 unsigned\) \(long int\) a3;} 1 "original" } } */
+
+/*
+** _Z17uintcap_to_int128u11__uintcap_t:
+** mov x1, 0
+** ret
+*/
+ __int128 uintcap_to_int128(unsigned __intcap a4)
+ {
+ return a4;
+ }
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128\) \(long unsigned int\) a4;} 1 "original" } } */
+
+/*
+** _Z16intcap_to_int128u10__intcap_t:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 intcap_to_int128(__intcap a5)
+ {
+ return a5;
+ }
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128\) \(long int\) a5;} 1 "original" } } */
+
+/*
+** _Z13ptr_to_int128Pi:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 ptr_to_int128(int *a6)
+ {
+ return a6; /* { dg-warning \[-fpermissive\] } */
+ }
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128\) \(long int\) a6;} 1 "original" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c b/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c
new file mode 100644
index 00000000000..c88dad5d6a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c
@@ -0,0 +1,72 @@
+/* Check that __int128 conversion semantics are implemented
+ correctly in the front and middle-end. */
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps -fdump-tree-original" } */
+/* { dg-final { check-function-bodies "**" "" { {-O[123s]} } } } */
+/* { dg-require-effective-target cheri_capability_pure } */
+
+/*
+** uintcap_to_uint128:
+** mov x1, 0
+** ret
+*/
+unsigned __int128 uintcap_to_uint128(unsigned __intcap a1)
+{
+ return a1;
+}
+/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long unsigned int\) a1;} 1 "original" } } */
+
+/*
+** intcap_to_uint128:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 intcap_to_uint128(__intcap a2)
+{
+ return a2;
+}
+/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long int\) a2;} 1 "original" } } */
+
+/*
+** ptr_to_uint128:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 ptr_to_uint128(int *a3)
+{
+ return a3; /* { dg-warning \[-fpermissive\] } */
+}
+/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long int\) a3;} 1 "original" } } */
+
+/*
+** uintcap_to_int128:
+** mov x1, 0
+** ret
+*/
+ __int128 uintcap_to_int128(unsigned __intcap a4)
+ {
+ return a4;
+ }
+/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long unsigned int\) a4;} 1 "original" } } */
+
+/*
+** intcap_to_int128:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 intcap_to_int128(__intcap a5)
+ {
+ return a5;
+ }
+/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long int\) a5;} 1 "original" } } */
+
+/*
+** ptr_to_int128:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 ptr_to_int128(int *a6)
+ {
+ return a6; /* { dg-warning \[-fpermissive\] } */
+ }
+/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long int\) a6;} 1 "original" } } */
^ permalink raw reply [flat|nested] 2+ messages in thread
* [gcc(refs/vendors/ARM/heads/morello)] convert.c: Add logic for widening conversions of capabilities
@ 2022-11-22 12:43 Stam Markianos-Wright
0 siblings, 0 replies; 2+ messages in thread
From: Stam Markianos-Wright @ 2022-11-22 12:43 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:c69da8925365a04afdcc222e98235e8b7459756d
commit c69da8925365a04afdcc222e98235e8b7459756d
Author: Victor Do Nascimento <Victor.DoNascimento@arm.com>
Date: Wed Nov 16 13:41:56 2022 +0000
convert.c: Add logic for widening conversions of capabilities
This patch provides a pathway for conversion of capabilities to
__int128 types, extending extracted capability values according to the
underlying capability type.
As a direct conversion from capability to __int128 would imply the
exposure of capability metadata, an indirect conversion path via
noncapability_type is provided, dropping capability metadata prior to
converting to the final integer type.
Further logic is also added to prevent the folding of the resulting
2-step conversion back to the original expression during optimization.
Pointers are sign extended to follow GCC's existing
implementation-defined choice for the result of converting a pointer
to a wider integer type, while __intcap values are extended in
accordance with their signedness.
This fixes an ICE seen in libstdc++
25_algorithms/{fill|generate}_n/87982_neg.cc tests.
gcc/ChangeLog:
* gcc/convert.c (convert_to_integer_1): add capability ->
__int128 conversion logic.
* gcc/match.pd: Prevent folding of metadata-exposing widening
conversions for capabilities.
gcc/testsuite/ChangeLog:
* g++.target/aarch64/morello/int128-conv-semantics.C: New.
* gcc.target/aarch64/morello/int128-conv-semantics.c: Likewise.
Diff:
---
gcc/convert.c | 42 ++++++++++---
gcc/match.pd | 4 +-
.../aarch64/morello/int128-conv-semantics.C | 73 ++++++++++++++++++++++
.../aarch64/morello/int128-conv-semantics.c | 72 +++++++++++++++++++++
4 files changed, 180 insertions(+), 11 deletions(-)
diff --git a/gcc/convert.c b/gcc/convert.c
index e076be027f4..8bcb58489d0 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -514,6 +514,8 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
unsigned int outprec = element_precision (type);
location_t loc = EXPR_LOCATION (expr);
+ gcc_assert (!capability_type_p (type));
+
/* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can
be. Consider `enum E = { a, b = (enum E) 3 };'. */
if (!COMPLETE_TYPE_P (type))
@@ -688,17 +690,37 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
&& !TREE_OVERFLOW (tree_strip_any_location_wrapper (expr)))
return build_int_cst (type, 0);
- /* Convert to an unsigned integer of the correct width first, and from
- there widen/truncate to the required type. Some targets support the
- coexistence of multiple valid pointer sizes, so fetch the one we need
+ /* Convert to integer of the correct width first, and from there
+ widen/truncate to the required type. In the case of intcap
+ values, the signedness of the intermediate type mirrors that
+ of the original intcap type. In the case of capabilities,
+ GCC's implementation-defined behavior of sign-extending
+ pointers is preserved. Some targets support the coexistence
+ of multiple valid pointer sizes, so fetch the one we need
from the type. */
- if (!dofold)
- return build1 (CONVERT_EXPR, type, expr);
- expr = fold_build1 (CONVERT_EXPR,
- lang_hooks.types.type_for_size
- (TYPE_NONCAP_PRECISION (intype), 0),
- expr);
- return fold_convert (type, expr);
+ {
+ int unsigned_p = INTCAP_TYPE_P (intype) ? TYPE_UNSIGNED (intype) : 0;
+ if (!dofold)
+ {
+ /* Enable conversion from capability and __intcap to __int128
+ via initial conversion to (unsigned) long int. */
+ if (capability_type_p (intype)
+ && INTEGRAL_TYPE_P (type)
+ && outprec > TYPE_NONCAP_PRECISION (intype))
+ {
+ expr = build1 (CONVERT_EXPR,
+ lang_hooks.types.type_for_size
+ (TYPE_NONCAP_PRECISION (intype), unsigned_p),
+ expr);
+ }
+ return build1 (CONVERT_EXPR, type, expr);
+ }
+ expr = fold_build1 (CONVERT_EXPR,
+ lang_hooks.types.type_for_size
+ (TYPE_NONCAP_PRECISION (intype), unsigned_p),
+ expr);
+ return fold_convert (type, expr);
+ }
case INTEGER_TYPE:
case ENUMERAL_TYPE:
diff --git a/gcc/match.pd b/gcc/match.pd
index fa196c23ba9..07640ffe0a9 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3188,6 +3188,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(with
{
tree inside_type = TREE_TYPE (@0);
+ bool inside_iscap = capability_type_p (inside_type);
tree inter_type = TREE_TYPE (@1);
int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type);
@@ -3262,7 +3263,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& ((inter_unsignedp && inter_prec > inside_prec)
== (final_unsignedp && final_prec > inter_prec))
&& ! (inside_ptr && inter_prec != final_prec)
- && ! (final_ptr && inside_prec != inter_prec))
+ && ! (final_ptr && inside_prec != inter_prec)
+ && ! (inside_iscap && final_prec > inside_prec))
(ocvt @0))
/* A truncation to an unsigned type (a zero-extension) should be
diff --git a/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C b/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C
new file mode 100644
index 00000000000..f464f4cb5ac
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C
@@ -0,0 +1,73 @@
+/* Check that __int128 conversion semantics are implemented
+ correctly in the front and middle-end. */
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps=obj -fdump-tree-original -fpermissive" } */
+/* { dg-final { check-function-bodies "**" "" { {-O[123s]} } } } */
+/* { dg-require-effective-target cheri_capability_pure } */
+/* { dg-skip-if "" { *-*-* } { -fuse-linker-plugin } } */
+
+/*
+** _Z18uintcap_to_uint128u11__uintcap_t:
+** mov x1, 0
+** ret
+*/
+unsigned __int128 uintcap_to_uint128(unsigned __intcap a1)
+{
+ return a1;
+}
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128 unsigned\) \(long unsigned int\) a1;} 1 "original" } } */
+
+/*
+** _Z17intcap_to_uint128u10__intcap_t:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 intcap_to_uint128(__intcap a2)
+{
+ return a2;
+}
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128 unsigned\) \(long int\) a2;} 1 "original" } } */
+
+/*
+** _Z14ptr_to_uint128Pi:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 ptr_to_uint128(int *a3)
+{
+ return a3; /* { dg-warning \[-fpermissive\] } */
+}
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128 unsigned\) \(long int\) a3;} 1 "original" } } */
+
+/*
+** _Z17uintcap_to_int128u11__uintcap_t:
+** mov x1, 0
+** ret
+*/
+ __int128 uintcap_to_int128(unsigned __intcap a4)
+ {
+ return a4;
+ }
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128\) \(long unsigned int\) a4;} 1 "original" } } */
+
+/*
+** _Z16intcap_to_int128u10__intcap_t:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 intcap_to_int128(__intcap a5)
+ {
+ return a5;
+ }
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128\) \(long int\) a5;} 1 "original" } } */
+
+/*
+** _Z13ptr_to_int128Pi:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 ptr_to_int128(int *a6)
+ {
+ return a6; /* { dg-warning \[-fpermissive\] } */
+ }
+/* { dg-final { scan-tree-dump-times {<retval> = \(__int128\) \(long int\) a6;} 1 "original" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c b/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c
new file mode 100644
index 00000000000..c88dad5d6a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c
@@ -0,0 +1,72 @@
+/* Check that __int128 conversion semantics are implemented
+ correctly in the front and middle-end. */
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps -fdump-tree-original" } */
+/* { dg-final { check-function-bodies "**" "" { {-O[123s]} } } } */
+/* { dg-require-effective-target cheri_capability_pure } */
+
+/*
+** uintcap_to_uint128:
+** mov x1, 0
+** ret
+*/
+unsigned __int128 uintcap_to_uint128(unsigned __intcap a1)
+{
+ return a1;
+}
+/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long unsigned int\) a1;} 1 "original" } } */
+
+/*
+** intcap_to_uint128:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 intcap_to_uint128(__intcap a2)
+{
+ return a2;
+}
+/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long int\) a2;} 1 "original" } } */
+
+/*
+** ptr_to_uint128:
+** asr x1, x0, 63
+** ret
+*/
+unsigned __int128 ptr_to_uint128(int *a3)
+{
+ return a3; /* { dg-warning \[-fpermissive\] } */
+}
+/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long int\) a3;} 1 "original" } } */
+
+/*
+** uintcap_to_int128:
+** mov x1, 0
+** ret
+*/
+ __int128 uintcap_to_int128(unsigned __intcap a4)
+ {
+ return a4;
+ }
+/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long unsigned int\) a4;} 1 "original" } } */
+
+/*
+** intcap_to_int128:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 intcap_to_int128(__intcap a5)
+ {
+ return a5;
+ }
+/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long int\) a5;} 1 "original" } } */
+
+/*
+** ptr_to_int128:
+** asr x1, x0, 63
+** ret
+*/
+ __int128 ptr_to_int128(int *a6)
+ {
+ return a6; /* { dg-warning \[-fpermissive\] } */
+ }
+/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long int\) a6;} 1 "original" } } */
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-11-22 12:43 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-16 13:44 [gcc(refs/vendors/ARM/heads/morello)] convert.c: Add logic for widening conversions of capabilities Alex Coplan
2022-11-22 12:43 Stam Markianos-Wright
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).