i386.md (adddi3_carry_rex64, [...]): Name pattern.

* i386.md (adddi3_carry_rex64, subdi3_carry_rex64): Name pattern.
	(addhi3_carry, addqi3_carry, subhi3_carry, subqi3_carry): New patterns.
	(add??cc): New expanders.
	* i386.c (expand_int_addcc): New function.
	* i386-protos.h (expand_int_addcc): Declare.

	* alias.c (memory_modified_1): New static function.
	(memory_modified): New static varaible.
	(memory_modified_in_insn_p): New global function.
	* rtl.h (memory_modified_in_insn_p): Declare.
	* rtlanal.c (modified_between_p, modified_in_p): Be smart about memory
	references.

	* expr.h (emit_conditional_add): Declare.

From-SVN: r61038
This commit is contained in:
Jan Hubicka 2003-01-08 12:20:23 +01:00 committed by Jan Hubicka
parent 67d96a1661
commit 7b52eedeed
8 changed files with 220 additions and 10 deletions

View File

@ -1,3 +1,20 @@
Wed Jan 8 12:10:57 CET 2003 Jan Hubicka <jh@suse.cz>
* i386.md (adddi3_carry_rex64, subdi3_carry_rex64): Name pattern.
(addhi3_carry, addqi3_carry, subhi3_carry, subqi3_carry): New patterns.
(add??cc): New expanders.
* i386.c (expand_int_addcc): New function.
* i386-protos.h (expand_int_addcc): Declare.
* alias.c (memory_modified_1): New static function.
(memory_modified): New static varaible.
(memory_modified_in_insn_p): New global function.
* rtl.h (memory_modified_in_insn_p): Declare.
* rtlanal.c (modified_between_p, modified_in_p): Be smart about memory
references.
* expr.h (emit_conditional_add): Declare.
2003-01-07 Janis Johnson <janis187@us.ibm.com>
PR other/8947

View File

@ -119,6 +119,7 @@ static int nonlocal_referenced_p_1 PARAMS ((rtx *, void *));
static int nonlocal_referenced_p PARAMS ((rtx));
static int nonlocal_set_p_1 PARAMS ((rtx *, void *));
static int nonlocal_set_p PARAMS ((rtx));
static void memory_modified_1 PARAMS ((rtx, rtx, void *));
/* Set up all info needed to perform alias analysis on memory references. */
@ -2703,6 +2704,35 @@ init_alias_once ()
alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
}
/* Set MEMORY_MODIFIED when X modifies DATA (that is assumed
to be memory reference. */
static bool memory_modified;
static void
memory_modified_1 (x, pat, data)
rtx x, pat ATTRIBUTE_UNUSED;
void *data;
{
if (GET_CODE (x) == MEM)
{
if (anti_dependence (x, (rtx)data) || output_dependence (x, (rtx)data))
memory_modified = true;
}
}
/* Return true when INSN possibly modify memory contents of MEM
(ie address can be modified). */
bool
memory_modified_in_insn_p (mem, insn)
rtx mem, insn;
{
if (!INSN_P (insn))
return false;
memory_modified = false;
note_stores (PATTERN (insn), memory_modified_1, mem);
return memory_modified;
}
/* Initialize the aliasing machinery. Initialize the REG_KNOWN_VALUE
array. */

View File

@ -141,6 +141,7 @@ extern void ix86_expand_branch PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_int_movcc PARAMS ((rtx[]));
extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
extern int ix86_expand_int_addcc PARAMS ((rtx[]));
extern void ix86_expand_call PARAMS ((rtx, rtx, rtx, rtx, rtx, int));
extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));

View File

