mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 01:50:34 +08:00
Use SImode instead of HImode if aligned.
From-SVN: r13479
This commit is contained in:
parent
72acf258c6
commit
5bc7cd8eb8
@ -388,6 +388,85 @@ optimization_options (level)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sign-extend a 16-bit constant */
|
||||
|
||||
struct rtx_def *
|
||||
i386_sext16_if_const (op)
|
||||
struct rtx_def *op;
|
||||
{
|
||||
if (GET_CODE (op) == CONST_INT)
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (op);
|
||||
HOST_WIDE_INT sext_val;
|
||||
if (val & 0x8000)
|
||||
sext_val = val | ~0xffff;
|
||||
else
|
||||
sext_val = val & 0xffff;
|
||||
if (sext_val != val)
|
||||
op = GEN_INT (sext_val);
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
/* Return nonzero if the rtx is aligned */
|
||||
|
||||
static int
|
||||
i386_aligned_reg_p (regno)
|
||||
int regno;
|
||||
{
|
||||
return (regno == STACK_POINTER_REGNUM
|
||||
|| (!flag_omit_frame_pointer
|
||||
&& regno == FRAME_POINTER_REGNUM));
|
||||
}
|
||||
|
||||
int
|
||||
i386_aligned_p (op)
|
||||
rtx op;
|
||||
{
|
||||
/* registers and immediate operands are always "aligned" */
|
||||
if (GET_CODE (op) != MEM)
|
||||
return 1;
|
||||
|
||||
/* Don't even try to do any aligned optimizations with volatiles */
|
||||
if (MEM_VOLATILE_P (op))
|
||||
return 0;
|
||||
|
||||
/* Get address of memory operand */
|
||||
op = XEXP (op, 0);
|
||||
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case CONST_INT:
|
||||
if (INTVAL (op) & 3)
|
||||
break;
|
||||
return 1;
|
||||
|
||||
/* match "reg + offset" */
|
||||
case PLUS:
|
||||
if (GET_CODE (XEXP (op, 1)) != CONST_INT)
|
||||
break;
|
||||
if (INTVAL (XEXP (op, 1)) & 3)
|
||||
break;
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != REG)
|
||||
break;
|
||||
/* fall through */
|
||||
case REG:
|
||||
return i386_aligned_reg_p (REGNO (op));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return nonzero if INSN looks like it won't compute useful cc bits
|
||||
as a side effect. This information is only a hint. */
|
||||
|
||||
int
|
||||
i386_cc_probably_useless_p (insn)
|
||||
rtx insn;
|
||||
{
|
||||
return !next_cc0_user (insn);
|
||||
}
|
||||
|
||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
|
||||
attribute for DECL. The attributes in ATTRIBUTES have previously been
|
||||
assigned to DECL. */
|
||||
@ -854,7 +933,7 @@ asm_add (n, x)
|
||||
output_asm_insn (AS1 (dec%L0,%0), xops);
|
||||
else if (n == 1)
|
||||
output_asm_insn (AS1 (inc%L0,%0), xops);
|
||||
else if (n < 0)
|
||||
else if (n < 0 || n == 128)
|
||||
{
|
||||
xops[1] = GEN_INT (-n);
|
||||
output_asm_insn (AS2 (sub%L0,%1,%0), xops);
|
||||
|
@ -157,7 +157,8 @@ extern int target_flags;
|
||||
#define TARGET_PENTIUMPRO (ix86_cpu == PROCESSOR_PENTIUMPRO)
|
||||
#define TARGET_USE_LEAVE (ix86_cpu == PROCESSOR_I386)
|
||||
#define TARGET_PUSH_MEMORY (ix86_cpu == PROCESSOR_I386)
|
||||
#define TARGET_ZERO_EXTEND_WITH_AND (ix86_cpu != PROCESSOR_I386)
|
||||
#define TARGET_ZERO_EXTEND_WITH_AND (ix86_cpu != PROCESSOR_I386 \
|
||||
&& ix86_cpu != PROCESSOR_PENTIUMPRO)
|
||||
#define TARGET_DOUBLE_WITH_ADD (ix86_cpu != PROCESSOR_I386)
|
||||
#define TARGET_USE_BIT_TEST (ix86_cpu == PROCESSOR_I386)
|
||||
#define TARGET_UNROLL_STRLEN (ix86_cpu != PROCESSOR_I386)
|
||||
@ -2604,6 +2605,9 @@ do { \
|
||||
extern void override_options ();
|
||||
extern void order_regs_for_local_alloc ();
|
||||
extern char *output_strlen_unroll ();
|
||||
extern struct rtx_def *i386_sext16_if_const ();
|
||||
extern int i386_aligned_p ();
|
||||
extern int i386_cc_probably_useless_p ();
|
||||
extern int i386_valid_decl_attribute_p ();
|
||||
extern int i386_valid_type_attribute_p ();
|
||||
extern int i386_return_pops_args ();
|
||||
|
@ -770,6 +770,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* use 32-bit test instruction if there are no sign issues */
|
||||
if (GET_CODE (operands[1]) == CONST_INT
|
||||
&& !(INTVAL (operands[1]) & ~0x7fff)
|
||||
&& i386_aligned_p (operands[0]))
|
||||
return AS2 (test%L0,%1,%k0);
|
||||
|
||||
if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
|
||||
return AS2 (test%W0,%1,%0);
|
||||
|
||||
@ -931,10 +937,21 @@
|
||||
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
if (REG_P (operands[1]))
|
||||
return AS2 (mov%L0,%k1,%k0);
|
||||
else if (CONSTANT_P (operands[1]))
|
||||
return AS2 (mov%L0,%1,%k0);
|
||||
if (i386_aligned_p (operands[1]))
|
||||
{
|
||||
operands[1] = i386_sext16_if_const (operands[1]);
|
||||
return AS2 (mov%L0,%k1,%k0);
|
||||
}
|
||||
if (TARGET_PENTIUMPRO)
|
||||
{
|
||||
/* movzwl is faster than movw on the Pentium Pro,
|
||||
* although not as fast as an aligned movl. */
|
||||
#ifdef INTEL_SYNTAX
|
||||
return AS2 (movzx,%1,%k0);
|
||||
#else
|
||||
return AS2 (movz%W0%L0,%1,%k0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return AS2 (mov%W0,%1,%0);
|
||||
@ -1040,7 +1057,7 @@
|
||||
{
|
||||
rtx link;
|
||||
if (operands[1] == const0_rtx && REG_P (operands[0]))
|
||||
return AS2 (xor%B0,%0,%0);
|
||||
return AS2 (xor%L0,%k0,%k0);
|
||||
|
||||
if (operands[1] == const1_rtx
|
||||
&& (link = find_reg_note (insn, REG_WAS_0, 0))
|
||||
@ -1747,7 +1764,10 @@
|
||||
{
|
||||
xops[0] = operands[0];
|
||||
xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xffff);
|
||||
output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
|
||||
if (i386_aligned_p (operands[1]))
|
||||
output_asm_insn (AS2 (mov%L0,%k1,%k0),operands);
|
||||
else
|
||||
output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
|
||||
output_asm_insn (AS2 (and%L0,%1,%k0), xops);
|
||||
RET;
|
||||
}
|
||||
@ -2752,7 +2772,7 @@
|
||||
}")
|
||||
|
||||
(define_insn "addsidi3_2"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,r,o,o,!o")
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o")
|
||||
(plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,o,ri,ri,i,r"))
|
||||
(match_operand:DI 1 "general_operand" "0,0,0,iF,ro,roiF,riF,o,o")))
|
||||
(clobber (match_scratch:SI 3 "=X,X,X,X,X,X,X,&r,&r"))]
|
||||
@ -2952,6 +2972,18 @@
|
||||
if (operands[2] == constm1_rtx)
|
||||
return AS1 (dec%L0,%0);
|
||||
|
||||
/* subl $-128,%ebx is smaller than addl $128,%ebx. */
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& INTVAL (operands[2]) == 128)
|
||||
{
|
||||
/* This doesn't compute the carry bit in the same way
|
||||
* as add%L0, but we use inc and dec above and they
|
||||
* don't set the carry bit at all. If inc/dec don't need
|
||||
* a CC_STATUS_INIT, this doesn't either... */
|
||||
operands[2] = GEN_INT (-128);
|
||||
return AS2 (sub%L0,%2,%0);
|
||||
}
|
||||
|
||||
return AS2 (add%L0,%2,%0);
|
||||
}")
|
||||
|
||||
@ -3003,9 +3035,11 @@
|
||||
"*
|
||||
{
|
||||
/* ??? what about offsettable memory references? */
|
||||
if (QI_REG_P (operands[0])
|
||||
if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */
|
||||
&& QI_REG_P (operands[0])
|
||||
&& GET_CODE (operands[2]) == CONST_INT
|
||||
&& (INTVAL (operands[2]) & 0xff) == 0)
|
||||
&& (INTVAL (operands[2]) & 0xff) == 0
|
||||
&& i386_cc_probably_useless_p (insn))
|
||||
{
|
||||
int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
|
||||
CC_STATUS_INIT;
|
||||
@ -3019,6 +3053,28 @@
|
||||
return AS2 (add%B0,%2,%h0);
|
||||
}
|
||||
|
||||
/* Use a 32-bit operation when possible, to avoid the prefix penalty. */
|
||||
if (REG_P (operands[0])
|
||||
&& i386_aligned_p (operands[2])
|
||||
&& i386_cc_probably_useless_p (insn))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
|
||||
if (GET_CODE (operands[2]) == CONST_INT)
|
||||
{
|
||||
HOST_WIDE_INT intval = 0xffff & INTVAL (operands[2]);
|
||||
|
||||
if (intval == 1)
|
||||
return AS1 (inc%L0,%k0);
|
||||
|
||||
if (intval == 0xffff)
|
||||
return AS1 (dec%L0,%k0);
|
||||
|
||||
operands[2] = i386_sext16_if_const (operands[2]);
|
||||
}
|
||||
return AS2 (add%L0,%k2,%k0);
|
||||
}
|
||||
|
||||
if (operands[2] == const1_rtx)
|
||||
return AS1 (inc%W0,%0);
|
||||
|
||||
@ -3246,7 +3302,18 @@
|
||||
(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
|
||||
(match_operand:HI 2 "general_operand" "ri,rm")))]
|
||||
"ix86_binary_operator_ok (MINUS, HImode, operands)"
|
||||
"* return AS2 (sub%W0,%2,%0);")
|
||||
"*
|
||||
{
|
||||
if (REG_P (operands[0])
|
||||
&& i386_aligned_p (operands[2])
|
||||
&& i386_cc_probably_useless_p (insn))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = i386_sext16_if_const (operands[2]);
|
||||
return AS2 (sub%L0,%k2,%k0);
|
||||
}
|
||||
return AS2 (sub%W0,%2,%0);
|
||||
}")
|
||||
|
||||
(define_expand "subqi3"
|
||||
[(set (match_operand:QI 0 "general_operand" "")
|
||||
@ -3518,7 +3585,6 @@
|
||||
;; The `r' in `rm' for operand 3 looks redundant, but it causes
|
||||
;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
|
||||
|
||||
;; ??? What if we only change one byte of an offsettable memory reference?
|
||||
(define_insn "andsi3"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
|
||||
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
|
||||
@ -3526,6 +3592,7 @@
|
||||
""
|
||||
"*
|
||||
{
|
||||
HOST_WIDE_INT intval;
|
||||
if (!rtx_equal_p (operands[0], operands[1])
|
||||
&& rtx_equal_p (operands[0], operands[2]))
|
||||
{
|
||||
@ -3534,10 +3601,14 @@
|
||||
operands[1] = operands[2];
|
||||
operands[2] = tmp;
|
||||
}
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
|
||||
switch (GET_CODE (operands[2]))
|
||||
{
|
||||
if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
|
||||
case CONST_INT:
|
||||
if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
|
||||
break;
|
||||
intval = INTVAL (operands[2]);
|
||||
/* zero-extend 16->32? */
|
||||
if (intval == 0xffff && REG_P (operands[0])
|
||||
&& (! REG_P (operands[1])
|
||||
|| REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
|
||||
&& (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1])))
|
||||
@ -3552,7 +3623,8 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
if (INTVAL (operands[2]) == 0xff && REG_P (operands[0])
|
||||
/* zero extend 8->32? */
|
||||
if (intval == 0xff && REG_P (operands[0])
|
||||
&& !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
|
||||
&& (! REG_P (operands[1])
|
||||
|| REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
|
||||
@ -3568,39 +3640,99 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
/* Check partial bytes.. non-QI-regs are not available */
|
||||
if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
|
||||
break;
|
||||
|
||||
if (INTVAL (operands[2]) == 0xffffff00)
|
||||
/* only low byte has zero bits? */
|
||||
if (~(intval | 0xff) == 0)
|
||||
{
|
||||
intval &= 0xff;
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
operands[2] = const0_rtx;
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
if (intval == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
return AS2 (xor%B0,%b0,%b0);
|
||||
}
|
||||
|
||||
/* we're better off with the 32-bit version if reg != EAX */
|
||||
/* the value is sign-extended in 8 bits */
|
||||
if (REGNO (operands[0]) != 0 && (intval & 0x80))
|
||||
break;
|
||||
}
|
||||
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
|
||||
CC_STATUS_INIT;
|
||||
|
||||
operands[2] = GEN_INT (intval);
|
||||
|
||||
if (intval == 0)
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
|
||||
return AS2 (and%B0,%2,%b0);
|
||||
}
|
||||
|
||||
if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0)
|
||||
/* only second byte has zero? */
|
||||
if (~(intval | 0xff00) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
|
||||
if (INTVAL (operands[2]) == 0xffff00ff)
|
||||
intval = (intval >> 8) & 0xff;
|
||||
operands[2] = GEN_INT (intval);
|
||||
if (intval == 0)
|
||||
{
|
||||
operands[2] = const0_rtx;
|
||||
return AS2 (mov%B0,%2,%h0);
|
||||
if (REG_P (operands[0]))
|
||||
return AS2 (xor%B0,%h0,%h0);
|
||||
operands[0] = adj_offsettable_operand (operands[0], 1);
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
}
|
||||
|
||||
operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
|
||||
return AS2 (and%B0,%2,%h0);
|
||||
if (REG_P (operands[0]))
|
||||
return AS2 (and%B0,%2,%h0);
|
||||
|
||||
operands[0] = adj_offsettable_operand (operands[0], 1);
|
||||
return AS2 (and%B0,%2,%b0);
|
||||
}
|
||||
|
||||
if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000)
|
||||
if (REG_P (operands[0]))
|
||||
break;
|
||||
|
||||
/* third byte has zero bits? */
|
||||
if (~(intval | 0xff0000) == 0)
|
||||
{
|
||||
intval = (intval >> 16) & 0xff;
|
||||
operands[0] = adj_offsettable_operand (operands[0], 2);
|
||||
byte_and_operation:
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = GEN_INT (intval);
|
||||
if (intval == 0)
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
return AS2 (and%B0,%2,%b0);
|
||||
}
|
||||
|
||||
/* fourth byte has zero bits? */
|
||||
if (~(intval | 0xff000000) == 0)
|
||||
{
|
||||
intval = (intval >> 24) & 0xff;
|
||||
operands[0] = adj_offsettable_operand (operands[0], 3);
|
||||
goto byte_and_operation;
|
||||
}
|
||||
|
||||
/* Low word is zero? */
|
||||
if (intval == 0xffff0000)
|
||||
{
|
||||
word_zero_and_operation:
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = const0_rtx;
|
||||
return AS2 (mov%W0,%2,%w0);
|
||||
}
|
||||
|
||||
/* High word is zero? */
|
||||
if (intval == 0x0000ffff)
|
||||
{
|
||||
operands[0] = adj_offsettable_operand (operands[0], 2);
|
||||
goto word_zero_and_operation;
|
||||
}
|
||||
}
|
||||
|
||||
return AS2 (and%L0,%2,%0);
|
||||
@ -3647,6 +3779,38 @@
|
||||
operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
|
||||
return AS2 (and%B0,%2,%h0);
|
||||
}
|
||||
|
||||
/* use 32-bit ops on registers when there are no sign issues.. */
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
if (!(INTVAL (operands[2]) & ~0x7fff))
|
||||
return AS2 (and%L0,%2,%k0);
|
||||
}
|
||||
}
|
||||
|
||||
if (REG_P (operands[0])
|
||||
&& i386_aligned_p (operands[2]))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
/* If op[2] is constant, we should zero-extend it and */
|
||||
/* make a note that op[0] has been zero-extended, so */
|
||||
/* that we could use 32-bit ops on it forthwith, but */
|
||||
/* there is no such reg-note available. Instead we do */
|
||||
/* a sign extension as that can result in shorter asm */
|
||||
operands[2] = i386_sext16_if_const (operands[2]);
|
||||
return AS2 (and%L0,%k2,%k0);
|
||||
}
|
||||
|
||||
/* Use a 32-bit word with the upper bits set, invalidate CC */
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& i386_aligned_p (operands[0]))
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (operands[2]);
|
||||
CC_STATUS_INIT;
|
||||
val |= ~0xffff;
|
||||
if (val != INTVAL (operands[2]))
|
||||
operands[2] = GEN_INT (val);
|
||||
return AS2 (and%L0,%k2,%k0);
|
||||
}
|
||||
|
||||
return AS2 (and%W0,%2,%0);
|
||||
@ -3685,7 +3849,10 @@
|
||||
|
||||
;;- Bit set (inclusive or) instructions
|
||||
|
||||
;; ??? What if we only change one byte of an offsettable memory reference?
|
||||
;; This optimizes known byte-wide operations to memory, and in some cases
|
||||
;; to QI registers.. Note that we don't want to use the QI registers too
|
||||
;; aggressively, because often the 32-bit register instruction is the same
|
||||
;; size, and likely to be faster on PentiumPro.
|
||||
(define_insn "iorsi3"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
|
||||
(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
|
||||
@ -3693,29 +3860,76 @@
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
|
||||
HOST_WIDE_INT intval;
|
||||
switch (GET_CODE (operands[2]))
|
||||
{
|
||||
if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
|
||||
&& (INTVAL (operands[2]) & ~0xff) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
case CONST_INT:
|
||||
|
||||
if (INTVAL (operands[2]) == 0xff)
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
|
||||
break;
|
||||
|
||||
return AS2 (or%B0,%2,%b0);
|
||||
/* don't try to optimize volatile accesses */
|
||||
if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
|
||||
break;
|
||||
|
||||
intval = INTVAL (operands[2]);
|
||||
if ((intval & ~0xff) == 0)
|
||||
{
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
/* Do low byte access only for %eax or when high bit is set */
|
||||
if (REGNO (operands[0]) != 0 && !(intval & 0x80))
|
||||
break;
|
||||
}
|
||||
|
||||
byte_or_operation:
|
||||
CC_STATUS_INIT;
|
||||
|
||||
if (intval != INTVAL (operands[2]))
|
||||
operands[2] = GEN_INT (intval);
|
||||
|
||||
if (intval == 0xff)
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
|
||||
return AS2 (or%B0,%2,%b0);
|
||||
}
|
||||
|
||||
if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
|
||||
/* second byte? */
|
||||
if ((intval & ~0xff00) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
|
||||
intval >>= 8;
|
||||
|
||||
if (INTVAL (operands[2]) == 0xff)
|
||||
return AS2 (mov%B0,%2,%h0);
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = GEN_INT (intval);
|
||||
if (intval == 0xff)
|
||||
return AS2 (mov%B0,%2,%h0);
|
||||
|
||||
return AS2 (or%B0,%2,%h0);
|
||||
return AS2 (or%B0,%2,%h0);
|
||||
}
|
||||
|
||||
operands[0] = adj_offsettable_operand (operands[0], 1);
|
||||
goto byte_or_operation;
|
||||
}
|
||||
|
||||
if (REG_P (operands[0]))
|
||||
break;
|
||||
|
||||
/* third byte? */
|
||||
if ((intval & ~0xff0000) == 0)
|
||||
{
|
||||
intval >>= 16;
|
||||
operands[0] = adj_offsettable_operand (operands[0], 2);
|
||||
goto byte_or_operation;
|
||||
}
|
||||
|
||||
/* fourth byte? */
|
||||
if ((intval & ~0xff000000) == 0)
|
||||
{
|
||||
intval = (intval >> 24) & 0xff;
|
||||
operands[0] = adj_offsettable_operand (operands[0], 3);
|
||||
goto byte_or_operation;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3729,38 +3943,77 @@
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
|
||||
HOST_WIDE_INT intval;
|
||||
switch (GET_CODE (operands[2]))
|
||||
{
|
||||
/* Can we ignore the upper byte? */
|
||||
if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
|
||||
&& (INTVAL (operands[2]) & 0xff00) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
if (INTVAL (operands[2]) & 0xffff0000)
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
|
||||
case CONST_INT:
|
||||
|
||||
if (INTVAL (operands[2]) == 0xff)
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
|
||||
break;
|
||||
|
||||
return AS2 (or%B0,%2,%b0);
|
||||
/* don't try to optimize volatile accesses */
|
||||
if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
|
||||
break;
|
||||
|
||||
intval = 0xffff & INTVAL (operands[2]);
|
||||
|
||||
if ((intval & 0xff00) == 0)
|
||||
{
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
/* Do low byte access only for %eax or when high bit is set */
|
||||
if (REGNO (operands[0]) != 0 && !(intval & 0x80))
|
||||
break;
|
||||
}
|
||||
|
||||
byte_or_operation:
|
||||
CC_STATUS_INIT;
|
||||
|
||||
if (intval == 0xff)
|
||||
return AS2 (mov%B0,%2,%b0);
|
||||
|
||||
return AS2 (or%B0,%2,%b0);
|
||||
}
|
||||
|
||||
/* Can we ignore the lower byte? */
|
||||
/* ??? what about offsettable memory references? */
|
||||
if (QI_REG_P (operands[0])
|
||||
&& (INTVAL (operands[2]) & 0xff) == 0)
|
||||
/* high byte? */
|
||||
if ((intval & 0xff) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
|
||||
intval >>= 8;
|
||||
operands[2] = GEN_INT (intval);
|
||||
|
||||
if (INTVAL (operands[2]) == 0xff)
|
||||
return AS2 (mov%B0,%2,%h0);
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
if (intval == 0xff)
|
||||
return AS2 (mov%B0,%2,%h0);
|
||||
|
||||
return AS2 (or%B0,%2,%h0);
|
||||
return AS2 (or%B0,%2,%h0);
|
||||
}
|
||||
|
||||
operands[0] = adj_offsettable_operand (operands[0], 1);
|
||||
|
||||
goto byte_or_operation;
|
||||
}
|
||||
}
|
||||
|
||||
if (REG_P (operands[0])
|
||||
&& i386_aligned_p (operands[2]))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = i386_sext16_if_const (operands[2]);
|
||||
return AS2 (or%L0,%k2,%k0);
|
||||
}
|
||||
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& i386_aligned_p (operands[0]))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
intval = 0xffff & INTVAL (operands[2]);
|
||||
if (intval != INTVAL (operands[2]))
|
||||
operands[2] = GEN_INT (intval);
|
||||
return AS2 (or%L0,%2,%k0);
|
||||
}
|
||||
|
||||
return AS2 (or%W0,%2,%0);
|
||||
}")
|
||||
|
||||
@ -3773,7 +4026,6 @@
|
||||
|
||||
;;- xor instructions
|
||||
|
||||
;; ??? What if we only change one byte of an offsettable memory reference?
|
||||
(define_insn "xorsi3"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
|
||||
(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
|
||||
@ -3781,29 +4033,76 @@
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
|
||||
HOST_WIDE_INT intval;
|
||||
switch (GET_CODE (operands[2]))
|
||||
{
|
||||
if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
|
||||
&& (INTVAL (operands[2]) & ~0xff) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
case CONST_INT:
|
||||
|
||||
if (INTVAL (operands[2]) == 0xff)
|
||||
return AS1 (not%B0,%b0);
|
||||
if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
|
||||
break;
|
||||
|
||||
return AS2 (xor%B0,%2,%b0);
|
||||
/* don't try to optimize volatile accesses */
|
||||
if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
|
||||
break;
|
||||
|
||||
intval = INTVAL (operands[2]);
|
||||
if ((intval & ~0xff) == 0)
|
||||
{
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
/* Do low byte access only for %eax or when high bit is set */
|
||||
if (REGNO (operands[0]) != 0 && !(intval & 0x80))
|
||||
break;
|
||||
}
|
||||
|
||||
byte_xor_operation:
|
||||
CC_STATUS_INIT;
|
||||
|
||||
if (intval == 0xff)
|
||||
return AS1 (not%B0,%b0);
|
||||
|
||||
if (intval != INTVAL (operands[2]))
|
||||
operands[2] = GEN_INT (intval);
|
||||
return AS2 (xor%B0,%2,%b0);
|
||||
}
|
||||
|
||||
if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
|
||||
/* second byte? */
|
||||
if ((intval & ~0xff00) == 0)
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
|
||||
intval >>= 8;
|
||||
|
||||
if (INTVAL (operands[2]) == 0xff)
|
||||
return AS1 (not%B0,%h0);
|
||||
if (REG_P (operands[0]))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
if (intval == 0xff)
|
||||
return AS1 (not%B0,%h0);
|
||||
|
||||
return AS2 (xor%B0,%2,%h0);
|
||||
operands[2] = GEN_INT (intval);
|
||||
return AS2 (xor%B0,%2,%h0);
|
||||
}
|
||||
|
||||
operands[0] = adj_offsettable_operand (operands[0], 1);
|
||||
|
||||
goto byte_xor_operation;
|
||||
}
|
||||
|
||||
if (REG_P (operands[0]))
|
||||
break;
|
||||
|
||||
/* third byte? */
|
||||
if ((intval & ~0xff0000) == 0)
|
||||
{
|
||||
intval >>= 16;
|
||||
operands[0] = adj_offsettable_operand (operands[0], 2);
|
||||
goto byte_xor_operation;
|
||||
}
|
||||
|
||||
/* fourth byte? */
|
||||
if ((intval & ~0xff000000) == 0)
|
||||
{
|
||||
intval = (intval >> 24) & 0xff;
|
||||
operands[0] = adj_offsettable_operand (operands[0], 3);
|
||||
goto byte_xor_operation;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3849,6 +4148,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (REG_P (operands[0])
|
||||
&& i386_aligned_p (operands[2]))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = i386_sext16_if_const (operands[2]);
|
||||
return AS2 (xor%L0,%k2,%k0);
|
||||
}
|
||||
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& i386_aligned_p (operands[0]))
|
||||
{
|
||||
HOST_WIDE_INT intval;
|
||||
CC_STATUS_INIT;
|
||||
intval = 0xffff & INTVAL (operands[2]);
|
||||
if (intval != INTVAL (operands[2]))
|
||||
operands[2] = GEN_INT (intval);
|
||||
return AS2 (xor%L0,%2,%k0);
|
||||
}
|
||||
|
||||
return AS2 (xor%W0,%2,%0);
|
||||
}")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user