https://gcc.gnu.org/g:b7385d51c8170c75b285b0a317884b51d4012e5a
commit r16-9148-gb7385d51c8170c75b285b0a317884b51d4012e5a Author: Jeevitha <[email protected]> Date: Mon Jun 22 15:09:15 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 0d82756a365ee6189af4490345bc0d2595007c84) 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 4d0e541351f2..f4f3772d6cc4 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -761,6 +761,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 af233a049a96..a3d802e97945 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2290,6 +2290,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 }; @@ -2334,6 +2336,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 a4e8344ef114..be92da06c3c8 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; +}
