aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2005-07-18 06:39:20 +0000
committerJan Beulich <jbeulich@gcc.gnu.org>2005-07-18 06:39:20 +0000
commit28356f52a9c5d00dcf7b6673a2e83309c63cee0c (patch)
tree151aba1a149c4300ec9d417932358767d50bb381 /gcc/config
parent422edd6fff341fb237a5fab947a1356f94172953 (diff)
downloadgcc-28356f52a9c5d00dcf7b6673a2e83309c63cee0c.zip
gcc-28356f52a9c5d00dcf7b6673a2e83309c63cee0c.tar.gz
gcc-28356f52a9c5d00dcf7b6673a2e83309c63cee0c.tar.bz2
i386.c (ix86_expand_branch, [...]): Handle TImode in 64-bit mode the same as DImode in 32-bit mode.
gcc/ 2005-07-18 Jan Beulich <jbeulich@novell.com> * config/i386/i386.c (ix86_expand_branch, ix86_expand_setcc, ix86_expand_carry_flag_compare, ix86_expand_int_movcc): Handle TImode in 64-bit mode the same as DImode in 32-bit mode. (ix86_expand_ashl_const, ix86_split_ashl, ix86_split_ashr, ix86_split_lshr): Likewise. Rename to no longer refer to a specific mode. Add new mode parameter. * config/i386/i386.h (CONST_OK_FOR_LETTER_P): Describe and handle 'O'. * config/i386/i386.md (cmpti, addti3, subti3, negti2, ashlti3, ashrti3, x86_64_shift_adj): New expanders. (*addti3_1, *subti3_1, *negti2_1, ashlti3_1, *ashlti3_2, ashrti3_1, *ashrti3_2, lshrti3_1, *lshrti3_2, x86_64_shld, x86_64_shrd): New insns. Respective new splitters. Use renamed shift splitter helpers in 32-bit DImode shift splitters. * config/i386/i386-protos.h (ix86_split_ashl, ix86_split_ashr, ix86_split_lshr): Renamed from ix86_split_[al]sh[rl]di. Added new mode parameter. From-SVN: r102129
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386-protos.h6
-rw-r--r--gcc/config/i386/i386.c219
-rw-r--r--gcc/config/i386/i386.h4
-rw-r--r--gcc/config/i386/i386.md343
4 files changed, 490 insertions, 82 deletions
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 957876c..dfbf11a 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -155,9 +155,9 @@ extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int);
extern void x86_initialize_trampoline (rtx, rtx, rtx);
extern rtx ix86_zero_extend_to_Pmode (rtx);
extern void ix86_split_long_move (rtx[]);
-extern void ix86_split_ashldi (rtx *, rtx);
-extern void ix86_split_ashrdi (rtx *, rtx);
-extern void ix86_split_lshrdi (rtx *, rtx);
+extern void ix86_split_ashl (rtx *, rtx, enum machine_mode);
+extern void ix86_split_ashr (rtx *, rtx, enum machine_mode);
+extern void ix86_split_lshr (rtx *, rtx, enum machine_mode);
extern rtx ix86_find_base_term (rtx);
extern int ix86_check_movabs (rtx, int);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 17d8ea0..8dd9698 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7200,7 +7200,7 @@ split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
}
}
}
-/* Split one or more TImode RTL references into pairs of SImode
+/* Split one or more TImode RTL references into pairs of DImode
references. The RTL can be REG, offsettable MEM, integer constant, or
CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
split and "num" is its length. lo_half and hi_half are output arrays
@@ -9344,10 +9344,12 @@ ix86_expand_branch (enum rtx_code code, rtx label)
case DImode:
if (TARGET_64BIT)
goto simple;
+ case TImode:
/* Expand DImode branch into multiple compare+branch. */
{
rtx lo[2], hi[2], label2;
enum rtx_code code1, code2, code3;
+ enum machine_mode submode;
if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
{
@@ -9356,8 +9358,18 @@ ix86_expand_branch (enum rtx_code code, rtx label)
ix86_compare_op1 = tmp;
code = swap_condition (code);
}
- split_di (&ix86_compare_op0, 1, lo+0, hi+0);
- split_di (&ix86_compare_op1, 1, lo+1, hi+1);
+ if (GET_MODE (ix86_compare_op0) == DImode)
+ {
+ split_di (&ix86_compare_op0, 1, lo+0, hi+0);
+ split_di (&ix86_compare_op1, 1, lo+1, hi+1);
+ submode = SImode;
+ }
+ else
+ {
+ split_ti (&ix86_compare_op0, 1, lo+0, hi+0);
+ split_ti (&ix86_compare_op1, 1, lo+1, hi+1);
+ submode = DImode;
+ }
/* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to
avoid two branches. This costs one extra insn, so disable when
@@ -9371,15 +9383,15 @@ ix86_expand_branch (enum rtx_code code, rtx label)
xor1 = hi[0];
if (hi[1] != const0_rtx)
- xor1 = expand_binop (SImode, xor_optab, xor1, hi[1],
+ xor1 = expand_binop (submode, xor_optab, xor1, hi[1],
NULL_RTX, 0, OPTAB_WIDEN);
xor0 = lo[0];
if (lo[1] != const0_rtx)
- xor0 = expand_binop (SImode, xor_optab, xor0, lo[1],
+ xor0 = expand_binop (submode, xor_optab, xor0, lo[1],
NULL_RTX, 0, OPTAB_WIDEN);
- tmp = expand_binop (SImode, ior_optab, xor1, xor0,
+ tmp = expand_binop (submode, ior_optab, xor1, xor0,
NULL_RTX, 0, OPTAB_WIDEN);
ix86_compare_op0 = tmp;
@@ -9547,8 +9559,7 @@ ix86_expand_setcc (enum rtx_code code, rtx dest)
rtx ret, tmp, tmpreg, equiv;
rtx second_test, bypass_test;
- if (GET_MODE (ix86_compare_op0) == DImode
- && !TARGET_64BIT)
+ if (GET_MODE (ix86_compare_op0) == (TARGET_64BIT ? TImode : DImode))
return 0; /* FAIL */
gcc_assert (GET_MODE (dest) == QImode);
@@ -9603,7 +9614,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
/* Do not handle DImode compares that go trought special path. Also we can't
deal with FP compares yet. This is possible to add. */
- if ((mode == DImode && !TARGET_64BIT))
+ if (mode == (TARGET_64BIT ? TImode : DImode))
return false;
if (FLOAT_MODE_P (mode))
{
@@ -9743,7 +9754,7 @@ ix86_expand_int_movcc (rtx operands[])
HImode insns, we'd be swallowed in word prefix ops. */
if ((mode != HImode || TARGET_FAST_PREFIX)
- && (mode != DImode || TARGET_64BIT)
+ && (mode != (TARGET_64BIT ? TImode : DImode))
&& GET_CODE (operands[2]) == CONST_INT
&& GET_CODE (operands[3]) == CONST_INT)
{
@@ -11092,68 +11103,81 @@ ix86_split_long_move (rtx operands[])
return;
}
-/* Helper function of ix86_split_ashldi used to generate an SImode
+/* Helper function of ix86_split_ashl used to generate an SImode/DImode
left shift by a constant, either using a single shift or
a sequence of add instructions. */
static void
-ix86_expand_ashlsi3_const (rtx operand, int count)
+ix86_expand_ashl_const (rtx operand, int count, enum machine_mode mode)
{
if (count == 1)
- emit_insn (gen_addsi3 (operand, operand, operand));
+ {
+ emit_insn ((mode == DImode
+ ? gen_addsi3
+ : gen_adddi3) (operand, operand, operand));
+ }
else if (!optimize_size
&& count * ix86_cost->add <= ix86_cost->shift_const)
{
int i;
for (i=0; i<count; i++)
- emit_insn (gen_addsi3 (operand, operand, operand));
+ {
+ emit_insn ((mode == DImode
+ ? gen_addsi3
+ : gen_adddi3) (operand, operand, operand));
+ }
}
else
- emit_insn (gen_ashlsi3 (operand, operand, GEN_INT (count)));
+ emit_insn ((mode == DImode
+ ? gen_ashlsi3
+ : gen_ashldi3) (operand, operand, GEN_INT (count)));
}
void
-ix86_split_ashldi (rtx *operands, rtx scratch)
+ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode)
{
rtx low[2], high[2];
int count;
+ const int single_width = mode == DImode ? 32 : 64;
if (GET_CODE (operands[2]) == CONST_INT)
{
- split_di (operands, 2, low, high);
- count = INTVAL (operands[2]) & 63;
+ (mode == DImode ? split_di : split_ti) (operands, 2, low, high);
+ count = INTVAL (operands[2]) & (single_width * 2 - 1);
- if (count >= 32)
+ if (count >= single_width)
{
emit_move_insn (high[0], low[1]);
emit_move_insn (low[0], const0_rtx);
- if (count > 32)
- ix86_expand_ashlsi3_const (high[0], count - 32);
+ if (count > single_width)
+ ix86_expand_ashl_const (high[0], count - single_width, mode);
}
else
{
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- emit_insn (gen_x86_shld_1 (high[0], low[0], GEN_INT (count)));
- ix86_expand_ashlsi3_const (low[0], count);
+ emit_insn ((mode == DImode
+ ? gen_x86_shld_1
+ : gen_x86_64_shld) (high[0], low[0], GEN_INT (count)));
+ ix86_expand_ashl_const (low[0], count, mode);
}
return;
}
- split_di (operands, 1, low, high);
+ (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
if (operands[1] == const1_rtx)
{
- /* Assuming we've chosen a QImode capable registers, then 1LL << N
- can be done with two 32-bit shifts, no branches, no cmoves. */
+ /* Assuming we've chosen a QImode capable registers, then 1 << N
+ can be done with two 32/64-bit shifts, no branches, no cmoves. */
if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
{
rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
ix86_expand_clear (low[0]);
ix86_expand_clear (high[0]);
- emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
+ emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (single_width)));
d = gen_lowpart (QImode, low[0]);
d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
@@ -11167,7 +11191,7 @@ ix86_split_ashldi (rtx *operands, rtx scratch)
}
/* Otherwise, we can get the same results by manually performing
- a bit extract operation on bit 5, and then performing the two
+ a bit extract operation on bit 5/6, and then performing the two
shifts. The two methods of getting 0/1 into low/high are exactly
the same size. Avoiding the shift in the bit extract case helps
pentium4 a bit; no one else seems to care much either way. */
@@ -11176,29 +11200,39 @@ ix86_split_ashldi (rtx *operands, rtx scratch)
rtx x;
if (TARGET_PARTIAL_REG_STALL && !optimize_size)
- x = gen_rtx_ZERO_EXTEND (SImode, operands[2]);
+ x = gen_rtx_ZERO_EXTEND (mode == DImode ? SImode : DImode, operands[2]);
else
- x = gen_lowpart (SImode, operands[2]);
+ x = gen_lowpart (mode == DImode ? SImode : DImode, operands[2]);
emit_insn (gen_rtx_SET (VOIDmode, high[0], x));
- emit_insn (gen_lshrsi3 (high[0], high[0], GEN_INT (5)));
- emit_insn (gen_andsi3 (high[0], high[0], GEN_INT (1)));
+ emit_insn ((mode == DImode
+ ? gen_lshrsi3
+ : gen_lshrdi3) (high[0], high[0], GEN_INT (mode == DImode ? 5 : 6)));
+ emit_insn ((mode == DImode
+ ? gen_andsi3
+ : gen_anddi3) (high[0], high[0], GEN_INT (1)));
emit_move_insn (low[0], high[0]);
- emit_insn (gen_xorsi3 (low[0], low[0], GEN_INT (1)));
+ emit_insn ((mode == DImode
+ ? gen_xorsi3
+ : gen_xordi3) (low[0], low[0], GEN_INT (1)));
}
- emit_insn (gen_ashlsi3 (low[0], low[0], operands[2]));
- emit_insn (gen_ashlsi3 (high[0], high[0], operands[2]));
+ emit_insn ((mode == DImode
+ ? gen_ashlsi3
+ : gen_ashldi3) (low[0], low[0], operands[2]));
+ emit_insn ((mode == DImode
+ ? gen_ashlsi3
+ : gen_ashldi3) (high[0], high[0], operands[2]));
return;
}
if (operands[1] == constm1_rtx)
{
- /* For -1LL << N, we can avoid the shld instruction, because we
- know that we're shifting 0...31 ones into a -1. */
+ /* For -1 << N, we can avoid the shld instruction, because we
+ know that we're shifting 0...31/63 ones into a -1. */
emit_move_insn (low[0], constm1_rtx);
if (optimize_size)
- emit_move_insn (high[0], low[0]);
+ emit_move_insn (high[0], low[0]);
else
emit_move_insn (high[0], constm1_rtx);
}
@@ -11207,53 +11241,71 @@ ix86_split_ashldi (rtx *operands, rtx scratch)
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- split_di (operands, 1, low, high);
- emit_insn (gen_x86_shld_1 (high[0], low[0], operands[2]));
+ (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
+ emit_insn ((mode == DImode
+ ? gen_x86_shld_1
+ : gen_x86_64_shld) (high[0], low[0], operands[2]));
}
- emit_insn (gen_ashlsi3 (low[0], low[0], operands[2]));
+ emit_insn ((mode == DImode ? gen_ashlsi3 : gen_ashldi3) (low[0], low[0], operands[2]));
if (TARGET_CMOVE && scratch)
{
ix86_expand_clear (scratch);
- emit_insn (gen_x86_shift_adj_1 (high[0], low[0], operands[2], scratch));
+ emit_insn ((mode == DImode
+ ? gen_x86_shift_adj_1
+ : gen_x86_64_shift_adj) (high[0], low[0], operands[2], scratch));
}
else
emit_insn (gen_x86_shift_adj_2 (high[0], low[0], operands[2]));
}
void
-ix86_split_ashrdi (rtx *operands, rtx scratch)
+ix86_split_ashr (rtx *operands, rtx scratch, enum machine_mode mode)
{
rtx low[2], high[2];
int count;
+ const int single_width = mode == DImode ? 32 : 64;
if (GET_CODE (operands[2]) == CONST_INT)
{
- split_di (operands, 2, low, high);
- count = INTVAL (operands[2]) & 63;
+ (mode == DImode ? split_di : split_ti) (operands, 2, low, high);
+ count = INTVAL (operands[2]) & (single_width * 2 - 1);
- if (count == 63)
+ if (count == single_width * 2 - 1)
{
emit_move_insn (high[0], high[1]);
- emit_insn (gen_ashrsi3 (high[0], high[0], GEN_INT (31)));
+ emit_insn ((mode == DImode
+ ? gen_ashrsi3
+ : gen_ashrdi3) (high[0], high[0],
+ GEN_INT (single_width - 1)));
emit_move_insn (low[0], high[0]);
}
- else if (count >= 32)
+ else if (count >= single_width)
{
emit_move_insn (low[0], high[1]);
emit_move_insn (high[0], low[0]);
- emit_insn (gen_ashrsi3 (high[0], high[0], GEN_INT (31)));
- if (count > 32)
- emit_insn (gen_ashrsi3 (low[0], low[0], GEN_INT (count - 32)));
+ emit_insn ((mode == DImode
+ ? gen_ashrsi3
+ : gen_ashrdi3) (high[0], high[0],
+ GEN_INT (single_width - 1)));
+ if (count > single_width)
+ emit_insn ((mode == DImode
+ ? gen_ashrsi3
+ : gen_ashrdi3) (low[0], low[0],
+ GEN_INT (count - single_width)));
}
else
{
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- emit_insn (gen_x86_shrd_1 (low[0], high[0], GEN_INT (count)));
- emit_insn (gen_ashrsi3 (high[0], high[0], GEN_INT (count)));
+ emit_insn ((mode == DImode
+ ? gen_x86_shrd_1
+ : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count)));
+ emit_insn ((mode == DImode
+ ? gen_ashrsi3
+ : gen_ashrdi3) (high[0], high[0], GEN_INT (count)));
}
}
else
@@ -11261,17 +11313,26 @@ ix86_split_ashrdi (rtx *operands, rtx scratch)
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- split_di (operands, 1, low, high);
+ (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
- emit_insn (gen_x86_shrd_1 (low[0], high[0], operands[2]));
- emit_insn (gen_ashrsi3 (high[0], high[0], operands[2]));
+ emit_insn ((mode == DImode
+ ? gen_x86_shrd_1
+ : gen_x86_64_shrd) (low[0], high[0], operands[2]));
+ emit_insn ((mode == DImode
+ ? gen_ashrsi3
+ : gen_ashrdi3) (high[0], high[0], operands[2]));
if (TARGET_CMOVE && scratch)
{
emit_move_insn (scratch, high[0]);
- emit_insn (gen_ashrsi3 (scratch, scratch, GEN_INT (31)));
- emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
- scratch));
+ emit_insn ((mode == DImode
+ ? gen_ashrsi3
+ : gen_ashrdi3) (scratch, scratch,
+ GEN_INT (single_width - 1)));
+ emit_insn ((mode == DImode
+ ? gen_x86_shift_adj_1
+ : gen_x86_64_shift_adj) (low[0], high[0], operands[2],
+ scratch));
}
else
emit_insn (gen_x86_shift_adj_3 (low[0], high[0], operands[2]));
@@ -11279,30 +11340,38 @@ ix86_split_ashrdi (rtx *operands, rtx scratch)
}
void
-ix86_split_lshrdi (rtx *operands, rtx scratch)
+ix86_split_lshr (rtx *operands, rtx scratch, enum machine_mode mode)
{
rtx low[2], high[2];
int count;
+ const int single_width = mode == DImode ? 32 : 64;
if (GET_CODE (operands[2]) == CONST_INT)
{
- split_di (operands, 2, low, high);
- count = INTVAL (operands[2]) & 63;
+ (mode == DImode ? split_di : split_ti) (operands, 2, low, high);
+ count = INTVAL (operands[2]) & (single_width * 2 - 1);
- if (count >= 32)
+ if (count >= single_width)
{
emit_move_insn (low[0], high[1]);
ix86_expand_clear (high[0]);
- if (count > 32)
- emit_insn (gen_lshrsi3 (low[0], low[0], GEN_INT (count - 32)));
+ if (count > single_width)
+ emit_insn ((mode == DImode
+ ? gen_lshrsi3
+ : gen_lshrdi3) (low[0], low[0],
+ GEN_INT (count - single_width)));
}
else
{
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- emit_insn (gen_x86_shrd_1 (low[0], high[0], GEN_INT (count)));
- emit_insn (gen_lshrsi3 (high[0], high[0], GEN_INT (count)));
+ emit_insn ((mode == DImode
+ ? gen_x86_shrd_1
+ : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count)));
+ emit_insn ((mode == DImode
+ ? gen_lshrsi3
+ : gen_lshrdi3) (high[0], high[0], GEN_INT (count)));
}
}
else
@@ -11310,17 +11379,23 @@ ix86_split_lshrdi (rtx *operands, rtx scratch)
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- split_di (operands, 1, low, high);
+ (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
- emit_insn (gen_x86_shrd_1 (low[0], high[0], operands[2]));
- emit_insn (gen_lshrsi3 (high[0], high[0], operands[2]));
+ emit_insn ((mode == DImode
+ ? gen_x86_shrd_1
+ : gen_x86_64_shrd) (low[0], high[0], operands[2]));
+ emit_insn ((mode == DImode
+ ? gen_lshrsi3
+ : gen_lshrdi3) (high[0], high[0], operands[2]));
/* Heh. By reversing the arguments, we can reuse this pattern. */
if (TARGET_CMOVE && scratch)
{
ix86_expand_clear (scratch);
- emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
- scratch));
+ emit_insn ((mode == DImode
+ ? gen_x86_shift_adj_1
+ : gen_x86_64_shift_adj) (low[0], high[0], operands[2],
+ scratch));
}
else
emit_insn (gen_x86_shift_adj_2 (low[0], high[0], operands[2]));
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 7a54cba..e140bd2 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1218,7 +1218,7 @@ enum reg_class
(C) == 'l' ? INDEX_REGS : \
NO_REGS)
-/* The letters I, J, K, L and M in a register constraint string
+/* The letters I, J, K, L, M, N, and O in a register constraint string
can be used to stand for particular ranges of immediate operands.
This macro defines what the ranges are.
C is the letter, and VALUE is a constant value.
@@ -1230,6 +1230,7 @@ enum reg_class
L is for andsi as zero-extending move.
M is for shifts that can be executed by the "lea" opcode.
N is for immediate operands for out/in instructions (0-255)
+ O is for TImode shifts.
*/
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
@@ -1239,6 +1240,7 @@ enum reg_class
: (C) == 'L' ? (VALUE) == 0xff || (VALUE) == 0xffff \
: (C) == 'M' ? (VALUE) >= 0 && (VALUE) <= 3 \
: (C) == 'N' ? (VALUE) >= 0 && (VALUE) <= 255 \
+ : (C) == 'O' ? (VALUE) >= 0 && (VALUE) <= 127 \
: 0)
/* Similar, but for floating constants, and defining letters G and H.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index e7f2e22..ba35331 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -478,6 +478,19 @@
;; actually generating RTL. The bCOND or sCOND (emitted immediately
;; after the cmp) will actually emit the cmpM.
+(define_expand "cmpti"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "x86_64_general_operand" "")))]
+ "TARGET_64BIT"
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ operands[0] = force_reg (TImode, operands[0]);
+ ix86_compare_op0 = operands[0];
+ ix86_compare_op1 = operands[1];
+ DONE;
+})
+
(define_expand "cmpdi"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
@@ -4694,6 +4707,42 @@
;; Add instructions
+;; %%% splits for addditi3
+
+(define_expand "addti3"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "x86_64_general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;")
+
+(define_insn "*addti3_1"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
+ (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:TI 2 "general_operand" "roiF,riF")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)"
+ "#")
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
+ UNSPEC_ADD_CARRY))
+ (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))])
+ (parallel [(set (match_dup 3)
+ (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 4))
+ (match_dup 5)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_ti (operands+0, 1, operands+0, operands+3);
+ split_ti (operands+1, 1, operands+1, operands+4);
+ split_ti (operands+2, 1, operands+2, operands+5);")
+
;; %%% splits for addsidi3
; [(set (match_operand:DI 0 "nonimmediate_operand" "")
; (plus:DI (match_operand:DI 1 "general_operand" "")
@@ -6392,6 +6441,41 @@
;; Subtract instructions
+;; %%% splits for subditi3
+
+(define_expand "subti3"
+ [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "x86_64_general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+ "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;")
+
+(define_insn "*subti3_1"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
+ (minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0")
+ (match_operand:TI 2 "general_operand" "roiF,riF")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)"
+ "#")
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))])
+ (parallel [(set (match_dup 3)
+ (minus:DI (match_dup 4)
+ (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 5))))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_ti (operands+0, 1, operands+0, operands+3);
+ split_ti (operands+1, 1, operands+1, operands+4);
+ split_ti (operands+2, 1, operands+2, operands+5);")
+
;; %%% splits for subsidi3
(define_expand "subdi3"
@@ -9198,6 +9282,43 @@
;; Negation instructions
+(define_expand "negti2"
+ [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+ "ix86_expand_unary_operator (NEG, TImode, operands); DONE;")
+
+(define_insn "*negti2_1"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=ro")
+ (neg:TI (match_operand:TI 1 "general_operand" "0")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT
+ && ix86_unary_operator_ok (NEG, TImode, operands)"
+ "#")
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (neg:TI (match_operand:TI 1 "general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(parallel
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (neg:DI (match_dup 2)) (const_int 0)))
+ (set (match_dup 0) (neg:DI (match_dup 2)))])
+ (parallel
+ [(set (match_dup 1)
+ (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 3))
+ (const_int 0)))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (match_dup 1)
+ (neg:DI (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_ti (operands+1, 1, operands+2, operands+3);
+ split_ti (operands+0, 1, operands+0, operands+1);")
+
(define_expand "negdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))
@@ -10079,6 +10200,92 @@
;; shift pair, instead using moves and sign extension for counts greater
;; than 31.
+(define_expand "ashlti3"
+ [(parallel [(set (match_operand:TI 0 "register_operand" "")
+ (ashift:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+{
+ if (! immediate_operand (operands[2], QImode))
+ {
+ emit_insn (gen_ashlti3_1 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ ix86_expand_binary_operator (ASHIFT, TImode, operands);
+ DONE;
+})
+
+(define_insn "ashlti3_1"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashift:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "c")))
+ (clobber (match_scratch:DI 3 "=&r"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_insn "*ashlti3_2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashift:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "O")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
+ (match_operand:QI 2 "register_operand" "")))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashl (operands, operands[3], TImode); DONE;")
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashift:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "immediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;")
+
+(define_insn "x86_64_shld"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
+ (ior:DI (ashift:DI (match_dup 0)
+ (match_operand:QI 2 "nonmemory_operand" "J,c"))
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
+ (minus:QI (const_int 64) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "@
+ shld{q}\t{%2, %1, %0|%0, %1, %2}
+ shld{q}\t{%s2%1, %0|%0, %1, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")
+ (set_attr "athlon_decode" "vector")])
+
+(define_expand "x86_64_shift_adj"
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
+ (const_int 64))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "")
+ (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
+ (match_operand:DI 1 "register_operand" "")
+ (match_dup 0)))
+ (set (match_dup 1)
+ (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
+ (match_operand:DI 3 "register_operand" "r")
+ (match_dup 1)))]
+ "TARGET_64BIT"
+ "")
+
(define_expand "ashldi3"
[(set (match_operand:DI 0 "shiftdi_operand" "")
(ashift:DI (match_operand:DI 1 "ashldi_input_operand" "")
@@ -10203,7 +10410,7 @@
(match_dup 3)]
"!TARGET_64BIT && TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_ashldi (operands, operands[3]); DONE;")
+ "ix86_split_ashl (operands, operands[3], DImode); DONE;")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -10212,7 +10419,7 @@
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && (flag_peephole2 ? flow2_completed : reload_completed)"
[(const_int 0)]
- "ix86_split_ashldi (operands, NULL_RTX); DONE;")
+ "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
(define_insn "x86_shld_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
@@ -10778,6 +10985,76 @@
;; See comment above `ashldi3' about how this works.
+(define_expand "ashrti3"
+ [(parallel [(set (match_operand:TI 0 "register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+{
+ if (! immediate_operand (operands[2], QImode))
+ {
+ emit_insn (gen_ashrti3_1 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ ix86_expand_binary_operator (ASHIFTRT, TImode, operands);
+ DONE;
+})
+
+(define_insn "ashrti3_1"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "c")))
+ (clobber (match_scratch:DI 3 "=&r"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_insn "*ashrti3_2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "O")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "register_operand" "")))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashr (operands, operands[3], TImode); DONE;")
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "immediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;")
+
+(define_insn "x86_64_shrd"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
+ (ior:DI (ashiftrt:DI (match_dup 0)
+ (match_operand:QI 2 "nonmemory_operand" "J,c"))
+ (ashift:DI (match_operand:DI 1 "register_operand" "r,r")
+ (minus:QI (const_int 64) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "@
+ shrd{q}\t{%2, %1, %0|%0, %1, %2}
+ shrd{q}\t{%s2%1, %0|%0, %1, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")
+ (set_attr "athlon_decode" "vector")])
+
(define_expand "ashrdi3"
[(set (match_operand:DI 0 "shiftdi_operand" "")
(ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
@@ -10887,7 +11164,7 @@
(match_dup 3)]
"!TARGET_64BIT && TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_ashrdi (operands, operands[3]); DONE;")
+ "ix86_split_ashr (operands, operands[3], DImode); DONE;")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -10896,7 +11173,7 @@
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && (flag_peephole2 ? flow2_completed : reload_completed)"
[(const_int 0)]
- "ix86_split_ashrdi (operands, NULL_RTX); DONE;")
+ "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;")
(define_insn "x86_shrd_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
@@ -11275,6 +11552,60 @@
;; See comment above `ashldi3' about how this works.
+(define_expand "lshrti3"
+ [(parallel [(set (match_operand:TI 0 "register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+{
+ if (! immediate_operand (operands[2], QImode))
+ {
+ emit_insn (gen_lshrti3_1 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ ix86_expand_binary_operator (LSHIFTRT, TImode, operands);
+ DONE;
+})
+
+(define_insn "lshrti3_1"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "c")))
+ (clobber (match_scratch:DI 3 "=&r"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_insn "*lshrti3_2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "O")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "register_operand" "")))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_lshr (operands, operands[3], TImode); DONE;")
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "immediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;")
+
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "shiftdi_operand" "")
(lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
@@ -11367,7 +11698,7 @@
(match_dup 3)]
"!TARGET_64BIT && TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_lshrdi (operands, operands[3]); DONE;")
+ "ix86_split_lshr (operands, operands[3], DImode); DONE;")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -11376,7 +11707,7 @@
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && (flag_peephole2 ? flow2_completed : reload_completed)"
[(const_int 0)]
- "ix86_split_lshrdi (operands, NULL_RTX); DONE;")
+ "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "")