aboutsummaryrefslogtreecommitdiff
path: root/gcc/alias.c
diff options
context:
space:
mode:
authorJeffrey A Law <law@cygnus.com>1999-05-30 23:51:39 +0000
committerJeff Law <law@gcc.gnu.org>1999-05-30 17:51:39 -0600
commit3c567fae5dd5c0d44cc6161ba6be51fea07e55e5 (patch)
tree5be7f88c52da36cd25e2163b4d94ea160ddd4246 /gcc/alias.c
parent71fb00565269ddc7398243b36f4615f601135e57 (diff)
downloadgcc-3c567fae5dd5c0d44cc6161ba6be51fea07e55e5.zip
gcc-3c567fae5dd5c0d44cc6161ba6be51fea07e55e5.tar.gz
gcc-3c567fae5dd5c0d44cc6161ba6be51fea07e55e5.tar.bz2
alias.c (find_base_term): Improve handling of addresses constructed from binary operations.
* alias.c (find_base_term): Improve handling of addresses constructed from binary operations. From-SVN: r27263
Diffstat (limited to 'gcc/alias.c')
-rw-r--r--gcc/alias.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/gcc/alias.c b/gcc/alias.c
index 3bfb440..9d8aac7 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -746,10 +746,55 @@ find_base_term (x)
case PLUS:
case MINUS:
{
- rtx tmp = find_base_term (XEXP (x, 0));
- if (tmp)
- return tmp;
- return find_base_term (XEXP (x, 1));
+ rtx tmp1 = XEXP (x, 0);
+ rtx tmp2 = XEXP (x, 1);
+
+ /* This is a litle bit tricky since we have to determine which of
+ the two operands represents the real base address. Otherwise this
+ routine may return the index register instead of the base register.
+
+ That may cause us to believe no aliasing was possible, when in
+ fact aliasing is possible.
+
+ We use a few simple tests to guess the base register. Additional
+ tests can certainly be added. For example, if one of the operands
+ is a shift or multiply, then it must be the index register and the
+ other operand is the base register. */
+
+ /* If either operand is known to be a pointer, then use it
+ to determine the base term. */
+ if (REG_P (tmp1) && REGNO_POINTER_FLAG (REGNO (tmp1)))
+ return find_base_term (tmp1);
+
+ if (REG_P (tmp2) && REGNO_POINTER_FLAG (REGNO (tmp2)))
+ return find_base_term (tmp2);
+
+ /* Neither operand was known to be a pointer. Go ahead and find the
+ base term for both operands. */
+ tmp1 = find_base_term (tmp1);
+ tmp2 = find_base_term (tmp2);
+
+ /* If either base term is named object or a special address
+ (like an argument or stack reference), then use it for the
+ base term. */
+ if (tmp1
+ && (GET_CODE (tmp1) == SYMBOL_REF
+ || GET_CODE (tmp1) == LABEL_REF
+ || (GET_CODE (tmp1) == ADDRESS
+ && GET_MODE (tmp1) != VOIDmode)))
+ return tmp1;
+
+ if (tmp2
+ && (GET_CODE (tmp2) == SYMBOL_REF
+ || GET_CODE (tmp2) == LABEL_REF
+ || (GET_CODE (tmp2) == ADDRESS
+ && GET_MODE (tmp2) != VOIDmode)))
+ return tmp2;
+
+ /* We could not determine which of the two operands was the
+ base register and which was the index. So we can determine
+ nothing from the base alias check. */
+ return 0;
}
case AND: