Hello, I use (define_subst ...) in a way that solves my .md factoring problems but I wonder if this use is expected and if will be maintained / documented in the future.
Target is a 64-bit core whose GPRs are 64-bit wide, but it also has 32-bit integer arithmetic instructions that clear the 32 upper bits of the destination register. For each instruction template, e.g. "addsi3", I define another one that zero-extends the result to 64 bits from 32 bits. Before using (define_subst ...), that was: (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (plus:SI (match_operand:SI 1 "register_operand" "r,r,r") (match_operand:SI 2 "register_w32_operand" "r,I10,W32")))] "" "addw %0 = %1, %2" [(set_attr "type" "alu_tiny,alu_tiny_w,alu_tiny_x") (set_attr "length" "4,4,8")] ) ;; zero-extend version of addsi3 (define_insn "*addsi3_zext" [(set (match_operand:DI 0 "register_operand" "=r,r,r") (zero_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "r,r,r") (match_operand:SI 2 "register_w32_operand" "r,I10,W32")))] "" "addw %0 = %1, %2" [(set_attr "type" "alu_tiny,alu_tiny_w,alu_tiny_x") (set_attr "length" "4,4,8")] ) The issue is to transform (set (match_operand:SI 0 ...)) to (set (match_operand:DI 0 ...)), that is, change SI mode to DI mode. However, using (match_dup 0) in the (define_subst ...) output-template expands to (set (match_operand:SI 0 ...)), that is, not DI mode. So I wrote the (define_subst ...) to force DI mode as follows: (define_subst "arith_zx_subst" [(set (match_operand:SI 0 "" "") (match_operand:SI 1 "" ""))] "" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (match_dup 1)))] ) (define_insn "addsi3<arith_zx>" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (plus:SI (match_operand:SI 1 "register_operand" "r,r,r") (match_operand:SI 2 "register_w32_operand" "r,I10,W32")))] "" "addw %0 = %1, %2" [(set_attr "type" "alu_tiny,alu_tiny_w,alu_tiny_x") (set_attr "length" "4,4,8")] ) That is, the output-template of (define_subst ...) uses (match_operand ...) to force the DI mode, and does not use (match_dup ..) as explained in the Internals. Is that the rigth way to do it? Then, by looking at the mddump, I noticed a seemingly strange value for the attribute generated by the (define_subst ...) expansion: ;; ../../gcc/config/kvx/scalar.md: 1044 (define_insn ("addsi3") [ (set (match_operand:SI 0 ("register_operand") ("=r,r,r")) (plus:SI (match_operand:SI 1 ("register_operand") ("r,r,r")) (match_operand:SI 2 ("register_w32_operand") ("r,I10,W32")))) ] ("") ("addw %0 = %1, %2") [ (set_attr ("type") ("alu_tiny,alu_tiny_w,alu_tiny_x")) (set_attr ("length") ("4,4,8")) ]) ;; ../../gcc/config/kvx/scalar.md: 1044 (define_insn ("addsi3_zx") [ (set (match_operand:DI 0 ("register_operand") ("=r,r,r")) (zero_extend:DI (plus:SI (match_operand:SI 1 ("register_operand") ("r,r,r")) (match_operand:SI 2 ("register_w32_operand") ("r,I10,W32"))))) ] ("") ("addw %0 = %1, %2") [ (set_attr ("type") ("alu_tiny,alu_tiny_w,alu_tiny_x")) (set_attr ("length") ("4,4,8")) (set_attr ("arith_zx_subst") ("no")) ]) Precisely, attribute "arith_zx_subst" is set to "no", whereas it has been declared by GCC in the mddump as: ;; ../../gcc/config/kvx/scalar.md: 1035 (define_attr ("arith_zx_subst") ("no,yes") (const_string ("no"))) Is there a way for "arith_zx_subst" to have the "yes" value in the templates generated by (define_subst ...)? Finally, to have both a template for zero_extend:DI and a template for sign_extend:DI to be generated from the original SI template, I have applied a double (define_subst ...) to the original "addsi3" template as follows: (define_subst_attr "arith_zx" "arith_zx_subst" "" "_zx") (define_subst "arith_zx_subst" [(set (match_operand:SI 0 "" "") (match_operand:SI 1 "" ""))] "" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (match_dup 1)))] ) (define_subst_attr "arith_sx" "arith_sx_subst" "" "_sx") (define_subst_attr "modif_sx" "arith_sx_subst" "" ".sx") (define_subst "arith_sx_subst" [(set (match_operand:SI 0 "" "") (match_operand:SI 1 "" ""))] "" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (match_dup 1)))] ) (define_insn "addsi3<arith_zx><arith_sx>" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (plus:SI (match_operand:SI 1 "register_operand" "r,r,r") (match_operand:SI 2 "register_w32_operand" "r,I10,W32")))] "" "addw<modif_sx> %0 = %1, %2" [(set_attr "type" "alu_tiny,alu_tiny_w,alu_tiny_x") (set_attr "length" "4,4,8")] ) While this produces the expected insn templates "addsi3", "addsi3_zx", "addsi3_sx", is this use of multiple (define_subst ...) is anticipated or correct? I have tried before combining a single (define_subst ...) with a code iterator ANY_EXTEND inside the output-template of (define_subst ...) to iterate zero_extend and sign_extend, but this did not work, as ANY_EXTEND was just replaced by the first in its list of operators. BenoƮt Dinechin CTO XPU Kalray