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:
parent
67d96a1661
commit
7b52eedeed
|
@ -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>
|
2003-01-07 Janis Johnson <janis187@us.ibm.com>
|
||||||
|
|
||||||
PR other/8947
|
PR other/8947
|
||||||
|
|
30
gcc/alias.c
30
gcc/alias.c
|
@ -119,6 +119,7 @@ static int nonlocal_referenced_p_1 PARAMS ((rtx *, void *));
|
||||||
static int nonlocal_referenced_p PARAMS ((rtx));
|
static int nonlocal_referenced_p PARAMS ((rtx));
|
||||||
static int nonlocal_set_p_1 PARAMS ((rtx *, void *));
|
static int nonlocal_set_p_1 PARAMS ((rtx *, void *));
|
||||||
static int nonlocal_set_p PARAMS ((rtx));
|
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. */
|
/* 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);
|
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
|
/* Initialize the aliasing machinery. Initialize the REG_KNOWN_VALUE
|
||||||
array. */
|
array. */
|
||||||
|
|
||||||
|
|
|
@ -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_setcc PARAMS ((enum rtx_code, rtx));
|
||||||
extern int ix86_expand_int_movcc PARAMS ((rtx[]));
|
extern int ix86_expand_int_movcc PARAMS ((rtx[]));
|
||||||
extern int ix86_expand_fp_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 ix86_expand_call PARAMS ((rtx, rtx, rtx, rtx, rtx, int));
|
||||||
extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
|
extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
|
||||||
extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));
|
extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));
|
||||||
|
|
|
@ -9981,6 +9981,69 @@ ix86_expand_fp_movcc (operands)
|
||||||
return 1;
|
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
|
/* Split operands 0 and 1 into SImode parts. Similar to split_di, but
|
||||||
works for floating pointer parameters and nonoffsetable memories.
|
works for floating pointer parameters and nonoffsetable memories.
|
||||||
For pushes, it returns just stack offsets; the values will be saved
|
For pushes, it returns just stack offsets; the values will be saved
|
||||||
|
|
|
@ -4951,7 +4951,7 @@
|
||||||
split_di (operands+1, 1, operands+1, operands+4);
|
split_di (operands+1, 1, operands+1, operands+4);
|
||||||
split_di (operands+2, 1, operands+2, operands+5);")
|
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")
|
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
|
||||||
(plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
|
(plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
|
||||||
(match_operand:DI 1 "nonimmediate_operand" "%0,0"))
|
(match_operand:DI 1 "nonimmediate_operand" "%0,0"))
|
||||||
|
@ -4976,7 +4976,33 @@
|
||||||
[(set_attr "type" "alu")
|
[(set_attr "type" "alu")
|
||||||
(set_attr "mode" "DI")])
|
(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")
|
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
|
||||||
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
|
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
|
||||||
(match_operand:SI 1 "nonimmediate_operand" "%0,0"))
|
(match_operand:SI 1 "nonimmediate_operand" "%0,0"))
|
||||||
|
@ -6653,6 +6679,31 @@
|
||||||
[(set_attr "type" "alu")
|
[(set_attr "type" "alu")
|
||||||
(set_attr "mode" "DI")])
|
(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"
|
(define_insn "subsi3_carry"
|
||||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
|
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
|
||||||
|
@ -16459,6 +16510,39 @@
|
||||||
(match_dup 1)
|
(match_dup 1)
|
||||||
(match_dup 2)))])
|
(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.
|
;; We can't represent the LT test directly. Do this by swapping the operands.
|
||||||
|
|
||||||
(define_split
|
(define_split
|
||||||
|
|
|
@ -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));
|
int can_conditionally_move_p PARAMS ((enum machine_mode mode));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx,
|
||||||
|
enum machine_mode, rtx, rtx,
|
||||||
|
enum machine_mode, int);
|
||||||
|
|
||||||
|
|
||||||
/* Functions from expmed.c: */
|
/* Functions from expmed.c: */
|
||||||
|
|
|
@ -2251,6 +2251,7 @@ extern void init_alias_once PARAMS ((void));
|
||||||
extern void init_alias_analysis PARAMS ((void));
|
extern void init_alias_analysis PARAMS ((void));
|
||||||
extern void end_alias_analysis PARAMS ((void));
|
extern void end_alias_analysis PARAMS ((void));
|
||||||
extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));
|
extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));
|
||||||
|
extern bool memory_modified_in_insn_p PARAMS ((rtx, rtx));
|
||||||
|
|
||||||
/* In sibcall.c */
|
/* In sibcall.c */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -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
|
/* 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
|
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
|
int
|
||||||
modified_between_p (x, start, end)
|
modified_between_p (x, start, end)
|
||||||
|
@ -1047,6 +1047,10 @@ modified_between_p (x, start, end)
|
||||||
enum rtx_code code = GET_CODE (x);
|
enum rtx_code code = GET_CODE (x);
|
||||||
const char *fmt;
|
const char *fmt;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
rtx insn;
|
||||||
|
|
||||||
|
if (start == end)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
|
@ -1063,10 +1067,14 @@ modified_between_p (x, start, end)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case MEM:
|
case MEM:
|
||||||
/* If the memory is not constant, assume it is modified. If it is
|
if (RTX_UNCHANGING_P (x))
|
||||||
constant, we still have to check the address. */
|
return 0;
|
||||||
if (! RTX_UNCHANGING_P (x))
|
if (modified_between_p (XEXP (x, 0), start, end))
|
||||||
return 1;
|
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;
|
break;
|
||||||
|
|
||||||
case REG:
|
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
|
/* 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
|
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
|
int
|
||||||
modified_in_p (x, insn)
|
modified_in_p (x, insn)
|
||||||
|
@ -1119,10 +1127,13 @@ modified_in_p (x, insn)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case MEM:
|
case MEM:
|
||||||
/* If the memory is not constant, assume it is modified. If it is
|
if (RTX_UNCHANGING_P (x))
|
||||||
constant, we still have to check the address. */
|
return 0;
|
||||||
if (! RTX_UNCHANGING_P (x))
|
if (modified_in_p (XEXP (x, 0), insn))
|
||||||
return 1;
|
return 1;
|
||||||
|
if (memory_modified_in_insn_p (x, insn))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG:
|
case REG:
|
||||||
|
|
Loading…
Reference in New Issue