]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
amdgcn: prefer scalar ALU instructions over vector
authorSandra Loosemore <sloosemore@baylibre.com>
Mon, 23 Feb 2026 16:10:01 +0000 (16:10 +0000)
committerSandra Loosemore <sloosemore@baylibre.com>
Mon, 23 Feb 2026 17:34:25 +0000 (17:34 +0000)
This patch fixes a performance regression that crept in with commit
gcc-16-2237-g0eee2dd2865 ("Don't clobber VCC if we don't need to").
Removing the clobber from vector-register ALU insn pattern
alternatives seems to make LRA think those alternatives are less
costly than the scalar-register alternatives, which do need the
clobber, resulting in extra move instructions instead.

In this patch I've adjusted all the ALU patterns (not just the ones
modified by the above-mentioned commit) where the scalar-register
alternatives clobber and vector-register alternatives don't, to
slightly disparage the latter using the "?" constraint modifier.

I also fixed a related issue: the comment on addptrdi3 says the
scalar-register alternative is preferred, but it was listed after the
vector alternative, so other things being equal it would still prefer
the vector expansion.  I've not changed the constraints, but simply
flipped the order of the alternatives.

Thanks to Tobias Burnus for identifying the commit that caused the
performance regression, Andrew Stubbs for making the connection between
clobbers and LRA costs, and Arsen Arsenović for setting up the benchmark
scripting I used to compare results.

gcc/ChangeLog
* config/gcn/gcn.md (addsi3): Disparage vector alternative.
(addptrdi3): Reverse order of vector and scalar alternatives
to prefer the latter.
(subsi3): Disparage vector alternatives.
(mulsi3): Likewise.
(muldi3): Likewise.
(bitunop <expander>si2): Likewise.
(vec_and_scalar_com <expander>si3): Likewise.
(vec_and_scalar_nocom <expander>si3): Likewise.
(one_cmpldi2): Likewise.
(vec_and_scalar64_com <expander>di3): Likwise.
(vec_and_scalar64_nocom <expander>di3): Likwise.

gcc/config/gcn/gcn.md

