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 > > >