https://gcc.gnu.org/g:92bd6918a1892d36a5ad51d4be12f004cc20d931
commit r15-11374-g92bd6918a1892d36a5ad51d4be12f004cc20d931 Author: Jeevitha <[email protected]> Date: Wed Jul 15 11:51:24 2026 -0500 rs6000: Fix PTImode attribute handling [PR106895] PTImode is used to generate even/odd register pairs for 128-bit values. When PTImode is specified via a type attribute, compilation fails because no internal type exists to represent this mode. Introduce signed and unsigned PTImode internal builtin types to handle PTImode. These __pti_internal types are not documented, as they are not intended for direct user use. 2026-06-04 Jeevitha Palanisamy <[email protected]> gcc/ PR target/106895 * config/rs6000/rs6000.h (enum rs6000_builtin_type_index): Add RS6000_BTI_INTPTI and RS6000_BTI_UINTPTI. (intPTI_type_internal_node, uintPTI_type_internal_node): New PTImode type macros. * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Register signed and unsigned PTImode internal builtin types. * config/rs6000/sync.md (trunctipti2): New splitter. (extendptiti2): Likewise. (zero_extendptiti2): Likewise. gcc/testsuite/ PR target/106895 * gcc.target/powerpc/pr106895-1.c: New test. * gcc.target/powerpc/pr106895-2.c: New test. (cherry picked from commit b7385d51c8170c75b285b0a317884b51d4012e5a) Diff: --- gcc/config/rs6000/rs6000-builtin.cc | 15 ++++++++ gcc/config/rs6000/rs6000.h | 4 +++ gcc/config/rs6000/sync.md | 51 +++++++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr106895-1.c | 16 +++++++++ gcc/testsuite/gcc.target/powerpc/pr106895-2.c | 24 +++++++++++++ 5 files changed, 110 insertions(+) diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc index b111691fc475..658757857fb7 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -756,6 +756,21 @@ rs6000_init_builtins (void) else ieee128_float_type_node = NULL_TREE; + /* PTImode to get even/odd register pairs. */ + if (TARGET_POWERPC64) + { + intPTI_type_internal_node = make_signed_type (GET_MODE_BITSIZE (PTImode)); + SET_TYPE_MODE (intPTI_type_internal_node, PTImode); + t = build_qualified_type (intPTI_type_internal_node, TYPE_QUAL_CONST); + lang_hooks.types.register_builtin_type (intPTI_type_internal_node, + "__pti_internal"); + + uintPTI_type_internal_node = make_unsigned_type (GET_MODE_BITSIZE (PTImode)); + SET_TYPE_MODE (uintPTI_type_internal_node, PTImode); + t = build_qualified_type (uintPTI_type_internal_node, TYPE_QUAL_CONST); + lang_hooks.types.register_builtin_type (uintPTI_type_internal_node, + "__upti_internal"); + } /* Vector pair and vector quad support. */ vector_pair_type_node = make_node (OPAQUE_TYPE); SET_TYPE_MODE (vector_pair_type_node, OOmode); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index e18d24d1317b..d66a46ff0914 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2289,6 +2289,8 @@ enum rs6000_builtin_type_index RS6000_BTI_ptr_vector_quad, RS6000_BTI_ptr_long_long, RS6000_BTI_ptr_long_long_unsigned, + RS6000_BTI_INTPTI, + RS6000_BTI_UINTPTI, RS6000_BTI_MAX }; @@ -2333,6 +2335,8 @@ enum rs6000_builtin_type_index #define uintDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTDI]) #define intTI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTTI]) #define uintTI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTTI]) +#define intPTI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTPTI]) +#define uintPTI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTPTI]) #define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float]) #define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double]) #define long_double_type_internal_node (rs6000_builtin_types[RS6000_BTI_long_double]) diff --git a/gcc/config/rs6000/sync.md b/gcc/config/rs6000/sync.md index e42cf9e9506c..656b8fb22378 100644 --- a/gcc/config/rs6000/sync.md +++ b/gcc/config/rs6000/sync.md @@ -198,6 +198,57 @@ DONE; }) +;; PTI and TI are both 128-bit modes; the following conversions are +;; register-class changes only, no actual truncation, sign or zero +;; extension occurs. +(define_insn_and_split "trunctipti2" + [(set (match_operand:PTI 0 "register_operand" "=r,r") + (truncate:PTI (match_operand:TI 1 "register_operand" "0,r")))] + "TARGET_POWERPC64" + "#" + "&& reload_completed" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +{ + operands[2] = gen_lowpart (DImode, operands[0]); + operands[3] = gen_highpart (DImode, operands[0]); + operands[4] = gen_lowpart (DImode, operands[1]); + operands[5] = gen_highpart (DImode, operands[1]); +} +[(set_attr "length" "0,8")]) + +(define_insn_and_split "extendptiti2" + [(set (match_operand:TI 0 "register_operand" "=r,r") + (sign_extend:TI (match_operand:PTI 1 "register_operand" "0,r")))] + "TARGET_POWERPC64" + "#" + "&& reload_completed" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +{ + operands[2] = gen_lowpart (DImode, operands[0]); + operands[3] = gen_highpart (DImode, operands[0]); + operands[4] = gen_lowpart (DImode, operands[1]); + operands[5] = gen_highpart (DImode, operands[1]); +} +[(set_attr "length" "0,8")]) + +(define_insn_and_split "zero_extendptiti2" + [(set (match_operand:TI 0 "register_operand" "=r,r") + (zero_extend:TI (match_operand:PTI 1 "register_operand" "0,r")))] + "TARGET_POWERPC64" + "#" + "&& reload_completed" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +{ + operands[2] = gen_lowpart (DImode, operands[0]); + operands[3] = gen_highpart (DImode, operands[0]); + operands[4] = gen_lowpart (DImode, operands[1]); + operands[5] = gen_highpart (DImode, operands[1]); +} +[(set_attr "length" "0,8")]) + ;; If TARGET_PREFIXED, always use pstq rather than stq. (define_insn "store_quadpti" [(set (match_operand:PTI 0 "quad_memory_operand" "=wQ") diff --git a/gcc/testsuite/gcc.target/powerpc/pr106895-1.c b/gcc/testsuite/gcc.target/powerpc/pr106895-1.c new file mode 100644 index 000000000000..dfcafcd57e7e --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr106895-1.c @@ -0,0 +1,16 @@ +/* PR target/106895 */ +/* { dg-do assemble } */ +/* { dg-require-effective-target int128 } */ +/* { dg-options "-O2 -save-temps" } */ + +/* Verify the following generates even/odd register pairs. */ + +typedef __int128 pti __attribute__((mode(PTI))); + +void +set128 (pti val, pti *mem) +{ + asm ("stq %1,%0" : "=m" (*mem) : "r" (val)); +} + +/* { dg-final { scan-assembler {\mstq\M} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr106895-2.c b/gcc/testsuite/gcc.target/powerpc/pr106895-2.c new file mode 100644 index 000000000000..db8e29c67061 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr106895-2.c @@ -0,0 +1,24 @@ +/* PR target/106895 */ +/* { dg-do run } */ +/* { dg-require-effective-target int128 } */ +/* { dg-options "-O2" } */ + +#include <stdlib.h> + +typedef __int128 ti; +typedef __int128 pti __attribute__((mode(PTI))); + +volatile ti a = 140; +volatile pti b; +volatile ti c; + +int main(void) +{ + b = (pti) a; + c = (ti) b; + + if (c != a) + abort(); + + return 0; +}
