Module Name:    src
Committed By:   rin
Date:           Sat Oct  7 12:10:59 UTC 2023

Modified Files:
        src/external/gpl3/gcc.old/dist/gcc/config/vax: vax.md

Log Message:
gcc.old: vax: PR port-vax/57646 patch provided by Kalvis Duckmanton [21/21]

Define separate instruction patterns for extzv for the cases where the fiel
d width and offset happen to be a multiple of a byte or word.

If in PIC mode, and the source operand to extzv is a memory
reference, and the address of the memory location is an external
symbol, load the address into a temporary register before expanding
the instruction.

Adjust the constraints to the zero_extract instruction pattern to
disallow indexed source operands, as the VAX extzv instruction
computes offsets based on the size of a byte (not a word or a
longword)


To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 \
    src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.md

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.md
diff -u src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.md:1.17 src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.md:1.18
--- src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.md:1.17	Sat Oct  7 12:10:38 2023
+++ src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.md	Sat Oct  7 12:10:59 2023
@@ -827,32 +827,87 @@
   return \"movw %3,%0\";
 }")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=&g")
-	(zero_extract:SI (match_operand:SI 1 "register_operand" "ro")
+;;
+;; Register source, field width is either 8 or 16, field start
+;; is zero - simple, this is a mov[bl].
+;;
+(define_insn "*extzvQISI"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
 			 (match_operand:QI 2 "const_int_operand" "n")
 			 (match_operand:SI 3 "const_int_operand" "n")))]
-  "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+  "INTVAL (operands[3]) == 0
+    && INTVAL (operands[2]) == GET_MODE_BITSIZE ( QImode )"
+  "movzbl %1, %0"
+)
+
+(define_insn "*extzvHISI"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+			 (match_operand:QI 2 "const_int_operand" "n")
+			 (match_operand:SI 3 "const_int_operand" "n")))]
+  "INTVAL (operands[3]) == 0
+    && INTVAL (operands[2]) == GET_MODE_BITSIZE ( HImode )"
+  "movzwl %1, %0"
+)
+
+;;
+;; Register source, field width is the entire register
+;;
+(define_insn "*extzvSISI"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+			 (match_operand:QI 2 "const_int_operand" "n")
+			 (match_operand:SI 3 "const_int_operand" "n")
+
+			 ))]
+  "INTVAL (operands[3]) == 0
+   && INTVAL (operands[2]) == GET_MODE_BITSIZE ( SImode )"
+  "*
+{
+  if (rtx_equal_p (operands[0], operands[1]))
+    return \"\";  /* no-op */
+  return \"movl %1,%0\";
+}")
+
+;; Register source, non-zero field start is handled elsewhere
+
+;; Offsettable memory, field width 8 or 16, field start on
+;; boundary matching the field width.
+
+(define_insn "*extzvQISI2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extract:SI (match_operand:SI 1 "memory_operand" "o")
+			 (match_operand:QI 2 "const_int_operand" "n")
+			 (match_operand:SI 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) == 8
    && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
-   && (REG_P (operands[1])
-       || (MEM_P (operands[1])
-          && ! mode_dependent_address_p (XEXP (operands[1], 0),
-				      MEM_ADDR_SPACE (operands[1]))))"
+   && ! mode_dependent_address_p (XEXP (operands[1], 0),
+				  MEM_ADDR_SPACE (operands[1]))"
   "*
 {
-  if (REG_P (operands[1]))
-    {
-      if (INTVAL (operands[3]) != 0)
-	return \"extzv %3,%2,%1,%0\";
-    }
-  else
-    operands[1]
-      = adjust_address (operands[1],
-			INTVAL (operands[2]) == 8 ? QImode : HImode,
-			INTVAL (operands[3]) / 8);
+  operands[1]
+    = adjust_address (operands[1],
+		      QImode,
+		      INTVAL (operands[3]) / 8);
+  return \"movzbl %1,%0\";
+}")
 
-  if (INTVAL (operands[2]) == 8)
-    return \"movzbl %1,%0\";
+(define_insn "*extzvHISI2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extract:SI (match_operand:SI 1 "memory_operand" "o")
+			 (match_operand:QI 2 "const_int_operand" "n")
+			 (match_operand:SI 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) == 16
+   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+   && ! mode_dependent_address_p (XEXP (operands[1], 0),
+				  MEM_ADDR_SPACE (operands[1]))"
+  "*
+{
+  operands[1]
+    = adjust_address (operands[1],
+                      HImode,
+                      INTVAL (operands[3]) / 8);
   return \"movzwl %1,%0\";
 }")
 
@@ -929,17 +984,26 @@
   return \"rotl %R3,%1,%0\;cvtwl %0,%0\";
 }")
 
+;; When the field position and size are constant and the destination
+;; is a register, extv and extzv are much slower than a rotate followed
+;; by a bicl or sign extension.  Because we might end up choosing ext[z]v
+;; anyway, we can't allow immediate values for the primary source operand.
+
+;; Because some of the instruction sequences generated by this pattern
+;; overwrite the output operand part way through, the output operand
+;; must be marked earlyclobber, may only be a register or memory
+;; operand and must not have any side effects (e.g. pre/post increment)
+;;
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
-	(zero_extract:SI (match_operand:SI 1 "register_operand" "ro")
-			 (match_operand:QI 2 "general_operand" "g")
-			 (match_operand:SI 3 "general_operand" "nrmT")))]
-  ""
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=&ro")
+	(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+			 (match_operand:QI 2 "const_int_operand" "n")
+			 (match_operand:SI 3 "const_int_operand" "n")
+
+			 ))]
+  "INTVAL (operands[3]) != 0"
   "*
 {
-  if (! CONST_INT_P (operands[3]) || ! CONST_INT_P (operands[2])
-      || ! REG_P (operands[0]))
-    return \"extzv %3,%2,%1,%0\";
   if (INTVAL (operands[2]) == 8)
     return \"rotl %R3,%1,%0\;movzbl %0,%0\";
   if (INTVAL (operands[2]) == 16)
@@ -1041,13 +1105,70 @@
   [(set (match_operand:SI 0 "general_operand" "")
 	(zero_extract:SI (match_operand:SI 1 "general_operand" "")
 			 (match_operand:QI 2 "general_operand" "")
-			 (match_operand:SI 3 "general_operand" "")))]
+			 (match_operand:SI 3 "general_operand" ""))
+   )]
   ""
-  "")
+  "{
+    if (CONST_INT_P (operands[1]))
+      {
+	/*
+	 * extzv of a constant doesn't work, so load the constant
+	 * into a register.
+	 */
+	rtx temp = gen_reg_rtx (SImode);
+	emit_move_insn (temp, operands[1]);
+	operands[1] = temp;
+      }
+
+
+    /*
+     * If the source operand is a memory reference, and the address
+     * is a symbol, and we're in PIC mode, load the address into a
+     * register.  Don't evaluate the field start or width at this time.
+     */
+    if (flag_pic
+     /*	&& !reload_completed */
+	&& MEM_P (operands[1])
+	&& !mode_dependent_address_p (XEXP (operands[1], 0),
+				      MEM_ADDR_SPACE (operands[1]))
+	&& SYMBOL_REF_P (XEXP (operands[1], 0))
+	&& !SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))
+       )
+      {
+	rtx address = XEXP (operands[1], 0);
+	rtx temp = gen_reg_rtx (Pmode);
+	emit_move_insn (temp, address);
+	/* copy the original memory reference, replacing the address */
+	operands[1] = change_address (operands[1], VOIDmode, temp);
+	set_mem_align (operands[1], MEM_ALIGN (operands[1]));
+      }
+    else
+      if ((MEM_P (operands[1]) && !CONST_INT_P (operands[2]))
+	  || SUBREG_P (operands[1])
+	 )
+	{
+	  /* Memory addresses for extzv are bytes, so load the source
+	     operand into a register */
+	  rtx temp = gen_reg_rtx (SImode);
+	  emit_move_insn (temp, operands[1]);
+	  operands[1] = temp;
+	}
+      else if (address_operand (operands[1], SImode))
+	{
+	  operands[1] = force_reg (SImode, operands[1]);
+	}
+
+  }"
+)
+
+;;
+;; Operand 1 must not, under any circumstances, be an indexed operand
+;; as extzv computes indices based on the size of a byte.
+;;
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
-	(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=&g")
+	(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "rQ")
 			 (match_operand:QI 2 "general_operand" "g")
 			 (match_operand:SI 3 "general_operand" "nrmT")))]
   ""
@@ -1056,10 +1177,7 @@
   if (! REG_P (operands[0]) || ! CONST_INT_P (operands[2])
       || ! CONST_INT_P (operands[3])
       || INTVAL (operands[2]) + INTVAL (operands[3]) > 32
-      || side_effects_p (operands[1])
-      || (MEM_P (operands[1])
-	  && mode_dependent_address_p (XEXP (operands[1], 0),
-				       MEM_ADDR_SPACE (operands[1]))))
+      || side_effects_p (operands[1]))
     return \"extzv %3,%2,%1,%0\";
   if (INTVAL (operands[2]) == 8)
     return \"rotl %R3,%1,%0\;movzbl %0,%0\";

Reply via email to