This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PR84682] disregard address constraints on non-addresses


LRA gets very confused when non-addresses are passed as operands to
asms with address contraints.  Even if other constraints are
available, and the operand is a perfect fit for them, we'd still
attempt to process the operand as an address, and fail miserably at
that.

Truth is, address constraints expect operands allowed by
address_operand, and we make sure this is the case throughout the
compiler, even in asm statements.  The problem was that, if multiple
constraints were available, we wouldn't insist that the operand be
allowed by address_operand, but we would proceed as if it was,
regardless of any other constraints.

To address this problem, I've arranged for LRA to attempt to deal with
address-constrained operands as addresses only when the is_address
flag is set, and to not set this flag in preprocess_constraints for
asm operands that are not allowed by address_operand.

Regstrapped on i686- and x86_64-linux-gnu.  Ok to install?

for  gcc/ChangeLog

	PR rtl-optimization/84682
	* lra-constraints.c (process_address_1): Check is_address flag
	for address constraints.
	(process_alt_operands): Likewise.
	* lra.c (lra_set_insn_recog_data): Pass asm operand locs to
	preprocess_constraints.
	* recog.h (preprocess_constraints): Add oploc parameter.
	Adjust callers.
	* recog.c (preprocess_constraints): Test address_operand for
	CT_ADDRESS constraints.

for  gcc/testsuite/ChangeLog

	PR rtl-optimization/84682
	* gcc.dg/torture/pr84682-1.c: New.
	* gcc.dg/torture/pr84682-2.c: New.
	* gcc.dg/torture/pr84682-3.c: New.
---
 gcc/lra-constraints.c                    |   15 ++++++++++++++-
 gcc/lra.c                                |    3 ++-
 gcc/recog.c                              |   24 +++++++++++++++++-------
 gcc/recog.h                              |    2 +-
 gcc/testsuite/gcc.dg/torture/pr84682-1.c |    5 +++++
 gcc/testsuite/gcc.dg/torture/pr84682-2.c |   10 ++++++++++
 gcc/testsuite/gcc.dg/torture/pr84682-3.c |    8 ++++++++
 7 files changed, 57 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr84682-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr84682-2.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr84682-3.c

diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 59b97540d98f..ae55c86f1777 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -2276,6 +2276,12 @@ process_alt_operands (int only_alternative)
 		      break;
 
 		    case CT_ADDRESS:
+		      /* An asm operand with an address constraint
+			 that doesn't satisfy address_operand has
+			 is_address cleared, so that we don't try to
+			 make a non-address fit.  */
+		      if (!curr_static_id->operand[nop].is_address)
+			break;
 		      /* If we didn't already win, we can reload the address
 			 into a base register.  */
 		      if (satisfies_address_constraint_p (op, cn))
@@ -3236,7 +3242,14 @@ process_address_1 (int nop, bool check_only_p,
       && GET_CODE (XEXP (op, 0)) == SCRATCH)
     return false;
 
-  if (insn_extra_address_constraint (cn))
+  if (insn_extra_address_constraint (cn)
+      /* When we find an asm operand with an address constraint that
+	 doesn't satisfy address_operand to begin with, we clear
+	 is_address, so that we don't try to make a non-address fit.
+	 If the asm statement got this far, it's because other
+	 constraints are available, and we'll use them, disregarding
+	 the unsatisfiable address ones.  */
+      && curr_static_id->operand[nop].is_address)
     decompose_lea_address (&ad, curr_id->operand_loc[nop]);
   /* Do not attempt to decompose arbitrary addresses generated by combine
      for asm operands with loose constraints, e.g 'X'.  */
diff --git a/gcc/lra.c b/gcc/lra.c
index a64d8f1a3011..0a251144026c 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -1039,7 +1039,8 @@ lra_set_insn_recog_data (rtx_insn *insn)
 	{
 	  operand_alternative *op_alt = XCNEWVEC (operand_alternative,
 						  nalt * nop);
-	  preprocess_constraints (nop, nalt, constraints, op_alt);
+	  preprocess_constraints (nop, nalt, constraints, op_alt,
+				  data->operand_loc);
 	  setup_operand_alternative (data, op_alt);
 	}
     }
diff --git a/gcc/recog.c b/gcc/recog.c
index af6a6b01d88c..fa8e261d1476 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -2331,15 +2331,20 @@ extract_insn (rtx_insn *insn)
   which_alternative = -1;
 }
 
-/* Fill in OP_ALT_BASE for an instruction that has N_OPERANDS operands,
-   N_ALTERNATIVES alternatives and constraint strings CONSTRAINTS.
-   OP_ALT_BASE has N_ALTERNATIVES * N_OPERANDS entries and CONSTRAINTS
-   has N_OPERANDS entries.  */
+/* Fill in OP_ALT_BASE for an instruction that has N_OPERANDS
+   operands, N_ALTERNATIVES alternatives and constraint strings
+   CONSTRAINTS.  OP_ALT_BASE has N_ALTERNATIVES * N_OPERANDS entries
+   and CONSTRAINTS has N_OPERANDS entries.  OPLOC should be passed in
+   if the insn is an asm statement and preprocessing should take the
+   asm operands into account, e.g. to determine whether they could be
+   addresses in constraints that require addresses; it should then
+   point to an array of pointers to each operand.  */
 
 void
 preprocess_constraints (int n_operands, int n_alternatives,
 			const char **constraints,
-			operand_alternative *op_alt_base)
+			operand_alternative *op_alt_base,
+			rtx **oploc)
 {
   for (int i = 0; i < n_operands; i++)
     {
@@ -2426,6 +2431,9 @@ preprocess_constraints (int n_operands, int n_alternatives,
 		      break;
 
 		    case CT_ADDRESS:
+		      if (oploc && !address_operand (*oploc[i], VOIDmode))
+			break;
+
 		      op_alt[i].is_address = 1;
 		      op_alt[i].cl
 			= (reg_class_subunion
@@ -2470,7 +2478,8 @@ preprocess_insn_constraints (unsigned int icode)
 
   for (int i = 0; i < n_operands; ++i)
     constraints[i] = insn_data[icode].operand[i].constraint;
-  preprocess_constraints (n_operands, n_alternatives, constraints, op_alt);
+  preprocess_constraints (n_operands, n_alternatives, constraints, op_alt,
+			  NULL);
 
   this_target_recog->x_op_alt[icode] = op_alt;
   return op_alt;
@@ -2493,7 +2502,8 @@ preprocess_constraints (rtx_insn *insn)
       int n_entries = n_operands * n_alternatives;
       memset (asm_op_alt, 0, n_entries * sizeof (operand_alternative));
       preprocess_constraints (n_operands, n_alternatives,
-			      recog_data.constraints, asm_op_alt);
+			      recog_data.constraints, asm_op_alt,
+			      NULL);
       recog_op_alt = asm_op_alt;
     }
 }
diff --git a/gcc/recog.h b/gcc/recog.h
index 4a47ff23ca95..eca62803458c 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -136,7 +136,7 @@ extern void extract_constrain_insn (rtx_insn *insn);
 extern void extract_constrain_insn_cached (rtx_insn *);
 extern void extract_insn_cached (rtx_insn *);
 extern void preprocess_constraints (int, int, const char **,
-				    operand_alternative *);
+				    operand_alternative *, rtx **);
 extern const operand_alternative *preprocess_insn_constraints (unsigned int);
 extern void preprocess_constraints (rtx_insn *);
 extern rtx_insn *peep2_next_insn (int);
diff --git a/gcc/testsuite/gcc.dg/torture/pr84682-1.c b/gcc/testsuite/gcc.dg/torture/pr84682-1.c
new file mode 100644
index 000000000000..b189ed78cdc3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr84682-1.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+void b(char a) {
+        asm("" : : "pir" (a));
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr84682-2.c b/gcc/testsuite/gcc.dg/torture/pr84682-2.c
new file mode 100644
index 000000000000..5abda5fd136c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr84682-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+int a;
+void b() {
+  float c;
+  for (int d; d;)
+    ;
+  a = c;
+  asm("" : : "pir"(c));
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr84682-3.c b/gcc/testsuite/gcc.dg/torture/pr84682-3.c
new file mode 100644
index 000000000000..543a307d6c12
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr84682-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* This is like pr84682-1.c, but with an extra memory constraint, to
+   check that we don't disable process_address altogether just because
+   of the disabled address constraint.  */
+
+void b(char a) {
+        asm("" : : "pmir" (a));
+}


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]