Thanks for reaching out, Julian, I greatly appreciate your help.  Please
forgive and over- or under-sharing.  If I've left something out, please let
me know.

>From my pdp10.md:

;; JIRA sw_gcc-68.  gcc recognizes the "movmemhi" 'instruction' for
;; doing block moves, as in struct assignment.  This pattern wasn't
;; present, however.  I've added it, and it's companion function
;; pdp10_expand_movmemhi().

(define_expand "movmemhi"
   [(match_operand:BLK 0 "general_operand" "=r")
    (match_operand:BLK 1 "general_operand" "=r")
    (match_operand:SI 2 "general_operand" "=r")
    (match_operand:SI 3 "const_int_operand" "")
   ]
   ""
   {
     if (pdp10_expand_movmemhi(operands)) {
       DONE;
     }
     FAIL;
     /*
      * if (!pdp10_expand_movmemhi(operands)) {
      *   FAIL;
      * }
      */
   }
)

And the definition for pdp10_expand_movmemhi:

// JIRA sw_gcc-68: Emit instructions to copy a memory block.  Return
// nonzero on success.  This is really a duplicate of the following
// function, but used specifically for the movmemhi operation.
// Duplicated to allow for any custimization.

int pdp10_expand_movmemhi(rtx *operands) {

   // operands[0] is the block destination address
   // operands[1] is the block source address
   // operands[2] is the block length
   // operands[3] is the known alignment.

   if (flag_enable_fix_sw_gcc_0068) {
     operands[0] = XEXP(operands[0], 0);
     operands[1] = XEXP(operands[1], 0);

     if (GET_CODE(operands[3]) != CONST_INT) {
       return 0;
     }
     if (INTVAL(operands[3]) != UNITS_PER_WORD) {
       return 0;
     }

     if (GET_CODE(operands[1]) == CONST &&
        GET_CODE(XEXP(operands[1], 0)) == PLUS &&
        GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == CONST_INT
        )
     {
       rtx x = XEXP(operands[1], 0);
       HOST_WIDE_INT offset = INTVAL(XEXP(x, 1));
       operands[1] = plus_constant(XEXP(x, 0), offset & ADDRESS_MASK);
     }

     if (use_xblt(operands[0], operands[1], operands[2])) {
       return expand_xblt(operands[0], operands[1], operands[2]);
     }
     return expand_blt(operands[0], operands[1], operands[2]);
   }
   return 0;
}

Here are use_xblt() and expand_xblt():

// Return nonzero if XBLT should be used instead of BLT.

static int use_xblt(rtx destination, rtx source, rtx length) {
   if (!HAVE_XBLT || !TARGET_EXTENDED) {
     return 0;
   }

   if (GET_CODE(destination) != CONST_INT) {
     return 1;
   }
   if (source && GET_CODE(source) != CONST_INT) {
     return 1;
   }
   if (GET_CODE(length) != CONST_INT) {
     return 1;
   }

   if (INTVAL(length) >> 32 > 0) {
     return 1;
   }

   if (source) {
       HOST_WIDE_INT destination_section = INTVAL(destination) >> 32;
       HOST_WIDE_INT source_section = INTVAL(source) >> 32;

       if (destination_section != source_section) {
         return 1;
       }
     }

   return 0;
}

// Try to emit instructions to XBLT a memory block of LENGTH storage
// units from SOURCE to DESTINATION.  Return nonzero on success.

static int expand_xblt(rtx destination, rtx source, rtx length) {
   rtx temp, mem, acs;
   int i, n;

   if (GET_CODE(length) != CONST_INT) {
     return 0;
   }
   n = INTVAL(length);

   switch (n / UNITS_PER_WORD) {
   case 0:
     break;

   case 2:
   case 3:
     temp = gen_reg_rtx(DImode);
     for (i = 0; i < n / 8; i++) {
       emit_move_insn(temp, gen_rtx_MEM(DImode, plus_constant(source, i)));
       emit_move_insn(gen_rtx_MEM(DImode, plus_constant(destination, i)),
temp);
     }

     // Fall through.

   case 1:
     if (n % 8 >= 4) {
       int m = 2 * (n / 8);
       temp = gen_reg_rtx(SImode);
       emit_move_insn(temp, gen_rtx_MEM(SImode, plus_constant(source, m)));
       emit_move_insn(gen_rtx_MEM(SImode, plus_constant(destination, m)),
temp);
     }
     break;

   default:
     acs = gen_reg_rtx(TImode);
     emit_move_insn(gen_rtx_SUBREG(SImode, acs, 0), GEN_INT(INTVAL(length)
/ UNITS_PER_WORD));
     emit_move_insn(gen_rtx_SUBREG(Pmode, acs, 4), source);
     emit_move_insn(gen_rtx_SUBREG(Pmode, acs, 8), destination);
     emit_insn(gen_XBLT(acs));
     break;
   }

   switch (n % UNITS_PER_WORD) {
   case 0:
     break;

   case 1:
     temp = gen_reg_rtx(QImode);
     mem = gen_rtx_MEM(QImode, plus_constant(source, n / 4));
     set_mem_align(mem, BITS_PER_WORD);
     emit_move_insn(temp, mem);
     mem = gen_rtx_MEM(QImode, plus_constant(destination, n / 4));
     set_mem_align(mem, BITS_PER_WORD);
     emit_move_insn(mem, temp);
     break;

   case 2:
     temp = gen_reg_rtx(HImode);
     mem = gen_rtx_MEM(HImode, plus_constant(source, n / 4));
     set_mem_align(mem, BITS_PER_WORD);
     emit_move_insn(temp, mem);
     mem = gen_rtx_MEM(HImode, plus_constant(destination, n / 4));
     set_mem_align(mem, BITS_PER_WORD);
     emit_move_insn(mem, temp);
     break;

   case 3:
     temp = gen_reg_rtx(SImode);
     emit_insn(gen_extzv(temp, gen_rtx_MEM(SImode, plus_constant(source, n
/ 4)), GEN_INT(27), GEN_INT(0)));
     emit_insn(gen_insv(gen_rtx_MEM(SImode, plus_constant(destination, n /
4)), GEN_INT(27), GEN_INT(0), temp));
     break;
   }

   return 1;
}


On Thu, Mar 23, 2023 at 3:09 AM Julian Brown <jul...@codesourcery.com>
wrote:

> On Wed, 22 Mar 2023 18:27:28 -0400
> Sid Maxwell via Gcc <gcc@gcc.gnu.org> wrote:
>
> > Is there anyone on the list with experience with the gcc 4.3
> > codebase?  I'm currently maintaining a fork of it, with a PDP10 code
> > generator.
> >
> > I've run into an issue involving the transformation of a movmemhi to a
> > single PDP10 instruction (an xblt, if you're curious).  The
> > transformation appears to 'lose' its knowledge of being a store,
> > resulting in certain following stores being declared dead, and code
> > motion that shouldn't happen (e.g. a load moved before the xblt that
> > depends on the result of the xblt).
> >
> > I'm hoping to find someone who can help me diagnose the problem.  We
> > want to use this instruction rather than the copy-word-loop currently
> > generated for struct assignments.
>
> I think we'd need a bit more info than that... what does the movmemhi
> instruction pattern look like, for example?
>
> Julian
>
>
>

Reply via email to