This patch fixes a wrong-code bug that can occur with subv64di3.

The pattern uses '0' constraints to override the early-clobber modifier, meaning that the output can be in the same register as one of the inputs, whilst still disallowing overlapping pairs of registers (which are the real problem).

The problem was that, in GCC 9, it used to be possible to have a '0' in all the operands and have it match just one of them, but now it ends up forcing *all* the inputs to match, resulting in wrong code. (It's possible that this never gave the benefits intended, but just didn't produce bad code?)

Adding an alternatives for each permutation fixes the problem. This has already been done for many other patterns.

Andrew
Fix amdgcn issue with '0' constraints

2020-01-06  Andrew Stubbs  <a...@codesourcery.com>

	gcc/
	* config/gcn/gcn-valu.md (subv64di3): Use separate alternatives for
	'0' matching inputs.
	(subv64di3_exec): Likewise.

diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index 9baef24b1c8..e301a4356ec 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -1292,10 +1292,10 @@
    (set_attr "length" "8")])
 
 (define_insn_and_split "subv64di3"
-  [(set (match_operand:V64DI 0 "register_operand"  "=  &v,   &v")
-	(minus:V64DI
-	  (match_operand:V64DI 1 "gcn_alu_operand" "vSvB0,   v0")
-	  (match_operand:V64DI 2 "gcn_alu_operand" "   v0,vSvB0")))
+  [(set (match_operand:V64DI 0 "register_operand"  "= &v,   &v,   &v,  &v")
+	(minus:V64DI                                                 
+	  (match_operand:V64DI 1 "gcn_alu_operand" "vSvB,vSvB0,    v,  v0")
+	  (match_operand:V64DI 2 "gcn_alu_operand" "  v0,    v,vSvB0,vSvB")))
    (clobber (reg:DI VCC_REG))]
   ""
   "#"
@@ -1318,17 +1318,17 @@
     DONE;
   }
   [(set_attr "type" "vmult")
-   (set_attr "length" "8,8")])
+   (set_attr "length" "8")])
 
 (define_insn_and_split "subv64di3_exec"
-  [(set (match_operand:V64DI 0 "register_operand"	       "=  &v,   &v")
-	(vec_merge:V64DI
-	  (minus:V64DI
-	    (match_operand:V64DI 1 "gcn_alu_operand"	       "vSvB0,   v0")
-	    (match_operand:V64DI 2 "gcn_alu_operand"	       "   v0,vSvB0"))
+  [(set (match_operand:V64DI 0 "register_operand"    "= &v,   &v,   &v,  &v")
+	(vec_merge:V64DI                                                         
+	  (minus:V64DI                                                           
+	    (match_operand:V64DI 1 "gcn_alu_operand" "vSvB,vSvB0,    v,  v0")
+	    (match_operand:V64DI 2 "gcn_alu_operand" "  v0,    v,vSvB0,vSvB"))
 	  (match_operand:V64DI 3 "gcn_register_or_unspec_operand"
-							       "   U0,   U0")
-	  (match_operand:DI 4 "gcn_exec_reg_operand"	       "    e,    e")))
+						     "  U0,   U0,   U0,  U0")
+	  (match_operand:DI 4 "gcn_exec_reg_operand" "   e,    e,    e,   e")))
    (clobber (reg:DI VCC_REG))]
   "register_operand (operands[1], VOIDmode)
    || register_operand (operands[2], VOIDmode)"
@@ -1357,7 +1357,7 @@
     DONE;
   }
   [(set_attr "type" "vmult")
-   (set_attr "length" "8,8")])
+   (set_attr "length" "8")])
 
 (define_insn_and_split "addv64di3_dup"
   [(set (match_operand:V64DI 0 "register_operand"   "= &v")

Reply via email to