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



Reply via email to