This patch introduces a new mode called QDOmode which is a 256 byte
opaque mode that maps to __dmr2048 type. The sha3hash instructions takes
a pair of dense math registers, therefore we need this type for those
builtins.

The DMR pair register maps to even numbered pair of consecutive DMR
register. For example, the DMR pair register 2 represents 2 DMR
registers 2 and 3.

movqdo pattern has been implemented, which splits the 2048 bit moves
into smalled 1024 bit tdo moves after the reload pass is completed.

2026-08-27  Avinash Jayakar  <[email protected]>

gcc/ChangeLog:
        * config/rs6000/mma.md (movqdo): New define_expand.
        (*movqdo): New define_insn_and_split
        * config/rs6000/rs6000-builtin.cc (rs6000_type_string): Add __dmr2048.
        (rs6000_init_builtins): Register dmr2048 type.
        (rs6000_gimple_fold_mma_builtin): Handle QDOmode.
        * config/rs6000/rs6000-call.cc (rs6000_return_in_memory): Allow QDOmode.
        (rs6000_function_arg): Likewise.
        * config/rs6000/rs6000-gen-builtins.cc (enum basetype): Add DMR2048.
        (match_type): Likewise.
        (complete_vector_type): Likewise.
        * config/rs6000/rs6000-modes.def: Define QDO mode.
        * config/rs6000/rs6000.cc (rs6000_hard_regno_mode_ok_uncached): Allow
        even number DMR regno for QDOmode.
        (rs6000_modes_tieable_p): Do not allow QDO with other mode.
        (rs6000_debug_reg_global): Add QDOmode.
        (rs6000_setup_reg_addr_masks): Allow QDOmode.
        (reg_offset_addressing_ok_p): QDOmode return TARGET_DMF.
        (rs6000_emit_move): Do not allow QDO mode to set to constants.
        (rs6000_secondary_reload_simple_move): Allow QDOmode.
        (rs6000_preferred_reload_class): QDOmode prefers DMR_REGS.
        (rs6000_mangle_type): Add __dmr2048 type.
        (rs6000_dmr_register_move_cost): QDOmode move cost is double of TDOmode.
        (rs6000_register_move_cost): Allow QDOmode.
        (rs6000_split_multireg_move): Likewise.
        (rs6000_invalid_conversion): Handle QDOmode.
        * config/rs6000/rs6000.h (VECTOR_ALIGNMENT_P): True if mode is QDOmode.
        (enum rs6000_builtin_type_index): Add dmr2048 and its ptr type.
        (dmr2048_type_node): Define __dmr2048 node.
        (ptr_dmr2048_type_node): Define pointer type for __dmr2048 node.
---
 gcc/config/rs6000/mma.md                 | 57 ++++++++++++++++
 gcc/config/rs6000/rs6000-builtin.cc      | 17 +++++
 gcc/config/rs6000/rs6000-call.cc         | 10 +--
 gcc/config/rs6000/rs6000-gen-builtins.cc | 17 ++++-
 gcc/config/rs6000/rs6000-modes.def       |  3 +-
 gcc/config/rs6000/rs6000.cc              | 82 ++++++++++++++++++------
 gcc/config/rs6000/rs6000.h               |  7 +-
 7 files changed, 166 insertions(+), 27 deletions(-)

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index f5085cd967e..7946ec88ae3 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -662,6 +662,63 @@ (define_insn_and_split "*movtdo"
   gcc_unreachable ();
 })
 
+;; QDO (2048-bit dense-math pair) move expander.
+;; Split into 2 TDO moves for the even and odd DMR.
+(define_expand "movqdo"
+  [(set (match_operand:QDO 0 "nonimmediate_operand")
+       (match_operand:QDO 1 "input_operand"))]
+  "TARGET_DMF"
+{
+  rs6000_emit_move (operands[0], operands[1], QDOmode);
+  DONE;
+})
+
+(define_insn_and_split "*movqdo"
+  [(set (match_operand:QDO 0 "nonimmediate_operand" "=wa,m,wa,wD,wa,wD")
+       (match_operand:QDO 1 "input_operand" "m,wa,wa,wD,wD,wa"))]
+  "TARGET_DMF
+   && (gpc_reg_operand (operands[0], QDOmode)
+       || gpc_reg_operand (operands[1], QDOmode))"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  rtx dst = operands[0];
+  rtx src = operands[1];
+
+  if (REG_P (dst) && MEM_P (src))
+    {
+      rtx tdo1 = gen_rtx_REG (TDOmode, REGNO (dst));
+      rtx tdo2 = gen_rtx_REG (TDOmode, REGNO (dst) + 8);
+      emit_insn (gen_move_insn (tdo1, adjust_address (src, TDOmode, 0)));
+      emit_insn (gen_move_insn (tdo2, adjust_address (src, TDOmode, 128)));
+      DONE;
+    }
+  else if (REG_P (src) && MEM_P (dst))
+    {
+      rtx tdo1 = gen_rtx_REG (TDOmode, REGNO (src));
+      rtx tdo2 = gen_rtx_REG (TDOmode, REGNO (src) + 8);
+      emit_insn (gen_move_insn (adjust_address (dst, TDOmode, 0), tdo1));
+      emit_insn (gen_move_insn (adjust_address (dst, TDOmode, 128), tdo2));
+      DONE;
+    }
+  else if (REG_P (src) && REG_P (dst))
+    {
+      rtx stdo1 = gen_rtx_REG (TDOmode, REGNO (src));
+      rtx stdo2 = gen_rtx_REG (TDOmode,
+                              REGNO (src)
+                              + (VSX_REGNO_P (REGNO (src)) ? 8 : 1));
+      rtx dtdo1 = gen_rtx_REG (TDOmode, REGNO (dst));
+      rtx dtdo2 = gen_rtx_REG (TDOmode,
+                              REGNO (dst)
+                              + (VSX_REGNO_P (REGNO (dst)) ? 8 : 1));
+      emit_insn (gen_move_insn (dtdo1, stdo1));
+      emit_insn (gen_move_insn (dtdo2, stdo2));
+      DONE;
+    }
+  gcc_unreachable ();
+})
+
 
 (define_insn_and_split "reload_tdo_load"
   [(set (match_operand:TDO 0 "dmr_register_operand" "=wD")
diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
b/gcc/config/rs6000/rs6000-builtin.cc
index 50c18ddee8f..7ad2d932f00 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -519,6 +519,8 @@ const char *rs6000_type_string (tree type_node)
     return "__vector_quad";
   else if (type_node == dmr1024_type_node)
     return "__dmr1024";
+  else if (type_node == dmr2048_type_node)
+    return "__dmr2048";
 
   return "unknown";
 }
@@ -835,6 +837,18 @@ rs6000_init_builtins (void)
   t = build_qualified_type (dmr1024_type_node, TYPE_QUAL_CONST);
   ptr_dmr1024_type_node = build_pointer_type (t);
 
+  /* QDOmode (2048-bit dmr pair).  Use 512-bit alignment like dmr1024.  */
+  dmr2048_type_node = make_node (OPAQUE_TYPE);
+  SET_TYPE_MODE (dmr2048_type_node, QDOmode);
+  TYPE_SIZE (dmr2048_type_node) = bitsize_int (GET_MODE_BITSIZE (QDOmode));
+  TYPE_PRECISION (dmr2048_type_node) = GET_MODE_BITSIZE (QDOmode);
+  TYPE_SIZE_UNIT (dmr2048_type_node) = size_int (GET_MODE_SIZE (QDOmode));
+  SET_TYPE_ALIGN (dmr2048_type_node, 512);
+  TYPE_USER_ALIGN (dmr2048_type_node) = 0;
+  lang_hooks.types.register_builtin_type (dmr2048_type_node, "__dmr2048");
+  t = build_qualified_type (dmr2048_type_node, TYPE_QUAL_CONST);
+  ptr_dmr2048_type_node = build_pointer_type (t);
+
   tdecl = add_builtin_type ("__bool char", bool_char_type_node);
   TYPE_NAME (bool_char_type_node) = tdecl;
 
@@ -1331,6 +1345,9 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi,
     case TDOmode:
       lhs_type = dmr1024_type_node;
       break;
+    case QDOmode:
+      lhs_type = dmr2048_type_node;
+      break;
     case XOmode:
       lhs_type = vector_quad_type_node;
       break;
diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc
index 0da2c1f6071..a33d38c68dd 100644
--- a/gcc/config/rs6000/rs6000-call.cc
+++ b/gcc/config/rs6000/rs6000-call.cc
@@ -439,7 +439,8 @@ rs6000_return_in_memory (const_tree type, const_tree fntype 
ATTRIBUTE_UNUSED)
       && TREE_TYPE (cfun->decl) == fntype
       && (TYPE_MODE (type) == OOmode
           || TYPE_MODE (type) == XOmode
-          || TYPE_MODE (type) == TDOmode))
+          || TYPE_MODE (type) == TDOmode
+          || TYPE_MODE (type) == QDOmode))
     {
       /* Record we have now handled function CFUN, so the next time we
         are called, we do not re-report the same error.  */
@@ -447,7 +448,8 @@ rs6000_return_in_memory (const_tree type, const_tree fntype 
ATTRIBUTE_UNUSED)
       if (TYPE_CANONICAL (type) != NULL_TREE)
        type = TYPE_CANONICAL (type);
       const char *type_class =
-        (TYPE_MODE (type) == TDOmode) ? "Dense Math" : "MMA";
+        (TYPE_MODE (type) == TDOmode || TYPE_MODE (type) == QDOmode)
+        ? "Dense Math" : "MMA";
       error ("invalid use of %s type %qs as a function return value",
             type_class,
             IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
@@ -1637,12 +1639,12 @@ rs6000_function_arg (cumulative_args_t cum_v, const 
function_arg_info &arg)
   int n_elts;
 
   /* We do not allow Dense Math/MMA types being used as function arguments.  */
-  if (mode == OOmode || mode == XOmode || mode == TDOmode)
+  if (mode == OOmode || mode == XOmode || mode == TDOmode || mode == QDOmode)
     {
       if (TYPE_CANONICAL (type) != NULL_TREE)
        type = TYPE_CANONICAL (type);
       const char *type_class =
-        (mode == TDOmode) ? "Dense Math" : "MMA";
+       (mode == TDOmode || mode == QDOmode) ? "Dense Math" : "MMA";
       error ("invalid use of %s operand of type %qs as a function parameter",
             type_class,
             IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc 
b/gcc/config/rs6000/rs6000-gen-builtins.cc
index 08068ba78fd..87273d1ef9c 100644
--- a/gcc/config/rs6000/rs6000-gen-builtins.cc
+++ b/gcc/config/rs6000/rs6000-gen-builtins.cc
@@ -340,7 +340,8 @@ enum basetype
   BT_IBM128,
   BT_VPAIR,
   BT_VQUAD,
-  BT_DMR
+  BT_DMR,
+  BT_DMR2048
 };
 
 /* Ways in which a const int value can be restricted.  RES_BITS indicates
@@ -562,6 +563,7 @@ static typemap type_map[] =
     { "pv16qi",                "ptr_V16QI" },
     { "pv1poi",                "ptr_vector_pair" },
     { "pv1pxi",                "ptr_vector_quad" },
+    { "pv1qdoi",       "ptr_dmr2048" },
     { "pv1tdoi",       "ptr_dmr1024" },
     { "pv1ti",         "ptr_V1TI" },
     { "pv2df",         "ptr_V2DF" },
@@ -593,6 +595,7 @@ static typemap type_map[] =
     { "v16qi",         "V16QI" },
     { "v1poi",         "vector_pair" },
     { "v1pxi",         "vector_quad" },
+    { "v1qdoi",        "dmr2048" },
     { "v1tdoi",        "dmr1024" },
     { "v1ti",          "V1TI" },
     { "v2df",          "V2DF" },
@@ -1080,6 +1083,7 @@ match_type (typeinfo *typedata, int voidok)
        v256    __vector_pair
        v512    __vector_quad
        dmr1024 __dmr1024
+       dmr2048 __dmr2048
 
      For simplicity, We don't support "short int" and "long long int".
      We don't currently support a <basetype> of "_Float16".  "signed"
@@ -1268,6 +1272,13 @@ match_type (typeinfo *typedata, int voidok)
       handle_pointer (typedata);
       return 1;
     }
+  else if (!strcmp (token, "dmr2048"))
+    {
+      typedata->isvector = 1;
+      typedata->base = BT_DMR2048;
+      handle_pointer (typedata);
+      return 1;
+    }
   else if (!strcmp (token, "signed"))
     typedata->issigned = 1;
   else if (!strcmp (token, "unsigned"))
@@ -1578,6 +1589,10 @@ complete_vector_type (typeinfo *typeptr, char *buf, int 
*bufi)
       memcpy (&buf[*bufi], "1tdoi", 5);
       *bufi += 5;
       break;
+    case BT_DMR2048:
+      memcpy (&buf[*bufi], "1qdoi", 5);
+      *bufi += 5;
+      break;
     default:
       diag (pos, "unhandled basetype %d.\n", typeptr->base);
       exit (1);
diff --git a/gcc/config/rs6000/rs6000-modes.def 
b/gcc/config/rs6000/rs6000-modes.def
index 0ad326751c4..899c08bf061 100644
--- a/gcc/config/rs6000/rs6000-modes.def
+++ b/gcc/config/rs6000/rs6000-modes.def
@@ -76,7 +76,8 @@ VECTOR_MODE (INT, SI, 2);     /*                 V2SI  */
    combination.  */
 PARTIAL_INT_MODE (TI, 128, PTI);
 
-/* Modes used by __vector_pair, __vector_quad and __dmr1024.  */
+/* Modes used by __vector_pair, __vector_quad, __dmr1024 and __dmr2048.  */
 OPAQUE_MODE (OO, 32);
 OPAQUE_MODE (XO, 64);
 OPAQUE_MODE (TDO, 128);
+OPAQUE_MODE (QDO, 256);
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 99555988913..a940d27faae 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -1869,7 +1869,8 @@ rs6000_hard_regno_mode_ok_uncached (int regno, 
machine_mode mode)
     mode = GET_MODE_INNER (mode);
 
   /* No other types other than XOmode or TDOmode can go in DMRs.  */
-  if (DMR_REGNO_P (regno) && !(mode ==XOmode || mode == TDOmode))
+  if (DMR_REGNO_P (regno)
+      && !(mode ==XOmode || mode == TDOmode || mode == QDOmode))
     return 0;
 
   /* TDOmode value can be held in either 1 DMR register or 8 VSX
@@ -1884,6 +1885,18 @@ rs6000_hard_regno_mode_ok_uncached (int regno, 
machine_mode mode)
       else
        return 0;
     }
+  if (mode == QDOmode)
+    {
+      if (TARGET_DMF)
+       return ((DMR_REGNO_P (regno)
+                && DMR_REGNO_P (last_regno)
+                && ((regno - FIRST_DMR_REGNO) % 2 == 0))
+               || (VSX_REGNO_P (regno)
+                   && VSX_REGNO_P (last_regno)
+                   && (regno & 1) == 0));
+      else
+       return 0;
+    }
 
   /* Vector pair modes need even/odd VSX register pairs.  Only allow vector
      registers.  */
@@ -2011,8 +2024,9 @@ static bool
 rs6000_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   if (mode1 == PTImode || mode1 == OOmode || mode1 == XOmode
-      || mode1 == TDOmode || mode2 == PTImode || mode2 == OOmode
-      || mode2 == XOmode || mode2 == TDOmode)
+      || mode1 == TDOmode || mode1 == QDOmode
+      || mode2 == PTImode || mode2 == OOmode
+      || mode2 == XOmode || mode2 == TDOmode || mode2 == QDOmode)
     return mode1 == mode2;
 
   if (ALTIVEC_OR_VSX_VECTOR_MODE (mode1))
@@ -2304,6 +2318,7 @@ rs6000_debug_reg_global (void)
     OOmode,
     XOmode,
     TDOmode,
+    QDOmode,
     CCmode,
     CCUNSmode,
     CCEQmode,
@@ -2668,7 +2683,8 @@ rs6000_setup_reg_addr_masks (void)
 
          if (rc == RELOAD_REG_DMR)
            {
-             if (TARGET_DMF && (m2 == XOmode || m2 == TDOmode))
+             if (TARGET_DMF
+                 && (m2 == XOmode || m2 == TDOmode || m2 == QDOmode))
                {
                  addr_mask = RELOAD_REG_VALID;
                  reg_addr[m].addr_mask[rc] = addr_mask;
@@ -2779,8 +2795,9 @@ rs6000_setup_reg_addr_masks (void)
             dmr1024 type can only do offset loads.  */
          else if ((addr_mask != 0)
                   && ((TARGET_MMA && (m2 == OOmode || m2 == XOmode))
-                       || (TARGET_DMF
-                           && (m2 == TDOmode || m2 == OOmode || m2 == 
XOmode))))
+                      || (TARGET_DMF
+                          && (m2 == TDOmode || m2 == QDOmode
+                              || m2 == OOmode || m2 == XOmode))))
            {
              addr_mask |= RELOAD_REG_OFFSET;
              if (rc == RELOAD_REG_FPR || rc == RELOAD_REG_VMX)
@@ -8756,6 +8773,7 @@ reg_offset_addressing_ok_p (machine_mode mode)
       return TARGET_MMA || TARGET_DMF;
 
     case E_TDOmode:
+    case E_QDOmode:
       return TARGET_DMF;
 
     case E_SDmode:
@@ -11317,6 +11335,12 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode 
mode)
               "__dmr1024");
       break;
 
+    case E_QDOmode:
+      if (CONST_INT_P (operands[1]))
+       error ("%qs is an opaque type, and you cannot set it to constants",
+              "__dmr2048");
+      break;
+
     case E_SImode:
     case E_DImode:
       /* Use default pattern for address of ELF small data */
@@ -12783,9 +12807,9 @@ rs6000_secondary_reload_simple_move (enum 
rs6000_reg_type to_type,
     return true;
 
   /* DMRs can be copied to VSX register, and vice versa.  */
-  if (TARGET_DMF && (mode == XOmode || mode == TDOmode)
+  if (TARGET_DMF && (mode == XOmode || mode == TDOmode || mode == QDOmode)
       && ((to_type == DMR_REG_TYPE && from_type == VSX_REG_TYPE)
-          || (to_type == VSX_REG_TYPE && from_type == DMR_REG_TYPE)))
+         || (to_type == VSX_REG_TYPE && from_type == DMR_REG_TYPE)))
     return true;
 
   return false;
@@ -13587,6 +13611,9 @@ rs6000_preferred_reload_class (rtx x, enum reg_class 
rclass)
       if (mode == TDOmode)
        return VSX_REGS;
 
+      if (mode == QDOmode)
+       return DMR_REGS;
+
       if (GET_MODE_CLASS (mode) == MODE_INT)
        return GENERAL_REGS;
     }
