\f
/* Extract the parts of an RTL expression that is a valid memory address
for an instruction. Return 0 if the structure of the address is
- grossly off. Return -1 if the address contains ASHIFT, so it is not
- strictly valid, but still used for computing length of lea instruction. */
+ grossly off. */
int
ix86_decompose_address (rtx addr, struct ix86_address *out)
HOST_WIDE_INT scale = 1;
rtx scale_rtx = NULL_RTX;
rtx tmp;
- int retval = 1;
addr_space_t seg = ADDR_SPACE_GENERIC;
/* Allow zero-extended SImode addresses,
if (CONST_INT_P (addr))
return 0;
}
+ else if (GET_CODE (addr) == AND)
+ {
+ /* For ASHIFT inside AND, combine will not generate
+ canonical zero-extend. Merge mask for AND and shift_count
+ to check if it is canonical zero-extend. */
+ tmp = XEXP (addr, 0);
+ rtx mask = XEXP (addr, 1);
+ if (tmp && GET_CODE(tmp) == ASHIFT)
+ {
+ rtx shift_val = XEXP (tmp, 1);
+ if (CONST_INT_P (mask) && CONST_INT_P (shift_val)
+ && (((unsigned HOST_WIDE_INT) INTVAL(mask)
+ | ((HOST_WIDE_INT_1U << INTVAL(shift_val)) - 1))
+ == 0xffffffff))
+ {
+ addr = lowpart_subreg (SImode, XEXP (addr, 0),
+ DImode);
+ }
+ }
+
+ }
}
/* Allow SImode subregs of DImode addresses,
if ((unsigned HOST_WIDE_INT) scale > 3)
return 0;
scale = 1 << scale;
- retval = -1;
}
else
disp = addr; /* displacement */
out->scale = scale;
out->seg = seg;
- return retval;
+ return 1;
}
\f
/* Return cost of the memory address x.
HOST_WIDE_INT scale;
addr_space_t seg;
- if (ix86_decompose_address (addr, &parts) <= 0)
+ if (ix86_decompose_address (addr, &parts) == 0)
/* Decomposition failed. */
return false;
<< (GET_MODE (XEXP (x, 1)) != DImode)));
return true;
}
+ else if (code == AND
+ && address_no_seg_operand (x, mode))
+ {
+ *total = cost->lea;
+ return true;
+ }
/* FALLTHRU */
case NEG: