diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2e8690f352da8ac8607e335ec851da22d82ddc56..724a8b90a2a2e4bc25270b2f94bbbffd070010ee 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,12 @@
-<<<<<<< ChangeLog
+2002-01-22  Richard Henderson  <rth@redhat.com>
+
+	* config/alpha/alpha.c (some_small_symbolic_mem_operand) Use
+	for_each_rtx instead of assuming we're already looking at the MEM.
+	(split_small_symbolic_mem_operand): Likewise.
+	* config/alpha/alpha.h (PREDICATE_CODES): Update.
+	* config/alpha/alpha.md (small symbolic memory splitters): Update.
+
+2002-01-22  Richard Henderson  <rth@redhat.com>
 
 	* config/alpha/alpha.md (divmodsi_internal_er): Generate lituse
 	sequence number for the literal.
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 8204c782cdfc6a7d20b3036483be78c78c0619d7..3bc6c6c92c70f6dfd5261e29e83d749a4bf34a52 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -116,6 +116,10 @@ int alpha_this_gpdisp_sequence_number;
 /* Declarations of static functions.  */
 static bool decl_in_text_section
   PARAMS ((tree));
+static int some_small_symbolic_mem_operand_1
+  PARAMS ((rtx *, void *));
+static int split_small_symbolic_mem_operand_1
+  PARAMS ((rtx *, void *));
 static bool local_symbol_p
   PARAMS ((rtx));
 static void alpha_set_memflags_1
@@ -1874,51 +1878,57 @@ some_small_symbolic_mem_operand (x, mode)
      rtx x;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  /* Get rid of SIGN_EXTEND, etc.  */
-  while (GET_RTX_CLASS (GET_CODE (x)) == '1')
-    x = XEXP (x, 0);
+  return for_each_rtx (&x, some_small_symbolic_mem_operand_1, NULL);
+}
+
+static int
+some_small_symbolic_mem_operand_1 (px, data)
+     rtx *px;
+     void *data ATTRIBUTE_UNUSED;
+{
+  rtx x = *px;
 
   if (GET_CODE (x) != MEM)
     return 0;
-
   x = XEXP (x, 0);
+
   /* If this is an ldq_u type address, discard the outer AND.  */
-  if (GET_CODE (x) == AND && GET_MODE (x) == DImode
-      && GET_CODE (XEXP (x, 1)) == CONST_INT
-      && INTVAL (XEXP (x, 1)) == -8)
+  if (GET_CODE (x) == AND)
     x = XEXP (x, 0);
-  return small_symbolic_operand (x, Pmode);
+
+  return small_symbolic_operand (x, Pmode) ? 1 : -1;
 }
 
 rtx
 split_small_symbolic_mem_operand (x)
      rtx x;
 {
-  rtx *p;
+  x = copy_rtx (x);
+  for_each_rtx (&x, split_small_symbolic_mem_operand_1, NULL);
+  return x;
+}
 
-  if (GET_CODE (x) == MEM)
-    {
-      rtx tmp = XEXP (x, 0);
+static int
+split_small_symbolic_mem_operand_1 (px, data)
+     rtx *px;
+     void *data ATTRIBUTE_UNUSED;
+{
+  rtx x = *px;
 
-      if (GET_CODE (tmp) == AND && GET_MODE (tmp) == DImode
-	  && GET_CODE (XEXP (tmp, 1)) == CONST_INT
-	  && INTVAL (XEXP (tmp, 1)) == -8)
-	{
-	  tmp = gen_rtx_LO_SUM (DImode, pic_offset_table_rtx, XEXP (tmp, 0));
-	  tmp = gen_rtx_AND (DImode, tmp, GEN_INT (-8));
-	}
-      else
-	tmp = gen_rtx_LO_SUM (DImode, pic_offset_table_rtx, tmp);
-      return replace_equiv_address (x, tmp);
-    }
+  if (GET_CODE (x) != MEM)
+    return 0;
 
-  x = copy_rtx (x);
-  p = &x;
-  while (GET_RTX_CLASS (GET_CODE (*p)) == '1')
-    p = &XEXP (*p, 0);
+  px = &XEXP (x, 0), x = *px;
+  if (GET_CODE (x) == AND)
+    px = &XEXP (x, 0), x = *px;
 
-  *p = split_small_symbolic_mem_operand (*p);
-  return x;
+  if (small_symbolic_operand (x, Pmode))
+    {
+      x = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, x);
+      *px = x;
+    }
+
+  return -1;
 }
 
 /* Try a machine-dependent way of reloading an illegitimate address
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index 0ff8ae3d398d9901aebaf3efac58297862eead20..dd8d82072613620219b9f09cddf5c073e773cc63 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -2079,8 +2079,7 @@ do {						\
   {"reg_no_subreg_operand", {REG}},					\
   {"addition_operation", {PLUS}},					\
   {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},			\
-  {"some_small_symbolic_mem_operand", {MEM, SIGN_EXTEND, ZERO_EXTEND,	\
-				       FLOAT_EXTEND}},
+  {"some_small_symbolic_mem_operand", {SET, PARALLEL}},
 
 /* Define the `__builtin_va_list' type for the ABI.  */
 #define BUILD_VA_LIST_TYPE(VALIST) \
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 94aeec69d7b56c072c07da264ae1d26727868fb5..e8a1a8c3c75b1d8912a580389562bdd0fee3e05d 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -5501,19 +5501,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   "operands[2] = pic_offset_table_rtx;")
 
 (define_split
-  [(set (match_operand 0 "some_small_symbolic_mem_operand" "")
-	(match_operand 1 "" ""))]
+  [(match_operand 0 "some_small_symbolic_mem_operand" "")]
   "TARGET_EXPLICIT_RELOCS && reload_completed"
-  [(set (match_dup 0) (match_dup 1))]
+  [(match_dup 0)]
   "operands[0] = split_small_symbolic_mem_operand (operands[0]);")
 
-(define_split
-  [(set (match_operand 0 "" "")
-	(match_operand 1 "some_small_symbolic_mem_operand" ""))]
-  "TARGET_EXPLICIT_RELOCS && reload_completed"
-  [(set (match_dup 0) (match_dup 1))]
-  "operands[1] = split_small_symbolic_mem_operand (operands[1]);")
-
 (define_insn "movdi_er_high_g"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 836457ff0ecbbd12ae0bc03dd1af75475c69dd92..67c44656284b6299b066a450ae7604cbb91a22fb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2002-01-22  Richard Henderson  <rth@redhat.com>
+
+	* gcc.dg/20020122-4.c: New.
+
 2002-01-22  H.J. Lu <hjl@gnu.org>
 
 	* g++.dg/special/ecos.exp: Append .exe instead of a.out as the
diff --git a/gcc/testsuite/gcc.dg/20020122-4.c b/gcc/testsuite/gcc.dg/20020122-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..9109bcfdad903b209411fed28c4a046fbc793b51
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20020122-4.c
@@ -0,0 +1,10 @@
+/* Alpha -msmall-data didn't transform (mem (symbol_ref)) to
+   (mem (lo_sum pic (symbol_ref))) within an asm at the right time.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fpic" } */
+
+void foo()
+{
+  static int test;
+  asm volatile ("" : "=m"(test) : "m"(test));
+}