@@ -20806,6 +20833,8 @@ rs6000_mangle_type (const_tree type)
     return "u13__vector_quad";
   if (type == dmr1024_type_node)
     return "u9__dmr1024";
+  if (type == dmr2048_type_node)
+    return "u9__dmr2048";
 
   /* For all other types, use the default mangling.  */
   return NULL;
@@ -22935,6 +22964,10 @@ rs6000_dmr_register_move_cost (machine_mode mode, 
reg_class_t rclass)
       else if (mode == TDOmode)
        return base_cost * 2;
 
+      /* QDOmode (dmr pair) can be copied in 4 instructions.  */
+      else if (mode == QDOmode)
+       return base_cost * 4;
+
       else
        return base_cost * 2 * hard_regno_nregs (FIRST_DMR_REGNO, mode);
     }
@@ -22964,7 +22997,8 @@ rs6000_register_move_cost (machine_mode mode,
   to_vsx = reg_class_contents[to] & reg_class_contents[VSX_REGS];
   from_vsx = reg_class_contents[from] & reg_class_contents[VSX_REGS];
 
-  if ((mode == TDOmode || mode==XOmode) && from == DMR_REGS && to == DMR_REGS)
+  if ((mode == TDOmode || mode == XOmode || mode == QDOmode)
+      && from == DMR_REGS && to == DMR_REGS)
     ret = 2 * hard_regno_nregs (FIRST_DMR_REGNO, mode);
 
   else if (from == DMR_REGS)
@@ -27625,15 +27659,17 @@ rs6000_split_multireg_move (rtx dst, rtx src)
   /* If we have a vector quad register for MMA or DMR register for Dense Math,
      and this is a load or store, see if we can use vector paired
      load/stores.  */
-  if ((mode == XOmode || mode == TDOmode) && (TARGET_MMA || TARGET_DMF)
+  if ((mode == XOmode || mode == TDOmode || mode == QDOmode)
+      && (TARGET_MMA || TARGET_DMF)
       && (MEM_P (dst) || MEM_P (src)))
     {
       reg_mode = OOmode;
       nregs /= 2;
     }
-  /* If we have a vector pair/quad mode, split it into two/four separate
-     vectors.  */
-  else if (mode == OOmode || mode == XOmode || mode == TDOmode)
+  /* If we have a vector pair/quad/dmr pair mode, split it into two/four/eight
+     separate vectors.  */
+  else if (mode == OOmode || mode == XOmode || mode == TDOmode
+          || mode == QDOmode)
     reg_mode = V1TImode;
   else if (FP_REGNO_P (reg))
     reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode :
@@ -27685,7 +27721,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
      below.  This means the last register gets the first memory
      location.  We also need to be careful of using the right register
      numbers if we are splitting XO to OO.  */
-  if (mode == OOmode || mode == XOmode || mode == TDOmode)
+  if (mode == OOmode || mode == XOmode || mode == TDOmode || mode == QDOmode)
     {
       nregs = hard_regno_nregs (reg, mode);
       int reg_mode_nregs = hard_regno_nregs (reg, reg_mode);
@@ -27823,8 +27859,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
       /* Move register range backwards, if we might have destructive
         overlap.  */
       int i;
-      /* XO/OO/TDO are opaque so cannot use subregs. */
-      if (mode == OOmode || mode == XOmode || mode == TDOmode)
+      /* XO/OO/TDO/QDO are opaque so cannot use subregs.  */
+      if (mode == OOmode || mode == XOmode || mode == TDOmode
+         || mode == QDOmode)
        {
          for (i = nregs - 1; i >= 0; i--)
            {
@@ -27999,8 +28036,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
          if (j == 0 && used_update)
            continue;
 
-         /* XO/OO/TDO are opaque so cannot use subregs. */
-         if (mode == OOmode || mode == XOmode || mode == TDOmode)
+         /* XO/OO/TDO/QDO are opaque so cannot use subregs.  */
+         if (mode == OOmode || mode == XOmode || mode == TDOmode
+             || mode == QDOmode)
            {
              rtx dst_i = gen_rtx_REG (reg_mode, REGNO (dst) + j);
              rtx src_i = gen_rtx_REG (reg_mode, REGNO (src) + j);
@@ -29029,8 +29067,8 @@ rs6000_invalid_conversion (const_tree fromtype, 
const_tree totype)
 
   if (frommode != tomode)
     {
-      /* Do not allow conversions to/from XOmode, OOmode and TDOmode
-        types.  */
+      /* Do not allow conversions to/from XOmode, OOmode, TDOmode and QDOmode
+  types.  */
       if (frommode == XOmode)
        return N_("invalid conversion from type %<__vector_quad%>");
       if (tomode == XOmode)
@@ -29043,6 +29081,10 @@ rs6000_invalid_conversion (const_tree fromtype, 
const_tree totype)
        return N_("invalid conversion from type %<__dmr1024%>");
       if (tomode == TDOmode)
        return N_("invalid conversion to type %<__dmr1024%>");
+      if (frommode == QDOmode)
+       return N_("invalid conversion from type %<__dmr2048%>");
+      if (tomode == QDOmode)
+       return N_("invalid conversion to type %<__dmr2048%>");
     }
 
   /* Conversion allowed.  */
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index bcd4c39d24d..16862ded01b 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -985,7 +985,8 @@ enum data_align { align_abi, align_opt, align_both };
 /* Modes that are not vectors, but require vector alignment.  Treat these like
    vectors in terms of loads and stores.  */
 #define VECTOR_ALIGNMENT_P(MODE)                                       \
-  (FLOAT128_VECTOR_P (MODE) || (MODE) == OOmode || (MODE) == XOmode || (MODE) 
== TDOmode)
+  (FLOAT128_VECTOR_P (MODE) || (MODE) == OOmode || (MODE) == XOmode     \
+   || (MODE) == TDOmode || (MODE) == QDOmode)
 
 #define ALTIVEC_VECTOR_MODE(MODE)                                      \
   ((MODE) == V16QImode                                                 \
@@ -2277,6 +2278,7 @@ enum rs6000_builtin_type_index
   RS6000_BTI_vector_pair,       /* unsigned 256-bit types (vector pair).  */
   RS6000_BTI_vector_quad,       /* unsigned 512-bit types (vector quad).  */
   RS6000_BTI_dmr1024,            /* unsigned 1024-bit type (dmr1024).  */
+  RS6000_BTI_dmr2048,            /* unsigned 2048-bit type (dmr2048).  */
   RS6000_BTI_const_ptr_void,     /* const pointer to void */
   RS6000_BTI_ptr_V16QI,
   RS6000_BTI_ptr_V1TI,
@@ -2316,6 +2318,7 @@ enum rs6000_builtin_type_index
   RS6000_BTI_ptr_vector_pair,
   RS6000_BTI_ptr_vector_quad,
   RS6000_BTI_ptr_dmr1024,
+  RS6000_BTI_ptr_dmr2048,
   RS6000_BTI_ptr_long_long,
   RS6000_BTI_ptr_long_long_unsigned,
   RS6000_BTI_INTPTI,
@@ -2378,6 +2381,7 @@ enum rs6000_builtin_type_index
 #define vector_pair_type_node           
(rs6000_builtin_types[RS6000_BTI_vector_pair])
 #define vector_quad_type_node           
(rs6000_builtin_types[RS6000_BTI_vector_quad])
 #define dmr1024_type_node                
(rs6000_builtin_types[RS6000_BTI_dmr1024])
+#define dmr2048_type_node                
(rs6000_builtin_types[RS6000_BTI_dmr2048])
 #define pcvoid_type_node                
(rs6000_builtin_types[RS6000_BTI_const_ptr_void])
 #define ptr_V16QI_type_node             
(rs6000_builtin_types[RS6000_BTI_ptr_V16QI])
 #define ptr_V1TI_type_node              
(rs6000_builtin_types[RS6000_BTI_ptr_V1TI])
@@ -2417,6 +2421,7 @@ enum rs6000_builtin_type_index
 #define ptr_vector_pair_type_node       
(rs6000_builtin_types[RS6000_BTI_ptr_vector_pair])
 #define ptr_vector_quad_type_node       
(rs6000_builtin_types[RS6000_BTI_ptr_vector_quad])
 #define ptr_dmr1024_type_node            
(rs6000_builtin_types[RS6000_BTI_ptr_dmr1024])
+#define ptr_dmr2048_type_node            
(rs6000_builtin_types[RS6000_BTI_ptr_dmr2048])
 #define ptr_long_long_integer_type_node         
(rs6000_builtin_types[RS6000_BTI_ptr_long_long])
 #define ptr_long_long_unsigned_type_node 
(rs6000_builtin_types[RS6000_BTI_ptr_long_long_unsigned])
 
-- 
2.54.0

Reply via email to