Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
b30f05db
Commit
b30f05db
authored
Aug 18, 1999
by
Bernd Schmidt
Committed by
Bernd Schmidt
Aug 18, 1999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Combined compare & jump infrastructure
From-SVN: r28752
parent
9bb21998
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
490 additions
and
482 deletions
+490
-482
gcc/ChangeLog
+46
-0
gcc/expmed.c
+8
-10
gcc/expr.c
+216
-300
gcc/expr.h
+3
-0
gcc/flow.c
+1
-1
gcc/integrate.c
+3
-2
gcc/optabs.c
+184
-129
gcc/unroll.c
+29
-40
No files found.
gcc/ChangeLog
View file @
b30f05db
Wed
Aug
18
18
:
20
:
40
1999
Bernd
Schmidt
<
bernds
@cygnus
.
co
.
uk
>
*
expmed
.
c
(
emit_store_flag
)
:
If
UNSIGNEDP
,
call
unsigned_condition
on
CODE
.
(
emit_store_flag_force
)
:
Use
do_compare_rtx_and_jump
.
(
do_cmp_and_jump
)
:
Formatting
fixes
.
*
expr
.
c
(
do_compare_and_jump
)
:
Renamed
from
compare
;
changed
to
call
do_compare_rtx_and_jump
instead
of
compare_from_rtx
.
(
do_compare_rtx_and_jump
)
:
New
function
;
mostly
copied
from
compare_from_rtx
.
(
do_jump_for_compare
)
:
Delete
.
(
expand_expr
)
:
Use
do_compare_rtx_and_jump
when
handling
MAX_EXPR
and
MIN_EXPR
.
(
do_jump
)
:
Use
do_compare_and_jump
or
do_compare_rtx_and_jump
instead
of
compare
/
do_jump_for_compare
pairs
.
(
do_jump_by_parts_greater
)
:
Use
do_jump_by_parts_greater_rtx
.
(
do_jump_by_parts_greater_rtx
)
:
Use
do_compare_rtx_and_jump
instead
of
compare_from_rtx
/
do_jump_for_compare
pairs
.
(
do_jump_by_parts_equality
)
:
Likewise
.
(
do_jump_by_parts_equality_rtx
)
:
Likewise
.
*
expr
.
h
(
do_compare_rtx_and_jump
)
:
Declare
.
*
optabs
.
c
(
prepare_cmp_insn
)
:
New
function
,
contains
most
of
the
code
that
used
to
be
in
emit_cmp_insn
.
(
cmp_available_p
)
:
New
function
.
(
prepare_operand
)
:
New
function
.
(
emit_cmp_and_jump_insn_1
)
:
New
function
,
contains
some
code
that
used
to
be
in
emit_cmp_insn
.
(
prepare_float_lib_cmp
)
:
Renamed
from
emit_float_lib_cmp
;
change
some
parameters
to
be
pointers
;
don
'
t
emit
final
compare
but
modify
some
of
the
values
pointed
to
by
the
args
so
the
caller
can
perform
the
correct
comparison
.
(
expand_binop
)
:
Call
emit_store_flag_force
with
signed
forms
of
comparison
code
.
(
expand_abs
)
:
Use
do_compare_rtx_and_jump
instead
of
compare_from_rtx
/
emit_jump_insn
pair
.
(
emit_cmp_and_jump_insn
)
:
Use
prepare_cmp_insn
and
emit_cmp_and_jump_insn_1
.
Call
emit_queue
.
(
emit_cmp_insn
)
:
Just
call
emit_cmp_and_jump_insns
with
zero
for
LABEL
arg
.
*
flow
.
c
(
tidy_fallthru_edge
)
:
If
HAVE_cc0
,
verify
insn
before
a
jump
sets
cc0
before
deleting
it
.
*
integrate
.
c
(
expand_inline_function
)
:
Likewise
.
*
unroll
.
c
(
unroll_loop
)
:
Similar
changes
in
several
places
.
(
copy_loop_body
)
:
If
HAVE_cc0
,
verify
insn
before
a
jump
sets
cc0
before
deleting
it
.
Wed
Aug
18
06
:
37
:
44
1999
Bernd
Schmidt
<
bernds
@cygnus
.
co
.
uk
>
*
Makefile
.
in
(
insn
-
recog
.
o
)
:
Update
dependencies
.
...
...
gcc/expmed.c
View file @
b30f05db
...
...
@@ -4093,6 +4093,9 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
rtx
last
=
get_last_insn
();
rtx
pattern
,
comparison
;
if
(
unsignedp
)
code
=
unsigned_condition
(
code
);
/* If one operand is constant, make it the second one. Only do this
if the other operand is not constant as well. */
...
...
@@ -4492,15 +4495,10 @@ emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
target
=
gen_reg_rtx
(
GET_MODE
(
target
));
emit_move_insn
(
target
,
const1_rtx
);
tem
=
compare_from_rtx
(
op0
,
op1
,
code
,
unsignedp
,
mode
,
NULL_RTX
,
0
);
if
(
GET_CODE
(
tem
)
==
CONST_INT
)
return
tem
;
label
=
gen_label_rtx
();
if
(
bcc_gen_fctn
[(
int
)
code
]
==
0
)
abort
(
);
do_compare_rtx_and_jump
(
op0
,
op1
,
code
,
unsignedp
,
mode
,
NULL_RTX
,
0
,
NULL_RTX
,
label
);
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
code
])
(
label
));
emit_move_insn
(
target
,
const0_rtx
);
emit_label
(
label
);
...
...
@@ -4519,13 +4517,13 @@ emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
static
void
do_cmp_and_jump
(
arg1
,
arg2
,
op
,
mode
,
label
)
rtx
arg1
,
arg2
,
label
;
enum
rtx_code
op
;
enum
machine_mode
mode
;
enum
rtx_code
op
;
enum
machine_mode
mode
;
{
/* If this mode is an integer too wide to compare properly,
compare word by word. Rely on cse to optimize constant cases. */
if
(
GET_MODE_CLASS
(
mode
)
==
MODE_INT
&&
!
can_compare_p
(
mode
))
if
(
GET_MODE_CLASS
(
mode
)
==
MODE_INT
&&
!
can_compare_p
(
mode
))
{
rtx
label2
=
gen_label_rtx
();
...
...
gcc/expr.c
View file @
b30f05db
...
...
@@ -152,8 +152,7 @@ static rtx expand_increment PROTO((tree, int, int));
static
void
preexpand_calls
PROTO
((
tree
));
static
void
do_jump_by_parts_greater
PROTO
((
tree
,
int
,
rtx
,
rtx
));
static
void
do_jump_by_parts_equality
PROTO
((
tree
,
rtx
,
rtx
));
static
void
do_jump_for_compare
PROTO
((
rtx
,
rtx
,
rtx
));
static
rtx
compare
PROTO
((
tree
,
enum
rtx_code
,
enum
rtx_code
));
static
void
do_compare_and_jump
PROTO
((
tree
,
enum
rtx_code
,
enum
rtx_code
,
rtx
,
rtx
));
static
rtx
do_store_flag
PROTO
((
tree
,
rtx
,
enum
machine_mode
,
int
));
/* Record for each mode whether we can move a register directly to or
...
...
@@ -7297,7 +7296,7 @@ expand_expr (exp, target, tmode, modifier)
/* If this mode is an integer too wide to compare properly,
compare word by word. Rely on cse to optimize constant cases. */
if
(
GET_MODE_CLASS
(
mode
)
==
MODE_INT
&&
!
can_compare_p
(
mode
))
if
(
GET_MODE_CLASS
(
mode
)
==
MODE_INT
&&
!
can_compare_p
(
mode
))
{
if
(
code
==
MAX_EXPR
)
do_jump_by_parts_greater_rtx
(
mode
,
TREE_UNSIGNED
(
type
),
...
...
@@ -7305,29 +7304,15 @@ expand_expr (exp, target, tmode, modifier)
else
do_jump_by_parts_greater_rtx
(
mode
,
TREE_UNSIGNED
(
type
),
op1
,
target
,
NULL_RTX
,
op0
);
emit_move_insn
(
target
,
op1
);
}
else
{
if
(
code
==
MAX_EXPR
)
temp
=
(
TREE_UNSIGNED
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
1
)))
?
compare_from_rtx
(
target
,
op1
,
GEU
,
1
,
mode
,
NULL_RTX
,
0
)
:
compare_from_rtx
(
target
,
op1
,
GE
,
0
,
mode
,
NULL_RTX
,
0
));
else
temp
=
(
TREE_UNSIGNED
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
1
)))
?
compare_from_rtx
(
target
,
op1
,
LEU
,
1
,
mode
,
NULL_RTX
,
0
)
:
compare_from_rtx
(
target
,
op1
,
LE
,
0
,
mode
,
NULL_RTX
,
0
));
if
(
temp
==
const0_rtx
)
emit_move_insn
(
target
,
op1
);
else
if
(
temp
!=
const_true_rtx
)
{
if
(
bcc_gen_fctn
[(
int
)
GET_CODE
(
temp
)]
!=
0
)
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
GET_CODE
(
temp
)])
(
op0
));
else
abort
();
emit_move_insn
(
target
,
op1
);
}
int
unsignedp
=
TREE_UNSIGNED
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
1
)));
do_compare_rtx_and_jump
(
target
,
op1
,
code
==
MAX_EXPR
?
GE
:
LE
,
unsignedp
,
mode
,
NULL_RTX
,
0
,
NULL_RTX
,
op0
);
}
emit_move_insn
(
target
,
op1
);
emit_label
(
op0
);
return
target
;
...
...
@@ -8626,7 +8611,6 @@ do_jump (exp, if_false_label, if_true_label)
These cases set DROP_THROUGH_LABEL nonzero. */
rtx
drop_through_label
=
0
;
rtx
temp
;
rtx
comparison
=
0
;
int
i
;
tree
type
;
enum
machine_mode
mode
;
...
...
@@ -8692,10 +8676,10 @@ do_jump (exp, if_false_label, if_true_label)
case
MINUS_EXPR
:
/* Non-zero iff operands of minus differ. */
comparison
=
compare
(
build
(
NE_EXPR
,
TREE_TYPE
(
exp
),
TREE_OPERAND
(
exp
,
0
),
TREE_OPERAND
(
exp
,
1
)),
NE
,
NE
);
do_compare_and_jump
(
build
(
NE_EXPR
,
TREE_TYPE
(
exp
),
TREE_OPERAND
(
exp
,
0
),
TREE_OPERAND
(
exp
,
1
)),
NE
,
NE
,
if_false_label
,
if_true_label
);
break
;
case
BIT_AND_EXPR
:
...
...
@@ -8854,7 +8838,7 @@ do_jump (exp, if_false_label, if_true_label)
&&
!
can_compare_p
(
TYPE_MODE
(
inner_type
)))
do_jump_by_parts_equality
(
exp
,
if_false_label
,
if_true_label
);
else
comparison
=
compare
(
exp
,
EQ
,
EQ
);
do_compare_and_jump
(
exp
,
EQ
,
EQ
,
if_false_label
,
if_true_label
);
break
;
}
...
...
@@ -8894,7 +8878,7 @@ do_jump (exp, if_false_label, if_true_label)
&&
!
can_compare_p
(
TYPE_MODE
(
inner_type
)))
do_jump_by_parts_equality
(
exp
,
if_true_label
,
if_false_label
);
else
comparison
=
compare
(
exp
,
NE
,
NE
);
do_compare_and_jump
(
exp
,
NE
,
NE
,
if_false_label
,
if_true_label
);
break
;
}
...
...
@@ -8904,7 +8888,7 @@ do_jump (exp, if_false_label, if_true_label)
&&
!
can_compare_p
(
TYPE_MODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)))))
do_jump_by_parts_greater
(
exp
,
1
,
if_false_label
,
if_true_label
);
else
comparison
=
compare
(
exp
,
LT
,
LTU
);
do_compare_and_jump
(
exp
,
LT
,
LTU
,
if_false_label
,
if_true_label
);
break
;
case
LE_EXPR
:
...
...
@@ -8913,7 +8897,7 @@ do_jump (exp, if_false_label, if_true_label)
&&
!
can_compare_p
(
TYPE_MODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)))))
do_jump_by_parts_greater
(
exp
,
0
,
if_true_label
,
if_false_label
);
else
comparison
=
compare
(
exp
,
LE
,
LEU
);
do_compare_and_jump
(
exp
,
LE
,
LEU
,
if_false_label
,
if_true_label
);
break
;
case
GT_EXPR
:
...
...
@@ -8922,7 +8906,7 @@ do_jump (exp, if_false_label, if_true_label)
&&
!
can_compare_p
(
TYPE_MODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)))))
do_jump_by_parts_greater
(
exp
,
0
,
if_false_label
,
if_true_label
);
else
comparison
=
compare
(
exp
,
GT
,
GTU
);
do_compare_and_jump
(
exp
,
GT
,
GTU
,
if_false_label
,
if_true_label
);
break
;
case
GE_EXPR
:
...
...
@@ -8931,7 +8915,7 @@ do_jump (exp, if_false_label, if_true_label)
&&
!
can_compare_p
(
TYPE_MODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)))))
do_jump_by_parts_greater
(
exp
,
1
,
if_true_label
,
if_false_label
);
else
comparison
=
compare
(
exp
,
GE
,
GEU
);
do_compare_and_jump
(
exp
,
GE
,
GEU
,
if_false_label
,
if_true_label
);
break
;
default
:
...
...
@@ -8947,42 +8931,28 @@ do_jump (exp, if_false_label, if_true_label)
temp = copy_to_reg (temp);
#endif
do_pending_stack_adjust
();
if
(
GET_CODE
(
temp
)
==
CONST_INT
)
comparison
=
(
temp
==
const0_rtx
?
const0_rtx
:
const_true_rtx
);
else
if
(
GET_CODE
(
temp
)
==
LABEL_REF
)
comparison
=
const_true_rtx
;
/* Do any postincrements in the expression that was tested. */
emit_queue
();
if
(
GET_CODE
(
temp
)
==
CONST_INT
||
GET_CODE
(
temp
)
==
LABEL_REF
)
{
rtx
target
=
temp
==
const0_rtx
?
if_false_label
:
if_true_label
;
if
(
target
)
emit_jump
(
target
);
}
else
if
(
GET_MODE_CLASS
(
GET_MODE
(
temp
))
==
MODE_INT
&&
!
can_compare_p
(
GET_MODE
(
temp
)))
&&
!
can_compare_p
(
GET_MODE
(
temp
)))
/* Note swapping the labels gives us not-equal. */
do_jump_by_parts_equality_rtx
(
temp
,
if_true_label
,
if_false_label
);
else
if
(
GET_MODE
(
temp
)
!=
VOIDmode
)
comparison
=
compare_from_rtx
(
temp
,
CONST0_RTX
(
GET_MODE
(
temp
)),
NE
,
TREE_UNSIGNED
(
TREE_TYPE
(
exp
)),
GET_MODE
(
temp
),
NULL_RTX
,
0
);
do_compare_rtx_and_jump
(
temp
,
CONST0_RTX
(
GET_MODE
(
temp
)),
NE
,
TREE_UNSIGNED
(
TREE_TYPE
(
exp
)),
GET_MODE
(
temp
),
NULL_RTX
,
0
,
if_false_label
,
if_true_label
);
else
abort
();
}
/* Do any postincrements in the expression that was tested. */
emit_queue
();
/* If COMPARISON is nonzero here, it is an rtx that can be substituted
straight into a conditional jump instruction as the jump condition.
Otherwise, all the work has been done already. */
if
(
comparison
==
const_true_rtx
)
{
if
(
if_true_label
)
emit_jump
(
if_true_label
);
}
else
if
(
comparison
==
const0_rtx
)
{
if
(
if_false_label
)
emit_jump
(
if_false_label
);
}
else
if
(
comparison
)
do_jump_for_compare
(
comparison
,
if_false_label
,
if_true_label
);
if
(
drop_through_label
)
{
/* If do_jump produces code that might be jumped around,
...
...
@@ -9007,57 +8977,9 @@ do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label)
rtx
op0
=
expand_expr
(
TREE_OPERAND
(
exp
,
swap
),
NULL_RTX
,
VOIDmode
,
0
);
rtx
op1
=
expand_expr
(
TREE_OPERAND
(
exp
,
!
swap
),
NULL_RTX
,
VOIDmode
,
0
);
enum
machine_mode
mode
=
TYPE_MODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)));
int
nwords
=
(
GET_MODE_SIZE
(
mode
)
/
UNITS_PER_WORD
);
rtx
drop_through_label
=
0
;
int
unsignedp
=
TREE_UNSIGNED
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)));
int
i
;
if
(
!
if_true_label
||
!
if_false_label
)
drop_through_label
=
gen_label_rtx
();
if
(
!
if_true_label
)
if_true_label
=
drop_through_label
;
if
(
!
if_false_label
)
if_false_label
=
drop_through_label
;
/* Compare a word at a time, high order first. */
for
(
i
=
0
;
i
<
nwords
;
i
++
)
{
rtx
comp
;
rtx
op0_word
,
op1_word
;
if
(
WORDS_BIG_ENDIAN
)
{
op0_word
=
operand_subword_force
(
op0
,
i
,
mode
);
op1_word
=
operand_subword_force
(
op1
,
i
,
mode
);
}
else
{
op0_word
=
operand_subword_force
(
op0
,
nwords
-
1
-
i
,
mode
);
op1_word
=
operand_subword_force
(
op1
,
nwords
-
1
-
i
,
mode
);
}
/* All but high-order word must be compared as unsigned. */
comp
=
compare_from_rtx
(
op0_word
,
op1_word
,
(
unsignedp
||
i
>
0
)
?
GTU
:
GT
,
unsignedp
,
word_mode
,
NULL_RTX
,
0
);
if
(
comp
==
const_true_rtx
)
emit_jump
(
if_true_label
);
else
if
(
comp
!=
const0_rtx
)
do_jump_for_compare
(
comp
,
NULL_RTX
,
if_true_label
);
/* Consider lower words only if these are equal. */
comp
=
compare_from_rtx
(
op0_word
,
op1_word
,
NE
,
unsignedp
,
word_mode
,
NULL_RTX
,
0
);
if
(
comp
==
const_true_rtx
)
emit_jump
(
if_false_label
);
else
if
(
comp
!=
const0_rtx
)
do_jump_for_compare
(
comp
,
NULL_RTX
,
if_false_label
);
}
if
(
if_false_label
)
emit_jump
(
if_false_label
);
if
(
drop_through_label
)
emit_label
(
drop_through_label
);
do_jump_by_parts_greater_rtx
(
mode
,
unsignedp
,
op0
,
op1
,
if_false_label
,
if_true_label
);
}
/* Compare OP0 with OP1, word at a time, in mode MODE.
...
...
@@ -9100,21 +9022,13 @@ do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true
}
/* All but high-order word must be compared as unsigned. */
comp
=
compare_from_rtx
(
op0_word
,
op1_word
,
(
unsignedp
||
i
>
0
)
?
GTU
:
GT
,
unsignedp
,
word_mode
,
NULL_RTX
,
0
);
if
(
comp
==
const_true_rtx
)
emit_jump
(
if_true_label
);
else
if
(
comp
!=
const0_rtx
)
do_jump_for_compare
(
comp
,
NULL_RTX
,
if_true_label
);
do_compare_rtx_and_jump
(
op0_word
,
op1_word
,
GT
,
(
unsignedp
||
i
>
0
),
word_mode
,
NULL_RTX
,
0
,
NULL_RTX
,
if_true_label
);
/* Consider lower words only if these are equal. */
comp
=
compare_from_rtx
(
op0_word
,
op1_word
,
NE
,
unsignedp
,
word_mode
,
NULL_RTX
,
0
);
if
(
comp
==
const_true_rtx
)
emit_jump
(
if_false_label
);
else
if
(
comp
!=
const0_rtx
)
do_jump_for_compare
(
comp
,
NULL_RTX
,
if_false_label
);
do_compare_rtx_and_jump
(
op0_word
,
op1_word
,
NE
,
unsignedp
,
word_mode
,
NULL_RTX
,
0
,
NULL_RTX
,
if_false_label
);
}
if
(
if_false_label
)
...
...
@@ -9142,16 +9056,11 @@ do_jump_by_parts_equality (exp, if_false_label, if_true_label)
drop_through_label
=
if_false_label
=
gen_label_rtx
();
for
(
i
=
0
;
i
<
nwords
;
i
++
)
{
rtx
comp
=
compare_from_rtx
(
operand_subword_force
(
op0
,
i
,
mode
),
operand_subword_force
(
op1
,
i
,
mode
),
EQ
,
TREE_UNSIGNED
(
TREE_TYPE
(
exp
)),
word_mode
,
NULL_RTX
,
0
);
if
(
comp
==
const_true_rtx
)
emit_jump
(
if_false_label
);
else
if
(
comp
!=
const0_rtx
)
do_jump_for_compare
(
comp
,
if_false_label
,
NULL_RTX
);
}
do_compare_rtx_and_jump
(
operand_subword_force
(
op0
,
i
,
mode
),
operand_subword_force
(
op1
,
i
,
mode
),
EQ
,
TREE_UNSIGNED
(
TREE_TYPE
(
exp
)),
word_mode
,
NULL_RTX
,
0
,
if_false_label
,
NULL_RTX
);
if
(
if_true_label
)
emit_jump
(
if_true_label
);
...
...
@@ -9187,15 +9096,8 @@ do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
if
(
part
!=
0
)
{
rtx
comp
=
compare_from_rtx
(
part
,
const0_rtx
,
EQ
,
1
,
word_mode
,
NULL_RTX
,
0
);
if
(
comp
==
const_true_rtx
)
emit_jump
(
if_false_label
);
else
if
(
comp
==
const0_rtx
)
emit_jump
(
if_true_label
);
else
do_jump_for_compare
(
comp
,
if_false_label
,
if_true_label
);
do_compare_rtx_and_jump
(
part
,
const0_rtx
,
EQ
,
1
,
word_mode
,
NULL_RTX
,
0
,
if_false_label
,
if_true_label
);
return
;
}
...
...
@@ -9205,15 +9107,9 @@ do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
drop_through_label
=
if_false_label
=
gen_label_rtx
();
for
(
i
=
0
;
i
<
nwords
;
i
++
)
{
rtx
comp
=
compare_from_rtx
(
operand_subword_force
(
op0
,
i
,
GET_MODE
(
op0
)),
const0_rtx
,
EQ
,
1
,
word_mode
,
NULL_RTX
,
0
);
if
(
comp
==
const_true_rtx
)
emit_jump
(
if_false_label
);
else
if
(
comp
!=
const0_rtx
)
do_jump_for_compare
(
comp
,
if_false_label
,
NULL_RTX
);
}
do_compare_rtx_and_jump
(
operand_subword_force
(
op0
,
i
,
GET_MODE
(
op0
)),
const0_rtx
,
EQ
,
1
,
word_mode
,
NULL_RTX
,
0
,
if_false_label
,
NULL_RTX
);
if
(
if_true_label
)
emit_jump
(
if_true_label
);
...
...
@@ -9221,168 +9117,84 @@ do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
if
(
drop_through_label
)
emit_label
(
drop_through_label
);
}
/* Given a comparison expression in rtl form, output conditional branches to
IF_TRUE_LABEL, IF_FALSE_LABEL, or both. */
static
void
do_jump_for_compare
(
comparison
,
if_false_label
,
if_true_label
)
rtx
comparison
,
if_false_label
,
if_true_label
;
{
if
(
if_true_label
)
{
if
(
bcc_gen_fctn
[(
int
)
GET_CODE
(
comparison
)]
!=
0
)
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
GET_CODE
(
comparison
)])
(
if_true_label
));
else
abort
();
if
(
if_false_label
)
emit_jump
(
if_false_label
);
}
else
if
(
if_false_label
)
{
rtx
first
=
get_last_insn
(),
insn
,
branch
;
int
br_count
;
/* Output the branch with the opposite condition. Then try to invert
what is generated. If more than one insn is a branch, or if the
branch is not the last insn written, abort. If we can't invert
the branch, emit make a true label, redirect this jump to that,
emit a jump to the false label and define the true label. */
/* ??? Note that we wouldn't have to do any of this nonsense if
we passed both labels into a combined compare-and-branch.
Ah well, jump threading does a good job of repairing the damage. */
if
(
bcc_gen_fctn
[(
int
)
GET_CODE
(
comparison
)]
!=
0
)
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
GET_CODE
(
comparison
)])
(
if_false_label
));
else
abort
();
/* Here we get the first insn that was just emitted. It used to be the
case that, on some machines, emitting the branch would discard
the previous compare insn and emit a replacement. This isn't
done anymore, but abort if we see that FIRST is deleted. */
if
(
first
==
0
)
first
=
get_insns
();
else
if
(
INSN_DELETED_P
(
first
))
abort
();
else
first
=
NEXT_INSN
(
first
);
/* Look for multiple branches in this sequence, as might be generated
for a multi-word integer comparison. */
br_count
=
0
;
branch
=
NULL_RTX
;
for
(
insn
=
first
;
insn
;
insn
=
NEXT_INSN
(
insn
))
if
(
GET_CODE
(
insn
)
==
JUMP_INSN
)
{
branch
=
insn
;
br_count
+=
1
;
}
/* If we've got one branch at the end of the sequence,
we can try to reverse it. */
if
(
br_count
==
1
&&
NEXT_INSN
(
branch
)
==
NULL_RTX
)
{
rtx
insn_label
;
insn_label
=
XEXP
(
condjump_label
(
branch
),
0
);
JUMP_LABEL
(
branch
)
=
insn_label
;
if
(
insn_label
!=
if_false_label
)
abort
();
if
(
invert_jump
(
branch
,
if_false_label
))
return
;
}
/* Multiple branches, or reversion failed. Convert to branches
around an unconditional jump. */
if_true_label
=
gen_label_rtx
();
for
(
insn
=
first
;
insn
;
insn
=
NEXT_INSN
(
insn
))
if
(
GET_CODE
(
insn
)
==
JUMP_INSN
)
{
rtx
insn_label
;
insn_label
=
XEXP
(
condjump_label
(
insn
),
0
);
JUMP_LABEL
(
insn
)
=
insn_label
;
if
(
insn_label
==
if_false_label
)
redirect_jump
(
insn
,
if_true_label
);
}
emit_jump
(
if_false_label
);
emit_label
(
if_true_label
);
}
}
/* Generate code for a comparison
expression EXP
/* Generate code for a comparison
of OP0 and OP1 with rtx code CODE.
(including code to compute the values to be compared)
and set (CC0) according to the result.
SIGNED_CODE should be the rtx operation for this comparison for
signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
The decision as to signed or unsigned comparison must be made by the caller.
We force a stack adjustment unless there are currently
things pushed on the stack that aren't yet used.
*/
things pushed on the stack that aren't yet used.
static
rtx
compare
(
exp
,
signed_code
,
unsigned_code
)
register
tree
exp
;
enum
rtx_code
signed_code
,
unsigned_code
;
If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
compared.
If ALIGN is non-zero, it is the alignment of this type; if zero, the
size of MODE should be used. */
rtx
compare_from_rtx
(
op0
,
op1
,
code
,
unsignedp
,
mode
,
size
,
align
)
register
rtx
op0
,
op1
;
enum
rtx_code
code
;
int
unsignedp
;
enum
machine_mode
mode
;
rtx
size
;
int
align
;
{
register
rtx
op0
,
op1
;
register
tree
type
;
register
enum
machine_mode
mode
;
int
unsignedp
;
enum
rtx_code
code
;
rtx
tem
;
/* Don't crash if the comparison was erroneous. */
op0
=
expand_expr
(
TREE_OPERAND
(
exp
,
0
),
NULL_RTX
,
VOIDmode
,
0
);
if
(
TREE_CODE
(
TREE_OPERAND
(
exp
,
0
))
==
ERROR_MARK
)
return
op0
;
op1
=
expand_expr
(
TREE_OPERAND
(
exp
,
1
),
NULL_RTX
,
VOIDmode
,
0
);
type
=
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
));
mode
=
TYPE_MODE
(
type
);
unsignedp
=
TREE_UNSIGNED
(
type
);
code
=
unsignedp
?
unsigned_code
:
signed_code
;
/* If one operand is constant, make it the second one. Only do this
if the other operand is not constant as well. */
#ifdef HAVE_canonicalize_funcptr_for_compare
/* If function pointers need to be "canonicalized" before they can
be reliably compared, then canonicalize them. */
if
(
HAVE_canonicalize_funcptr_for_compare
&&
TREE_CODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)))
==
POINTER_TYPE
&&
(
TREE_CODE
(
TREE_TYPE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
))))
==
FUNCTION_TYPE
))
if
((
CONSTANT_P
(
op0
)
&&
!
CONSTANT_P
(
op1
))
||
(
GET_CODE
(
op0
)
==
CONST_INT
&&
GET_CODE
(
op1
)
!=
CONST_INT
))
{
rtx
new_op0
=
gen_reg_rtx
(
mode
)
;
emit_insn
(
gen_canonicalize_funcptr_for_compare
(
new_op0
,
op0
))
;
op0
=
new_op0
;
tem
=
op0
;
op0
=
op1
;
op1
=
tem
;
code
=
swap_condition
(
code
)
;
}
if
(
HAVE_canonicalize_funcptr_for_compare
&&
TREE_CODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
1
)))
==
POINTER_TYPE
&&
(
TREE_CODE
(
TREE_TYPE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
1
))))
==
FUNCTION_TYPE
))
if
(
flag_force_mem
)
{
rtx
new_op1
=
gen_reg_rtx
(
mode
);
op0
=
force_not_mem
(
op0
);
op1
=
force_not_mem
(
op1
);
}
emit_insn
(
gen_canonicalize_funcptr_for_compare
(
new_op1
,
op1
));
op1
=
new_op1
;
do_pending_stack_adjust
();
if
(
GET_CODE
(
op0
)
==
CONST_INT
&&
GET_CODE
(
op1
)
==
CONST_INT
&&
(
tem
=
simplify_relational_operation
(
code
,
mode
,
op0
,
op1
))
!=
0
)
return
tem
;
#if 0
/* There's no need to do this now that combine.c can eliminate lots of
sign extensions. This can be less efficient in certain cases on other
machines. */
/* If this is a signed equality comparison, we can do it as an
unsigned comparison since zero-extension is cheaper than sign
extension and comparisons with zero are done as unsigned. This is
the case even on machines that can do fast sign extension, since
zero-extension is easier to combine with other operations than
sign-extension is. If we are comparing against a constant, we must
convert it to what it would look like unsigned. */
if ((code == EQ || code == NE) && ! unsignedp
&& GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
{
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
unsignedp = 1;
}
#endif
emit_cmp_insn
(
op0
,
op1
,
code
,
size
,
mode
,
unsignedp
,
align
);
return
compare_from_rtx
(
op0
,
op1
,
code
,
unsignedp
,
mode
,
((
mode
==
BLKmode
)
?
expr_size
(
TREE_OPERAND
(
exp
,
0
))
:
NULL_RTX
),
TYPE_ALIGN
(
TREE_TYPE
(
exp
))
/
BITS_PER_UNIT
);
return
gen_rtx_fmt_ee
(
code
,
VOIDmode
,
cc0_rtx
,
const0_rtx
);
}
/* Like
compare
but expects the values to compare as two rtx's.
/* Like
do_compare_and_jump
but expects the values to compare as two rtx's.
The decision as to signed or unsigned comparison must be made by the caller.
If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
...
...
@@ -9391,16 +9203,28 @@ compare (exp, signed_code, unsigned_code)
If ALIGN is non-zero, it is the alignment of this type; if zero, the
size of MODE should be used. */
rtx
compare_from_rtx
(
op0
,
op1
,
code
,
unsignedp
,
mode
,
size
,
align
)
void
do_compare_rtx_and_jump
(
op0
,
op1
,
code
,
unsignedp
,
mode
,
size
,
align
,
if_false_label
,
if_true_label
)
register
rtx
op0
,
op1
;
enum
rtx_code
code
;
int
unsignedp
;
enum
machine_mode
mode
;
rtx
size
;
int
align
;
rtx
if_false_label
,
if_true_label
;
{
rtx
tem
;
int
dummy_true_label
=
0
;
/* Reverse the comparison if that is safe and we want to jump if it is
false. */
if
(
!
if_true_label
&&
!
FLOAT_MODE_P
(
mode
))
{
if_true_label
=
if_false_label
;
if_false_label
=
0
;
code
=
reverse_condition
(
code
);
}
/* If one operand is constant, make it the second one. Only do this
if the other operand is not constant as well. */
...
...
@@ -9424,7 +9248,19 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
if
(
GET_CODE
(
op0
)
==
CONST_INT
&&
GET_CODE
(
op1
)
==
CONST_INT
&&
(
tem
=
simplify_relational_operation
(
code
,
mode
,
op0
,
op1
))
!=
0
)
return
tem
;
{
if
(
tem
==
const_true_rtx
)
{
if
(
if_true_label
)
emit_jump
(
if_true_label
);
}
else
{
if
(
if_false_label
)
emit_jump
(
if_false_label
);
}
return
;
}
#if 0
/* There's no need to do this now that combine.c can eliminate lots of
...
...
@@ -9447,10 +9283,90 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
unsignedp = 1;
}
#endif
emit_cmp_insn
(
op0
,
op1
,
code
,
size
,
mode
,
unsignedp
,
align
);
return
gen_rtx_fmt_ee
(
code
,
VOIDmode
,
cc0_rtx
,
const0_rtx
);
if
(
!
if_true_label
)
{
dummy_true_label
=
1
;
if_true_label
=
gen_label_rtx
();
}
emit_cmp_and_jump_insns
(
op0
,
op1
,
code
,
size
,
mode
,
unsignedp
,
align
,
if_true_label
);
if
(
if_false_label
)
emit_jump
(
if_false_label
);
if
(
dummy_true_label
)
emit_label
(
if_true_label
);
}
/* Generate code for a comparison expression EXP (including code to compute
the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
IF_TRUE_LABEL. One of the labels can be NULL_RTX, in which case the
generated code will drop through.
SIGNED_CODE should be the rtx operation for this comparison for
signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
We force a stack adjustment unless there are currently
things pushed on the stack that aren't yet used. */
static
void
do_compare_and_jump
(
exp
,
signed_code
,
unsigned_code
,
if_false_label
,
if_true_label
)
register
tree
exp
;
enum
rtx_code
signed_code
,
unsigned_code
;
rtx
if_false_label
,
if_true_label
;
{
register
rtx
op0
,
op1
;
register
tree
type
;
register
enum
machine_mode
mode
;
int
unsignedp
;
enum
rtx_code
code
;
/* Don't crash if the comparison was erroneous. */
op0
=
expand_expr
(
TREE_OPERAND
(
exp
,
0
),
NULL_RTX
,
VOIDmode
,
0
);
if
(
TREE_CODE
(
TREE_OPERAND
(
exp
,
0
))
==
ERROR_MARK
)
return
;
op1
=
expand_expr
(
TREE_OPERAND
(
exp
,
1
),
NULL_RTX
,
VOIDmode
,
0
);
type
=
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
));
mode
=
TYPE_MODE
(
type
);
unsignedp
=
TREE_UNSIGNED
(
type
);
code
=
unsignedp
?
unsigned_code
:
signed_code
;
#ifdef HAVE_canonicalize_funcptr_for_compare
/* If function pointers need to be "canonicalized" before they can
be reliably compared, then canonicalize them. */
if
(
HAVE_canonicalize_funcptr_for_compare
&&
TREE_CODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
)))
==
POINTER_TYPE
&&
(
TREE_CODE
(
TREE_TYPE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
0
))))
==
FUNCTION_TYPE
))
{
rtx
new_op0
=
gen_reg_rtx
(
mode
);
emit_insn
(
gen_canonicalize_funcptr_for_compare
(
new_op0
,
op0
));
op0
=
new_op0
;
}
if
(
HAVE_canonicalize_funcptr_for_compare
&&
TREE_CODE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
1
)))
==
POINTER_TYPE
&&
(
TREE_CODE
(
TREE_TYPE
(
TREE_TYPE
(
TREE_OPERAND
(
exp
,
1
))))
==
FUNCTION_TYPE
))
{
rtx
new_op1
=
gen_reg_rtx
(
mode
);
emit_insn
(
gen_canonicalize_funcptr_for_compare
(
new_op1
,
op1
));
op1
=
new_op1
;
}
#endif
/* Do any postincrements in the expression that was tested. */
emit_queue
();
do_compare_rtx_and_jump
(
op0
,
op1
,
code
,
unsignedp
,
mode
,
((
mode
==
BLKmode
)
?
expr_size
(
TREE_OPERAND
(
exp
,
0
))
:
NULL_RTX
),
TYPE_ALIGN
(
TREE_TYPE
(
exp
))
/
BITS_PER_UNIT
,
if_false_label
,
if_true_label
);
}
/* Generate code to calculate EXP using a store-flag instruction
...
...
gcc/expr.h
View file @
b30f05db
...
...
@@ -801,6 +801,9 @@ extern void do_jump PROTO((tree, rtx, rtx));
/* Generate rtl to compare two rtx's, will call emit_cmp_insn. */
extern
rtx
compare_from_rtx
PROTO
((
rtx
,
rtx
,
enum
rtx_code
,
int
,
enum
machine_mode
,
rtx
,
int
));
extern
void
do_compare_rtx_and_jump
PROTO
((
rtx
,
rtx
,
enum
rtx_code
,
int
,
enum
machine_mode
,
rtx
,
int
,
rtx
,
rtx
));
/* Generate a tablejump instruction (used for switch statements). */
extern
void
do_tablejump
PROTO
((
rtx
,
enum
machine_mode
,
rtx
,
rtx
,
rtx
));
...
...
gcc/flow.c
View file @
b30f05db
...
...
@@ -1998,7 +1998,7 @@ tidy_fallthru_edge (e, b, c)
#ifdef HAVE_cc0
/* If this was a conditional jump, we need to also delete
the insn that set cc0. */
if
(
!
simplejump_p
(
q
)
&&
condjump_p
(
q
))
if
(
!
simplejump_p
(
q
)
&&
condjump_p
(
q
)
&&
sets_cc0_p
(
PREV_INSN
(
q
))
)
q
=
PREV_INSN
(
q
);
#endif
...
...
gcc/integrate.c
View file @
b30f05db
...
...
@@ -1958,8 +1958,9 @@ expand_inline_function (fndecl, parms, target, ignore, type,
if
(
condjump_p
(
insn
)
&&
!
simplejump_p
(
insn
)
&&
map
->
last_pc_value
)
{
#ifdef HAVE_cc0
/* The previous insn set cc0 for us. So delete it. */
delete_insn
(
PREV_INSN
(
copy
));
/* If the previous insn set cc0 for us, delete it. */
if
(
sets_cc0_p
(
PREV_INSN
(
copy
)))
delete_insn
(
PREV_INSN
(
copy
));
#endif
/* If this is now a no-op, delete it. */
...
...
gcc/optabs.c
View file @
b30f05db
...
...
@@ -267,6 +267,15 @@ static void init_floating_libfuncs PROTO((optab, const char *, int));
#ifdef HAVE_conditional_trap
static
void
init_traps
PROTO
((
void
));
#endif
static
int
cmp_available_p
PROTO
((
enum
machine_mode
,
enum
rtx_code
,
int
));
static
void
emit_cmp_and_jump_insn_1
PROTO
((
rtx
,
rtx
,
enum
machine_mode
,
enum
rtx_code
,
int
,
rtx
));
static
void
prepare_cmp_insn
PROTO
((
rtx
*
,
rtx
*
,
enum
rtx_code
,
rtx
,
enum
machine_mode
*
,
int
*
,
int
));
static
rtx
prepare_operand
PROTO
((
int
,
rtx
,
int
,
enum
machine_mode
,
enum
machine_mode
,
int
));
static
void
prepare_float_lib_cmp
PROTO
((
rtx
*
,
rtx
*
,
enum
rtx_code
,
enum
machine_mode
*
,
int
*
));
/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
the result of operation CODE applied to OP0 (and OP1 if it is a binary
...
...
@@ -1326,7 +1335,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
carry_out
=
gen_reg_rtx
(
word_mode
);
carry_out
=
emit_store_flag_force
(
carry_out
,
(
binoptab
==
add_optab
?
LT
U
:
GTU
),
?
LT
:
GT
),
x
,
op0_piece
,
word_mode
,
1
,
normalizep
);
}
...
...
@@ -1349,7 +1358,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
/* Get out carry from adding/subtracting carry in. */
carry_tmp
=
emit_store_flag_force
(
carry_tmp
,
binoptab
==
add_optab
?
LT
U
:
GTU
,
?
LT
:
GT
,
x
,
carry_in
,
word_mode
,
1
,
normalizep
);
...
...
@@ -2463,19 +2472,8 @@ expand_abs (mode, op0, target, safe)
do_jump_by_parts_greater_rtx
(
mode
,
0
,
target
,
const0_rtx
,
NULL_RTX
,
op1
);
else
{
temp
=
compare_from_rtx
(
target
,
CONST0_RTX
(
mode
),
GE
,
0
,
mode
,
NULL_RTX
,
0
);
if
(
temp
==
const1_rtx
)
return
target
;
else
if
(
temp
!=
const0_rtx
)
{
if
(
bcc_gen_fctn
[(
int
)
GET_CODE
(
temp
)]
!=
0
)
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
GET_CODE
(
temp
)])
(
op1
));
else
abort
();
}
}
do_compare_rtx_and_jump
(
target
,
CONST0_RTX
(
mode
),
GE
,
0
,
mode
,
NULL_RTX
,
0
,
NULL_RTX
,
op1
);
op0
=
expand_unop
(
mode
,
neg_optab
,
target
,
target
,
0
);
if
(
op0
!=
target
)
...
...
@@ -2983,31 +2981,57 @@ emit_0_to_1_insn (x)
emit_move_insn
(
x
,
const1_rtx
);
}
/*
Generate code to compare X with Y
s
o that the condition codes are set.
/*
Nonzero if we can perform a comparison of mode MODE for a conditional jump
s
traightforwardly. */
MODE is the mode of the inputs (in case they are const_int).
UNSIGNEDP nonzero says that X and Y are unsigned;
static
int
cmp_available_p
(
mode
,
code
,
can_use_tst_p
)
enum
machine_mode
mode
;
enum
rtx_code
code
;
int
can_use_tst_p
;
{
do
{
if
(
cmp_optab
->
handlers
[(
int
)
mode
].
insn_code
!=
CODE_FOR_nothing
||
(
can_use_tst_p
&&
tst_optab
->
handlers
[(
int
)
mode
].
insn_code
!=
CODE_FOR_nothing
))
return
1
;
mode
=
GET_MODE_WIDER_MODE
(
mode
);
}
while
(
mode
!=
VOIDmode
);
return
0
;
}
/* This function is called when we are going to emit a compare instruction that
compares the values found in *PX and *PY, using the rtl operator COMPARISON.
*PMODE is the mode of the inputs (in case they are const_int).
*PUNSIGNEDP nonzero says that the operands are unsigned;
this matters if they need to be widened.
If they have mode BLKmode, then SIZE specifies the size of both
X and Y
,
and ALIGN specifies the known shared alignment of
X and Y
.
If they have mode BLKmode, then SIZE specifies the size of both
operands
,
and ALIGN specifies the known shared alignment of
the operands
.
COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
It is ignored for fixed-point and block comparisons;
it is used only for floating-point comparisons. */
This function performs all the setup necessary so that the caller only has
to emit a single comparison insn. This setup can involve doing a BLKmode
comparison or emitting a library call to perform the comparison if no insn
is available to handle it.
The values which are passed in through pointers can be modified; the caller
should perform the comparison on the modified values. */
void
emit_cmp_insn
(
x
,
y
,
comparison
,
size
,
mode
,
unsignedp
,
align
)
rtx
x
,
y
;
prepare_cmp_insn
(
px
,
py
,
comparison
,
size
,
pmode
,
p
unsignedp
,
align
)
rtx
*
px
,
*
p
y
;
enum
rtx_code
comparison
;
rtx
size
;
enum
machine_mode
mode
;
int
unsignedp
;
enum
machine_mode
*
p
mode
;
int
*
p
unsignedp
;
int
align
;
{
enum
machine_mode
mode
=
*
pmode
;
rtx
x
=
*
px
,
y
=
*
py
;
int
unsignedp
=
*
punsignedp
;
enum
mode_class
class
;
enum
machine_mode
wider_mode
;
class
=
GET_MODE_CLASS
(
mode
);
...
...
@@ -3046,6 +3070,9 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
if
(
mode
==
BLKmode
)
{
rtx
result
;
enum
machine_mode
result_mode
;
emit_queue
();
x
=
protect_from_queue
(
x
,
0
);
y
=
protect_from_queue
(
y
,
0
);
...
...
@@ -3057,12 +3084,9 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
&&
GET_CODE
(
size
)
==
CONST_INT
&&
INTVAL
(
size
)
<
(
1
<<
GET_MODE_BITSIZE
(
QImode
)))
{
enum
machine_mode
result_mode
=
insn_operand_mode
[(
int
)
CODE_FOR_cmpstrqi
][
0
];
rtx
result
=
gen_reg_rtx
(
result_mode
);
result_mode
=
insn_operand_mode
[(
int
)
CODE_FOR_cmpstrqi
][
0
];
result
=
gen_reg_rtx
(
result_mode
);
emit_insn
(
gen_cmpstrqi
(
result
,
x
,
y
,
size
,
GEN_INT
(
align
)));
emit_cmp_insn
(
result
,
const0_rtx
,
comparison
,
NULL_RTX
,
result_mode
,
0
,
0
);
}
else
#endif
...
...
@@ -3071,33 +3095,25 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
&&
GET_CODE
(
size
)
==
CONST_INT
&&
INTVAL
(
size
)
<
(
1
<<
GET_MODE_BITSIZE
(
HImode
)))
{
enum
machine_mode
result_mode
=
insn_operand_mode
[(
int
)
CODE_FOR_cmpstrhi
][
0
];
rtx
result
=
gen_reg_rtx
(
result_mode
);
result_mode
=
insn_operand_mode
[(
int
)
CODE_FOR_cmpstrhi
][
0
];
result
=
gen_reg_rtx
(
result_mode
);
emit_insn
(
gen_cmpstrhi
(
result
,
x
,
y
,
size
,
GEN_INT
(
align
)));
emit_cmp_insn
(
result
,
const0_rtx
,
comparison
,
NULL_RTX
,
result_mode
,
0
,
0
);
}
else
#endif
#ifdef HAVE_cmpstrsi
if
(
HAVE_cmpstrsi
)
{
enum
machine_mode
result_mode
=
insn_operand_mode
[(
int
)
CODE_FOR_cmpstrsi
][
0
];
rtx
result
=
gen_reg_rtx
(
result_mode
);
result_mode
=
insn_operand_mode
[(
int
)
CODE_FOR_cmpstrsi
][
0
];
result
=
gen_reg_rtx
(
result_mode
);
size
=
protect_from_queue
(
size
,
0
);
emit_insn
(
gen_cmpstrsi
(
result
,
x
,
y
,
convert_to_mode
(
SImode
,
size
,
1
),
GEN_INT
(
align
)));
emit_cmp_insn
(
result
,
const0_rtx
,
comparison
,
NULL_RTX
,
result_mode
,
0
,
0
);
}
else
#endif
{
rtx
result
;
#ifdef TARGET_MEM_FUNCTIONS
emit_library_call
(
memcmp_libfunc
,
0
,
TYPE_MODE
(
integer_type_node
),
3
,
...
...
@@ -3119,83 +3135,24 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
register so reload doesn't clobber the value if it needs
the return register for a spill reg. */
result
=
gen_reg_rtx
(
TYPE_MODE
(
integer_type_node
));
result_mode
=
TYPE_MODE
(
integer_type_node
);
emit_move_insn
(
result
,
hard_libcall_value
(
TYPE_MODE
(
integer_type_node
)));
emit_cmp_insn
(
result
,
const0_rtx
,
comparison
,
NULL_RTX
,
TYPE_MODE
(
integer_type_node
),
0
,
0
);
hard_libcall_value
(
result_mode
));
}
*
px
=
result
;
*
py
=
const0_rtx
;
*
pmode
=
result_mode
;
return
;
}
/* Handle some compares against zero. */
if
(
y
==
CONST0_RTX
(
mode
)
&&
tst_optab
->
handlers
[(
int
)
mode
].
insn_code
!=
CODE_FOR_nothing
)
{
int
icode
=
(
int
)
tst_optab
->
handlers
[(
int
)
mode
].
insn_code
;
emit_queue
();
x
=
protect_from_queue
(
x
,
0
);
y
=
protect_from_queue
(
y
,
0
);
/* Now, if insn does accept these operands, put them into pseudos. */
if
(
!
(
*
insn_operand_predicate
[
icode
][
0
])
(
x
,
insn_operand_mode
[
icode
][
0
]))
x
=
copy_to_mode_reg
(
insn_operand_mode
[
icode
][
0
],
x
);
emit_insn
(
GEN_FCN
(
icode
)
(
x
));
return
;
}
/* Handle compares for which there is a directly suitable insn. */
if
(
cmp_optab
->
handlers
[(
int
)
mode
].
insn_code
!=
CODE_FOR_nothing
)
{
int
icode
=
(
int
)
cmp_optab
->
handlers
[(
int
)
mode
].
insn_code
;
emit_queue
();
x
=
protect_from_queue
(
x
,
0
);
y
=
protect_from_queue
(
y
,
0
);
/* Now, if insn doesn't accept these operands, put them into pseudos. */
if
(
!
(
*
insn_operand_predicate
[
icode
][
0
])
(
x
,
insn_operand_mode
[
icode
][
0
]))
x
=
copy_to_mode_reg
(
insn_operand_mode
[
icode
][
0
],
x
);
if
(
!
(
*
insn_operand_predicate
[
icode
][
1
])
(
y
,
insn_operand_mode
[
icode
][
1
]))
y
=
copy_to_mode_reg
(
insn_operand_mode
[
icode
][
1
],
y
);
emit_insn
(
GEN_FCN
(
icode
)
(
x
,
y
));
return
;
}
/* Try widening if we can find a direct insn that way. */
if
(
class
==
MODE_INT
||
class
==
MODE_FLOAT
||
class
==
MODE_COMPLEX_FLOAT
)
{
for
(
wider_mode
=
GET_MODE_WIDER_MODE
(
mode
);
wider_mode
!=
VOIDmode
;
wider_mode
=
GET_MODE_WIDER_MODE
(
wider_mode
))
{
if
(
cmp_optab
->
handlers
[(
int
)
wider_mode
].
insn_code
!=
CODE_FOR_nothing
)
{
x
=
protect_from_queue
(
x
,
0
);
y
=
protect_from_queue
(
y
,
0
);
x
=
convert_modes
(
wider_mode
,
mode
,
x
,
unsignedp
);
y
=
convert_modes
(
wider_mode
,
mode
,
y
,
unsignedp
);
emit_cmp_insn
(
x
,
y
,
comparison
,
NULL_RTX
,
wider_mode
,
unsignedp
,
align
);
return
;
}
}
}
*
px
=
x
;
*
py
=
y
;
if
(
cmp_available_p
(
mode
,
comparison
,
y
==
CONST0_RTX
(
mode
)))
return
;
/* Handle a lib call just for the mode we are using. */
if
(
cmp_optab
->
handlers
[(
int
)
mode
].
libfunc
&&
class
!=
MODE_FLOAT
)
if
(
cmp_optab
->
handlers
[(
int
)
mode
].
libfunc
&&
class
!=
MODE_FLOAT
)
{
rtx
libfunc
=
cmp_optab
->
handlers
[(
int
)
mode
].
libfunc
;
rtx
result
;
...
...
@@ -3217,18 +3174,99 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
/* Integer comparison returns a result that must be compared against 1,
so that even if we do an unsigned compare afterward,
there is still a value that can represent the result "less than". */
emit_cmp_insn
(
result
,
const1_rtx
,
comparison
,
NULL_RTX
,
word_mode
,
unsignedp
,
0
);
*
px
=
result
;
*
py
=
const1_rtx
;
*
pmode
=
word_mode
;
return
;
}
if
(
class
==
MODE_FLOAT
)
emit_float_lib_cmp
(
x
,
y
,
comparison
);
prepare_float_lib_cmp
(
px
,
py
,
comparison
,
pmode
,
punsignedp
);
else
abort
();
}
/* Before emitting an insn with code ICODE, make sure that X, which is going
to be used for operand OPNUM of the insn, is converted from mode MODE to
WIDER_MODE (UNSIGNEDP determines whether it is a unsigned conversion), and
that it is accepted by the operand predicate. Return the new value. */
static
rtx
prepare_operand
(
icode
,
x
,
opnum
,
mode
,
wider_mode
,
unsignedp
)
int
icode
;
rtx
x
;
int
opnum
;
enum
machine_mode
mode
,
wider_mode
;
int
unsignedp
;
{
x
=
protect_from_queue
(
x
,
0
);
if
(
mode
!=
wider_mode
)
x
=
convert_modes
(
wider_mode
,
mode
,
x
,
unsignedp
);
if
(
!
(
*
insn_operand_predicate
[
icode
][
opnum
])
(
x
,
insn_operand_mode
[
icode
][
opnum
]))
x
=
copy_to_mode_reg
(
insn_operand_mode
[
icode
][
opnum
],
x
);
return
x
;
}
/* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
we can do the comparison.
The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
be NULL_RTX which indicates that only a comparison is to be generated. */
static
void
emit_cmp_and_jump_insn_1
(
x
,
y
,
mode
,
comparison
,
unsignedp
,
label
)
rtx
x
,
y
;
enum
machine_mode
mode
;
enum
rtx_code
comparison
;
int
unsignedp
;
rtx
label
;
{
rtx
test
=
gen_rtx_fmt_ee
(
comparison
,
mode
,
x
,
y
);
enum
mode_class
class
=
GET_MODE_CLASS
(
mode
);
enum
machine_mode
wider_mode
=
mode
;
/* Try combined insns first. */
do
{
enum
insn_code
icode
;
PUT_MODE
(
test
,
wider_mode
);
/* Handle some compares against zero. */
icode
=
(
int
)
tst_optab
->
handlers
[(
int
)
wider_mode
].
insn_code
;
if
(
y
==
CONST0_RTX
(
mode
)
&&
icode
!=
CODE_FOR_nothing
)
{
x
=
prepare_operand
(
icode
,
x
,
0
,
mode
,
wider_mode
,
unsignedp
);
emit_insn
(
GEN_FCN
(
icode
)
(
x
));
if
(
label
)
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
comparison
])
(
label
));
return
;
}
/* Handle compares for which there is a directly suitable insn. */
icode
=
(
int
)
cmp_optab
->
handlers
[(
int
)
wider_mode
].
insn_code
;
if
(
icode
!=
CODE_FOR_nothing
)
{
x
=
prepare_operand
(
icode
,
x
,
0
,
mode
,
wider_mode
,
unsignedp
);
y
=
prepare_operand
(
icode
,
y
,
1
,
mode
,
wider_mode
,
unsignedp
);
emit_insn
(
GEN_FCN
(
icode
)
(
x
,
y
));
if
(
label
)
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
comparison
])
(
label
));
return
;
}
if
(
class
!=
MODE_INT
&&
class
!=
MODE_FLOAT
&&
class
!=
MODE_COMPLEX_FLOAT
)
break
;
wider_mode
=
GET_MODE_WIDER_MODE
(
wider_mode
);
}
while
(
wider_mode
!=
VOIDmode
);
abort
();
}
/* Generate code to compare X with Y so that the condition codes are
set and to jump to LABEL if the condition is true. If X is a
constant and Y is not a constant, then the comparison is swapped to
...
...
@@ -3281,11 +3319,24 @@ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
op0
=
force_reg
(
mode
,
op0
);
#endif
emit_cmp_insn
(
op0
,
op1
,
comparison
,
size
,
mode
,
unsignedp
,
align
);
emit_queue
();
if
(
unsignedp
)
comparison
=
unsigned_condition
(
comparison
);
emit_jump_insn
((
*
bcc_gen_fctn
[(
int
)
comparison
])
(
label
));
prepare_cmp_insn
(
&
op0
,
&
op1
,
comparison
,
size
,
&
mode
,
&
unsignedp
,
align
);
emit_cmp_and_jump_insn_1
(
op0
,
op1
,
mode
,
comparison
,
unsignedp
,
label
);
}
/* Like emit_cmp_and_jump_insns, but generate only the comparison. */
void
emit_cmp_insn
(
x
,
y
,
comparison
,
size
,
mode
,
unsignedp
,
align
)
rtx
x
,
y
;
enum
rtx_code
comparison
;
rtx
size
;
enum
machine_mode
mode
;
int
unsignedp
;
int
align
;
{
emit_cmp_and_jump_insns
(
x
,
y
,
comparison
,
size
,
mode
,
unsignedp
,
align
,
0
);
}
...
...
@@ -3310,10 +3361,13 @@ can_compare_p (mode)
COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
void
emit_float_lib_cmp
(
x
,
y
,
comparison
)
rtx
x
,
y
;
prepare_float_lib_cmp
(
px
,
py
,
comparison
,
pmode
,
punsignedp
)
rtx
*
px
,
*
p
y
;
enum
rtx_code
comparison
;
enum
machine_mode
*
pmode
;
int
*
punsignedp
;
{
rtx
x
=
*
px
,
y
=
*
py
;
enum
machine_mode
mode
=
GET_MODE
(
x
);
rtx
libfunc
=
0
;
rtx
result
;
...
...
@@ -3481,9 +3535,9 @@ emit_float_lib_cmp (x, y, comparison)
{
x
=
protect_from_queue
(
x
,
0
);
y
=
protect_from_queue
(
y
,
0
);
x
=
convert_to_mode
(
wider_mode
,
x
,
0
);
y
=
convert_to_mode
(
wider_mode
,
y
,
0
);
emit_float_lib_cmp
(
x
,
y
,
comparison
);
*
p
x
=
convert_to_mode
(
wider_mode
,
x
,
0
);
*
p
y
=
convert_to_mode
(
wider_mode
,
y
,
0
);
prepare_float_lib_cmp
(
px
,
py
,
comparison
,
pmode
,
punsignedp
);
return
;
}
}
...
...
@@ -3501,9 +3555,10 @@ emit_float_lib_cmp (x, y, comparison)
the return register for a spill reg. */
result
=
gen_reg_rtx
(
word_mode
);
emit_move_insn
(
result
,
hard_libcall_value
(
word_mode
));
emit_cmp_insn
(
result
,
const0_rtx
,
comparison
,
NULL_RTX
,
word_mode
,
0
,
0
);
*
px
=
result
;
*
py
=
const0_rtx
;
*
pmode
=
word_mode
;
*
punsignedp
=
0
;
}
/* Generate code to indirectly jump to a location given in the rtx LOC. */
...
...
gcc/unroll.c
View file @
b30f05db
...
...
@@ -339,15 +339,13 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
}
else
if
(
GET_CODE
(
last_loop_insn
)
==
JUMP_INSN
)
{
rtx
prev
=
PREV_INSN
(
last_loop_insn
);
delete_insn
(
last_loop_insn
);
#ifdef HAVE_cc0
/* The immediately preceding insn
is
a compare which must be
/* The immediately preceding insn
may be
a compare which must be
deleted. */
delete_insn
(
last_loop_insn
);
delete_insn
(
PREV_INSN
(
last_loop_insn
));
#else
/* The immediately preceding insn may not be the compare, so don't
delete it. */
delete_insn
(
last_loop_insn
);
if
(
sets_cc0_p
(
prev
))
delete_insn
(
prev
);
#endif
}
return
;
...
...
@@ -479,14 +477,12 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
copy_end
=
PREV_INSN
(
PREV_INSN
(
last_loop_insn
));
else
if
(
GET_CODE
(
last_loop_insn
)
==
JUMP_INSN
)
{
copy_end
=
PREV_INSN
(
last_loop_insn
);
#ifdef HAVE_cc0
/* The instruction immediately before the JUMP_INSN
is
a compare
/* The instruction immediately before the JUMP_INSN
may be
a compare
instruction which we do not want to copy. */
copy_end
=
PREV_INSN
(
PREV_INSN
(
last_loop_insn
));
#else
/* The instruction immediately before the JUMP_INSN may not be the
compare, so we must copy it. */
copy_end
=
PREV_INSN
(
last_loop_insn
);
if
(
sets_cc0_p
(
PREV_INSN
(
copy_end
)))
copy_end
=
PREV_INSN
(
copy_end
);
#endif
}
else
...
...
@@ -520,17 +516,14 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
}
else
if
(
GET_CODE
(
last_loop_insn
)
==
JUMP_INSN
)
{
insert_before
=
last_loop_insn
;
#ifdef HAVE_cc0
/* The instruction immediately before the JUMP_INSN
is
a compare
/* The instruction immediately before the JUMP_INSN
may be
a compare
instruction which we do not want to copy or delete. */
insert_before
=
PREV_INSN
(
last_loop_insn
);
copy_end
=
PREV_INSN
(
insert_before
);
#else
/* The instruction immediately before the JUMP_INSN may not be the
compare, so we must copy it. */
insert_before
=
last_loop_insn
;
copy_end
=
PREV_INSN
(
last_loop_insn
);
if
(
sets_cc0_p
(
PREV_INSN
(
insert_before
)))
insert_before
=
PREV_INSN
(
insert_before
);
#endif
copy_end
=
PREV_INSN
(
insert_before
);
}
else
{
...
...
@@ -793,9 +786,9 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
copy_end_luid
--
;
/* If we have a target that uses cc0, then we also must not duplicate
the insn that sets cc0 before the jump insn. */
the insn that sets cc0 before the jump insn
, if one is present
. */
#ifdef HAVE_cc0
if
(
GET_CODE
(
copy_end
)
==
JUMP_INSN
)
if
(
GET_CODE
(
copy_end
)
==
JUMP_INSN
&&
sets_cc0_p
(
PREV_INSN
(
copy_end
))
)
copy_end_luid
--
;
#endif
...
...
@@ -1036,14 +1029,12 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
copy_end
=
PREV_INSN
(
PREV_INSN
(
last_loop_insn
));
else
if
(
GET_CODE
(
last_loop_insn
)
==
JUMP_INSN
)
{
copy_end
=
PREV_INSN
(
last_loop_insn
);
#ifdef HAVE_cc0
/* The immediately preceding insn
is
a compare which we do not
/* The immediately preceding insn
may be
a compare which we do not
want to copy. */
copy_end
=
PREV_INSN
(
PREV_INSN
(
last_loop_insn
));
#else
/* The immediately preceding insn may not be a compare, so we
must copy it. */
copy_end
=
PREV_INSN
(
last_loop_insn
);
if
(
sets_cc0_p
(
PREV_INSN
(
copy_end
)))
copy_end
=
PREV_INSN
(
copy_end
);
#endif
}
else
...
...
@@ -1098,17 +1089,14 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
}
else
{
#ifdef HAVE_cc0
/* The immediately preceding insn is a compare which we do not
want to copy. */
insert_before
=
PREV_INSN
(
last_loop_insn
);
copy_end
=
PREV_INSN
(
insert_before
);
#else
/* The immediately preceding insn may not be a compare, so we
must copy it. */
insert_before
=
last_loop_insn
;
copy_end
=
PREV_INSN
(
last_loop_insn
);
#ifdef HAVE_cc0
/* The instruction immediately before the JUMP_INSN may be a compare
instruction which we do not want to copy or delete. */
if
(
sets_cc0_p
(
PREV_INSN
(
insert_before
)))
insert_before
=
PREV_INSN
(
insert_before
);
#endif
copy_end
=
PREV_INSN
(
insert_before
);
}
/* Set unroll type to MODULO now. */
...
...
@@ -2089,8 +2077,9 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
if
(
condjump_p
(
insn
)
&&
!
simplejump_p
(
insn
)
&&
map
->
last_pc_value
)
{
#ifdef HAVE_cc0
/* The previous insn set cc0 for us. So delete it. */
delete_insn
(
PREV_INSN
(
copy
));
/* If the previous insn set cc0 for us, delete it. */
if
(
sets_cc0_p
(
PREV_INSN
(
copy
)))
delete_insn
(
PREV_INSN
(
copy
));
#endif
/* If this is now a no-op, delete it. */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment