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
c05a9b68
Commit
c05a9b68
authored
Apr 01, 1992
by
Richard Stallman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
*** empty log message ***
From-SVN: r664
parent
dc2a006b
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
653 additions
and
318 deletions
+653
-318
gcc/fold-const.c
+653
-318
No files found.
gcc/fold-const.c
View file @
c05a9b68
...
...
@@ -778,18 +778,40 @@ target_isnan (x)
}
}
/* Check for
minus zero in an
IEEE double precision number. */
/* Check for
a negative
IEEE double precision number. */
int
target_
minus_zero
(
x
)
target_
negative
(
x
)
REAL_VALUE_TYPE
x
;
{
REAL_VALUE_TYPE
d1
,
d2
;
d1
=
REAL_VALUE_NEGATE
(
x
);
d2
=
dconst0
;
/* The IEEE 64-bit double format. */
union
{
REAL_VALUE_TYPE
d
;
struct
{
unsigned
sign
:
1
;
unsigned
exponent
:
11
;
unsigned
mantissa1
:
20
;
unsigned
mantissa2
;
}
little_endian
;
struct
{
unsigned
mantissa2
;
unsigned
mantissa1
:
20
;
unsigned
exponent
:
11
;
unsigned
sign
:
1
;
}
big_endian
;
}
u
;
return
!
bcmp
(
&
d1
,
&
d2
,
sizeof
(
d1
));
u
.
d
=
dconstm1
;
if
(
u
.
big_endian
.
sign
==
1
)
{
u
.
d
=
x
;
return
u
.
big_endian
.
sign
;
}
else
{
u
.
d
=
x
;
return
u
.
little_endian
.
sign
;
}
}
#else
/* Target not IEEE */
...
...
@@ -812,12 +834,12 @@ target_isnan (x)
}
/* Let's assume other float formats don't have minus zero.
(This can be overridden by redefining REAL_VALUE_
MINUS_ZERO
.) */
(This can be overridden by redefining REAL_VALUE_
NEGATIVE
.) */
target_
minus_zero
(
x
)
target_
negative
(
x
)
REAL_VALUE_TYPE
x
;
{
return
0
;
return
x
<
0
;
}
#endif
/* Target not IEEE */
...
...
@@ -1267,11 +1289,8 @@ size_int (number)
return
size_table
[
number
];
if
(
number
>=
0
&&
number
<
2
*
HOST_BITS_PER_INT
+
1
)
{
int
temp
=
allocation_temporary_p
();
push_obstacks_nochange
();
/* Make this a permanent node. */
if
(
temp
)
end_temporary_allocation
();
t
=
build_int_2
(
number
,
0
);
TREE_TYPE
(
t
)
=
sizetype
;
...
...
@@ -1347,10 +1366,12 @@ fold_convert (t, arg1)
#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
else
if
(
TREE_CODE
(
arg1
)
==
REAL_CST
)
{
if
(
REAL_VALUES_LESS
(
real_value_from_int_cst
(
TYPE_MAX_VALUE
(
type
)),
TREE_REAL_CST
(
arg1
))
||
REAL_VALUES_LESS
(
TREE_REAL_CST
(
arg1
),
real_value_from_int_cst
(
TYPE_MIN_VALUE
(
type
))))
REAL_VALUE_TYPE
l
=
real_value_from_int_cst
(
TYPE_MIN_VALUE
(
type
)),
x
=
TREE_REAL_CST
(
arg1
),
u
=
real_value_from_int_cst
(
TYPE_MAX_VALUE
(
type
));
if
(
!
((
REAL_VALUES_LESS
(
l
,
x
)
||
REAL_VALUES_EQUAL
(
l
,
x
))
&&
(
REAL_VALUES_LESS
(
x
,
u
)
||
REAL_VALUES_EQUAL
(
x
,
u
))))
{
warning
(
"real constant out of range for integer conversion"
);
return
t
;
...
...
@@ -1420,6 +1441,58 @@ non_lvalue (x)
return
result
;
}
/* Given a tree comparison code, return the code that is the logical inverse
of the given code. It is not safe to do this for floating-point
comparisons, except for NE_EXPR and EQ_EXPR. */
static
enum
tree_code
invert_tree_comparison
(
code
)
enum
tree_code
code
;
{
switch
(
code
)
{
case
EQ_EXPR
:
return
NE_EXPR
;
case
NE_EXPR
:
return
EQ_EXPR
;
case
GT_EXPR
:
return
LE_EXPR
;
case
GE_EXPR
:
return
LT_EXPR
;
case
LT_EXPR
:
return
GE_EXPR
;
case
LE_EXPR
:
return
GT_EXPR
;
default
:
abort
();
}
}
/* Similar, but return the comparison that results if the operands are
swapped. This is safe for floating-point. */
static
enum
tree_code
swap_tree_comparison
(
code
)
enum
tree_code
code
;
{
switch
(
code
)
{
case
EQ_EXPR
:
case
NE_EXPR
:
return
code
;
case
GT_EXPR
:
return
LT_EXPR
;
case
GE_EXPR
:
return
LE_EXPR
;
case
LT_EXPR
:
return
GT_EXPR
;
case
LE_EXPR
:
return
GE_EXPR
;
default
:
abort
();
}
}
/* Return nonzero if two operands are necessarily equal.
If ONLY_CONST is non-zero, only return non-zero for constants. */
...
...
@@ -1461,7 +1534,11 @@ operand_equal_p (arg0, arg1, only_const)
But reject weird values because we can't be sure what to do with them. */
if
(
TREE_CODE
(
arg0
)
==
TREE_CODE
(
arg1
)
&&
TREE_CODE
(
arg0
)
==
REAL_CST
&&
REAL_VALUES_EQUAL
(
TREE_REAL_CST
(
arg0
),
TREE_REAL_CST
(
arg1
))
&&
!
bcmp
(
&
TREE_REAL_CST
(
arg0
),
&
TREE_REAL_CST
(
arg1
),
sizeof
(
REAL_VALUE_TYPE
))
/* Some people say these are not necessary.
But they do little harm, and taking them out would be risky.
So leave them and let's not spend any more time on them--rms. */
&&
!
REAL_VALUE_ISINF
(
TREE_REAL_CST
(
arg0
))
&&
!
REAL_VALUE_ISNAN
(
TREE_REAL_CST
(
arg0
)))
return
1
;
...
...
@@ -1526,64 +1603,219 @@ operand_equal_p (arg0, arg1, only_const)
return
0
;
}
/* Return nonzero if comparing COMP1 with COMP2
gives the same result as comparing OP1 with OP2.
/* Similar to operand_equal_p, but see if ARG0 might have been made by
shorten_compare from ARG1 when ARG1 was being compared with OTHER.
When in doubt, return 0. */
static
int
comparison_equiv_p
(
comp1
,
comp2
,
op1
,
op2
)
tree
comp1
,
comp2
,
op1
,
op2
;
operand_equal_for_comparison_p
(
arg0
,
arg1
,
other
)
tree
arg0
,
arg1
;
tree
other
;
{
int
unsignedp1
,
unsignedp
2
;
tree
prim
op1
,
primop2
;
int
unsignedp1
,
unsignedp
o
;
tree
prim
arg1
,
primother
;
int
correct_width
;
if
(
operand_equal_p
(
comp1
,
op1
,
0
)
&&
operand_equal_p
(
comp2
,
op2
,
0
))
if
(
operand_equal_p
(
arg0
,
arg1
,
0
))
return
1
;
if
(
TREE_CODE
(
TREE_TYPE
(
op1
))
!=
INTEGER_TYPE
)
return
0
;
if
(
TREE_TYPE
(
op1
)
!=
TREE_TYPE
(
op2
))
if
(
TREE_CODE
(
TREE_TYPE
(
arg0
))
!=
INTEGER_TYPE
)
return
0
;
if
(
TREE_TYPE
(
comp1
)
!=
TREE_TYPE
(
comp2
))
return
0
;
/* Duplicate what shorten_compare does to the comparison operands,
and see if that gives the actual comparison operands, COMP1 and COMP2. */
/* Duplicate what shorten_compare does to ARG1 and see if that gives the
actual comparison operand, ARG0.
/* T
hrow away any conversions to wider types
First t
hrow away any conversions to wider types
already present in the operands. */
primop1
=
get_narrower
(
op1
,
&
unsignedp1
);
primop2
=
get_narrower
(
op2
,
&
unsignedp2
);
correct_width
=
TYPE_PRECISION
(
TREE_TYPE
(
op2
));
if
(
unsignedp1
==
unsignedp2
&&
TYPE_PRECISION
(
TREE_TYPE
(
primop1
))
<
correct_width
&&
TYPE_PRECISION
(
TREE_TYPE
(
primop2
))
<
correct_width
)
primarg1
=
get_narrower
(
arg1
,
&
unsignedp1
);
primother
=
get_narrower
(
other
,
&
unsignedpo
);
correct_width
=
TYPE_PRECISION
(
TREE_TYPE
(
arg1
));
if
(
unsignedp1
==
unsignedpo
&&
TYPE_PRECISION
(
TREE_TYPE
(
primarg1
))
<
correct_width
&&
TYPE_PRECISION
(
TREE_TYPE
(
primother
))
<
correct_width
)
{
tree
type
=
TREE_TYPE
(
comp1
);
tree
type
=
TREE_TYPE
(
arg0
);
/* Make sure shorter operand is extended the right way
to match the longer operand. */
primop1
=
convert
(
signed_or_unsigned_type
(
unsignedp1
,
TREE_TYPE
(
primop1
)),
primop1
);
primop2
=
convert
(
signed_or_unsigned_type
(
unsignedp2
,
TREE_TYPE
(
primop2
)),
primop2
);
primarg1
=
convert
(
signed_or_unsigned_type
(
unsignedp1
,
TREE_TYPE
(
primarg1
)),
primarg1
);
if
(
operand_equal_p
(
arg0
,
convert
(
type
,
primarg1
),
0
))
return
1
;
}
return
0
;
}
/* See if ARG is an expression is either a comparison or is peforming
arithmetic on comparisons. The comparisons must only be comparing
two different values, which will be stored in *CVAL1 and *CVAL2; if
they are non-zero it means that some operands have already been found.
No variables may be used anywhere else in the expression except in the
comparisons.
If this is true, return 1. Otherwise, return zero. */
static
int
twoval_comparison_p
(
arg
,
cval1
,
cval2
)
tree
arg
;
tree
*
cval1
,
*
cval2
;
{
enum
tree_code
code
=
TREE_CODE
(
arg
);
char
class
=
TREE_CODE_CLASS
(
code
);
/* We can handle some of the 'e' cases here. */
if
(
class
==
'e'
&&
(
code
==
TRUTH_NOT_EXPR
||
(
code
==
SAVE_EXPR
&&
SAVE_EXPR_RTL
(
arg
)
==
0
)))
class
=
'1'
;
else
if
(
class
==
'e'
&&
(
code
==
TRUTH_ANDIF_EXPR
||
code
==
TRUTH_ORIF_EXPR
||
code
==
COMPOUND_EXPR
))
class
=
'2'
;
switch
(
class
)
{
case
'1'
:
return
twoval_comparison_p
(
TREE_OPERAND
(
arg
,
0
),
cval1
,
cval2
);
case
'2'
:
return
(
twoval_comparison_p
(
TREE_OPERAND
(
arg
,
0
),
cval1
,
cval2
)
&&
twoval_comparison_p
(
TREE_OPERAND
(
arg
,
1
),
cval1
,
cval2
));
case
'c'
:
return
1
;
case
'e'
:
if
(
code
==
COND_EXPR
)
return
(
twoval_comparison_p
(
TREE_OPERAND
(
arg
,
0
),
cval1
,
cval2
)
&&
twoval_comparison_p
(
TREE_OPERAND
(
arg
,
1
),
cval1
,
cval2
)
&&
twoval_comparison_p
(
TREE_OPERAND
(
arg
,
2
),
cval1
,
cval2
));
return
0
;
case
'<'
:
/* First see if we can handle the first operand, then the second. For
the second operand, we know *CVAL1 can't be zero. It must be that
one side of the comparison is each of the values; test for the
case where this isn't true by failing if the two operands
are the same. */
if
(
operand_equal_p
(
TREE_OPERAND
(
arg
,
0
),
TREE_OPERAND
(
arg
,
1
),
0
))
return
0
;
if
(
*
cval1
==
0
)
*
cval1
=
TREE_OPERAND
(
arg
,
0
);
else
if
(
operand_equal_p
(
*
cval1
,
TREE_OPERAND
(
arg
,
0
),
0
))
;
else
if
(
*
cval2
==
0
)
*
cval2
=
TREE_OPERAND
(
arg
,
0
);
else
if
(
operand_equal_p
(
*
cval2
,
TREE_OPERAND
(
arg
,
0
),
0
))
;
else
return
0
;
primop1
=
convert
(
type
,
primop1
);
primop2
=
convert
(
type
,
primop2
);
if
(
operand_equal_p
(
*
cval1
,
TREE_OPERAND
(
arg
,
1
),
0
))
;
else
if
(
*
cval2
==
0
)
*
cval2
=
TREE_OPERAND
(
arg
,
1
);
else
if
(
operand_equal_p
(
*
cval2
,
TREE_OPERAND
(
arg
,
1
),
0
))
;
else
return
0
;
if
(
operand_equal_p
(
comp1
,
primop1
,
0
)
&&
operand_equal_p
(
comp2
,
primop2
,
0
))
return
1
;
}
return
0
;
}
/* ARG is a tree that is known to contain just arithmetic operations and
comparisons. Evaluate the operations in the tree substituting NEW0 for
any occurrance of OLD0 as an operand of a comparison and likewise for
NEW1 and OLD1. */
static
tree
eval_subst
(
arg
,
old0
,
new0
,
old1
,
new1
)
tree
arg
;
tree
old0
,
new0
,
old1
,
new1
;
{
tree
type
=
TREE_TYPE
(
arg
);
enum
tree_code
code
=
TREE_CODE
(
arg
);
char
class
=
TREE_CODE_CLASS
(
code
);
/* We can handle some of the 'e' cases here. */
if
(
class
==
'e'
&&
code
==
TRUTH_NOT_EXPR
)
class
=
'1'
;
else
if
(
class
==
'e'
&&
(
code
==
TRUTH_ANDIF_EXPR
||
code
==
TRUTH_ORIF_EXPR
))
class
=
'2'
;
switch
(
class
)
{
case
'1'
:
return
fold
(
build1
(
code
,
type
,
eval_subst
(
TREE_OPERAND
(
arg
,
0
),
old0
,
new0
,
old1
,
new1
)));
case
'2'
:
return
fold
(
build
(
code
,
type
,
eval_subst
(
TREE_OPERAND
(
arg
,
0
),
old0
,
new0
,
old1
,
new1
),
eval_subst
(
TREE_OPERAND
(
arg
,
1
),
old0
,
new0
,
old1
,
new1
)));
case
'e'
:
switch
(
code
)
{
case
SAVE_EXPR
:
return
eval_subst
(
TREE_OPERAND
(
arg
,
0
),
old0
,
new0
,
old1
,
new1
);
case
COMPOUND_EXPR
:
return
eval_subst
(
TREE_OPERAND
(
arg
,
1
),
old0
,
new0
,
old1
,
new1
);
case
COND_EXPR
:
return
fold
(
build
(
code
,
type
,
eval_subst
(
TREE_OPERAND
(
arg
,
0
),
old0
,
new0
,
old1
,
new1
),
eval_subst
(
TREE_OPERAND
(
arg
,
1
),
old0
,
new0
,
old1
,
new1
),
eval_subst
(
TREE_OPERAND
(
arg
,
2
),
old0
,
new0
,
old1
,
new1
)));
}
case
'<'
:
{
tree
arg0
=
TREE_OPERAND
(
arg
,
0
);
tree
arg1
=
TREE_OPERAND
(
arg
,
1
);
/* We need to check both for exact equality and tree equality. The
former will be true if the operand has a side-effect. In that
case, we know the operand occurred exactly once. */
if
(
arg0
==
old0
||
operand_equal_p
(
arg0
,
old0
,
0
))
arg0
=
new0
;
else
if
(
arg0
==
old1
||
operand_equal_p
(
arg0
,
old1
,
0
))
arg0
=
new1
;
if
(
arg1
==
old0
||
operand_equal_p
(
arg1
,
old0
,
0
))
arg1
=
new0
;
else
if
(
arg1
==
old1
||
operand_equal_p
(
arg1
,
old1
,
0
))
arg1
=
new1
;
return
fold
(
build
(
code
,
type
,
arg0
,
arg1
));
}
}
return
arg
;
}
/* Return a tree for the case when the result of an expression is RESULT
converted to TYPE and OMITTED was previously an operand of the expression
but is now not needed (e.g., we folded OMITTED * 0).
...
...
@@ -1612,39 +1844,26 @@ invert_truthvalue (arg)
tree
arg
;
{
tree
type
=
TREE_TYPE
(
arg
);
enum
tree_code
code
=
TREE_CODE
(
arg
);
/* For floating-point comparisons, it isn't safe to invert the condition.
So just enclose a TRUTH_NOT_EXPR around what we have. */
if
(
TREE_CODE_CLASS
(
TREE_CODE
(
arg
))
==
'<'
&&
TREE_CODE
(
TREE_TYPE
(
TREE_OPERAND
(
arg
,
0
)))
==
REAL_TYPE
)
return
build1
(
TRUTH_NOT_EXPR
,
type
,
arg
);
/* If this is a comparison, we can simply invert it, except for
floating-point non-equality comparisons, in which case we just
enclose a TRUTH_NOT_EXPR around what we have. */
switch
(
TREE_CODE
(
arg
)
)
if
(
TREE_CODE_CLASS
(
code
)
==
'<'
)
{
case
NE_EXPR
:
TREE_SET_CODE
(
arg
,
EQ_EXPR
);
return
arg
;
case
EQ_EXPR
:
TREE_SET_CODE
(
arg
,
NE_EXPR
);
return
arg
;
case
GE_EXPR
:
TREE_SET_CODE
(
arg
,
LT_EXPR
);
return
arg
;
case
GT_EXPR
:
TREE_SET_CODE
(
arg
,
LE_EXPR
);
return
arg
;
case
LE_EXPR
:
TREE_SET_CODE
(
arg
,
GT_EXPR
);
return
arg
;
case
LT_EXPR
:
TREE_SET_CODE
(
arg
,
GE_EXPR
);
if
(
TREE_CODE
(
TREE_TYPE
(
TREE_OPERAND
(
arg
,
0
)))
==
REAL_TYPE
&&
code
!=
NE_EXPR
&&
code
!=
EQ_EXPR
)
return
build1
(
TRUTH_NOT_EXPR
,
type
,
arg
);
else
{
TREE_SET_CODE
(
arg
,
invert_tree_comparison
(
code
));
return
arg
;
}
}
switch
(
code
)
{
case
INTEGER_CST
:
return
convert
(
type
,
build_int_2
(
TREE_INT_CST_LOW
(
arg
)
==
0
&&
TREE_INT_CST_HIGH
(
arg
)
==
0
,
0
));
...
...
@@ -1814,7 +2033,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
extraction at all and so can do nothing. */
linner
=
get_inner_reference
(
lhs
,
&
lbitsize
,
&
lbitpos
,
&
lmode
,
&
lunsignedp
,
&
lvolatilep
);
if
(
lbitsize
==
GET_MODE_BITSIZE
(
lmode
))
if
(
lbitsize
==
GET_MODE_BITSIZE
(
lmode
)
||
lbitsize
<
0
)
return
0
;
if
(
!
const_p
)
...
...
@@ -2003,6 +2222,8 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
inner
=
get_inner_reference
(
exp
,
pbitsize
,
pbitpos
,
pmode
,
punsignedp
,
pvolatilep
);
if
(
*
pbitsize
<
0
)
return
0
;
if
(
mask
==
0
)
{
...
...
@@ -2311,10 +2532,12 @@ fold (expr)
{
register
tree
t
=
expr
;
tree
t1
=
NULL_TREE
;
tree
tem
;
tree
type
=
TREE_TYPE
(
expr
);
register
tree
arg0
,
arg1
;
register
enum
tree_code
code
=
TREE_CODE
(
t
);
register
int
kind
;
int
invert
;
/* WINS will be nonzero when the switch is done
if all operands are constant. */
...
...
@@ -2368,11 +2591,10 @@ fold (expr)
||
code
==
BIT_AND_EXPR
)
&&
(
TREE_CODE
(
arg0
)
==
INTEGER_CST
||
TREE_CODE
(
arg0
)
==
REAL_CST
))
{
tree
tem
=
arg0
;
arg0
=
arg1
;
arg1
=
tem
;
tem
=
arg0
;
arg0
=
arg1
;
arg1
=
tem
;
TREE_OPERAND
(
t
,
0
)
=
arg0
;
TREE_OPERAND
(
t
,
1
)
=
arg1
;
tem
=
TREE_OPERAND
(
t
,
0
);
TREE_OPERAND
(
t
,
0
)
=
TREE_OPERAND
(
t
,
1
)
;
TREE_OPERAND
(
t
,
1
)
=
tem
;
}
/* Now WINS is set as described above,
...
...
@@ -2467,6 +2689,14 @@ fold (expr)
return
convert
(
type
,
test
);
}
}
else
if
(
TREE_CODE_CLASS
(
code
)
==
'<'
&&
TREE_CODE
(
arg0
)
==
COMPOUND_EXPR
)
return
build
(
COMPOUND_EXPR
,
type
,
TREE_OPERAND
(
arg0
,
0
),
fold
(
build
(
code
,
type
,
TREE_OPERAND
(
arg0
,
1
),
arg1
)));
else
if
(
TREE_CODE_CLASS
(
code
)
==
'<'
&&
TREE_CODE
(
arg1
)
==
COMPOUND_EXPR
)
return
build
(
COMPOUND_EXPR
,
type
,
TREE_OPERAND
(
arg1
,
0
),
fold
(
build
(
code
,
type
,
arg0
,
TREE_OPERAND
(
arg1
,
1
))));
switch
(
code
)
{
...
...
@@ -2599,7 +2829,7 @@ fold (expr)
}
else
if
(
TREE_CODE
(
arg0
)
==
REAL_CST
)
{
if
(
REAL_VALUE
S_LESS
(
TREE_REAL_CST
(
arg0
),
dconst0
))
if
(
REAL_VALUE
_NEGATIVE
(
TREE_REAL_CST
(
arg0
)
))
t
=
build_real
(
type
,
REAL_VALUE_NEGATE
(
TREE_REAL_CST
(
arg0
)));
}
...
...
@@ -2662,7 +2892,7 @@ fold (expr)
The rest of the code applies to all associative operations. */
if
(
!
wins
)
{
tree
var
,
con
,
tem
;
tree
var
,
con
;
int
varsign
;
if
(
split_tree
(
arg0
,
code
,
&
var
,
&
con
,
&
varsign
))
...
...
@@ -2762,12 +2992,13 @@ fold (expr)
/* Convert A - (-B) to A + B. */
else
if
(
TREE_CODE
(
arg1
)
==
NEGATE_EXPR
)
return
fold
(
build
(
PLUS_EXPR
,
type
,
arg0
,
TREE_OPERAND
(
arg1
,
0
)));
else
else
if
(
TARGET_FLOAT_FORMAT
!=
IEEE_FLOAT_FORMAT
)
{
/* Except with IEEE floating point, 0-x equals -x. */
if
(
!
wins
&&
real_zerop
(
arg0
))
return
build1
(
NEGATE_EXPR
,
type
,
arg1
);
/*
In IEEE floating point, x-0 may not equal
x. */
if
(
real_zerop
(
arg1
)
&&
TARGET_FLOAT_FORMAT
!=
IEEE_FLOAT_FORMAT
)
/*
Except with IEEE floating point, x-0 equals
x. */
if
(
real_zerop
(
arg1
))
return
non_lvalue
(
convert
(
type
,
arg0
));
}
/* Fold &x - &x. This can happen from &x.foo - &x.
...
...
@@ -2798,13 +3029,13 @@ fold (expr)
return
fold
(
build
(
LSHIFT_EXPR
,
type
,
arg1
,
TREE_OPERAND
(
arg0
,
1
)));
}
/* In IEEE floating point, these optimizations are not correct. */
else
{
/* x*0 is 0, except for IEEE floating point. */
if
(
TARGET_FLOAT_FORMAT
!=
IEEE_FLOAT_FORMAT
&&
real_zerop
(
arg1
))
return
omit_one_operand
(
type
,
arg1
,
arg0
);
/* In IEEE floating point, x*1 is not equivalent to x for nans.
/* In IEEE floating point, x*1 is not equivalent to x for
s
nans.
However, ANSI says we can drop signals,
so we can do this anyway. */
if
(
real_onep
(
arg1
))
...
...
@@ -2965,8 +3196,6 @@ fold (expr)
rhs. Then try to merge our lhs and rhs. */
if
(
optimize
)
{
tree
tem
;
if
(
TREE_CODE
(
arg0
)
==
code
)
{
tem
=
merge_component_references
(
code
,
type
,
...
...
@@ -3013,21 +3242,7 @@ fold (expr)
TREE_OPERAND
(
t
,
1
)
=
arg0
;
arg0
=
TREE_OPERAND
(
t
,
0
);
arg1
=
TREE_OPERAND
(
t
,
1
);
switch
(
code
)
{
case
GT_EXPR
:
code
=
LT_EXPR
;
break
;
case
GE_EXPR
:
code
=
LE_EXPR
;
break
;
case
LT_EXPR
:
code
=
GT_EXPR
;
break
;
case
LE_EXPR
:
code
=
GE_EXPR
;
break
;
}
code
=
swap_tree_comparison
(
code
);
TREE_SET_CODE
(
t
,
code
);
}
...
...
@@ -3045,46 +3260,37 @@ fold (expr)
if
(
constop
&&
TREE_CODE
(
varop
)
==
POSTINCREMENT_EXPR
)
{
tree
newconst
=
fold
(
build
(
PLUS_EXPR
,
TREE_TYPE
(
varop
),
constop
,
TREE_OPERAND
(
varop
,
1
)));
/* This optimization is invalid for ordered comparisons
if CONST+INCR overflows or if foo+incr might overflow.
This optimization is invalid for floating point due to rounding.
For pointer types we assume overflow doesn't happen. */
if
(
TREE_CODE
(
TREE_TYPE
(
varop
))
==
POINTER_TYPE
||
code
==
EQ_EXPR
||
code
==
NE_EXPR
)
{
/* This optimization is invalid for floating point
if adding one to the constant does not change it. */
if
(
TREE_CODE
(
TREE_TYPE
(
newconst
))
!=
REAL_TYPE
||
!
REAL_VALUES_EQUAL
(
TREE_REAL_CST
(
newconst
),
TREE_REAL_CST
(
constop
)))
||
(
TREE_CODE
(
TREE_TYPE
(
varop
))
!=
REAL_TYPE
&&
(
code
==
EQ_EXPR
||
code
==
NE_EXPR
)))
{
tree
newconst
=
fold
(
build
(
PLUS_EXPR
,
TREE_TYPE
(
varop
),
constop
,
TREE_OPERAND
(
varop
,
1
)));
TREE_SET_CODE
(
varop
,
PREINCREMENT_EXPR
);
*
constoploc
=
newconst
;
return
t
;
}
}
}
else
if
(
constop
&&
TREE_CODE
(
varop
)
==
POSTDECREMENT_EXPR
)
{
if
(
TREE_CODE
(
TREE_TYPE
(
varop
))
==
POINTER_TYPE
||
(
TREE_CODE
(
TREE_TYPE
(
varop
))
!=
REAL_TYPE
&&
(
code
==
EQ_EXPR
||
code
==
NE_EXPR
)))
{
tree
newconst
=
fold
(
build
(
MINUS_EXPR
,
TREE_TYPE
(
varop
),
constop
,
TREE_OPERAND
(
varop
,
1
)));
if
(
TREE_CODE
(
TREE_TYPE
(
varop
))
==
POINTER_TYPE
||
code
==
EQ_EXPR
||
code
==
NE_EXPR
)
{
if
(
TREE_CODE
(
TREE_TYPE
(
newconst
))
!=
REAL_TYPE
||
!
REAL_VALUES_EQUAL
(
TREE_REAL_CST
(
newconst
),
TREE_REAL_CST
(
constop
)))
{
TREE_SET_CODE
(
varop
,
PREDECREMENT_EXPR
);
*
constoploc
=
newconst
;
return
t
;
}
}
}
}
/* Change X >= CST to X > (CST - 1) if CST is positive. */
if
(
TREE_CODE
(
arg1
)
==
INTEGER_CST
...
...
@@ -3108,89 +3314,6 @@ fold (expr)
}
}
/* If we are comparing the result of a comparison to a constant,
we can often simplify this, since the comparison result is known to
be either 0 or 1. We can ignore conversions if the LHS is a
comparison. */
if
(
TREE_CODE
(
arg1
)
==
INTEGER_CST
)
{
tree
comparison
=
arg0
;
while
(
TREE_CODE
(
comparison
)
==
NOP_EXPR
||
TREE_CODE
(
comparison
)
==
CONVERT_EXPR
)
comparison
=
TREE_OPERAND
(
comparison
,
0
);
if
(
TREE_CODE_CLASS
(
TREE_CODE
(
comparison
))
==
'<'
||
TREE_CODE
(
comparison
)
==
TRUTH_ANDIF_EXPR
||
TREE_CODE
(
comparison
)
==
TRUTH_ORIF_EXPR
||
TREE_CODE
(
comparison
)
==
TRUTH_AND_EXPR
||
TREE_CODE
(
comparison
)
==
TRUTH_OR_EXPR
||
TREE_CODE
(
comparison
)
==
TRUTH_NOT_EXPR
)
{
/* We do different things depending on whether the
constant being compared against is < 0, == 0, == 1, or > 1.
Each of those cases, in order, corresponds to one
character in a string. The value of the character is
the result to return. A '0' or '1' means return always true
or always false, respectively; 'c' means return the result
of the comparison, and 'i' means return the result of the
inverted comparison. */
char
*
actions
,
action
;
switch
(
code
)
{
case
EQ_EXPR
:
actions
=
"0ic0"
;
break
;
case
NE_EXPR
:
actions
=
"1ci1"
;
break
;
case
LE_EXPR
:
actions
=
"0i11"
;
break
;
case
LT_EXPR
:
actions
=
"00i1"
;
break
;
case
GE_EXPR
:
actions
=
"11c0"
;
break
;
case
GT_EXPR
:
actions
=
"1c00"
;
break
;
}
if
(
tree_int_cst_lt
(
arg1
,
integer_zero_node
))
action
=
actions
[
0
];
else
if
(
integer_zerop
(
arg1
))
action
=
actions
[
1
];
else
if
(
integer_onep
(
arg1
))
action
=
actions
[
2
];
else
action
=
actions
[
3
];
switch
(
action
)
{
case
'0'
:
return
omit_one_operand
(
type
,
integer_zero_node
,
comparison
);
case
'1'
:
return
omit_one_operand
(
type
,
integer_one_node
,
comparison
);
case
'c'
:
return
convert
(
type
,
comparison
);
case
'i'
:
return
convert
(
type
,
invert_truthvalue
(
comparison
));
default
:
abort
();
}
}
}
/* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
two operations, but the latter can be done in one less insn
...
...
@@ -3241,20 +3364,30 @@ fold (expr)
return
build
(
code
==
EQ_EXPR
?
NE_EXPR
:
EQ_EXPR
,
type
,
arg0
,
integer_zero_node
);
/* Simplify comparison of an integer with itself.
(This may not be safe with IEEE floats if they are nans.) */
if
(
operand_equal_p
(
arg0
,
arg1
,
0
)
&&
TREE_CODE
(
TREE_TYPE
(
arg1
))
==
INTEGER_TYPE
)
/* Simplify comparison of something with itself. (For IEEE
floating-point, we can only do some of these simplifications.) */
if
(
operand_equal_p
(
arg0
,
arg1
,
0
))
{
switch
(
code
)
{
case
EQ_EXPR
:
case
GE_EXPR
:
case
LE_EXPR
:
if
(
TREE_CODE
(
TREE_TYPE
(
arg0
))
==
INTEGER_TYPE
)
{
t
=
build_int_2
(
1
,
0
);
TREE_TYPE
(
t
)
=
type
;
return
t
;
}
code
=
EQ_EXPR
;
TREE_SET_CODE
(
t
,
code
);
break
;
case
NE_EXPR
:
/* For NE, we can only do this simplification if integer. */
if
(
TREE_CODE
(
TREE_TYPE
(
arg0
))
!=
INTEGER_TYPE
)
break
;
/* ... fall through ... */
case
GT_EXPR
:
case
LT_EXPR
:
t
=
build_int_2
(
0
,
0
);
...
...
@@ -3272,9 +3405,11 @@ fold (expr)
switch
(
TREE_CODE
(
t
))
{
case
GT_EXPR
:
code
=
NE_EXPR
;
TREE_SET_CODE
(
t
,
NE_EXPR
);
break
;
case
LE_EXPR
:
code
=
EQ_EXPR
;
TREE_SET_CODE
(
t
,
EQ_EXPR
);
break
;
case
GE_EXPR
:
...
...
@@ -3286,33 +3421,155 @@ fold (expr)
}
}
/* To compute GT, swap the arguments and do LT.
/* If we are comparing an expression that just has comparisons
of two integer values, arithmetic expressions of those comparisons,
and constants, we can simplify it. There are only three cases
to check: the two values can either be equal, the first can be
greater, or the second can be greater. Fold the expression for
those three values. Since each value must be 0 or 1, we have
eight possibilities, each of which corresponds to the constant 0
or 1 or one of the six possible comparisons.
This handles common cases like (a > b) == 0 but also handles
expressions like ((x > y) - (y > x)) > 0, which supposedly
occur in macroized code. */
if
(
TREE_CODE
(
arg1
)
==
INTEGER_CST
&&
TREE_CODE
(
arg0
)
!=
INTEGER_CST
)
{
tree
cval1
=
0
,
cval2
=
0
;
if
(
twoval_comparison_p
(
arg0
,
&
cval1
,
&
cval2
)
/* Don't handle degenerate cases here; they should already
have been handled anyway. */
&&
cval1
!=
0
&&
cval2
!=
0
&&
!
(
TREE_CONSTANT
(
cval1
)
&&
TREE_CONSTANT
(
cval2
))
&&
TREE_TYPE
(
cval1
)
==
TREE_TYPE
(
cval2
)
&&
TREE_CODE
(
TREE_TYPE
(
cval1
))
==
INTEGER_TYPE
&&
!
operand_equal_p
(
TYPE_MIN_VALUE
(
TREE_TYPE
(
cval1
)),
TYPE_MAX_VALUE
(
TREE_TYPE
(
cval2
)),
0
))
{
tree
maxval
=
TYPE_MAX_VALUE
(
TREE_TYPE
(
cval1
));
tree
minval
=
TYPE_MIN_VALUE
(
TREE_TYPE
(
cval1
));
/* We can't just pass T to eval_subst in case cval1 or cval2
was the same as ARG1. */
tree
high_result
=
fold
(
build
(
code
,
type
,
eval_subst
(
arg0
,
cval1
,
maxval
,
cval2
,
minval
),
arg1
));
tree
equal_result
=
fold
(
build
(
code
,
type
,
eval_subst
(
arg0
,
cval1
,
maxval
,
cval2
,
maxval
),
arg1
));
tree
low_result
=
fold
(
build
(
code
,
type
,
eval_subst
(
arg0
,
cval1
,
minval
,
cval2
,
maxval
),
arg1
));
/* All three of these results should be 0 or 1. Confirm they
are. Then use those values to select the proper code
to use. */
if
((
integer_zerop
(
high_result
)
||
integer_onep
(
high_result
))
&&
(
integer_zerop
(
equal_result
)
||
integer_onep
(
equal_result
))
&&
(
integer_zerop
(
low_result
)
||
integer_onep
(
low_result
)))
{
/* Make a 3-bit mask with the high-order bit being the
value for `>', the next for '=', and the low for '<'. */
switch
((
integer_onep
(
high_result
)
*
4
)
+
(
integer_onep
(
equal_result
)
*
2
)
+
integer_onep
(
low_result
))
{
case
0
:
/* Always false. */
return
convert
(
type
,
integer_zero_node
);
case
1
:
code
=
LT_EXPR
;
break
;
case
2
:
code
=
EQ_EXPR
;
break
;
case
3
:
code
=
LE_EXPR
;
break
;
case
4
:
code
=
GT_EXPR
;
break
;
case
5
:
code
=
NE_EXPR
;
break
;
case
6
:
code
=
GE_EXPR
;
break
;
case
7
:
/* Always true. */
return
convert
(
type
,
integer_one_node
);
}
return
fold
(
build
(
code
,
type
,
cval1
,
cval2
));
}
}
}
/* If this is a comparison of a field, we may be able to simplify it. */
if
((
TREE_CODE
(
arg0
)
==
COMPONENT_REF
||
TREE_CODE
(
arg0
)
==
BIT_FIELD_REF
)
&&
(
code
==
EQ_EXPR
||
code
==
NE_EXPR
)
/* Handle the constant case even without -O
to make sure the warnings are given. */
&&
(
optimize
||
TREE_CODE
(
arg1
)
==
INTEGER_CST
))
{
t1
=
optimize_bit_field_compare
(
code
,
type
,
arg0
,
arg1
);
return
t1
?
t1
:
t
;
}
/* From here on, the only cases we handle are when the result is
known to be a constant.
To compute GT, swap the arguments and do LT.
To compute GE, do LT and invert the result.
To compute LE, swap the arguments, do LT and invert the result.
To compute NE, do EQ and invert the result. */
To compute NE, do EQ and invert the result.
Therefore, the code below must handle only EQ and LT. */
if
(
code
==
LE_EXPR
||
code
==
GT_EXPR
)
{
register
tree
temp
=
arg0
;
arg0
=
arg1
;
arg1
=
temp
;
tem
=
arg0
,
arg0
=
arg1
,
arg1
=
tem
;
code
=
swap_tree_comparison
(
code
);
}
/* Note that it is safe to invert for real values here because we
will check below in the one case that it matters. */
invert
=
0
;
if
(
code
==
NE_EXPR
||
code
==
GE_EXPR
)
{
invert
=
1
;
code
=
invert_tree_comparison
(
code
);
}
/* Compute a result for LT or EQ if args permit;
otherwise return T. */
if
(
TREE_CODE
(
arg0
)
==
INTEGER_CST
&&
TREE_CODE
(
arg1
)
==
INTEGER_CST
)
if
(
TREE_CODE
(
arg0
)
==
INTEGER_CST
&&
TREE_CODE
(
arg1
)
==
INTEGER_CST
)
{
if
(
code
==
EQ_EXPR
||
code
==
NE_EXPR
)
t
=
build_int_2
(
TREE_INT_CST_LOW
(
arg0
)
==
TREE_INT_CST_LOW
(
arg1
)
&&
TREE_INT_CST_HIGH
(
arg0
)
==
TREE_INT_CST_HIGH
(
arg1
),
if
(
code
==
EQ_EXPR
)
t1
=
build_int_2
((
TREE_INT_CST_LOW
(
arg0
)
==
TREE_INT_CST_LOW
(
arg1
))
&&
(
TREE_INT_CST_HIGH
(
arg0
)
==
TREE_INT_CST_HIGH
(
arg1
)),
0
);
else
t
=
build_int_2
((
TREE_UNSIGNED
(
TREE_TYPE
(
arg0
))
t
1
=
build_int_2
((
TREE_UNSIGNED
(
TREE_TYPE
(
arg0
))
?
INT_CST_LT_UNSIGNED
(
arg0
,
arg1
)
:
INT_CST_LT
(
arg0
,
arg1
)),
0
);
}
/* Assume a nonexplicit constant cannot equal an explicit one,
since such code would be undefined anyway.
Exception: on sysvr4, using #pragma weak,
...
...
@@ -3321,133 +3578,211 @@ fold (expr)
&&
!
integer_zerop
(
arg1
)
&&
TREE_CONSTANT
(
arg0
)
&&
TREE_CODE
(
arg0
)
==
ADDR_EXPR
&&
(
code
==
EQ_EXPR
||
code
==
NE_EXPR
))
{
t
=
build_int_2
(
0
,
0
);
}
&&
code
==
EQ_EXPR
)
t1
=
build_int_2
(
0
,
0
);
/* Two real constants can be compared explicitly. */
else
if
(
TREE_CODE
(
arg0
)
==
REAL_CST
&&
TREE_CODE
(
arg1
)
==
REAL_CST
)
else
if
(
TREE_CODE
(
arg0
)
==
REAL_CST
&&
TREE_CODE
(
arg1
)
==
REAL_CST
)
{
if
(
code
==
EQ_EXPR
||
code
==
NE_EXPR
)
t
=
build_int_2
(
REAL_VALUES_EQUAL
(
TREE_REAL_CST
(
arg0
),
/* If either operand is a NaN, the result is false with two
exceptions: First, an NE_EXPR is true on NaNs, but that case
is already handled correctly since we will be inverting the
result for NE_EXPR. Second, if we had inverted a LE_EXPR
or a GE_EXPR into a LT_EXPR, we must return true so that it
will be inverted into false. */
if
(
REAL_VALUE_ISNAN
(
TREE_REAL_CST
(
arg0
))
||
REAL_VALUE_ISNAN
(
TREE_REAL_CST
(
arg1
)))
t1
=
build_int_2
(
invert
&&
code
==
LT_EXPR
,
0
);
else
if
(
code
==
EQ_EXPR
)
t1
=
build_int_2
(
REAL_VALUES_EQUAL
(
TREE_REAL_CST
(
arg0
),
TREE_REAL_CST
(
arg1
)),
0
);
else
t
=
build_int_2
(
REAL_VALUES_LESS
(
TREE_REAL_CST
(
arg0
),
t
1
=
build_int_2
(
REAL_VALUES_LESS
(
TREE_REAL_CST
(
arg0
),
TREE_REAL_CST
(
arg1
)),
0
);
}
else
if
((
TREE_CODE
(
arg0
)
==
COMPONENT_REF
||
TREE_CODE
(
arg0
)
==
BIT_FIELD_REF
)
&&
(
code
==
EQ_EXPR
||
code
==
NE_EXPR
)
/* Handle the constant case even without -O
to make sure the warnings are given. */
&&
(
optimize
||
TREE_CODE
(
arg1
)
==
INTEGER_CST
))
{
tree
tem
=
optimize_bit_field_compare
(
code
,
type
,
arg0
,
arg1
);
return
tem
?
tem
:
t
;
}
/* If what we want is other than LT or EQ, invert the result. */
if
((
code
==
GE_EXPR
||
code
==
LE_EXPR
||
code
==
NE_EXPR
)
&&
TREE_CODE
(
t
)
==
INTEGER_CST
)
TREE_INT_CST_LOW
(
t
)
^=
1
;
TREE_TYPE
(
t
)
=
type
;
if
(
t1
==
NULL_TREE
)
return
t
;
if
(
invert
)
TREE_INT_CST_LOW
(
t1
)
^=
1
;
TREE_TYPE
(
t1
)
=
type
;
return
t1
;
case
COND_EXPR
:
if
(
TREE_CODE
(
arg0
)
==
INTEGER_CST
)
return
TREE_OPERAND
(
t
,
(
integer_zerop
(
arg0
)
?
2
:
1
));
else
if
(
operand_equal_p
(
arg1
,
TREE_OPERAND
(
expr
,
2
),
0
))
return
omit_one_operand
(
type
,
arg1
,
arg0
);
else
if
(
integer_onep
(
TREE_OPERAND
(
t
,
1
))
&&
integer_zerop
(
TREE_OPERAND
(
t
,
2
))
/* If we try to convert TREE_OPERAND (t, 0) to our type, the
call to fold will try to move the conversion inside
a COND, which will recurse. In that case, the COND_EXPR
is probably the best choice, so leave it alone. */
&&
type
==
TREE_TYPE
(
arg0
))
return
arg0
;
else
if
(
integer_zerop
(
arg1
)
&&
integer_onep
(
TREE_OPERAND
(
t
,
2
)))
return
convert
(
type
,
invert_truthvalue
(
arg0
));
/* If we have (a >= 0 ? a : -a) or the same with ">", this is an
absolute value expression. */
/* If the second operand is zero, invert the comparison and swap
the second and third operands. Likewise if the second operand
is constant and the third is not or if the third operand is
equivalent to the first operand of the comparison. */
if
((
TREE_CODE
(
arg0
)
==
GE_EXPR
||
TREE_CODE
(
arg0
)
==
GT_EXPR
)
&&
integer_zerop
(
TREE_OPERAND
(
arg0
,
1
))
&&
TREE_CODE
(
TREE_OPERAND
(
t
,
2
))
==
NEGATE_EXPR
&&
operand_equal_p
(
TREE_OPERAND
(
arg0
,
0
),
arg1
,
0
)
&&
operand_equal_p
(
TREE_OPERAND
(
TREE_OPERAND
(
t
,
2
),
0
),
arg1
,
0
))
if
(
integer_zerop
(
arg1
)
||
(
TREE_CONSTANT
(
arg1
)
&&
!
TREE_CONSTANT
(
TREE_OPERAND
(
t
,
2
)))
||
(
TREE_CODE_CLASS
(
TREE_CODE
(
arg0
))
==
'<'
&&
operand_equal_for_comparison_p
(
TREE_OPERAND
(
arg0
,
0
),
TREE_OPERAND
(
t
,
2
),
TREE_OPERAND
(
arg0
,
1
))))
{
/* See if this can be inverted. If it can't, possibly because
it was a floating-point inequality comparison, don't do
anything. */
tem
=
invert_truthvalue
(
arg0
);
if
(
TREE_CODE
(
tem
)
!=
TRUTH_NOT_EXPR
)
{
arg0
=
TREE_OPERAND
(
t
,
0
)
=
tem
;
TREE_OPERAND
(
t
,
1
)
=
TREE_OPERAND
(
t
,
2
);
TREE_OPERAND
(
t
,
2
)
=
arg1
;
arg1
=
TREE_OPERAND
(
t
,
1
);
}
}
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
of B and C. */
if
(
TREE_CODE_CLASS
(
TREE_CODE
(
arg0
))
==
'<'
&&
operand_equal_for_comparison_p
(
TREE_OPERAND
(
arg0
,
0
),
arg1
,
TREE_OPERAND
(
arg0
,
1
)))
{
tree
arg2
=
TREE_OPERAND
(
t
,
2
);
enum
tree_code
comp_code
=
TREE_CODE
(
arg0
);
/* If we have A op 0 ? A : -A, this is A, -A, abs (A), or abs (-A),
depending on the comparison operation. */
if
(
integer_zerop
(
TREE_OPERAND
(
arg0
,
1
))
&&
TREE_CODE
(
arg2
)
==
NEGATE_EXPR
&&
operand_equal_p
(
TREE_OPERAND
(
arg2
,
0
),
arg1
,
0
))
switch
(
comp_code
)
{
case
EQ_EXPR
:
return
fold
(
build1
(
NEGATE_EXPR
,
type
,
arg1
));
case
NE_EXPR
:
return
arg1
;
case
GE_EXPR
:
case
GT_EXPR
:
return
fold
(
build1
(
ABS_EXPR
,
type
,
arg1
));
case
LE_EXPR
:
case
LT_EXPR
:
return
fold
(
build1
(
NEGATE_EXPR
,
type
,
fold
(
build1
(
ABS_EXPR
,
type
,
arg1
))));
}
/* Similarly for (a <= 0 ? -a : a). */
/* If this is A != 0 ? A : 0, this is simply A. For ==, it is
always zero. */
if
((
TREE_CODE
(
arg0
)
==
LE_EXPR
||
TREE_CODE
(
arg0
)
==
LT_EXPR
)
&&
integer_zerop
(
TREE_OPERAND
(
arg0
,
1
))
&&
TREE_CODE
(
arg1
)
==
NEGATE_EXPR
&&
operand_equal_p
(
TREE_OPERAND
(
arg0
,
0
),
TREE_OPERAND
(
t
,
2
),
0
)
&&
operand_equal_p
(
TREE_OPERAND
(
arg1
,
0
),
TREE_OPERAND
(
t
,
2
),
0
))
return
fold
(
build1
(
ABS_EXPR
,
type
,
TREE_OPERAND
(
t
,
2
)));
if
(
integer_zerop
(
arg2
))
{
if
(
comp_code
==
NE_EXPR
)
return
arg1
;
else
if
(
comp_code
==
EQ_EXPR
)
return
convert
(
type
,
integer_zero_node
);
}
/* If we have a GT, GE, LT, or LE comparison, this might be a MIN or
MAX test. If so, make a MIN_EXPR or MAX_EXPR
. */
/* If this is A op B ? A : B, this is either A, B, min (A, B),
or max (A, B), depending on the operation
. */
if
(
TREE_CODE
(
arg0
)
==
GT_EXPR
||
TREE_CODE
(
arg0
)
==
GE_EXPR
||
TREE_CODE
(
arg0
)
==
LT_EXPR
||
TREE_CODE
(
arg0
)
==
LE_EXPR
)
if
(
operand_equal_for_comparison_p
(
TREE_OPERAND
(
arg0
,
1
),
arg2
,
TREE_OPERAND
(
arg0
,
0
)))
switch
(
comp_code
)
{
tree
hi_true
,
lo_true
;
case
EQ_EXPR
:
return
arg2
;
case
NE_EXPR
:
return
arg1
;
case
LE_EXPR
:
case
LT_EXPR
:
return
fold
(
build
(
MIN_EXPR
,
type
,
arg1
,
arg2
));
case
GE_EXPR
:
case
GT_EXPR
:
return
fold
(
build
(
MAX_EXPR
,
type
,
arg1
,
arg2
));
}
if
(
TREE_CODE
(
arg0
)
==
GT_EXPR
||
TREE_CODE
(
arg0
)
==
GE_EXPR
)
hi_true
=
TREE_OPERAND
(
arg0
,
0
),
lo_true
=
TREE_OPERAND
(
arg0
,
1
);
else
hi_true
=
TREE_OPERAND
(
arg0
,
1
),
lo_true
=
TREE_OPERAND
(
arg0
,
0
);
/* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
we might still be able to simplify this. For example,
if C1 is one less or one more than C2, this might have started
out as a MIN or MAX and been transformed by this function. */
if
(
comparison_equiv_p
(
hi_true
,
lo_true
,
arg1
,
TREE_OPERAND
(
t
,
2
)))
/* We use arg1 and the other arg because they must have the same
type as the intended result.
The values being compared might have a narrower type. */
return
fold
(
build
(
MAX_EXPR
,
type
,
arg1
,
TREE_OPERAND
(
t
,
2
)));
else
if
(
comparison_equiv_p
(
lo_true
,
hi_true
,
arg1
,
TREE_OPERAND
(
t
,
2
)))
return
fold
(
build
(
MIN_EXPR
,
type
,
arg1
,
TREE_OPERAND
(
t
,
2
)));
if
(
TREE_CODE
(
TREE_OPERAND
(
arg0
,
1
))
==
INTEGER_CST
&&
TREE_CODE
(
arg2
)
==
INTEGER_CST
)
switch
(
comp_code
)
{
case
EQ_EXPR
:
/* We can replace A with C1 in this case. */
arg1
=
TREE_OPERAND
(
t
,
1
)
=
convert
(
type
,
TREE_OPERAND
(
arg0
,
1
));
break
;
case
LT_EXPR
:
/* If C1 is C2 + 1, this is min(A, C2). */
if
(
!
operand_equal_p
(
arg2
,
TYPE_MAX_VALUE
(
type
),
1
)
&&
operand_equal_p
(
TREE_OPERAND
(
arg0
,
1
),
const_binop
(
PLUS_EXPR
,
arg2
,
integer_one_node
),
1
))
return
fold
(
build
(
MIN_EXPR
,
type
,
arg1
,
arg2
));
break
;
case
LE_EXPR
:
/* If C1 is C2 - 1, this is min(A, C2). */
if
(
!
operand_equal_p
(
arg2
,
TYPE_MIN_VALUE
(
type
),
1
)
&&
operand_equal_p
(
TREE_OPERAND
(
arg0
,
1
),
const_binop
(
MINUS_EXPR
,
arg2
,
integer_one_node
),
1
))
return
fold
(
build
(
MIN_EXPR
,
type
,
arg1
,
arg2
));
break
;
case
GT_EXPR
:
/* If C1 is C2 - 1, this is max(A, C2). */
if
(
!
operand_equal_p
(
arg2
,
TYPE_MIN_VALUE
(
type
),
1
)
&&
operand_equal_p
(
TREE_OPERAND
(
arg0
,
1
),
const_binop
(
MINUS_EXPR
,
arg2
,
integer_one_node
),
1
))
return
fold
(
build
(
MAX_EXPR
,
type
,
arg1
,
arg2
));
break
;
case
GE_EXPR
:
/* If C1 is C2 + 1, this is max(A, C2). */
if
(
!
operand_equal_p
(
arg2
,
TYPE_MAX_VALUE
(
type
),
1
)
&&
operand_equal_p
(
TREE_OPERAND
(
arg0
,
1
),
const_binop
(
PLUS_EXPR
,
arg2
,
integer_one_node
),
1
))
return
fold
(
build
(
MAX_EXPR
,
type
,
arg1
,
arg2
));
break
;
}
}
/* Look for cases when we are comparing some expression A for equality
with zero and the result is to be zero if A is zero. In that case,
check to see if the value of A is the same as the value to be
returned when A is non-zero.
/* Convert A ? 1 : 0 to simply A. */
if
(
integer_onep
(
TREE_OPERAND
(
t
,
1
))
&&
integer_zerop
(
TREE_OPERAND
(
t
,
2
))
/* If we try to convert TREE_OPERAND (t, 0) to our type, the
call to fold will try to move the conversion inside
a COND, which will recurse. In that case, the COND_EXPR
is probably the best choice, so leave it alone. */
&&
type
==
TREE_TYPE
(
arg0
))
return
arg0
;
There are two cases: One is where we have (A ? A : 0) and the
other is when a single bit is tested (e.g., A & 2 ? 2 : 0).
In these cases, the result of the conditional is simply A.
Start by setting ARG1 to be the true value and ARG0 to be the thing
compared with zero. Then check for the two cases above
. */
/* Look for expressions of the form A & 2 ? 2 : 0. The result of this
operation is simply A & 2
. */
if
(
integer_zerop
(
TREE_OPERAND
(
t
,
2
))
&&
TREE_CODE
(
arg0
)
==
NE_EXPR
&&
integer_zerop
(
TREE_OPERAND
(
arg0
,
1
))
&&
!
TREE_SIDE_EFFECTS
(
arg1
))
;
else
if
(
integer_zerop
(
arg1
)
&&
TREE_CODE
(
arg0
)
==
EQ_EXPR
&&
integer_zerop
(
TREE_OPERAND
(
arg0
,
1
))
&&
!
TREE_SIDE_EFFECTS
(
TREE_OPERAND
(
t
,
2
)))
arg1
=
TREE_OPERAND
(
t
,
2
);
else
return
t
;
arg0
=
TREE_OPERAND
(
arg0
,
0
);
STRIP_NOPS
(
arg1
);
if
(
operand_equal_p
(
arg0
,
arg1
,
0
)
||
(
TREE_CODE
(
arg1
)
==
INTEGER_CST
&&
integer_pow2p
(
arg1
)
&&
TREE_CODE
(
arg0
)
==
BIT_AND_EXPR
&&
operand_equal_p
(
TREE_OPERAND
(
arg0
,
1
),
arg1
,
0
)))
return
convert
(
type
,
arg0
);
&&
TREE_CODE
(
TREE_OPERAND
(
arg0
,
0
))
==
BIT_AND_EXPR
&&
operand_equal_p
(
TREE_OPERAND
(
TREE_OPERAND
(
arg0
,
0
),
1
),
arg1
,
1
))
return
convert
(
type
,
TREE_OPERAND
(
arg0
,
0
));
return
t
;
case
COMPOUND_EXPR
:
...
...
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