annotate src/share/vm/opto/divnode.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children 6e825ad773c6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 // Portions of code courtesy of Clifford Click
a61af66fc99e Initial load
duke
parents:
diff changeset
26
a61af66fc99e Initial load
duke
parents:
diff changeset
27 // Optimization - Graph Style
a61af66fc99e Initial load
duke
parents:
diff changeset
28
a61af66fc99e Initial load
duke
parents:
diff changeset
29 #include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
30 #include "incls/_divnode.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
31 #include <math.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 // Implement the integer constant divide -> long multiply transform found in
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // "Division by Invariant Integers using Multiplication"
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // by Granlund and Montgomery
a61af66fc99e Initial load
duke
parents:
diff changeset
36 static Node *transform_int_divide_to_long_multiply( PhaseGVN *phase, Node *dividend, int divisor ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
37
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // Check for invalid divisors
a61af66fc99e Initial load
duke
parents:
diff changeset
39 assert( divisor != 0 && divisor != min_jint && divisor != 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
40 "bad divisor for transforming to long multiply" );
a61af66fc99e Initial load
duke
parents:
diff changeset
41
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // Compute l = ceiling(log2(d))
a61af66fc99e Initial load
duke
parents:
diff changeset
43 // presumes d is more likely small
a61af66fc99e Initial load
duke
parents:
diff changeset
44 bool d_pos = divisor >= 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
45 int d = d_pos ? divisor : -divisor;
a61af66fc99e Initial load
duke
parents:
diff changeset
46 unsigned ud = (unsigned)d;
a61af66fc99e Initial load
duke
parents:
diff changeset
47 const int N = 32;
a61af66fc99e Initial load
duke
parents:
diff changeset
48 int l = log2_intptr(d-1)+1;
a61af66fc99e Initial load
duke
parents:
diff changeset
49 int sh_post = l;
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51 const uint64_t U1 = (uint64_t)1;
a61af66fc99e Initial load
duke
parents:
diff changeset
52
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // Cliff pointed out how to prevent overflow (from the paper)
a61af66fc99e Initial load
duke
parents:
diff changeset
54 uint64_t m_low = (((U1 << l) - ud) << N) / ud + (U1 << N);
a61af66fc99e Initial load
duke
parents:
diff changeset
55 uint64_t m_high = ((((U1 << l) - ud) << N) + (U1 << (l+1))) / ud + (U1 << N);
a61af66fc99e Initial load
duke
parents:
diff changeset
56
a61af66fc99e Initial load
duke
parents:
diff changeset
57 // Reduce to lowest terms
a61af66fc99e Initial load
duke
parents:
diff changeset
58 for ( ; sh_post > 0; sh_post-- ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
59 uint64_t m_low_1 = m_low >> 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
60 uint64_t m_high_1 = m_high >> 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
61 if ( m_low_1 >= m_high_1 )
a61af66fc99e Initial load
duke
parents:
diff changeset
62 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
63 m_low = m_low_1;
a61af66fc99e Initial load
duke
parents:
diff changeset
64 m_high = m_high_1;
a61af66fc99e Initial load
duke
parents:
diff changeset
65 }
a61af66fc99e Initial load
duke
parents:
diff changeset
66
a61af66fc99e Initial load
duke
parents:
diff changeset
67 // Result
a61af66fc99e Initial load
duke
parents:
diff changeset
68 Node *q;
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 // division by +/- 1
a61af66fc99e Initial load
duke
parents:
diff changeset
71 if (d == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // Filtered out as identity above
a61af66fc99e Initial load
duke
parents:
diff changeset
73 if (d_pos)
a61af66fc99e Initial load
duke
parents:
diff changeset
74 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 // Just negate the value
a61af66fc99e Initial load
duke
parents:
diff changeset
77 else {
a61af66fc99e Initial load
duke
parents:
diff changeset
78 q = new (phase->C, 3) SubINode(phase->intcon(0), dividend);
a61af66fc99e Initial load
duke
parents:
diff changeset
79 }
a61af66fc99e Initial load
duke
parents:
diff changeset
80 }
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 // division by +/- a power of 2
a61af66fc99e Initial load
duke
parents:
diff changeset
83 else if ( is_power_of_2(d) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
84
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // See if we can simply do a shift without rounding
a61af66fc99e Initial load
duke
parents:
diff changeset
86 bool needs_rounding = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
87 const Type *dt = phase->type(dividend);
a61af66fc99e Initial load
duke
parents:
diff changeset
88 const TypeInt *dti = dt->isa_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
89
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // we don't need to round a positive dividend
a61af66fc99e Initial load
duke
parents:
diff changeset
91 if (dti && dti->_lo >= 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
92 needs_rounding = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
93
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // An AND mask of sufficient size clears the low bits and
a61af66fc99e Initial load
duke
parents:
diff changeset
95 // I can avoid rounding.
a61af66fc99e Initial load
duke
parents:
diff changeset
96 else if( dividend->Opcode() == Op_AndI ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
97 const TypeInt *andconi = phase->type( dividend->in(2) )->isa_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
98 if( andconi && andconi->is_con(-d) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
99 dividend = dividend->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
100 needs_rounding = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // Add rounding to the shift to handle the sign bit
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if( needs_rounding ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 Node *t1 = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(l - 1)));
a61af66fc99e Initial load
duke
parents:
diff changeset
107 Node *t2 = phase->transform(new (phase->C, 3) URShiftINode(t1, phase->intcon(N - l)));
a61af66fc99e Initial load
duke
parents:
diff changeset
108 dividend = phase->transform(new (phase->C, 3) AddINode(dividend, t2));
a61af66fc99e Initial load
duke
parents:
diff changeset
109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111 q = new (phase->C, 3) RShiftINode(dividend, phase->intcon(l));
a61af66fc99e Initial load
duke
parents:
diff changeset
112
a61af66fc99e Initial load
duke
parents:
diff changeset
113 if (!d_pos)
a61af66fc99e Initial load
duke
parents:
diff changeset
114 q = new (phase->C, 3) SubINode(phase->intcon(0), phase->transform(q));
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // division by something else
a61af66fc99e Initial load
duke
parents:
diff changeset
118 else if (m_high < (U1 << (N-1))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
119 Node *t1 = phase->transform(new (phase->C, 2) ConvI2LNode(dividend));
a61af66fc99e Initial load
duke
parents:
diff changeset
120 Node *t2 = phase->transform(new (phase->C, 3) MulLNode(t1, phase->longcon(m_high)));
a61af66fc99e Initial load
duke
parents:
diff changeset
121 Node *t3 = phase->transform(new (phase->C, 3) RShiftLNode(t2, phase->intcon(sh_post+N)));
a61af66fc99e Initial load
duke
parents:
diff changeset
122 Node *t4 = phase->transform(new (phase->C, 2) ConvL2INode(t3));
a61af66fc99e Initial load
duke
parents:
diff changeset
123 Node *t5 = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(N-1)));
a61af66fc99e Initial load
duke
parents:
diff changeset
124
a61af66fc99e Initial load
duke
parents:
diff changeset
125 q = new (phase->C, 3) SubINode(d_pos ? t4 : t5, d_pos ? t5 : t4);
a61af66fc99e Initial load
duke
parents:
diff changeset
126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
127
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // This handles that case where m_high is >= 2**(N-1). In that case,
a61af66fc99e Initial load
duke
parents:
diff changeset
129 // we subtract out 2**N from the multiply and add it in later as
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // "dividend" in the equation (t5). This case computes the same result
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // as the immediately preceeding case, save that rounding and overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // are accounted for.
a61af66fc99e Initial load
duke
parents:
diff changeset
133 else {
a61af66fc99e Initial load
duke
parents:
diff changeset
134 Node *t1 = phase->transform(new (phase->C, 2) ConvI2LNode(dividend));
a61af66fc99e Initial load
duke
parents:
diff changeset
135 Node *t2 = phase->transform(new (phase->C, 3) MulLNode(t1, phase->longcon(m_high - (U1 << N))));
a61af66fc99e Initial load
duke
parents:
diff changeset
136 Node *t3 = phase->transform(new (phase->C, 3) RShiftLNode(t2, phase->intcon(N)));
a61af66fc99e Initial load
duke
parents:
diff changeset
137 Node *t4 = phase->transform(new (phase->C, 2) ConvL2INode(t3));
a61af66fc99e Initial load
duke
parents:
diff changeset
138 Node *t5 = phase->transform(new (phase->C, 3) AddINode(dividend, t4));
a61af66fc99e Initial load
duke
parents:
diff changeset
139 Node *t6 = phase->transform(new (phase->C, 3) RShiftINode(t5, phase->intcon(sh_post)));
a61af66fc99e Initial load
duke
parents:
diff changeset
140 Node *t7 = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(N-1)));
a61af66fc99e Initial load
duke
parents:
diff changeset
141
a61af66fc99e Initial load
duke
parents:
diff changeset
142 q = new (phase->C, 3) SubINode(d_pos ? t6 : t7, d_pos ? t7 : t6);
a61af66fc99e Initial load
duke
parents:
diff changeset
143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 return (q);
a61af66fc99e Initial load
duke
parents:
diff changeset
146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
149 //------------------------------Identity---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // If the divisor is 1, we are an identity on the dividend.
a61af66fc99e Initial load
duke
parents:
diff changeset
151 Node *DivINode::Identity( PhaseTransform *phase ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
152 return (phase->type( in(2) )->higher_equal(TypeInt::ONE)) ? in(1) : this;
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155 //------------------------------Idealize---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
156 // Divides can be changed to multiplies and/or shifts
a61af66fc99e Initial load
duke
parents:
diff changeset
157 Node *DivINode::Ideal(PhaseGVN *phase, bool can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
158 if (in(0) && remove_dead_region(phase, can_reshape)) return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
159
a61af66fc99e Initial load
duke
parents:
diff changeset
160 const Type *t = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
161 if( t == TypeInt::ONE ) // Identity?
a61af66fc99e Initial load
duke
parents:
diff changeset
162 return NULL; // Skip it
a61af66fc99e Initial load
duke
parents:
diff changeset
163
a61af66fc99e Initial load
duke
parents:
diff changeset
164 const TypeInt *ti = t->isa_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
165 if( !ti ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
166 if( !ti->is_con() ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 int i = ti->get_con(); // Get divisor
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 if (i == 0) return NULL; // Dividing by zero constant does not idealize
a61af66fc99e Initial load
duke
parents:
diff changeset
170
a61af66fc99e Initial load
duke
parents:
diff changeset
171 set_req(0,NULL); // Dividing by a not-zero constant; no faulting
a61af66fc99e Initial load
duke
parents:
diff changeset
172
a61af66fc99e Initial load
duke
parents:
diff changeset
173 // Dividing by MININT does not optimize as a power-of-2 shift.
a61af66fc99e Initial load
duke
parents:
diff changeset
174 if( i == min_jint ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
175
a61af66fc99e Initial load
duke
parents:
diff changeset
176 return transform_int_divide_to_long_multiply( phase, in(1), i );
a61af66fc99e Initial load
duke
parents:
diff changeset
177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
178
a61af66fc99e Initial load
duke
parents:
diff changeset
179 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // A DivINode divides its inputs. The third input is a Control input, used to
a61af66fc99e Initial load
duke
parents:
diff changeset
181 // prevent hoisting the divide above an unsafe test.
a61af66fc99e Initial load
duke
parents:
diff changeset
182 const Type *DivINode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
184 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
185 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
186 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
187 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
188
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // x/x == 1 since we always generate the dynamic divisor check for 0.
a61af66fc99e Initial load
duke
parents:
diff changeset
190 if( phase->eqv( in(1), in(2) ) )
a61af66fc99e Initial load
duke
parents:
diff changeset
191 return TypeInt::ONE;
a61af66fc99e Initial load
duke
parents:
diff changeset
192
a61af66fc99e Initial load
duke
parents:
diff changeset
193 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
194 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
195 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
196 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
197 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
198
a61af66fc99e Initial load
duke
parents:
diff changeset
199 // Divide the two numbers. We approximate.
a61af66fc99e Initial load
duke
parents:
diff changeset
200 // If divisor is a constant and not zero
a61af66fc99e Initial load
duke
parents:
diff changeset
201 const TypeInt *i1 = t1->is_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
202 const TypeInt *i2 = t2->is_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
203 int widen = MAX2(i1->_widen, i2->_widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 if( i2->is_con() && i2->get_con() != 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 int32 d = i2->get_con(); // Divisor
a61af66fc99e Initial load
duke
parents:
diff changeset
207 jint lo, hi;
a61af66fc99e Initial load
duke
parents:
diff changeset
208 if( d >= 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 lo = i1->_lo/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
210 hi = i1->_hi/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
211 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
212 if( d == -1 && i1->_lo == min_jint ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
213 // 'min_jint/-1' throws arithmetic exception during compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
214 lo = min_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // do not support holes, 'hi' must go to either min_jint or max_jint:
a61af66fc99e Initial load
duke
parents:
diff changeset
216 // [min_jint, -10]/[-1,-1] ==> [min_jint] UNION [10,max_jint]
a61af66fc99e Initial load
duke
parents:
diff changeset
217 hi = i1->_hi == min_jint ? min_jint : max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 lo = i1->_hi/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
220 hi = i1->_lo/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
221 }
a61af66fc99e Initial load
duke
parents:
diff changeset
222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
223 return TypeInt::make(lo, hi, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // If the dividend is a constant
a61af66fc99e Initial load
duke
parents:
diff changeset
227 if( i1->is_con() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
228 int32 d = i1->get_con();
a61af66fc99e Initial load
duke
parents:
diff changeset
229 if( d < 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
230 if( d == min_jint ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // (-min_jint) == min_jint == (min_jint / -1)
a61af66fc99e Initial load
duke
parents:
diff changeset
232 return TypeInt::make(min_jint, max_jint/2 + 1, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
233 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
234 return TypeInt::make(d, -d, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
237 return TypeInt::make(-d, d, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
239
a61af66fc99e Initial load
duke
parents:
diff changeset
240 // Otherwise we give up all hope
a61af66fc99e Initial load
duke
parents:
diff changeset
241 return TypeInt::INT;
a61af66fc99e Initial load
duke
parents:
diff changeset
242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
243
a61af66fc99e Initial load
duke
parents:
diff changeset
244
a61af66fc99e Initial load
duke
parents:
diff changeset
245 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
246 //------------------------------Identity---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // If the divisor is 1, we are an identity on the dividend.
a61af66fc99e Initial load
duke
parents:
diff changeset
248 Node *DivLNode::Identity( PhaseTransform *phase ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
249 return (phase->type( in(2) )->higher_equal(TypeLong::ONE)) ? in(1) : this;
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 //------------------------------Idealize---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // Dividing by a power of 2 is a shift.
a61af66fc99e Initial load
duke
parents:
diff changeset
254 Node *DivLNode::Ideal( PhaseGVN *phase, bool can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
255 if (in(0) && remove_dead_region(phase, can_reshape)) return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
256
a61af66fc99e Initial load
duke
parents:
diff changeset
257 const Type *t = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
258 if( t == TypeLong::ONE ) // Identity?
a61af66fc99e Initial load
duke
parents:
diff changeset
259 return NULL; // Skip it
a61af66fc99e Initial load
duke
parents:
diff changeset
260
a61af66fc99e Initial load
duke
parents:
diff changeset
261 const TypeLong *ti = t->isa_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
262 if( !ti ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
263 if( !ti->is_con() ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
264 jlong i = ti->get_con(); // Get divisor
a61af66fc99e Initial load
duke
parents:
diff changeset
265 if( i ) set_req(0, NULL); // Dividing by a not-zero constant; no faulting
a61af66fc99e Initial load
duke
parents:
diff changeset
266
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // Dividing by MININT does not optimize as a power-of-2 shift.
a61af66fc99e Initial load
duke
parents:
diff changeset
268 if( i == min_jlong ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
269
a61af66fc99e Initial load
duke
parents:
diff changeset
270 // Check for negative power of 2 divisor, if so, negate it and set a flag
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // to indicate result needs to be negated. Note that negating the dividend
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // here does not work when it has the value MININT
a61af66fc99e Initial load
duke
parents:
diff changeset
273 Node *dividend = in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
274 bool negate_res = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
275 if (is_power_of_2_long(-i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
276 i = -i; // Flip divisor
a61af66fc99e Initial load
duke
parents:
diff changeset
277 negate_res = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
278 }
a61af66fc99e Initial load
duke
parents:
diff changeset
279
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // Check for power of 2
a61af66fc99e Initial load
duke
parents:
diff changeset
281 if (!is_power_of_2_long(i)) // Is divisor a power of 2?
a61af66fc99e Initial load
duke
parents:
diff changeset
282 return NULL; // Not a power of 2
a61af66fc99e Initial load
duke
parents:
diff changeset
283
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // Compute number of bits to shift
a61af66fc99e Initial load
duke
parents:
diff changeset
285 int log_i = log2_long(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
286
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // See if we can simply do a shift without rounding
a61af66fc99e Initial load
duke
parents:
diff changeset
288 bool needs_rounding = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
289 const Type *dt = phase->type(dividend);
a61af66fc99e Initial load
duke
parents:
diff changeset
290 const TypeLong *dtl = dt->isa_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 if (dtl && dtl->_lo > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
293 // we don't need to round a positive dividend
a61af66fc99e Initial load
duke
parents:
diff changeset
294 needs_rounding = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
295 } else if( dividend->Opcode() == Op_AndL ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
296 // An AND mask of sufficient size clears the low bits and
a61af66fc99e Initial load
duke
parents:
diff changeset
297 // I can avoid rounding.
a61af66fc99e Initial load
duke
parents:
diff changeset
298 const TypeLong *andconi = phase->type( dividend->in(2) )->isa_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
299 if( andconi &&
a61af66fc99e Initial load
duke
parents:
diff changeset
300 andconi->is_con() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
301 andconi->get_con() == -i ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
302 dividend = dividend->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
303 needs_rounding = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
306
a61af66fc99e Initial load
duke
parents:
diff changeset
307 if (!needs_rounding) {
a61af66fc99e Initial load
duke
parents:
diff changeset
308 Node *result = new (phase->C, 3) RShiftLNode(dividend, phase->intcon(log_i));
a61af66fc99e Initial load
duke
parents:
diff changeset
309 if (negate_res) {
a61af66fc99e Initial load
duke
parents:
diff changeset
310 result = phase->transform(result);
a61af66fc99e Initial load
duke
parents:
diff changeset
311 result = new (phase->C, 3) SubLNode(phase->longcon(0), result);
a61af66fc99e Initial load
duke
parents:
diff changeset
312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
313 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
315
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // Divide-by-power-of-2 can be made into a shift, but you have to do
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // more math for the rounding. You need to add 0 for positive
a61af66fc99e Initial load
duke
parents:
diff changeset
318 // numbers, and "i-1" for negative numbers. Example: i=4, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
319 // shift is by 2. You need to add 3 to negative dividends and 0 to
a61af66fc99e Initial load
duke
parents:
diff changeset
320 // positive ones. So (-7+3)>>2 becomes -1, (-4+3)>>2 becomes -1,
a61af66fc99e Initial load
duke
parents:
diff changeset
321 // (-2+3)>>2 becomes 0, etc.
a61af66fc99e Initial load
duke
parents:
diff changeset
322
a61af66fc99e Initial load
duke
parents:
diff changeset
323 // Compute 0 or -1, based on sign bit
a61af66fc99e Initial load
duke
parents:
diff changeset
324 Node *sign = phase->transform(new (phase->C, 3) RShiftLNode(dividend,phase->intcon(63)));
a61af66fc99e Initial load
duke
parents:
diff changeset
325 // Mask sign bit to the low sign bits
a61af66fc99e Initial load
duke
parents:
diff changeset
326 Node *round = phase->transform(new (phase->C, 3) AndLNode(sign,phase->longcon(i-1)));
a61af66fc99e Initial load
duke
parents:
diff changeset
327 // Round up before shifting
a61af66fc99e Initial load
duke
parents:
diff changeset
328 Node *sum = phase->transform(new (phase->C, 3) AddLNode(dividend,round));
a61af66fc99e Initial load
duke
parents:
diff changeset
329 // Shift for division
a61af66fc99e Initial load
duke
parents:
diff changeset
330 Node *result = new (phase->C, 3) RShiftLNode(sum, phase->intcon(log_i));
a61af66fc99e Initial load
duke
parents:
diff changeset
331 if (negate_res) {
a61af66fc99e Initial load
duke
parents:
diff changeset
332 result = phase->transform(result);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 result = new (phase->C, 3) SubLNode(phase->longcon(0), result);
a61af66fc99e Initial load
duke
parents:
diff changeset
334 }
a61af66fc99e Initial load
duke
parents:
diff changeset
335
a61af66fc99e Initial load
duke
parents:
diff changeset
336 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
338
a61af66fc99e Initial load
duke
parents:
diff changeset
339 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // A DivLNode divides its inputs. The third input is a Control input, used to
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // prevent hoisting the divide above an unsafe test.
a61af66fc99e Initial load
duke
parents:
diff changeset
342 const Type *DivLNode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
343 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
344 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
345 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
346 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
347 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
348
a61af66fc99e Initial load
duke
parents:
diff changeset
349 // x/x == 1 since we always generate the dynamic divisor check for 0.
a61af66fc99e Initial load
duke
parents:
diff changeset
350 if( phase->eqv( in(1), in(2) ) )
a61af66fc99e Initial load
duke
parents:
diff changeset
351 return TypeLong::ONE;
a61af66fc99e Initial load
duke
parents:
diff changeset
352
a61af66fc99e Initial load
duke
parents:
diff changeset
353 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
354 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
355 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
356 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
357 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
358
a61af66fc99e Initial load
duke
parents:
diff changeset
359 // Divide the two numbers. We approximate.
a61af66fc99e Initial load
duke
parents:
diff changeset
360 // If divisor is a constant and not zero
a61af66fc99e Initial load
duke
parents:
diff changeset
361 const TypeLong *i1 = t1->is_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
362 const TypeLong *i2 = t2->is_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
363 int widen = MAX2(i1->_widen, i2->_widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
364
a61af66fc99e Initial load
duke
parents:
diff changeset
365 if( i2->is_con() && i2->get_con() != 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
366 jlong d = i2->get_con(); // Divisor
a61af66fc99e Initial load
duke
parents:
diff changeset
367 jlong lo, hi;
a61af66fc99e Initial load
duke
parents:
diff changeset
368 if( d >= 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
369 lo = i1->_lo/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
370 hi = i1->_hi/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
371 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
372 if( d == CONST64(-1) && i1->_lo == min_jlong ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
373 // 'min_jlong/-1' throws arithmetic exception during compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
374 lo = min_jlong;
a61af66fc99e Initial load
duke
parents:
diff changeset
375 // do not support holes, 'hi' must go to either min_jlong or max_jlong:
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // [min_jlong, -10]/[-1,-1] ==> [min_jlong] UNION [10,max_jlong]
a61af66fc99e Initial load
duke
parents:
diff changeset
377 hi = i1->_hi == min_jlong ? min_jlong : max_jlong;
a61af66fc99e Initial load
duke
parents:
diff changeset
378 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
379 lo = i1->_hi/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
380 hi = i1->_lo/d;
a61af66fc99e Initial load
duke
parents:
diff changeset
381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
383 return TypeLong::make(lo, hi, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
385
a61af66fc99e Initial load
duke
parents:
diff changeset
386 // If the dividend is a constant
a61af66fc99e Initial load
duke
parents:
diff changeset
387 if( i1->is_con() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
388 jlong d = i1->get_con();
a61af66fc99e Initial load
duke
parents:
diff changeset
389 if( d < 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
390 if( d == min_jlong ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
391 // (-min_jlong) == min_jlong == (min_jlong / -1)
a61af66fc99e Initial load
duke
parents:
diff changeset
392 return TypeLong::make(min_jlong, max_jlong/2 + 1, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
393 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
394 return TypeLong::make(d, -d, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
395 }
a61af66fc99e Initial load
duke
parents:
diff changeset
396 }
a61af66fc99e Initial load
duke
parents:
diff changeset
397 return TypeLong::make(-d, d, widen);
a61af66fc99e Initial load
duke
parents:
diff changeset
398 }
a61af66fc99e Initial load
duke
parents:
diff changeset
399
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // Otherwise we give up all hope
a61af66fc99e Initial load
duke
parents:
diff changeset
401 return TypeLong::LONG;
a61af66fc99e Initial load
duke
parents:
diff changeset
402 }
a61af66fc99e Initial load
duke
parents:
diff changeset
403
a61af66fc99e Initial load
duke
parents:
diff changeset
404
a61af66fc99e Initial load
duke
parents:
diff changeset
405 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
406 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // An DivFNode divides its inputs. The third input is a Control input, used to
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // prevent hoisting the divide above an unsafe test.
a61af66fc99e Initial load
duke
parents:
diff changeset
409 const Type *DivFNode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
410 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
411 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
412 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
413 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
414 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
415
a61af66fc99e Initial load
duke
parents:
diff changeset
416 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
417 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
418 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
419 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
420 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
421
a61af66fc99e Initial load
duke
parents:
diff changeset
422 // x/x == 1, we ignore 0/0.
a61af66fc99e Initial load
duke
parents:
diff changeset
423 // Note: if t1 and t2 are zero then result is NaN (JVMS page 213)
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // does not work for variables because of NaN's
a61af66fc99e Initial load
duke
parents:
diff changeset
425 if( phase->eqv( in(1), in(2) ) && t1->base() == Type::FloatCon)
a61af66fc99e Initial load
duke
parents:
diff changeset
426 if (!g_isnan(t1->getf()) && g_isfinite(t1->getf()) && t1->getf() != 0.0) // could be negative ZERO or NaN
a61af66fc99e Initial load
duke
parents:
diff changeset
427 return TypeF::ONE;
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429 if( t2 == TypeF::ONE )
a61af66fc99e Initial load
duke
parents:
diff changeset
430 return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
431
a61af66fc99e Initial load
duke
parents:
diff changeset
432 // If divisor is a constant and not zero, divide them numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
433 if( t1->base() == Type::FloatCon &&
a61af66fc99e Initial load
duke
parents:
diff changeset
434 t2->base() == Type::FloatCon &&
a61af66fc99e Initial load
duke
parents:
diff changeset
435 t2->getf() != 0.0 ) // could be negative zero
a61af66fc99e Initial load
duke
parents:
diff changeset
436 return TypeF::make( t1->getf()/t2->getf() );
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // If the dividend is a constant zero
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // Note: if t1 and t2 are zero then result is NaN (JVMS page 213)
a61af66fc99e Initial load
duke
parents:
diff changeset
440 // Test TypeF::ZERO is not sufficient as it could be negative zero
a61af66fc99e Initial load
duke
parents:
diff changeset
441
a61af66fc99e Initial load
duke
parents:
diff changeset
442 if( t1 == TypeF::ZERO && !g_isnan(t2->getf()) && t2->getf() != 0.0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
443 return TypeF::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
444
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // Otherwise we give up all hope
a61af66fc99e Initial load
duke
parents:
diff changeset
446 return Type::FLOAT;
a61af66fc99e Initial load
duke
parents:
diff changeset
447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
448
a61af66fc99e Initial load
duke
parents:
diff changeset
449 //------------------------------isA_Copy---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
450 // Dividing by self is 1.
a61af66fc99e Initial load
duke
parents:
diff changeset
451 // If the divisor is 1, we are an identity on the dividend.
a61af66fc99e Initial load
duke
parents:
diff changeset
452 Node *DivFNode::Identity( PhaseTransform *phase ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
453 return (phase->type( in(2) ) == TypeF::ONE) ? in(1) : this;
a61af66fc99e Initial load
duke
parents:
diff changeset
454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
455
a61af66fc99e Initial load
duke
parents:
diff changeset
456
a61af66fc99e Initial load
duke
parents:
diff changeset
457 //------------------------------Idealize---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
458 Node *DivFNode::Ideal(PhaseGVN *phase, bool can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 if (in(0) && remove_dead_region(phase, can_reshape)) return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
460
a61af66fc99e Initial load
duke
parents:
diff changeset
461 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
462 if( t2 == TypeF::ONE ) // Identity?
a61af66fc99e Initial load
duke
parents:
diff changeset
463 return NULL; // Skip it
a61af66fc99e Initial load
duke
parents:
diff changeset
464
a61af66fc99e Initial load
duke
parents:
diff changeset
465 const TypeF *tf = t2->isa_float_constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
466 if( !tf ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
467 if( tf->base() != Type::FloatCon ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
468
a61af66fc99e Initial load
duke
parents:
diff changeset
469 // Check for out of range values
a61af66fc99e Initial load
duke
parents:
diff changeset
470 if( tf->is_nan() || !tf->is_finite() ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
471
a61af66fc99e Initial load
duke
parents:
diff changeset
472 // Get the value
a61af66fc99e Initial load
duke
parents:
diff changeset
473 float f = tf->getf();
a61af66fc99e Initial load
duke
parents:
diff changeset
474 int exp;
a61af66fc99e Initial load
duke
parents:
diff changeset
475
a61af66fc99e Initial load
duke
parents:
diff changeset
476 // Only for special case of dividing by a power of 2
a61af66fc99e Initial load
duke
parents:
diff changeset
477 if( frexp((double)f, &exp) != 0.5 ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
478
a61af66fc99e Initial load
duke
parents:
diff changeset
479 // Limit the range of acceptable exponents
a61af66fc99e Initial load
duke
parents:
diff changeset
480 if( exp < -126 || exp > 126 ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
481
a61af66fc99e Initial load
duke
parents:
diff changeset
482 // Compute the reciprocal
a61af66fc99e Initial load
duke
parents:
diff changeset
483 float reciprocal = ((float)1.0) / f;
a61af66fc99e Initial load
duke
parents:
diff changeset
484
a61af66fc99e Initial load
duke
parents:
diff changeset
485 assert( frexp((double)reciprocal, &exp) == 0.5, "reciprocal should be power of 2" );
a61af66fc99e Initial load
duke
parents:
diff changeset
486
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // return multiplication by the reciprocal
a61af66fc99e Initial load
duke
parents:
diff changeset
488 return (new (phase->C, 3) MulFNode(in(1), phase->makecon(TypeF::make(reciprocal))));
a61af66fc99e Initial load
duke
parents:
diff changeset
489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
490
a61af66fc99e Initial load
duke
parents:
diff changeset
491 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
492 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // An DivDNode divides its inputs. The third input is a Control input, used to
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // prvent hoisting the divide above an unsafe test.
a61af66fc99e Initial load
duke
parents:
diff changeset
495 const Type *DivDNode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
496 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
497 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
498 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
499 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
500 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
501
a61af66fc99e Initial load
duke
parents:
diff changeset
502 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
503 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
504 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
505 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
506 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
507
a61af66fc99e Initial load
duke
parents:
diff changeset
508 // x/x == 1, we ignore 0/0.
a61af66fc99e Initial load
duke
parents:
diff changeset
509 // Note: if t1 and t2 are zero then result is NaN (JVMS page 213)
a61af66fc99e Initial load
duke
parents:
diff changeset
510 // Does not work for variables because of NaN's
a61af66fc99e Initial load
duke
parents:
diff changeset
511 if( phase->eqv( in(1), in(2) ) && t1->base() == Type::DoubleCon)
a61af66fc99e Initial load
duke
parents:
diff changeset
512 if (!g_isnan(t1->getd()) && g_isfinite(t1->getd()) && t1->getd() != 0.0) // could be negative ZERO or NaN
a61af66fc99e Initial load
duke
parents:
diff changeset
513 return TypeD::ONE;
a61af66fc99e Initial load
duke
parents:
diff changeset
514
a61af66fc99e Initial load
duke
parents:
diff changeset
515 if( t2 == TypeD::ONE )
a61af66fc99e Initial load
duke
parents:
diff changeset
516 return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
517
a61af66fc99e Initial load
duke
parents:
diff changeset
518 // If divisor is a constant and not zero, divide them numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
519 if( t1->base() == Type::DoubleCon &&
a61af66fc99e Initial load
duke
parents:
diff changeset
520 t2->base() == Type::DoubleCon &&
a61af66fc99e Initial load
duke
parents:
diff changeset
521 t2->getd() != 0.0 ) // could be negative zero
a61af66fc99e Initial load
duke
parents:
diff changeset
522 return TypeD::make( t1->getd()/t2->getd() );
a61af66fc99e Initial load
duke
parents:
diff changeset
523
a61af66fc99e Initial load
duke
parents:
diff changeset
524 // If the dividend is a constant zero
a61af66fc99e Initial load
duke
parents:
diff changeset
525 // Note: if t1 and t2 are zero then result is NaN (JVMS page 213)
a61af66fc99e Initial load
duke
parents:
diff changeset
526 // Test TypeF::ZERO is not sufficient as it could be negative zero
a61af66fc99e Initial load
duke
parents:
diff changeset
527 if( t1 == TypeD::ZERO && !g_isnan(t2->getd()) && t2->getd() != 0.0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
528 return TypeD::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
529
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // Otherwise we give up all hope
a61af66fc99e Initial load
duke
parents:
diff changeset
531 return Type::DOUBLE;
a61af66fc99e Initial load
duke
parents:
diff changeset
532 }
a61af66fc99e Initial load
duke
parents:
diff changeset
533
a61af66fc99e Initial load
duke
parents:
diff changeset
534
a61af66fc99e Initial load
duke
parents:
diff changeset
535 //------------------------------isA_Copy---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
536 // Dividing by self is 1.
a61af66fc99e Initial load
duke
parents:
diff changeset
537 // If the divisor is 1, we are an identity on the dividend.
a61af66fc99e Initial load
duke
parents:
diff changeset
538 Node *DivDNode::Identity( PhaseTransform *phase ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 return (phase->type( in(2) ) == TypeD::ONE) ? in(1) : this;
a61af66fc99e Initial load
duke
parents:
diff changeset
540 }
a61af66fc99e Initial load
duke
parents:
diff changeset
541
a61af66fc99e Initial load
duke
parents:
diff changeset
542 //------------------------------Idealize---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
543 Node *DivDNode::Ideal(PhaseGVN *phase, bool can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
544 if (in(0) && remove_dead_region(phase, can_reshape)) return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
545
a61af66fc99e Initial load
duke
parents:
diff changeset
546 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
547 if( t2 == TypeD::ONE ) // Identity?
a61af66fc99e Initial load
duke
parents:
diff changeset
548 return NULL; // Skip it
a61af66fc99e Initial load
duke
parents:
diff changeset
549
a61af66fc99e Initial load
duke
parents:
diff changeset
550 const TypeD *td = t2->isa_double_constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
551 if( !td ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
552 if( td->base() != Type::DoubleCon ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
553
a61af66fc99e Initial load
duke
parents:
diff changeset
554 // Check for out of range values
a61af66fc99e Initial load
duke
parents:
diff changeset
555 if( td->is_nan() || !td->is_finite() ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
556
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // Get the value
a61af66fc99e Initial load
duke
parents:
diff changeset
558 double d = td->getd();
a61af66fc99e Initial load
duke
parents:
diff changeset
559 int exp;
a61af66fc99e Initial load
duke
parents:
diff changeset
560
a61af66fc99e Initial load
duke
parents:
diff changeset
561 // Only for special case of dividing by a power of 2
a61af66fc99e Initial load
duke
parents:
diff changeset
562 if( frexp(d, &exp) != 0.5 ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
563
a61af66fc99e Initial load
duke
parents:
diff changeset
564 // Limit the range of acceptable exponents
a61af66fc99e Initial load
duke
parents:
diff changeset
565 if( exp < -1021 || exp > 1022 ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
566
a61af66fc99e Initial load
duke
parents:
diff changeset
567 // Compute the reciprocal
a61af66fc99e Initial load
duke
parents:
diff changeset
568 double reciprocal = 1.0 / d;
a61af66fc99e Initial load
duke
parents:
diff changeset
569
a61af66fc99e Initial load
duke
parents:
diff changeset
570 assert( frexp(reciprocal, &exp) == 0.5, "reciprocal should be power of 2" );
a61af66fc99e Initial load
duke
parents:
diff changeset
571
a61af66fc99e Initial load
duke
parents:
diff changeset
572 // return multiplication by the reciprocal
a61af66fc99e Initial load
duke
parents:
diff changeset
573 return (new (phase->C, 3) MulDNode(in(1), phase->makecon(TypeD::make(reciprocal))));
a61af66fc99e Initial load
duke
parents:
diff changeset
574 }
a61af66fc99e Initial load
duke
parents:
diff changeset
575
a61af66fc99e Initial load
duke
parents:
diff changeset
576 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
577 //------------------------------Idealize---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
578 Node *ModINode::Ideal(PhaseGVN *phase, bool can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
579 // Check for dead control input
a61af66fc99e Initial load
duke
parents:
diff changeset
580 if( remove_dead_region(phase, can_reshape) ) return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
581
a61af66fc99e Initial load
duke
parents:
diff changeset
582 // Get the modulus
a61af66fc99e Initial load
duke
parents:
diff changeset
583 const Type *t = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
584 if( t == Type::TOP ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
585 const TypeInt *ti = t->is_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
586
a61af66fc99e Initial load
duke
parents:
diff changeset
587 // Check for useless control input
a61af66fc99e Initial load
duke
parents:
diff changeset
588 // Check for excluding mod-zero case
a61af66fc99e Initial load
duke
parents:
diff changeset
589 if( in(0) && (ti->_hi < 0 || ti->_lo > 0) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
590 set_req(0, NULL); // Yank control input
a61af66fc99e Initial load
duke
parents:
diff changeset
591 return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
592 }
a61af66fc99e Initial load
duke
parents:
diff changeset
593
a61af66fc99e Initial load
duke
parents:
diff changeset
594 // See if we are MOD'ing by 2^k or 2^k-1.
a61af66fc99e Initial load
duke
parents:
diff changeset
595 if( !ti->is_con() ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
596 jint con = ti->get_con();
a61af66fc99e Initial load
duke
parents:
diff changeset
597
a61af66fc99e Initial load
duke
parents:
diff changeset
598 Node *hook = new (phase->C, 1) Node(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
599
a61af66fc99e Initial load
duke
parents:
diff changeset
600 // First, special check for modulo 2^k-1
a61af66fc99e Initial load
duke
parents:
diff changeset
601 if( con >= 0 && con < max_jint && is_power_of_2(con+1) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
602 uint k = exact_log2(con+1); // Extract k
a61af66fc99e Initial load
duke
parents:
diff changeset
603
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // Basic algorithm by David Detlefs. See fastmod_int.java for gory details.
a61af66fc99e Initial load
duke
parents:
diff changeset
605 static int unroll_factor[] = { 999, 999, 29, 14, 9, 7, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 1 /*past here we assume 1 forever*/};
a61af66fc99e Initial load
duke
parents:
diff changeset
606 int trip_count = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
607 if( k < ARRAY_SIZE(unroll_factor)) trip_count = unroll_factor[k];
a61af66fc99e Initial load
duke
parents:
diff changeset
608
a61af66fc99e Initial load
duke
parents:
diff changeset
609 // If the unroll factor is not too large, and if conditional moves are
a61af66fc99e Initial load
duke
parents:
diff changeset
610 // ok, then use this case
a61af66fc99e Initial load
duke
parents:
diff changeset
611 if( trip_count <= 5 && ConditionalMoveLimit != 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
612 Node *x = in(1); // Value being mod'd
a61af66fc99e Initial load
duke
parents:
diff changeset
613 Node *divisor = in(2); // Also is mask
a61af66fc99e Initial load
duke
parents:
diff changeset
614
a61af66fc99e Initial load
duke
parents:
diff changeset
615 hook->init_req(0, x); // Add a use to x to prevent him from dying
a61af66fc99e Initial load
duke
parents:
diff changeset
616 // Generate code to reduce X rapidly to nearly 2^k-1.
a61af66fc99e Initial load
duke
parents:
diff changeset
617 for( int i = 0; i < trip_count; i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
618 Node *xl = phase->transform( new (phase->C, 3) AndINode(x,divisor) );
a61af66fc99e Initial load
duke
parents:
diff changeset
619 Node *xh = phase->transform( new (phase->C, 3) RShiftINode(x,phase->intcon(k)) ); // Must be signed
a61af66fc99e Initial load
duke
parents:
diff changeset
620 x = phase->transform( new (phase->C, 3) AddINode(xh,xl) );
a61af66fc99e Initial load
duke
parents:
diff changeset
621 hook->set_req(0, x);
a61af66fc99e Initial load
duke
parents:
diff changeset
622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
623
a61af66fc99e Initial load
duke
parents:
diff changeset
624 // Generate sign-fixup code. Was original value positive?
a61af66fc99e Initial load
duke
parents:
diff changeset
625 // int hack_res = (i >= 0) ? divisor : 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
626 Node *cmp1 = phase->transform( new (phase->C, 3) CmpINode( in(1), phase->intcon(0) ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
627 Node *bol1 = phase->transform( new (phase->C, 2) BoolNode( cmp1, BoolTest::ge ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
628 Node *cmov1= phase->transform( new (phase->C, 4) CMoveINode(bol1, phase->intcon(1), divisor, TypeInt::POS) );
a61af66fc99e Initial load
duke
parents:
diff changeset
629 // if( x >= hack_res ) x -= divisor;
a61af66fc99e Initial load
duke
parents:
diff changeset
630 Node *sub = phase->transform( new (phase->C, 3) SubINode( x, divisor ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
631 Node *cmp2 = phase->transform( new (phase->C, 3) CmpINode( x, cmov1 ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
632 Node *bol2 = phase->transform( new (phase->C, 2) BoolNode( cmp2, BoolTest::ge ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
633 // Convention is to not transform the return value of an Ideal
a61af66fc99e Initial load
duke
parents:
diff changeset
634 // since Ideal is expected to return a modified 'this' or a new node.
a61af66fc99e Initial load
duke
parents:
diff changeset
635 Node *cmov2= new (phase->C, 4) CMoveINode(bol2, x, sub, TypeInt::INT);
a61af66fc99e Initial load
duke
parents:
diff changeset
636 // cmov2 is now the mod
a61af66fc99e Initial load
duke
parents:
diff changeset
637
a61af66fc99e Initial load
duke
parents:
diff changeset
638 // Now remove the bogus extra edges used to keep things alive
a61af66fc99e Initial load
duke
parents:
diff changeset
639 if (can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
640 phase->is_IterGVN()->remove_dead_node(hook);
a61af66fc99e Initial load
duke
parents:
diff changeset
641 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
642 hook->set_req(0, NULL); // Just yank bogus edge during Parse phase
a61af66fc99e Initial load
duke
parents:
diff changeset
643 }
a61af66fc99e Initial load
duke
parents:
diff changeset
644 return cmov2;
a61af66fc99e Initial load
duke
parents:
diff changeset
645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
647
a61af66fc99e Initial load
duke
parents:
diff changeset
648 // Fell thru, the unroll case is not appropriate. Transform the modulo
a61af66fc99e Initial load
duke
parents:
diff changeset
649 // into a long multiply/int multiply/subtract case
a61af66fc99e Initial load
duke
parents:
diff changeset
650
a61af66fc99e Initial load
duke
parents:
diff changeset
651 // Cannot handle mod 0, and min_jint isn't handled by the transform
a61af66fc99e Initial load
duke
parents:
diff changeset
652 if( con == 0 || con == min_jint ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
653
a61af66fc99e Initial load
duke
parents:
diff changeset
654 // Get the absolute value of the constant; at this point, we can use this
a61af66fc99e Initial load
duke
parents:
diff changeset
655 jint pos_con = (con >= 0) ? con : -con;
a61af66fc99e Initial load
duke
parents:
diff changeset
656
a61af66fc99e Initial load
duke
parents:
diff changeset
657 // integer Mod 1 is always 0
a61af66fc99e Initial load
duke
parents:
diff changeset
658 if( pos_con == 1 ) return new (phase->C, 1) ConINode(TypeInt::ZERO);
a61af66fc99e Initial load
duke
parents:
diff changeset
659
a61af66fc99e Initial load
duke
parents:
diff changeset
660 int log2_con = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
661
a61af66fc99e Initial load
duke
parents:
diff changeset
662 // If this is a power of two, they maybe we can mask it
a61af66fc99e Initial load
duke
parents:
diff changeset
663 if( is_power_of_2(pos_con) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
664 log2_con = log2_intptr((intptr_t)pos_con);
a61af66fc99e Initial load
duke
parents:
diff changeset
665
a61af66fc99e Initial load
duke
parents:
diff changeset
666 const Type *dt = phase->type(in(1));
a61af66fc99e Initial load
duke
parents:
diff changeset
667 const TypeInt *dti = dt->isa_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
668
a61af66fc99e Initial load
duke
parents:
diff changeset
669 // See if this can be masked, if the dividend is non-negative
a61af66fc99e Initial load
duke
parents:
diff changeset
670 if( dti && dti->_lo >= 0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
671 return ( new (phase->C, 3) AndINode( in(1), phase->intcon( pos_con-1 ) ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
672 }
a61af66fc99e Initial load
duke
parents:
diff changeset
673
a61af66fc99e Initial load
duke
parents:
diff changeset
674 // Save in(1) so that it cannot be changed or deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
675 hook->init_req(0, in(1));
a61af66fc99e Initial load
duke
parents:
diff changeset
676
a61af66fc99e Initial load
duke
parents:
diff changeset
677 // Divide using the transform from DivI to MulL
a61af66fc99e Initial load
duke
parents:
diff changeset
678 Node *divide = phase->transform( transform_int_divide_to_long_multiply( phase, in(1), pos_con ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
679
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // Re-multiply, using a shift if this is a power of two
a61af66fc99e Initial load
duke
parents:
diff changeset
681 Node *mult = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
682
a61af66fc99e Initial load
duke
parents:
diff changeset
683 if( log2_con >= 0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
684 mult = phase->transform( new (phase->C, 3) LShiftINode( divide, phase->intcon( log2_con ) ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
685 else
a61af66fc99e Initial load
duke
parents:
diff changeset
686 mult = phase->transform( new (phase->C, 3) MulINode( divide, phase->intcon( pos_con ) ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
687
a61af66fc99e Initial load
duke
parents:
diff changeset
688 // Finally, subtract the multiplied divided value from the original
a61af66fc99e Initial load
duke
parents:
diff changeset
689 Node *result = new (phase->C, 3) SubINode( in(1), mult );
a61af66fc99e Initial load
duke
parents:
diff changeset
690
a61af66fc99e Initial load
duke
parents:
diff changeset
691 // Now remove the bogus extra edges used to keep things alive
a61af66fc99e Initial load
duke
parents:
diff changeset
692 if (can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
693 phase->is_IterGVN()->remove_dead_node(hook);
a61af66fc99e Initial load
duke
parents:
diff changeset
694 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
695 hook->set_req(0, NULL); // Just yank bogus edge during Parse phase
a61af66fc99e Initial load
duke
parents:
diff changeset
696 }
a61af66fc99e Initial load
duke
parents:
diff changeset
697
a61af66fc99e Initial load
duke
parents:
diff changeset
698 // return the value
a61af66fc99e Initial load
duke
parents:
diff changeset
699 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
700 }
a61af66fc99e Initial load
duke
parents:
diff changeset
701
a61af66fc99e Initial load
duke
parents:
diff changeset
702 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
703 const Type *ModINode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
704 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
705 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
706 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
707 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
708 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
709
a61af66fc99e Initial load
duke
parents:
diff changeset
710 // We always generate the dynamic check for 0.
a61af66fc99e Initial load
duke
parents:
diff changeset
711 // 0 MOD X is 0
a61af66fc99e Initial load
duke
parents:
diff changeset
712 if( t1 == TypeInt::ZERO ) return TypeInt::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
713 // X MOD X is 0
a61af66fc99e Initial load
duke
parents:
diff changeset
714 if( phase->eqv( in(1), in(2) ) ) return TypeInt::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
715
a61af66fc99e Initial load
duke
parents:
diff changeset
716 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
717 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
718 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
719 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
720 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
721
a61af66fc99e Initial load
duke
parents:
diff changeset
722 const TypeInt *i1 = t1->is_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
723 const TypeInt *i2 = t2->is_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
724 if( !i1->is_con() || !i2->is_con() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
725 if( i1->_lo >= 0 && i2->_lo >= 0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
726 return TypeInt::POS;
a61af66fc99e Initial load
duke
parents:
diff changeset
727 // If both numbers are not constants, we know little.
a61af66fc99e Initial load
duke
parents:
diff changeset
728 return TypeInt::INT;
a61af66fc99e Initial load
duke
parents:
diff changeset
729 }
a61af66fc99e Initial load
duke
parents:
diff changeset
730 // Mod by zero? Throw exception at runtime!
a61af66fc99e Initial load
duke
parents:
diff changeset
731 if( !i2->get_con() ) return TypeInt::POS;
a61af66fc99e Initial load
duke
parents:
diff changeset
732
a61af66fc99e Initial load
duke
parents:
diff changeset
733 // We must be modulo'ing 2 float constants.
a61af66fc99e Initial load
duke
parents:
diff changeset
734 // Check for min_jint % '-1', result is defined to be '0'.
a61af66fc99e Initial load
duke
parents:
diff changeset
735 if( i1->get_con() == min_jint && i2->get_con() == -1 )
a61af66fc99e Initial load
duke
parents:
diff changeset
736 return TypeInt::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
737
a61af66fc99e Initial load
duke
parents:
diff changeset
738 return TypeInt::make( i1->get_con() % i2->get_con() );
a61af66fc99e Initial load
duke
parents:
diff changeset
739 }
a61af66fc99e Initial load
duke
parents:
diff changeset
740
a61af66fc99e Initial load
duke
parents:
diff changeset
741
a61af66fc99e Initial load
duke
parents:
diff changeset
742 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
743 //------------------------------Idealize---------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
744 Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
745 // Check for dead control input
a61af66fc99e Initial load
duke
parents:
diff changeset
746 if( remove_dead_region(phase, can_reshape) ) return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
747
a61af66fc99e Initial load
duke
parents:
diff changeset
748 // Get the modulus
a61af66fc99e Initial load
duke
parents:
diff changeset
749 const Type *t = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
750 if( t == Type::TOP ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
751 const TypeLong *ti = t->is_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
752
a61af66fc99e Initial load
duke
parents:
diff changeset
753 // Check for useless control input
a61af66fc99e Initial load
duke
parents:
diff changeset
754 // Check for excluding mod-zero case
a61af66fc99e Initial load
duke
parents:
diff changeset
755 if( in(0) && (ti->_hi < 0 || ti->_lo > 0) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
756 set_req(0, NULL); // Yank control input
a61af66fc99e Initial load
duke
parents:
diff changeset
757 return this;
a61af66fc99e Initial load
duke
parents:
diff changeset
758 }
a61af66fc99e Initial load
duke
parents:
diff changeset
759
a61af66fc99e Initial load
duke
parents:
diff changeset
760 // See if we are MOD'ing by 2^k or 2^k-1.
a61af66fc99e Initial load
duke
parents:
diff changeset
761 if( !ti->is_con() ) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
762 jlong con = ti->get_con();
a61af66fc99e Initial load
duke
parents:
diff changeset
763 bool m1 = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
764 if( !is_power_of_2_long(con) ) { // Not 2^k
a61af66fc99e Initial load
duke
parents:
diff changeset
765 if( !is_power_of_2_long(con+1) ) // Not 2^k-1?
a61af66fc99e Initial load
duke
parents:
diff changeset
766 return NULL; // No interesting mod hacks
a61af66fc99e Initial load
duke
parents:
diff changeset
767 m1 = true; // Found 2^k-1
a61af66fc99e Initial load
duke
parents:
diff changeset
768 con++; // Convert to 2^k form
a61af66fc99e Initial load
duke
parents:
diff changeset
769 }
a61af66fc99e Initial load
duke
parents:
diff changeset
770 uint k = log2_long(con); // Extract k
a61af66fc99e Initial load
duke
parents:
diff changeset
771
a61af66fc99e Initial load
duke
parents:
diff changeset
772 // Expand mod
a61af66fc99e Initial load
duke
parents:
diff changeset
773 if( !m1 ) { // Case 2^k
a61af66fc99e Initial load
duke
parents:
diff changeset
774 } else { // Case 2^k-1
a61af66fc99e Initial load
duke
parents:
diff changeset
775 // Basic algorithm by David Detlefs. See fastmod_long.java for gory details.
a61af66fc99e Initial load
duke
parents:
diff changeset
776 // Used to help a popular random number generator which does a long-mod
a61af66fc99e Initial load
duke
parents:
diff changeset
777 // of 2^31-1 and shows up in SpecJBB and SciMark.
a61af66fc99e Initial load
duke
parents:
diff changeset
778 static int unroll_factor[] = { 999, 999, 61, 30, 20, 15, 12, 10, 8, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 /*past here we assume 1 forever*/};
a61af66fc99e Initial load
duke
parents:
diff changeset
779 int trip_count = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
780 if( k < ARRAY_SIZE(unroll_factor)) trip_count = unroll_factor[k];
a61af66fc99e Initial load
duke
parents:
diff changeset
781 if( trip_count > 4 ) return NULL; // Too much unrolling
a61af66fc99e Initial load
duke
parents:
diff changeset
782 if (ConditionalMoveLimit == 0) return NULL; // cmov is required
a61af66fc99e Initial load
duke
parents:
diff changeset
783
a61af66fc99e Initial load
duke
parents:
diff changeset
784 Node *x = in(1); // Value being mod'd
a61af66fc99e Initial load
duke
parents:
diff changeset
785 Node *divisor = in(2); // Also is mask
a61af66fc99e Initial load
duke
parents:
diff changeset
786
a61af66fc99e Initial load
duke
parents:
diff changeset
787 Node *hook = new (phase->C, 1) Node(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
788 // Generate code to reduce X rapidly to nearly 2^k-1.
a61af66fc99e Initial load
duke
parents:
diff changeset
789 for( int i = 0; i < trip_count; i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
790 Node *xl = phase->transform( new (phase->C, 3) AndLNode(x,divisor) );
a61af66fc99e Initial load
duke
parents:
diff changeset
791 Node *xh = phase->transform( new (phase->C, 3) RShiftLNode(x,phase->intcon(k)) ); // Must be signed
a61af66fc99e Initial load
duke
parents:
diff changeset
792 x = phase->transform( new (phase->C, 3) AddLNode(xh,xl) );
a61af66fc99e Initial load
duke
parents:
diff changeset
793 hook->set_req(0, x); // Add a use to x to prevent him from dying
a61af66fc99e Initial load
duke
parents:
diff changeset
794 }
a61af66fc99e Initial load
duke
parents:
diff changeset
795 // Generate sign-fixup code. Was original value positive?
a61af66fc99e Initial load
duke
parents:
diff changeset
796 // long hack_res = (i >= 0) ? divisor : CONST64(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
797 Node *cmp1 = phase->transform( new (phase->C, 3) CmpLNode( in(1), phase->longcon(0) ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
798 Node *bol1 = phase->transform( new (phase->C, 2) BoolNode( cmp1, BoolTest::ge ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
799 Node *cmov1= phase->transform( new (phase->C, 4) CMoveLNode(bol1, phase->longcon(1), divisor, TypeLong::LONG) );
a61af66fc99e Initial load
duke
parents:
diff changeset
800 // if( x >= hack_res ) x -= divisor;
a61af66fc99e Initial load
duke
parents:
diff changeset
801 Node *sub = phase->transform( new (phase->C, 3) SubLNode( x, divisor ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
802 Node *cmp2 = phase->transform( new (phase->C, 3) CmpLNode( x, cmov1 ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
803 Node *bol2 = phase->transform( new (phase->C, 2) BoolNode( cmp2, BoolTest::ge ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
804 // Convention is to not transform the return value of an Ideal
a61af66fc99e Initial load
duke
parents:
diff changeset
805 // since Ideal is expected to return a modified 'this' or a new node.
a61af66fc99e Initial load
duke
parents:
diff changeset
806 Node *cmov2= new (phase->C, 4) CMoveLNode(bol2, x, sub, TypeLong::LONG);
a61af66fc99e Initial load
duke
parents:
diff changeset
807 // cmov2 is now the mod
a61af66fc99e Initial load
duke
parents:
diff changeset
808
a61af66fc99e Initial load
duke
parents:
diff changeset
809 // Now remove the bogus extra edges used to keep things alive
a61af66fc99e Initial load
duke
parents:
diff changeset
810 if (can_reshape) {
a61af66fc99e Initial load
duke
parents:
diff changeset
811 phase->is_IterGVN()->remove_dead_node(hook);
a61af66fc99e Initial load
duke
parents:
diff changeset
812 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
813 hook->set_req(0, NULL); // Just yank bogus edge during Parse phase
a61af66fc99e Initial load
duke
parents:
diff changeset
814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
815 return cmov2;
a61af66fc99e Initial load
duke
parents:
diff changeset
816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
817 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
819
a61af66fc99e Initial load
duke
parents:
diff changeset
820 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
821 const Type *ModLNode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
822 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
823 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
824 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
825 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
826 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
827
a61af66fc99e Initial load
duke
parents:
diff changeset
828 // We always generate the dynamic check for 0.
a61af66fc99e Initial load
duke
parents:
diff changeset
829 // 0 MOD X is 0
a61af66fc99e Initial load
duke
parents:
diff changeset
830 if( t1 == TypeLong::ZERO ) return TypeLong::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
831 // X MOD X is 0
a61af66fc99e Initial load
duke
parents:
diff changeset
832 if( phase->eqv( in(1), in(2) ) ) return TypeLong::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
833
a61af66fc99e Initial load
duke
parents:
diff changeset
834 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
835 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
836 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
837 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
838 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
839
a61af66fc99e Initial load
duke
parents:
diff changeset
840 const TypeLong *i1 = t1->is_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
841 const TypeLong *i2 = t2->is_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
842 if( !i1->is_con() || !i2->is_con() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
843 if( i1->_lo >= CONST64(0) && i2->_lo >= CONST64(0) )
a61af66fc99e Initial load
duke
parents:
diff changeset
844 return TypeLong::POS;
a61af66fc99e Initial load
duke
parents:
diff changeset
845 // If both numbers are not constants, we know little.
a61af66fc99e Initial load
duke
parents:
diff changeset
846 return TypeLong::LONG;
a61af66fc99e Initial load
duke
parents:
diff changeset
847 }
a61af66fc99e Initial load
duke
parents:
diff changeset
848 // Mod by zero? Throw exception at runtime!
a61af66fc99e Initial load
duke
parents:
diff changeset
849 if( !i2->get_con() ) return TypeLong::POS;
a61af66fc99e Initial load
duke
parents:
diff changeset
850
a61af66fc99e Initial load
duke
parents:
diff changeset
851 // We must be modulo'ing 2 float constants.
a61af66fc99e Initial load
duke
parents:
diff changeset
852 // Check for min_jint % '-1', result is defined to be '0'.
a61af66fc99e Initial load
duke
parents:
diff changeset
853 if( i1->get_con() == min_jlong && i2->get_con() == -1 )
a61af66fc99e Initial load
duke
parents:
diff changeset
854 return TypeLong::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
855
a61af66fc99e Initial load
duke
parents:
diff changeset
856 return TypeLong::make( i1->get_con() % i2->get_con() );
a61af66fc99e Initial load
duke
parents:
diff changeset
857 }
a61af66fc99e Initial load
duke
parents:
diff changeset
858
a61af66fc99e Initial load
duke
parents:
diff changeset
859
a61af66fc99e Initial load
duke
parents:
diff changeset
860 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
861 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
862 const Type *ModFNode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
863 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
864 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
865 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
866 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
867 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
868
a61af66fc99e Initial load
duke
parents:
diff changeset
869 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
870 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
871 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
872 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
873 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
874
a61af66fc99e Initial load
duke
parents:
diff changeset
875 // If either is a NaN, return an input NaN
a61af66fc99e Initial load
duke
parents:
diff changeset
876 if( g_isnan(t1->getf()) ) return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
877 if( g_isnan(t2->getf()) ) return t2;
a61af66fc99e Initial load
duke
parents:
diff changeset
878
a61af66fc99e Initial load
duke
parents:
diff changeset
879 // It is not worth trying to constant fold this stuff!
a61af66fc99e Initial load
duke
parents:
diff changeset
880 return Type::FLOAT;
a61af66fc99e Initial load
duke
parents:
diff changeset
881
a61af66fc99e Initial load
duke
parents:
diff changeset
882 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
883 // If dividend is infinity or divisor is zero, or both, the result is NaN
a61af66fc99e Initial load
duke
parents:
diff changeset
884 if( !g_isfinite(t1->getf()) || ((t2->getf() == 0.0) || (jint_cast(t2->getf()) == 0x80000000)) )
a61af66fc99e Initial load
duke
parents:
diff changeset
885
a61af66fc99e Initial load
duke
parents:
diff changeset
886 // X MOD infinity = X
a61af66fc99e Initial load
duke
parents:
diff changeset
887 if( !g_isfinite(t2->getf()) && !g_isnan(t2->getf()) ) return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
888 // 0 MOD finite = dividend (positive or negative zero)
a61af66fc99e Initial load
duke
parents:
diff changeset
889 // Not valid for: NaN MOD any; any MOD nan; 0 MOD 0; or for 0 MOD NaN
a61af66fc99e Initial load
duke
parents:
diff changeset
890 // NaNs are handled previously.
a61af66fc99e Initial load
duke
parents:
diff changeset
891 if( !(t2->getf() == 0.0) && !((int)t2->getf() == 0x80000000)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
892 if (((t1->getf() == 0.0) || ((int)t1->getf() == 0x80000000)) && g_isfinite(t2->getf()) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
893 return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
894 }
a61af66fc99e Initial load
duke
parents:
diff changeset
895 }
a61af66fc99e Initial load
duke
parents:
diff changeset
896 // X MOD X is 0
a61af66fc99e Initial load
duke
parents:
diff changeset
897 // Does not work for variables because of NaN's
a61af66fc99e Initial load
duke
parents:
diff changeset
898 if( phase->eqv( in(1), in(2) ) && t1->base() == Type::FloatCon)
a61af66fc99e Initial load
duke
parents:
diff changeset
899 if (!g_isnan(t1->getf()) && (t1->getf() != 0.0) && ((int)t1->getf() != 0x80000000)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
900 if(t1->getf() < 0.0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
901 float result = jfloat_cast(0x80000000);
a61af66fc99e Initial load
duke
parents:
diff changeset
902 return TypeF::make( result );
a61af66fc99e Initial load
duke
parents:
diff changeset
903 }
a61af66fc99e Initial load
duke
parents:
diff changeset
904 else
a61af66fc99e Initial load
duke
parents:
diff changeset
905 return TypeF::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
907
a61af66fc99e Initial load
duke
parents:
diff changeset
908 // If both numbers are not constants, we know nothing.
a61af66fc99e Initial load
duke
parents:
diff changeset
909 if( (t1->base() != Type::FloatCon) || (t2->base() != Type::FloatCon) )
a61af66fc99e Initial load
duke
parents:
diff changeset
910 return Type::FLOAT;
a61af66fc99e Initial load
duke
parents:
diff changeset
911
a61af66fc99e Initial load
duke
parents:
diff changeset
912 // We must be modulo'ing 2 float constants.
a61af66fc99e Initial load
duke
parents:
diff changeset
913 // Make sure that the sign of the fmod is equal to the sign of the dividend
a61af66fc99e Initial load
duke
parents:
diff changeset
914 float result = (float)fmod( t1->getf(), t2->getf() );
a61af66fc99e Initial load
duke
parents:
diff changeset
915 float dividend = t1->getf();
a61af66fc99e Initial load
duke
parents:
diff changeset
916 if( (dividend < 0.0) || ((int)dividend == 0x80000000) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
917 if( result > 0.0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
918 result = 0.0 - result;
a61af66fc99e Initial load
duke
parents:
diff changeset
919 else if( result == 0.0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
920 result = jfloat_cast(0x80000000);
a61af66fc99e Initial load
duke
parents:
diff changeset
921 }
a61af66fc99e Initial load
duke
parents:
diff changeset
922 }
a61af66fc99e Initial load
duke
parents:
diff changeset
923 return TypeF::make( result );
a61af66fc99e Initial load
duke
parents:
diff changeset
924 */
a61af66fc99e Initial load
duke
parents:
diff changeset
925 }
a61af66fc99e Initial load
duke
parents:
diff changeset
926
a61af66fc99e Initial load
duke
parents:
diff changeset
927
a61af66fc99e Initial load
duke
parents:
diff changeset
928 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
929 //------------------------------Value------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
930 const Type *ModDNode::Value( PhaseTransform *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
931 // Either input is TOP ==> the result is TOP
a61af66fc99e Initial load
duke
parents:
diff changeset
932 const Type *t1 = phase->type( in(1) );
a61af66fc99e Initial load
duke
parents:
diff changeset
933 const Type *t2 = phase->type( in(2) );
a61af66fc99e Initial load
duke
parents:
diff changeset
934 if( t1 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
935 if( t2 == Type::TOP ) return Type::TOP;
a61af66fc99e Initial load
duke
parents:
diff changeset
936
a61af66fc99e Initial load
duke
parents:
diff changeset
937 // Either input is BOTTOM ==> the result is the local BOTTOM
a61af66fc99e Initial load
duke
parents:
diff changeset
938 const Type *bot = bottom_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
939 if( (t1 == bot) || (t2 == bot) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
940 (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
a61af66fc99e Initial load
duke
parents:
diff changeset
941 return bot;
a61af66fc99e Initial load
duke
parents:
diff changeset
942
a61af66fc99e Initial load
duke
parents:
diff changeset
943 // If either is a NaN, return an input NaN
a61af66fc99e Initial load
duke
parents:
diff changeset
944 if( g_isnan(t1->getd()) ) return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
945 if( g_isnan(t2->getd()) ) return t2;
a61af66fc99e Initial load
duke
parents:
diff changeset
946 // X MOD infinity = X
a61af66fc99e Initial load
duke
parents:
diff changeset
947 if( !g_isfinite(t2->getd())) return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
948 // 0 MOD finite = dividend (positive or negative zero)
a61af66fc99e Initial load
duke
parents:
diff changeset
949 // Not valid for: NaN MOD any; any MOD nan; 0 MOD 0; or for 0 MOD NaN
a61af66fc99e Initial load
duke
parents:
diff changeset
950 // NaNs are handled previously.
a61af66fc99e Initial load
duke
parents:
diff changeset
951 if( !(t2->getd() == 0.0) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
952 if( t1->getd() == 0.0 && g_isfinite(t2->getd()) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
953 return t1;
a61af66fc99e Initial load
duke
parents:
diff changeset
954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
955 }
a61af66fc99e Initial load
duke
parents:
diff changeset
956
a61af66fc99e Initial load
duke
parents:
diff changeset
957 // X MOD X is 0
a61af66fc99e Initial load
duke
parents:
diff changeset
958 // does not work for variables because of NaN's
a61af66fc99e Initial load
duke
parents:
diff changeset
959 if( phase->eqv( in(1), in(2) ) && t1->base() == Type::DoubleCon )
a61af66fc99e Initial load
duke
parents:
diff changeset
960 if (!g_isnan(t1->getd()) && t1->getd() != 0.0)
a61af66fc99e Initial load
duke
parents:
diff changeset
961 return TypeD::ZERO;
a61af66fc99e Initial load
duke
parents:
diff changeset
962
a61af66fc99e Initial load
duke
parents:
diff changeset
963
a61af66fc99e Initial load
duke
parents:
diff changeset
964 // If both numbers are not constants, we know nothing.
a61af66fc99e Initial load
duke
parents:
diff changeset
965 if( (t1->base() != Type::DoubleCon) || (t2->base() != Type::DoubleCon) )
a61af66fc99e Initial load
duke
parents:
diff changeset
966 return Type::DOUBLE;
a61af66fc99e Initial load
duke
parents:
diff changeset
967
a61af66fc99e Initial load
duke
parents:
diff changeset
968 // We must be modulo'ing 2 double constants.
a61af66fc99e Initial load
duke
parents:
diff changeset
969 return TypeD::make( fmod( t1->getd(), t2->getd() ) );
a61af66fc99e Initial load
duke
parents:
diff changeset
970 }
a61af66fc99e Initial load
duke
parents:
diff changeset
971
a61af66fc99e Initial load
duke
parents:
diff changeset
972 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
973
a61af66fc99e Initial load
duke
parents:
diff changeset
974 DivModNode::DivModNode( Node *c, Node *dividend, Node *divisor ) : MultiNode(3) {
a61af66fc99e Initial load
duke
parents:
diff changeset
975 init_req(0, c);
a61af66fc99e Initial load
duke
parents:
diff changeset
976 init_req(1, dividend);
a61af66fc99e Initial load
duke
parents:
diff changeset
977 init_req(2, divisor);
a61af66fc99e Initial load
duke
parents:
diff changeset
978 }
a61af66fc99e Initial load
duke
parents:
diff changeset
979
a61af66fc99e Initial load
duke
parents:
diff changeset
980 //------------------------------make------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
981 DivModINode* DivModINode::make(Compile* C, Node* div_or_mod) {
a61af66fc99e Initial load
duke
parents:
diff changeset
982 Node* n = div_or_mod;
a61af66fc99e Initial load
duke
parents:
diff changeset
983 assert(n->Opcode() == Op_DivI || n->Opcode() == Op_ModI,
a61af66fc99e Initial load
duke
parents:
diff changeset
984 "only div or mod input pattern accepted");
a61af66fc99e Initial load
duke
parents:
diff changeset
985
a61af66fc99e Initial load
duke
parents:
diff changeset
986 DivModINode* divmod = new (C, 3) DivModINode(n->in(0), n->in(1), n->in(2));
a61af66fc99e Initial load
duke
parents:
diff changeset
987 Node* dproj = new (C, 1) ProjNode(divmod, DivModNode::div_proj_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
988 Node* mproj = new (C, 1) ProjNode(divmod, DivModNode::mod_proj_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
989 return divmod;
a61af66fc99e Initial load
duke
parents:
diff changeset
990 }
a61af66fc99e Initial load
duke
parents:
diff changeset
991
a61af66fc99e Initial load
duke
parents:
diff changeset
992 //------------------------------make------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
993 DivModLNode* DivModLNode::make(Compile* C, Node* div_or_mod) {
a61af66fc99e Initial load
duke
parents:
diff changeset
994 Node* n = div_or_mod;
a61af66fc99e Initial load
duke
parents:
diff changeset
995 assert(n->Opcode() == Op_DivL || n->Opcode() == Op_ModL,
a61af66fc99e Initial load
duke
parents:
diff changeset
996 "only div or mod input pattern accepted");
a61af66fc99e Initial load
duke
parents:
diff changeset
997
a61af66fc99e Initial load
duke
parents:
diff changeset
998 DivModLNode* divmod = new (C, 3) DivModLNode(n->in(0), n->in(1), n->in(2));
a61af66fc99e Initial load
duke
parents:
diff changeset
999 Node* dproj = new (C, 1) ProjNode(divmod, DivModNode::div_proj_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 Node* mproj = new (C, 1) ProjNode(divmod, DivModNode::mod_proj_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 return divmod;
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1003
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 //------------------------------match------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1005 // return result(s) along with their RegMask info
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 Node *DivModINode::match( const ProjNode *proj, const Matcher *match ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 uint ideal_reg = proj->ideal_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 RegMask rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 if (proj->_con == div_proj_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 rm = match->divI_proj_mask();
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 assert(proj->_con == mod_proj_num, "must be div or mod projection");
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 rm = match->modI_proj_mask();
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 return new (match->C, 1)MachProjNode(this, proj->_con, rm, ideal_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1017
a61af66fc99e Initial load
duke
parents:
diff changeset
1018
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 //------------------------------match------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 // return result(s) along with their RegMask info
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 Node *DivModLNode::match( const ProjNode *proj, const Matcher *match ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 uint ideal_reg = proj->ideal_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 RegMask rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1024 if (proj->_con == div_proj_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 rm = match->divL_proj_mask();
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 assert(proj->_con == mod_proj_num, "must be div or mod projection");
a61af66fc99e Initial load
duke
parents:
diff changeset
1028 rm = match->modL_proj_mask();
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 return new (match->C, 1)MachProjNode(this, proj->_con, rm, ideal_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 }