diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 43d4cb8..d076ad6 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5460,6 +5460,7 @@ strip_address_mutations (rtx *loc, enum rtx_code
*outer_code)
 	/* (and ... (const_int -X)) is used to align to X bytes.  */
 	loc = &XEXP (*loc, 0);
       else if (code == SUBREG
+	       && GET_MODE (*loc) == Pmode
                && !OBJECT_P (SUBREG_REG (*loc))
                && subreg_lowpart_p (*loc))
 	/* (subreg (operator ...) ...) inside and is used for mode
diff --git a/gcc/testsuite/gcc.target/i386/pr55116-2.c
b/gcc/testsuite/gcc.target/i386/pr55116-2.c
new file mode 100644
index 0000000..7ef8ead
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr55116-2.c
@@ -0,0 +1,86 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
+
+typedef struct rtx_def *rtx;
+enum rtx_code { MINUS };
+union rtunion_def {
+  rtx rt_rtx;
+};
+typedef union rtunion_def rtunion;
+struct rtx_def {
+  enum rtx_code code: 16;
+  union u {
+    rtunion fld[1];
+  }
+  u;
+};
+rtx simplify_binary_operation (enum rtx_code code, int mode,
+			       rtx op0, rtx op1);
+struct simplify_plus_minus_op_data {
+  rtx op;
+  short neg;
+};
+void simplify_plus_minus (enum rtx_code code, int mode, rtx op0, rtx op1)
+{
+  struct simplify_plus_minus_op_data ops[8];
+  rtx tem = (rtx) 0;
+  int n_ops = 2, input_ops = 2;
+  int changed, canonicalized = 0;
+  int i, j;
+  __builtin_memset (ops, 0, sizeof (ops));
+  do
+    {
+      changed = 0;
+      for (i = 0; i < n_ops; i++)
+	{
+	  rtx this_op = ops[i].op;
+	  int this_neg = ops[i].neg;
+	  enum rtx_code this_code = ((enum rtx_code) (this_op)->code);
+	  switch (this_code)
+	    {
+	    case MINUS:
+	      if (n_ops == 7)
+		return;
+	      n_ops++;
+	      input_ops++;
+	      changed = 1;
+	      canonicalized |= this_neg;
+	      break;
+	    }
+	}
+    }
+  while (changed);
+  do
+    {
+      j =  n_ops - 1;
+      for (i = n_ops - 1; j >= 0; j--)
+	{
+	  rtx lhs = ops[j].op, rhs = ops[i].op;
+	  int lneg = ops[j].neg, rneg = ops[i].neg;
+	  if (lhs != 0 && rhs != 0)
+	    {
+	      enum rtx_code ncode = MINUS;
+	      if (((enum rtx_code) (lhs)->code) == MINUS)
+		tem = simplify_binary_operation (ncode, mode, lhs, rhs);
+	      if (tem && ! (((enum rtx_code) (tem)->code) == MINUS
+			    && ((((((tem)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx) == lhs
+			    && ((((((tem)->u.fld[0]).rt_rtx))->u.fld[1]).rt_rtx) == rhs))
+		{
+		  lneg &= rneg;
+		  ops[i].op = tem;
+		  ops[i].neg = lneg;
+		  ops[j].op = (rtx) 0;
+		  changed = 1;
+		  canonicalized = 1;
+		}
+	    }
+	}
+      for (i = 0, j = 0; j < n_ops; j++)
+	if (ops[j].op)
+	  {
+	    ops[i] = ops[j];
+	    i++;
+	  }
+    }
+  while (changed);
+}