@ -9981,6 +9981,69 @@ ix86_expand_fp_movcc (operands)
return 1;
}
/* Expand conditional increment or decrement using adb/sbb instructions.
The default case using setcc followed by the conditional move can be
done by generic code. */
int
ix86_expand_int_addcc (operands)
rtx operands[];
{
enum rtx_code code = GET_CODE (operands[1]);
rtx compare_op;
rtx val = const0_rtx;
if (operands[3] != const1_rtx
&& operands[3] != constm1_rtx)
return 0;
if (!ix86_expand_carry_flag_compare (code, ix86_compare_op0,
ix86_compare_op1, &compare_op))
return 0;
if (GET_CODE (compare_op) != LTU)
val = operands[3] == const1_rtx ? constm1_rtx : const1_rtx;
if ((GET_CODE (compare_op) == LTU) == (operands[3] == constm1_rtx))
{
switch (GET_MODE (operands[0]))
{
case QImode:
emit_insn (gen_subqi3_carry (operands[0], operands[2], val));
break;
case HImode:
emit_insn (gen_subhi3_carry (operands[0], operands[2], val));
break;
case SImode:
emit_insn (gen_subsi3_carry (operands[0], operands[2], val));
break;
case DImode:
emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val));
break;
default:
abort ();
}
}
else
{
switch (GET_MODE (operands[0]))
{
case QImode:
emit_insn (gen_addqi3_carry (operands[0], operands[2], val));
break;
case HImode:
emit_insn (gen_addhi3_carry (operands[0], operands[2], val));
break;
case SImode:
emit_insn (gen_addsi3_carry (operands[0], operands[2], val));
break;
case DImode:
emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val));
break;
default:
abort ();
}
}
return 1; /* DONE */
}
/* Split operands 0 and 1 into SImode parts. Similar to split_di, but
works for floating pointer parameters and nonoffsetable memories.
For pushes, it returns just stack offsets; the values will be saved

View File

@ -4951,7 +4951,7 @@
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
(define_insn "*adddi3_carry_rex64"
(define_insn "adddi3_carry_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
(match_operand:DI 1 "nonimmediate_operand" "%0,0"))
@ -4976,7 +4976,33 @@
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
(define_insn "*addsi3_carry"
(define_insn "addqi3_carry"
[(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r")
(plus:QI (plus:QI (ltu:QI (reg:CC 17) (const_int 0))
(match_operand:QI 1 "nonimmediate_operand" "%0,0"))
(match_operand:QI 2 "general_operand" "ri,rm")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (PLUS, QImode, operands)"
"adc{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
(set_attr "mode" "QI")
(set_attr "ppro_uops" "few")])
(define_insn "addhi3_carry"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(plus:HI (plus:HI (ltu:HI (reg:CC 17) (const_int 0))
(match_operand:HI 1 "nonimmediate_operand" "%0,0"))
(match_operand:HI 2 "general_operand" "ri,rm")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (PLUS, HImode, operands)"
"adc{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
(set_attr "mode" "HI")
(set_attr "ppro_uops" "few")])
(define_insn "addsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
(match_operand:SI 1 "nonimmediate_operand" "%0,0"))
@ -6653,6 +6679,31 @@
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
(define_insn "subqi3_carry"
[(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r")
(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(plus:QI (ltu:QI (reg:CC 17) (const_int 0))
(match_operand:QI 2 "general_operand" "ri,rm"))))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (MINUS, QImode, operands)"
"sbb{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
(set_attr "ppro_uops" "few")
(set_attr "mode" "QI")])
(define_insn "subhi3_carry"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(plus:HI (ltu:HI (reg:CC 17) (const_int 0))
(match_operand:HI 2 "general_operand" "ri,rm"))))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (MINUS, HImode, operands)"
"sbb{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
(set_attr "ppro_uops" "few")
(set_attr "mode" "HI")])
(define_insn "subsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
@ -16459,6 +16510,39 @@
(match_dup 1)
(match_dup 2)))])
;; Conditional addition patterns
(define_expand "addqicc"
[(match_operand:QI 0 "register_operand" "")
(match_operand 1 "comparison_operator" "")
(match_operand:QI 2 "register_operand" "")
(match_operand:QI 3 "const_int_operand" "")]
""
"if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
(define_expand "addhicc"
[(match_operand:HI 0 "register_operand" "")
(match_operand 1 "comparison_operator" "")
(match_operand:HI 2 "register_operand" "")
(match_operand:HI 3 "const_int_operand" "")]
""
"if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
(define_expand "addsicc"
[(match_operand:SI 0 "register_operand" "")
(match_operand 1 "comparison_operator" "")
(match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "const_int_operand" "")]
""
"if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
(define_expand "adddicc"
[(match_operand:DI 0 "register_operand" "")
(match_operand 1 "comparison_operator" "")
(match_operand:DI 2 "register_operand" "")
(match_operand:DI 3 "const_int_operand" "")]
"TARGET_64BIT"
"if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
;; We can't represent the LT test directly. Do this by swapping the operands.
(define_split

View File

@ -307,6 +307,9 @@ rtx emit_conditional_move PARAMS ((rtx, enum rtx_code, rtx, rtx,
int can_conditionally_move_p PARAMS ((enum machine_mode mode));
#endif
rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx,
enum machine_mode, rtx, rtx,
enum machine_mode, int);
/* Functions from expmed.c: */

View File

@ -2251,6 +2251,7 @@ extern void init_alias_once PARAMS ((void));
extern void init_alias_analysis PARAMS ((void));
extern void end_alias_analysis PARAMS ((void));
extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));
extern bool memory_modified_in_insn_p PARAMS ((rtx, rtx));
/* In sibcall.c */
typedef enum {

View File

@ -1037,7 +1037,7 @@ regs_set_between_p (x, start, end)
/* Similar to reg_set_between_p, but check all registers in X. Return 0
only if none of them are modified between START and END. Return 1 if
X contains a MEM; this routine does not perform any memory aliasing. */
X contains a MEM; this routine does usememory aliasing. */
int
modified_between_p (x, start, end)
@ -1047,6 +1047,10 @@ modified_between_p (x, start, end)
enum rtx_code code = GET_CODE (x);
const char *fmt;
int i, j;
rtx insn;
if (start == end)
return 0;
switch (code)
{
@ -1063,10 +1067,14 @@ modified_between_p (x, start, end)
return 1;
case MEM:
/* If the memory is not constant, assume it is modified. If it is
constant, we still have to check the address. */
if (! RTX_UNCHANGING_P (x))
if (RTX_UNCHANGING_P (x))
return 0;
if (modified_between_p (XEXP (x, 0), start, end))
return 1;
for (insn = NEXT_INSN (start); insn != end; insn = NEXT_INSN (insn))
if (memory_modified_in_insn_p (x, insn))
return 1;
return 0;
break;
case REG:
@ -1093,7 +1101,7 @@ modified_between_p (x, start, end)
/* Similar to reg_set_p, but check all registers in X. Return 0 only if none
of them are modified in INSN. Return 1 if X contains a MEM; this routine
does not perform any memory aliasing. */
does use memory aliasing. */
int
modified_in_p (x, insn)
@ -1119,10 +1127,13 @@ modified_in_p (x, insn)
return 1;
case MEM:
/* If the memory is not constant, assume it is modified. If it is
constant, we still have to check the address. */
if (! RTX_UNCHANGING_P (x))
if (RTX_UNCHANGING_P (x))
return 0;
if (modified_in_p (XEXP (x, 0), insn))
return 1;
if (memory_modified_in_insn_p (x, insn))
return 1;
return 0;
break;
case REG: