Hi All, The following patch has been bootstrapped and regtested on powerpc64le-linux.
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-02-19 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.c: New test. diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc index 45c88fe063b..6663e23f9ac 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -756,6 +756,19 @@ rs6000_init_builtins (void) else ieee128_float_type_node = NULL_TREE; + /* PTImode to get even/odd register pairs. */ + 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 2b90694cef1..d85f71aa65d 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2285,6 +2285,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 }; @@ -2329,6 +2331,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 a4e8344ef11..c31339e7b2e 100644 --- a/gcc/config/rs6000/sync.md +++ b/gcc/config/rs6000/sync.md @@ -198,6 +198,54 @@ 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") + (truncate:PTI (match_operand:TI 1 "register_operand" "r")))] + "" + "#" + "&& 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]); +}) + +(define_insn_and_split "extendptiti2" + [(set (match_operand:TI 0 "register_operand" "=r") + (sign_extend:TI (match_operand:PTI 1 "register_operand" "r")))] + "" + "#" + "&& 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]); +}) + +(define_insn_and_split "zero_extendptiti2" + [(set (match_operand:TI 0 "register_operand" "=r") + (zero_extend:TI (match_operand:PTI 1 "register_operand" "r")))] + "" + "#" + "&& 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]); +}) + ;; 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.c b/gcc/testsuite/gcc.target/powerpc/pr106895.c new file mode 100644 index 00000000000..d38d58f5d42 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr106895.c @@ -0,0 +1,17 @@ +/* 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} } } */ +
