aboutsummaryrefslogtreecommitdiff
path: root/gcc/rtlanal.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r--gcc/rtlanal.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index f5e104fbdb9..f45f888517c 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -153,6 +153,10 @@ rtx_varies_p (x, for_alias)
case LABEL_REF:
return 0;
+ case ADDRESSOF:
+ /* This will resolve to some offset from the frame pointer. */
+ return 0;
+
case REG:
/* Note that we have to test for the actual rtx used for the frame
and arg pointers and not just the register number in case we have
@@ -225,6 +229,10 @@ rtx_addr_can_trap_p (x)
case LABEL_REF:
return 0;
+ case ADDRESSOF:
+ /* This will resolve to some offset from the frame pointer. */
+ return 0;
+
case REG:
/* As in rtx_varies_p, we have to use the actual rtx, not reg number. */
if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
@@ -269,6 +277,90 @@ rtx_addr_can_trap_p (x)
return 1;
}
+/* Return true if X is an address that is known to not be zero. */
+
+bool
+nonzero_address_p (x)
+ rtx x;
+{
+ enum rtx_code code = GET_CODE (x);
+
+ switch (code)
+ {
+ case SYMBOL_REF:
+ return !SYMBOL_REF_WEAK (x);
+
+ case LABEL_REF:
+ return true;
+
+ case ADDRESSOF:
+ /* This will resolve to some offset from the frame pointer. */
+ return true;
+
+ case REG:
+ /* As in rtx_varies_p, we have to use the actual rtx, not reg number. */
+ if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
+ || x == stack_pointer_rtx
+ || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM]))
+ return true;
+ /* All of the virtual frame registers are stack references. */
+ if (REGNO (x) >= FIRST_VIRTUAL_REGISTER
+ && REGNO (x) <= LAST_VIRTUAL_REGISTER)
+ return true;
+ return false;
+
+ case CONST:
+ return nonzero_address_p (XEXP (x, 0));
+
+ case PLUS:
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ /* Pointers aren't allowed to wrap. If we've got a register
+ that is known to be a pointer, and a positive offset, then
+ the composite can't be zero. */
+ if (INTVAL (XEXP (x, 1)) > 0
+ && REG_P (XEXP (x, 0))
+ && REG_POINTER (XEXP (x, 0)))
+ return true;
+
+ return nonzero_address_p (XEXP (x, 0));
+ }
+ /* Handle PIC references. */
+ else if (XEXP (x, 0) == pic_offset_table_rtx
+ && CONSTANT_P (XEXP (x, 1)))
+ return true;
+ return false;
+
+ case PRE_MODIFY:
+ /* Similar to the above; allow positive offsets. Further, since
+ auto-inc is only allowed in memories, the register must be a
+ pointer. */
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) > 0)
+ return true;
+ return nonzero_address_p (XEXP (x, 0));
+
+ case PRE_INC:
+ /* Similarly. Further, the offset is always positive. */
+ return true;
+
+ case PRE_DEC:
+ case POST_DEC:
+ case POST_INC:
+ case POST_MODIFY:
+ return nonzero_address_p (XEXP (x, 0));
+
+ case LO_SUM:
+ return nonzero_address_p (XEXP (x, 1));
+
+ default:
+ break;
+ }
+
+ /* If it isn't one of the case above, might be zero. */
+ return false;
+}
+
/* Return 1 if X refers to a memory location whose address
cannot be compared reliably with constant addresses,
or if X refers to a BLKmode memory object.