===================================================================
*************** arm_split_constant (enum rtx_code code,
Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c
*/
if (!after_arm_reorg
! && !cond
! && (arm_gen_constant (code, mode, NULL_RTX, val, target, source,
! 1, 0)
! > (arm_constant_limit (optimize_function_for_size_p (cfun))
! + (code != SET))))
! {
! if (code == SET)
! {
! /* Currently SET is the only monadic value for CODE, all
! the rest are diadic. */
! if (TARGET_USE_MOVT)
! arm_emit_movpair (target, GEN_INT (val));
! else
! emit_set_insn (target, GEN_INT (val));
!
! return 1;
! }
! else
! {
! rtx temp = subtargets ? gen_reg_rtx (mode) : target;
!
! if (TARGET_USE_MOVT)
! arm_emit_movpair (temp, GEN_INT (val));
! else
! emit_set_insn (temp, GEN_INT (val));
! /* For MINUS, the value is subtracted from, since we never
! have subtraction of a constant. */
! if (code == MINUS)
! emit_set_insn (target, gen_rtx_MINUS (mode, temp, source));
! else
! emit_set_insn (target,
! gen_rtx_fmt_ee (code, mode, source, temp));
! return 2;
! }
! }
}
return arm_gen_constant (code, mode, cond, val, target, source, subtargets,
Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c
*/
if (!after_arm_reorg
! && !cond)
! {
! bool size_p = optimize_function_for_size_p (cfun);
! int constant_insn_limit = arm_constant_limit (size_p) + (code != SET);
!
! /* If not optimize for size and set constant code,
! then allow two extra insn if not load scheduling supported */
! if ((!size_p) && (optimize > 2)
! && (code == SET)
! && (constant_insn_limit == 1)
! && !arm_ld_sched)
! {
! constant_insn_limit += 2;
! }
! if (arm_gen_constant (code, mode, NULL_RTX, val, target, source,
! 1, 0) > constant_insn_limit)
! {
! if (code == SET)
! {
! /* Currently SET is the only monadic value for CODE, all
! the rest are diadic. */
! if (TARGET_USE_MOVT)
! arm_emit_movpair (target, GEN_INT (val));
! else
! emit_set_insn (target, GEN_INT (val));
!
! return 1;
! }
! else
! {
! rtx temp = subtargets ? gen_reg_rtx (mode) : target;
!
! if (TARGET_USE_MOVT)
! arm_emit_movpair (temp, GEN_INT (val));
! else
! emit_set_insn (temp, GEN_INT (val));
!
! /* For MINUS, the value is subtracted from, since we never
! have subtraction of a constant. */
! if (code == MINUS)
! emit_set_insn (target, gen_rtx_MINUS (mode, temp, source));
! else
! emit_set_insn (target,
! gen_rtx_fmt_ee (code, mode, source, temp));
! return 2;
! }
! }
! }
}
return arm_gen_constant (code, mode, cond, val, target, source, subtargets,
*************** arm_gen_constant (enum rtx_code code, en
return 1;
}
+ /* See of we can generate this by set 8 bits and then shift. */
+
+ /* For ARM we can generate 8 bit value with even number of
+ shift steps, but we have a special case where we must need
+ an odd number of steps, example 0x7f800000 or 0x40800000.
+ Constants of the form eg. (0x00FF0000 >> 1).
+ Also the shift may well merge into a subsequent insn. */
+
+ /* If odd number leading zeros and 8 bit constant */
+ if ((clear_sign_bit_copies & 1) &&
+ ((clear_sign_bit_copies + clear_zero_bit_copies) == 24))
+ {
+ temp1 = ARM_SIGN_EXTEND (remainder << clear_sign_bit_copies);
+
+ if (generate)
+ {
+ rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, new_src,
+ GEN_INT (temp1)));
+ emit_constant_insn (cond,
+ gen_lshrsi3 (target, new_src,
+ GEN_INT (clear_sign_bit_copies)));
+ }
+ return 2;
+ }
+
/* See if we can do this by sign_extending a constant that is known
to be negative. This is a good, way of doing it, since the shift
may well merge into a subsequent insn. */
*************** arm_gen_constant (enum rtx_code code, en
}
}
+ /* See of we can generate constant by set 8 bits and then shift in zeros
+ from left or right.
+ Eg. 0xfffefdf8 (using lsl) or 0x1ffefdff (using lsr)
+ */
+
+ /* If any leading zeros */
+ if (clear_sign_bit_copies > 0)
+ {
+ /* Shift up leading zeros */
+ temp1 = remainder << clear_sign_bit_copies;
+ /* Set lowest bits */
+ temp2 = (1 << clear_sign_bit_copies) - 1;
+ temp1 |= temp2;
+
+ /* Try negate and check if value can be loaded into 8 bits */
+ temp2 = ~temp1;
+ /* Count and shift down trailing zeros */
+ for (i = 0; i <= 31; i++)
+ {
+ if (temp2 & 1)
+ break;
+ else
+ temp2 >>= 1;
+ }
+
+ if ((temp2 < 256) || (((temp2 & 0xffff0000) == 0) &&
+ (temp2 & 0x8000)))
+ {
+ if (generate)
+ {
+ rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
+
+ insns = arm_gen_constant (code, /* SET */
+ mode,
+ cond,
+ temp1,
+ new_src,
+ source,
+ subtargets,
+ 1);
+ source = new_src;
+ }
+ else
+ {
+ rtx new_src = subtargets ? NULL_RTX : target;
+
+ insns = arm_gen_constant (code, /* SET */
+ mode,
+ cond,
+ temp1,
+ new_src,
+ source,
+ subtargets,
+ 0);
+ source = new_src;
+ }
+
+ if (generate)
+ {
+ /* rtx new_src = subtargets ? gen_reg_rtx (mode) : target; */
+ rtx shift = GEN_INT (clear_sign_bit_copies);
+
+
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode,
+ target,
+ gen_rtx_LSHIFTRT (mode,
+ source,
+ shift)));
+
+ /* emit_constant_insn (cond, gen_lshrsi3 (target, new_src, shift)); */
+ }
+
+ return insns + 1;
+ }
+ }
+
+ /* If any trailing zeros */
+ if (clear_zero_bit_copies > 0)
+ {
+ /* Shift down trailing zeros */
+ temp1 = remainder >> clear_zero_bit_copies;
+ /* Set highest bits */
+ temp2 = (1 << clear_zero_bit_copies) - 1;
+ temp1 |= (temp2 << (32 - clear_zero_bit_copies));
+
+ /* Try negate and check if value can be loaded into 8 bits */
+ temp2 = ~temp1;
+ /* Count and shift down trailing zeros */
+ for (i = 0; i <= 31; i++)
+ {
+ if (temp2 & 1)
+ break;
+ else
+ temp2 >>= 1;
+ }
+
+ if ((temp2 < 256) || (((temp2 & 0xffff0000) == 0) &&
+ (temp2 & 0x8000)))
+ {
+ if (generate)
+ {
+ rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
+
+ insns = arm_gen_constant (code, /* SET */
+ mode,
+ cond,
+ temp1,
+ new_src,
+ source,
+ subtargets,
+ 1);
+ source = new_src;
+ }
+ else
+ {
+ rtx new_src = subtargets ? NULL_RTX : target;
+
+ insns = arm_gen_constant (code, /* SET */
+ mode,
+ cond,
+ temp1,
+ new_src,
+ source,
+ subtargets,
+ 0);
+ source = new_src;
+ }
+
+ if (generate)
+ {
+ /* rtx new_src = subtargets ? gen_reg_rtx (mode) : target; */
+ rtx shift = GEN_INT (clear_zero_bit_copies);
+
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode,
+ target,
+ gen_rtx_ASHIFT (mode,
+ source,
+ shift)));
+
+ /* emit_constant_insn (cond, gen_lshrsi3 (target, new_src, shift)); */
+ }
+
+ return insns + 1;
+ }
+ }
+
/* See if we can generate this by setting the bottom (or the top)
16 bits, and then shifting these into the other half of the
word. We only look for the simplest cases, to do more would cost
*************** arm_gen_constant (enum rtx_code code, en
GEN_INT (i)),
source)));
return insns + 1;
! }
! }
/* Don't duplicate cases already considered. */
for (i = 17; i < 24; i++)
GEN_INT (i)),
source)));
return insns + 1;
! }
!
! /* Also check cases where we could generate constant using XOR.
! eg. (0x11110000 + ~0xffff1111) */
! else if (((((temp2 | 0xffff0000) ^ ((temp2 | 0xffff0000) << i))
! & 0xffffffff) == remainder)
! && !const_ok_for_arm (temp2 | 0xffff0000))
! {
! rtx new_src = (subtargets
! ? (generate ? gen_reg_rtx (mode) : NULL_RTX)
! : target);
! insns = arm_gen_constant (code, mode, cond,
! (temp2 | 0xffff0000), new_src,
! source, subtargets, generate);
! source = new_src;
! if (generate)
! emit_constant_insn
! (cond,
! gen_rtx_SET
! (VOIDmode, target,
! gen_rtx_XOR (mode,
! gen_rtx_ASHIFT (mode, source,
! GEN_INT (i)),
! source)));
! return insns + 1;
! }
! }
/* Don't duplicate cases already considered. */
for (i = 17; i < 24; i++)