index 5957b29f748701ebee91045af5eaa64f83b23b54..c49bd6cf8bd26eadad509930d1815913f7031b52 100644 (file)
 ;; {{{ ALU special cases: Plus
 
 (define_insn "addsi3"
-  [(set (match_operand:SI 0 "register_operand"         "= Sg, Sg, Sg,   v")
+  [(set (match_operand:SI 0 "register_operand"         "= Sg, Sg, Sg,  ?v")
         (plus:SI (match_operand:SI 1 "gcn_alu_operand" "%SgA,  0,SgA,   v")
                 (match_operand:SI 2 "gcn_alu_operand" " SgA,SgJ,  B,vBSv")))
    (clobber (match_scratch:BI 3                               "= cs, cs, cs,   X"))]
 ; The SGPR alternative is preferred as it is typically used with mov_sgprbase.
 
 (define_insn "addptrdi3"
-  [(set (match_operand:DI 0 "register_operand"          "= v, Sg")
+  [(set (match_operand:DI 0 "register_operand"          "= Sg, v")
     (unspec:DI [
-       (plus:DI (match_operand:DI 1 "register_operand"  "^v0,Sg0")
-                (match_operand:DI 2 "nonmemory_operand" "vDA,SgDB"))]
+       (plus:DI (match_operand:DI 1 "register_operand"  " Sg0,^v0")
+                (match_operand:DI 2 "nonmemory_operand" "SgDB,vDA"))]
        UNSPEC_ADDPTR))]
   ""
   {
     if (which_alternative == 0)
-      {
-       rtx new_operands[4] = { operands[0], operands[1], operands[2],
-                               gen_rtx_REG (DImode, CC_SAVE_REG) };
-
-       output_asm_insn ("v_add_co_u32\t%L0, %3, %L2, %L1", new_operands);
-       output_asm_insn ("{v_addc_co_u32|v_add_co_ci_u32}\t%H0, %3, %H2, %H1, %3",
-                        new_operands);
-      }
-    else
       {
        rtx new_operands[4] = { operands[0], operands[1], operands[2],
                                gen_rtx_REG (BImode, CC_SAVE_REG) };
        output_asm_insn ("s_addc_u32\t%H0, %H1, %H2", new_operands);
        output_asm_insn ("s_cmpk_lg_u32\t%3, 0", new_operands);
       }
+    else
+      {
+       rtx new_operands[4] = { operands[0], operands[1], operands[2],
+                               gen_rtx_REG (DImode, CC_SAVE_REG) };
+
+       output_asm_insn ("v_add_co_u32\t%L0, %3, %L2, %L1", new_operands);
+       output_asm_insn ("{v_addc_co_u32|v_add_co_ci_u32}\t%H0, %3, %H2, %H1, %3",
+                        new_operands);
+      }
 
     return "";
   }
-  [(set_attr "type" "vmult,mult")
-   (set_attr "length" "16,24")])
+  [(set_attr "type" "mult,vmult")
+   (set_attr "length" "24,16")])
 
 ;; }}}
 ;; {{{ ALU special cases: Minus
 
 (define_insn "subsi3"
-  [(set (match_operand:SI 0 "register_operand"          "=Sg, Sg,    v,   v")
+  [(set (match_operand:SI 0 "register_operand"          "=Sg, Sg,   ?v,  ?v")
        (minus:SI (match_operand:SI 1 "gcn_alu_operand" "SgA,SgA,    v,vBSv")
                  (match_operand:SI 2 "gcn_alu_operand" "SgA,  B, vBSv,   v")))
    (clobber (match_scratch:BI 3                                "=cs, cs,    X,   X"))]
 ; The "s_mulk_i32" variant sets SCC to indicate overflow (which we don't care
 ; about here, but we need to indicate the clobbering).
 (define_insn "mulsi3"
-  [(set (match_operand:SI 0 "register_operand"        "= Sg,Sg, Sg,   v")
+  [(set (match_operand:SI 0 "register_operand"        "= Sg,Sg, Sg,  ?v")
         (mult:SI (match_operand:SI 1 "gcn_alu_operand" "%SgA, 0,SgA,   v")
                 (match_operand:SI 2 "gcn_alu_operand" " SgA, J,  B,vASv")))
    (clobber (match_scratch:BI 3                                 "=X,cs,  X,   X"))]
   })
 
 (define_insn_and_split "muldi3"
-  [(set (match_operand:DI 0 "register_operand"         "=&Sg,&Sg, &v,&v")
-       (mult:DI (match_operand:DI 1 "register_operand" "%Sg, Sg,  v, v")
-                (match_operand:DI 2 "nonmemory_operand" "Sg,  i,vSv, A")))
+  [(set (match_operand:DI 0 "register_operand"         "=&Sg,&Sg,?&v,?&v")
+       (mult:DI (match_operand:DI 1 "register_operand" "%Sg, Sg,  v,  v")
+                (match_operand:DI 2 "nonmemory_operand" "Sg,  i,vSv,  A")))
    (clobber (match_scratch:SI 3 "=&Sg,&Sg,&v,&v"))
    (clobber (match_scratch:BI 4  "=cs, cs, X, X"))]
   ""
 (define_code_attr popcount_extra_op [(not "") (popcount ", 0")])
 
 (define_insn "<expander>si2"
-  [(set (match_operand:SI 0 "register_operand"  "=Sg,   v")
+  [(set (match_operand:SI 0 "register_operand"  "=Sg,  ?v")
         (bitunop:SI
          (match_operand:SI 1 "gcn_alu_operand" "SgB,vSvB")))
    (clobber (match_scratch:BI 2                        "=cs,   X"))]
 (define_code_iterator vec_and_scalar_nocom [ashift lshiftrt ashiftrt])
 
 (define_insn "<expander>si3"
-  [(set (match_operand:SI 0 "gcn_valu_dst_operand"    "= Sg,   v,RD")
+  [(set (match_operand:SI 0 "gcn_valu_dst_operand"    "= Sg,  ?v,?RD")
         (vec_and_scalar_com:SI
          (match_operand:SI 1 "gcn_valu_src0_operand" "%SgA,vSvB, 0")
          (match_operand:SI 2 "gcn_alu_operand"       " SgB,   v, v")))
    (set_attr "length" "8")])
 
 (define_insn "<expander>si3"
-  [(set (match_operand:SI 0 "register_operand"  "=Sg, Sg,   v")
+  [(set (match_operand:SI 0 "register_operand"  "=Sg, Sg,  ?v")
         (vec_and_scalar_nocom:SI
          (match_operand:SI 1 "gcn_alu_operand" "SgB,SgA,   v")
          (match_operand:SI 2 "gcn_alu_operand" "SgA,SgB,vSvB")))
 ;; {{{ ALU: generic 64-bit
 
 (define_insn_and_split "one_cmpldi2"
-  [(set (match_operand:DI 0 "register_operand"        "=Sg,    v")
+  [(set (match_operand:DI 0 "register_operand"        "=Sg,   ?v")
        (not:DI (match_operand:DI 1 "gcn_alu_operand" "SgA,vSvDB")))
    (clobber (match_scratch:BI 2                              "=cs,    X"))]
   ""
 (define_code_iterator vec_and_scalar64_com [and ior xor])
 
 (define_insn_and_split "<expander>di3"
-   [(set (match_operand:DI 0 "register_operand"  "= Sg,    v")
+   [(set (match_operand:DI 0 "register_operand"  "= Sg,   ?v")
         (vec_and_scalar64_com:DI
          (match_operand:DI 1 "gcn_alu_operand"  "%SgA,vSvDB")
           (match_operand:DI 2 "gcn_alu_operand" " SgC,    v")))
    (set_attr "length" "8")])
 
 (define_insn "<expander>di3"
-  [(set (match_operand:DI 0 "register_operand"   "=Sg, Sg,   v")
+  [(set (match_operand:DI 0 "register_operand"   "=Sg, Sg,  ?v")
        (vec_and_scalar_nocom:DI
          (match_operand:DI 1 "gcn_alu_operand"  "SgC,SgA,   v")
          (match_operand:SI 2 "gcn_alu_operand"  "SgA,SgC,vSvC")))