Mon, 25 May 2020 14:24:27 +0800
8244407: JVM crashes after transformation in C2 IdealLoopTree::split_fall_in
Reviewed-by: thartmann, kvn, andrew
Contributed-by: zhouyong44@huawei.com
duke@435 | 1 | /* |
mikael@6198 | 2 | * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #ifndef SHARE_VM_OPTO_SUBNODE_HPP |
stefank@2314 | 26 | #define SHARE_VM_OPTO_SUBNODE_HPP |
stefank@2314 | 27 | |
stefank@2314 | 28 | #include "opto/node.hpp" |
stefank@2314 | 29 | #include "opto/opcodes.hpp" |
stefank@2314 | 30 | #include "opto/type.hpp" |
stefank@2314 | 31 | |
duke@435 | 32 | // Portions of code courtesy of Clifford Click |
duke@435 | 33 | |
duke@435 | 34 | //------------------------------SUBNode---------------------------------------- |
duke@435 | 35 | // Class SUBTRACTION functionality. This covers all the usual 'subtract' |
duke@435 | 36 | // behaviors. Subtract-integer, -float, -double, binary xor, compare-integer, |
duke@435 | 37 | // -float, and -double are all inherited from this class. The compare |
duke@435 | 38 | // functions behave like subtract functions, except that all negative answers |
duke@435 | 39 | // are compressed into -1, and all positive answers compressed to 1. |
duke@435 | 40 | class SubNode : public Node { |
duke@435 | 41 | public: |
duke@435 | 42 | SubNode( Node *in1, Node *in2 ) : Node(0,in1,in2) { |
duke@435 | 43 | init_class_id(Class_Sub); |
duke@435 | 44 | } |
duke@435 | 45 | |
duke@435 | 46 | // Handle algebraic identities here. If we have an identity, return the Node |
duke@435 | 47 | // we are equivalent to. We look for "add of zero" as an identity. |
duke@435 | 48 | virtual Node *Identity( PhaseTransform *phase ); |
duke@435 | 49 | |
duke@435 | 50 | // Compute a new Type for this node. Basically we just do the pre-check, |
duke@435 | 51 | // then call the virtual add() to set the type. |
duke@435 | 52 | virtual const Type *Value( PhaseTransform *phase ) const; |
kvn@6679 | 53 | const Type* Value_common( PhaseTransform *phase ) const; |
duke@435 | 54 | |
duke@435 | 55 | // Supplied function returns the subtractend of the inputs. |
duke@435 | 56 | // This also type-checks the inputs for sanity. Guaranteed never to |
duke@435 | 57 | // be passed a TOP or BOTTOM type, these are filtered out by a pre-check. |
duke@435 | 58 | virtual const Type *sub( const Type *, const Type * ) const = 0; |
duke@435 | 59 | |
duke@435 | 60 | // Supplied function to return the additive identity type. |
duke@435 | 61 | // This is returned whenever the subtracts inputs are the same. |
duke@435 | 62 | virtual const Type *add_id() const = 0; |
duke@435 | 63 | |
duke@435 | 64 | }; |
duke@435 | 65 | |
duke@435 | 66 | |
duke@435 | 67 | // NOTE: SubINode should be taken away and replaced by add and negate |
duke@435 | 68 | //------------------------------SubINode--------------------------------------- |
duke@435 | 69 | // Subtract 2 integers |
duke@435 | 70 | class SubINode : public SubNode { |
duke@435 | 71 | public: |
duke@435 | 72 | SubINode( Node *in1, Node *in2 ) : SubNode(in1,in2) {} |
duke@435 | 73 | virtual int Opcode() const; |
duke@435 | 74 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 75 | virtual const Type *sub( const Type *, const Type * ) const; |
duke@435 | 76 | const Type *add_id() const { return TypeInt::ZERO; } |
duke@435 | 77 | const Type *bottom_type() const { return TypeInt::INT; } |
duke@435 | 78 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 79 | }; |
duke@435 | 80 | |
duke@435 | 81 | //------------------------------SubLNode--------------------------------------- |
duke@435 | 82 | // Subtract 2 integers |
duke@435 | 83 | class SubLNode : public SubNode { |
duke@435 | 84 | public: |
duke@435 | 85 | SubLNode( Node *in1, Node *in2 ) : SubNode(in1,in2) {} |
duke@435 | 86 | virtual int Opcode() const; |
duke@435 | 87 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 88 | virtual const Type *sub( const Type *, const Type * ) const; |
duke@435 | 89 | const Type *add_id() const { return TypeLong::ZERO; } |
duke@435 | 90 | const Type *bottom_type() const { return TypeLong::LONG; } |
duke@435 | 91 | virtual uint ideal_reg() const { return Op_RegL; } |
duke@435 | 92 | }; |
duke@435 | 93 | |
duke@435 | 94 | // NOTE: SubFPNode should be taken away and replaced by add and negate |
duke@435 | 95 | //------------------------------SubFPNode-------------------------------------- |
duke@435 | 96 | // Subtract 2 floats or doubles |
duke@435 | 97 | class SubFPNode : public SubNode { |
duke@435 | 98 | protected: |
duke@435 | 99 | SubFPNode( Node *in1, Node *in2 ) : SubNode(in1,in2) {} |
duke@435 | 100 | public: |
duke@435 | 101 | const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 102 | }; |
duke@435 | 103 | |
duke@435 | 104 | // NOTE: SubFNode should be taken away and replaced by add and negate |
duke@435 | 105 | //------------------------------SubFNode--------------------------------------- |
duke@435 | 106 | // Subtract 2 doubles |
duke@435 | 107 | class SubFNode : public SubFPNode { |
duke@435 | 108 | public: |
duke@435 | 109 | SubFNode( Node *in1, Node *in2 ) : SubFPNode(in1,in2) {} |
duke@435 | 110 | virtual int Opcode() const; |
duke@435 | 111 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 112 | virtual const Type *sub( const Type *, const Type * ) const; |
duke@435 | 113 | const Type *add_id() const { return TypeF::ZERO; } |
duke@435 | 114 | const Type *bottom_type() const { return Type::FLOAT; } |
duke@435 | 115 | virtual uint ideal_reg() const { return Op_RegF; } |
duke@435 | 116 | }; |
duke@435 | 117 | |
duke@435 | 118 | // NOTE: SubDNode should be taken away and replaced by add and negate |
duke@435 | 119 | //------------------------------SubDNode--------------------------------------- |
duke@435 | 120 | // Subtract 2 doubles |
duke@435 | 121 | class SubDNode : public SubFPNode { |
duke@435 | 122 | public: |
duke@435 | 123 | SubDNode( Node *in1, Node *in2 ) : SubFPNode(in1,in2) {} |
duke@435 | 124 | virtual int Opcode() const; |
duke@435 | 125 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 126 | virtual const Type *sub( const Type *, const Type * ) const; |
duke@435 | 127 | const Type *add_id() const { return TypeD::ZERO; } |
duke@435 | 128 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 129 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 130 | }; |
duke@435 | 131 | |
duke@435 | 132 | //------------------------------CmpNode--------------------------------------- |
duke@435 | 133 | // Compare 2 values, returning condition codes (-1, 0 or 1). |
duke@435 | 134 | class CmpNode : public SubNode { |
duke@435 | 135 | public: |
duke@435 | 136 | CmpNode( Node *in1, Node *in2 ) : SubNode(in1,in2) { |
duke@435 | 137 | init_class_id(Class_Cmp); |
duke@435 | 138 | } |
duke@435 | 139 | virtual Node *Identity( PhaseTransform *phase ); |
duke@435 | 140 | const Type *add_id() const { return TypeInt::ZERO; } |
duke@435 | 141 | const Type *bottom_type() const { return TypeInt::CC; } |
duke@435 | 142 | virtual uint ideal_reg() const { return Op_RegFlags; } |
duke@435 | 143 | }; |
duke@435 | 144 | |
duke@435 | 145 | //------------------------------CmpINode--------------------------------------- |
duke@435 | 146 | // Compare 2 signed values, returning condition codes (-1, 0 or 1). |
duke@435 | 147 | class CmpINode : public CmpNode { |
duke@435 | 148 | public: |
duke@435 | 149 | CmpINode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} |
duke@435 | 150 | virtual int Opcode() const; |
duke@435 | 151 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 152 | virtual const Type *sub( const Type *, const Type * ) const; |
duke@435 | 153 | }; |
duke@435 | 154 | |
duke@435 | 155 | //------------------------------CmpUNode--------------------------------------- |
duke@435 | 156 | // Compare 2 unsigned values (integer or pointer), returning condition codes (-1, 0 or 1). |
duke@435 | 157 | class CmpUNode : public CmpNode { |
duke@435 | 158 | public: |
duke@435 | 159 | CmpUNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} |
duke@435 | 160 | virtual int Opcode() const; |
duke@435 | 161 | virtual const Type *sub( const Type *, const Type * ) const; |
kvn@6679 | 162 | const Type *Value( PhaseTransform *phase ) const; |
kvn@3910 | 163 | bool is_index_range_check() const; |
duke@435 | 164 | }; |
duke@435 | 165 | |
duke@435 | 166 | //------------------------------CmpPNode--------------------------------------- |
duke@435 | 167 | // Compare 2 pointer values, returning condition codes (-1, 0 or 1). |
duke@435 | 168 | class CmpPNode : public CmpNode { |
duke@435 | 169 | public: |
duke@435 | 170 | CmpPNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} |
duke@435 | 171 | virtual int Opcode() const; |
duke@435 | 172 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 173 | virtual const Type *sub( const Type *, const Type * ) const; |
duke@435 | 174 | }; |
duke@435 | 175 | |
coleenp@548 | 176 | //------------------------------CmpNNode-------------------------------------- |
coleenp@548 | 177 | // Compare 2 narrow oop values, returning condition codes (-1, 0 or 1). |
coleenp@548 | 178 | class CmpNNode : public CmpNode { |
coleenp@548 | 179 | public: |
coleenp@548 | 180 | CmpNNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} |
coleenp@548 | 181 | virtual int Opcode() const; |
coleenp@548 | 182 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
coleenp@548 | 183 | virtual const Type *sub( const Type *, const Type * ) const; |
coleenp@548 | 184 | }; |
coleenp@548 | 185 | |
duke@435 | 186 | //------------------------------CmpLNode--------------------------------------- |
duke@435 | 187 | // Compare 2 long values, returning condition codes (-1, 0 or 1). |
duke@435 | 188 | class CmpLNode : public CmpNode { |
duke@435 | 189 | public: |
duke@435 | 190 | CmpLNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} |
duke@435 | 191 | virtual int Opcode() const; |
duke@435 | 192 | virtual const Type *sub( const Type *, const Type * ) const; |
duke@435 | 193 | }; |
duke@435 | 194 | |
thartmann@8797 | 195 | //------------------------------CmpULNode--------------------------------------- |
thartmann@8797 | 196 | // Compare 2 unsigned long values, returning condition codes (-1, 0 or 1). |
thartmann@8797 | 197 | class CmpULNode : public CmpNode { |
thartmann@8797 | 198 | public: |
thartmann@8797 | 199 | CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { } |
thartmann@8797 | 200 | virtual int Opcode() const; |
thartmann@8797 | 201 | virtual const Type* sub(const Type*, const Type*) const; |
thartmann@8797 | 202 | }; |
thartmann@8797 | 203 | |
duke@435 | 204 | //------------------------------CmpL3Node-------------------------------------- |
duke@435 | 205 | // Compare 2 long values, returning integer value (-1, 0 or 1). |
duke@435 | 206 | class CmpL3Node : public CmpLNode { |
duke@435 | 207 | public: |
duke@435 | 208 | CmpL3Node( Node *in1, Node *in2 ) : CmpLNode(in1,in2) { |
duke@435 | 209 | // Since it is not consumed by Bools, it is not really a Cmp. |
duke@435 | 210 | init_class_id(Class_Sub); |
duke@435 | 211 | } |
duke@435 | 212 | virtual int Opcode() const; |
duke@435 | 213 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 214 | }; |
duke@435 | 215 | |
duke@435 | 216 | //------------------------------CmpFNode--------------------------------------- |
duke@435 | 217 | // Compare 2 float values, returning condition codes (-1, 0 or 1). |
duke@435 | 218 | // This implements the Java bytecode fcmpl, so unordered returns -1. |
duke@435 | 219 | // Operands may not commute. |
duke@435 | 220 | class CmpFNode : public CmpNode { |
duke@435 | 221 | public: |
duke@435 | 222 | CmpFNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} |
duke@435 | 223 | virtual int Opcode() const; |
duke@435 | 224 | virtual const Type *sub( const Type *, const Type * ) const { ShouldNotReachHere(); return NULL; } |
duke@435 | 225 | const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 226 | }; |
duke@435 | 227 | |
duke@435 | 228 | //------------------------------CmpF3Node-------------------------------------- |
duke@435 | 229 | // Compare 2 float values, returning integer value (-1, 0 or 1). |
duke@435 | 230 | // This implements the Java bytecode fcmpl, so unordered returns -1. |
duke@435 | 231 | // Operands may not commute. |
duke@435 | 232 | class CmpF3Node : public CmpFNode { |
duke@435 | 233 | public: |
duke@435 | 234 | CmpF3Node( Node *in1, Node *in2 ) : CmpFNode(in1,in2) { |
duke@435 | 235 | // Since it is not consumed by Bools, it is not really a Cmp. |
duke@435 | 236 | init_class_id(Class_Sub); |
duke@435 | 237 | } |
duke@435 | 238 | virtual int Opcode() const; |
duke@435 | 239 | // Since it is not consumed by Bools, it is not really a Cmp. |
duke@435 | 240 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 241 | }; |
duke@435 | 242 | |
duke@435 | 243 | |
duke@435 | 244 | //------------------------------CmpDNode--------------------------------------- |
duke@435 | 245 | // Compare 2 double values, returning condition codes (-1, 0 or 1). |
duke@435 | 246 | // This implements the Java bytecode dcmpl, so unordered returns -1. |
duke@435 | 247 | // Operands may not commute. |
duke@435 | 248 | class CmpDNode : public CmpNode { |
duke@435 | 249 | public: |
duke@435 | 250 | CmpDNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} |
duke@435 | 251 | virtual int Opcode() const; |
duke@435 | 252 | virtual const Type *sub( const Type *, const Type * ) const { ShouldNotReachHere(); return NULL; } |
duke@435 | 253 | const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 254 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 255 | }; |
duke@435 | 256 | |
duke@435 | 257 | //------------------------------CmpD3Node-------------------------------------- |
duke@435 | 258 | // Compare 2 double values, returning integer value (-1, 0 or 1). |
duke@435 | 259 | // This implements the Java bytecode dcmpl, so unordered returns -1. |
duke@435 | 260 | // Operands may not commute. |
duke@435 | 261 | class CmpD3Node : public CmpDNode { |
duke@435 | 262 | public: |
duke@435 | 263 | CmpD3Node( Node *in1, Node *in2 ) : CmpDNode(in1,in2) { |
duke@435 | 264 | // Since it is not consumed by Bools, it is not really a Cmp. |
duke@435 | 265 | init_class_id(Class_Sub); |
duke@435 | 266 | } |
duke@435 | 267 | virtual int Opcode() const; |
duke@435 | 268 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 269 | }; |
duke@435 | 270 | |
duke@435 | 271 | |
duke@435 | 272 | //------------------------------BoolTest--------------------------------------- |
duke@435 | 273 | // Convert condition codes to a boolean test value (0 or -1). |
duke@435 | 274 | // We pick the values as 3 bits; the low order 2 bits we compare against the |
duke@435 | 275 | // condition codes, the high bit flips the sense of the result. |
duke@435 | 276 | struct BoolTest VALUE_OBJ_CLASS_SPEC { |
rbackman@5791 | 277 | enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, overflow = 2, no_overflow = 6, illegal = 8 }; |
duke@435 | 278 | mask _test; |
duke@435 | 279 | BoolTest( mask btm ) : _test(btm) {} |
duke@435 | 280 | const Type *cc2logical( const Type *CC ) const; |
duke@435 | 281 | // Commute the test. I use a small table lookup. The table is created as |
duke@435 | 282 | // a simple char array where each element is the ASCII version of a 'mask' |
duke@435 | 283 | // enum from above. |
rbackman@5791 | 284 | mask commute( ) const { return mask("032147658"[_test]-'0'); } |
duke@435 | 285 | mask negate( ) const { return mask(_test^4); } |
rbackman@5791 | 286 | bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le || _test == BoolTest::overflow); } |
duke@435 | 287 | void dump_on(outputStream *st) const; |
duke@435 | 288 | }; |
duke@435 | 289 | |
duke@435 | 290 | //------------------------------BoolNode--------------------------------------- |
duke@435 | 291 | // A Node to convert a Condition Codes to a Logical result. |
duke@435 | 292 | class BoolNode : public Node { |
duke@435 | 293 | virtual uint hash() const; |
duke@435 | 294 | virtual uint cmp( const Node &n ) const; |
duke@435 | 295 | virtual uint size_of() const; |
duke@435 | 296 | public: |
duke@435 | 297 | const BoolTest _test; |
duke@435 | 298 | BoolNode( Node *cc, BoolTest::mask t): _test(t), Node(0,cc) { |
duke@435 | 299 | init_class_id(Class_Bool); |
duke@435 | 300 | } |
duke@435 | 301 | // Convert an arbitrary int value to a Bool or other suitable predicate. |
duke@435 | 302 | static Node* make_predicate(Node* test_value, PhaseGVN* phase); |
duke@435 | 303 | // Convert self back to an integer value. |
duke@435 | 304 | Node* as_int_value(PhaseGVN* phase); |
duke@435 | 305 | // Invert sense of self, returning new Bool. |
duke@435 | 306 | BoolNode* negate(PhaseGVN* phase); |
duke@435 | 307 | virtual int Opcode() const; |
duke@435 | 308 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
duke@435 | 309 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 310 | virtual const Type *bottom_type() const { return TypeInt::BOOL; } |
duke@435 | 311 | uint match_edge(uint idx) const { return 0; } |
duke@435 | 312 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 313 | |
duke@435 | 314 | bool is_counted_loop_exit_test(); |
duke@435 | 315 | #ifndef PRODUCT |
duke@435 | 316 | virtual void dump_spec(outputStream *st) const; |
duke@435 | 317 | #endif |
duke@435 | 318 | }; |
duke@435 | 319 | |
duke@435 | 320 | //------------------------------AbsNode---------------------------------------- |
duke@435 | 321 | // Abstract class for absolute value. Mostly used to get a handy wrapper |
duke@435 | 322 | // for finding this pattern in the graph. |
duke@435 | 323 | class AbsNode : public Node { |
duke@435 | 324 | public: |
duke@435 | 325 | AbsNode( Node *value ) : Node(0,value) {} |
duke@435 | 326 | }; |
duke@435 | 327 | |
duke@435 | 328 | //------------------------------AbsINode--------------------------------------- |
duke@435 | 329 | // Absolute value an integer. Since a naive graph involves control flow, we |
duke@435 | 330 | // "match" it in the ideal world (so the control flow can be removed). |
duke@435 | 331 | class AbsINode : public AbsNode { |
duke@435 | 332 | public: |
duke@435 | 333 | AbsINode( Node *in1 ) : AbsNode(in1) {} |
duke@435 | 334 | virtual int Opcode() const; |
duke@435 | 335 | const Type *bottom_type() const { return TypeInt::INT; } |
duke@435 | 336 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 337 | }; |
duke@435 | 338 | |
duke@435 | 339 | //------------------------------AbsFNode--------------------------------------- |
duke@435 | 340 | // Absolute value a float, a common float-point idiom with a cheap hardware |
duke@435 | 341 | // implemention on most chips. Since a naive graph involves control flow, we |
duke@435 | 342 | // "match" it in the ideal world (so the control flow can be removed). |
duke@435 | 343 | class AbsFNode : public AbsNode { |
duke@435 | 344 | public: |
duke@435 | 345 | AbsFNode( Node *in1 ) : AbsNode(in1) {} |
duke@435 | 346 | virtual int Opcode() const; |
duke@435 | 347 | const Type *bottom_type() const { return Type::FLOAT; } |
duke@435 | 348 | virtual uint ideal_reg() const { return Op_RegF; } |
duke@435 | 349 | }; |
duke@435 | 350 | |
duke@435 | 351 | //------------------------------AbsDNode--------------------------------------- |
duke@435 | 352 | // Absolute value a double, a common float-point idiom with a cheap hardware |
duke@435 | 353 | // implemention on most chips. Since a naive graph involves control flow, we |
duke@435 | 354 | // "match" it in the ideal world (so the control flow can be removed). |
duke@435 | 355 | class AbsDNode : public AbsNode { |
duke@435 | 356 | public: |
duke@435 | 357 | AbsDNode( Node *in1 ) : AbsNode(in1) {} |
duke@435 | 358 | virtual int Opcode() const; |
duke@435 | 359 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 360 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 361 | }; |
duke@435 | 362 | |
duke@435 | 363 | |
duke@435 | 364 | //------------------------------CmpLTMaskNode---------------------------------- |
duke@435 | 365 | // If p < q, return -1 else return 0. Nice for flow-free idioms. |
duke@435 | 366 | class CmpLTMaskNode : public Node { |
duke@435 | 367 | public: |
duke@435 | 368 | CmpLTMaskNode( Node *p, Node *q ) : Node(0, p, q) {} |
duke@435 | 369 | virtual int Opcode() const; |
duke@435 | 370 | const Type *bottom_type() const { return TypeInt::INT; } |
duke@435 | 371 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 372 | }; |
duke@435 | 373 | |
duke@435 | 374 | |
duke@435 | 375 | //------------------------------NegNode---------------------------------------- |
duke@435 | 376 | class NegNode : public Node { |
duke@435 | 377 | public: |
duke@435 | 378 | NegNode( Node *in1 ) : Node(0,in1) {} |
duke@435 | 379 | }; |
duke@435 | 380 | |
duke@435 | 381 | //------------------------------NegFNode--------------------------------------- |
duke@435 | 382 | // Negate value a float. Negating 0.0 returns -0.0, but subtracting from |
duke@435 | 383 | // zero returns +0.0 (per JVM spec on 'fneg' bytecode). As subtraction |
duke@435 | 384 | // cannot be used to replace negation we have to implement negation as ideal |
duke@435 | 385 | // node; note that negation and addition can replace subtraction. |
duke@435 | 386 | class NegFNode : public NegNode { |
duke@435 | 387 | public: |
duke@435 | 388 | NegFNode( Node *in1 ) : NegNode(in1) {} |
duke@435 | 389 | virtual int Opcode() const; |
duke@435 | 390 | const Type *bottom_type() const { return Type::FLOAT; } |
duke@435 | 391 | virtual uint ideal_reg() const { return Op_RegF; } |
duke@435 | 392 | }; |
duke@435 | 393 | |
duke@435 | 394 | //------------------------------NegDNode--------------------------------------- |
duke@435 | 395 | // Negate value a double. Negating 0.0 returns -0.0, but subtracting from |
duke@435 | 396 | // zero returns +0.0 (per JVM spec on 'dneg' bytecode). As subtraction |
duke@435 | 397 | // cannot be used to replace negation we have to implement negation as ideal |
duke@435 | 398 | // node; note that negation and addition can replace subtraction. |
duke@435 | 399 | class NegDNode : public NegNode { |
duke@435 | 400 | public: |
duke@435 | 401 | NegDNode( Node *in1 ) : NegNode(in1) {} |
duke@435 | 402 | virtual int Opcode() const; |
duke@435 | 403 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 404 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 405 | }; |
duke@435 | 406 | |
duke@435 | 407 | //------------------------------CosDNode--------------------------------------- |
duke@435 | 408 | // Cosinus of a double |
duke@435 | 409 | class CosDNode : public Node { |
duke@435 | 410 | public: |
roland@4617 | 411 | CosDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { |
roland@4617 | 412 | init_flags(Flag_is_expensive); |
roland@4617 | 413 | C->add_expensive_node(this); |
roland@4617 | 414 | } |
duke@435 | 415 | virtual int Opcode() const; |
duke@435 | 416 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 417 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 418 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 419 | }; |
duke@435 | 420 | |
duke@435 | 421 | //------------------------------CosDNode--------------------------------------- |
duke@435 | 422 | // Sinus of a double |
duke@435 | 423 | class SinDNode : public Node { |
duke@435 | 424 | public: |
roland@4617 | 425 | SinDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { |
roland@4617 | 426 | init_flags(Flag_is_expensive); |
roland@4617 | 427 | C->add_expensive_node(this); |
roland@4617 | 428 | } |
duke@435 | 429 | virtual int Opcode() const; |
duke@435 | 430 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 431 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 432 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 433 | }; |
duke@435 | 434 | |
duke@435 | 435 | |
duke@435 | 436 | //------------------------------TanDNode--------------------------------------- |
duke@435 | 437 | // tangens of a double |
duke@435 | 438 | class TanDNode : public Node { |
duke@435 | 439 | public: |
roland@4617 | 440 | TanDNode(Compile* C, Node *c,Node *in1) : Node(c, in1) { |
roland@4617 | 441 | init_flags(Flag_is_expensive); |
roland@4617 | 442 | C->add_expensive_node(this); |
roland@4617 | 443 | } |
duke@435 | 444 | virtual int Opcode() const; |
duke@435 | 445 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 446 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 447 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 448 | }; |
duke@435 | 449 | |
duke@435 | 450 | |
duke@435 | 451 | //------------------------------AtanDNode-------------------------------------- |
duke@435 | 452 | // arcus tangens of a double |
duke@435 | 453 | class AtanDNode : public Node { |
duke@435 | 454 | public: |
duke@435 | 455 | AtanDNode(Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {} |
duke@435 | 456 | virtual int Opcode() const; |
duke@435 | 457 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 458 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 459 | }; |
duke@435 | 460 | |
duke@435 | 461 | |
duke@435 | 462 | //------------------------------SqrtDNode-------------------------------------- |
duke@435 | 463 | // square root a double |
duke@435 | 464 | class SqrtDNode : public Node { |
duke@435 | 465 | public: |
roland@4617 | 466 | SqrtDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { |
roland@4617 | 467 | init_flags(Flag_is_expensive); |
roland@4617 | 468 | C->add_expensive_node(this); |
roland@4617 | 469 | } |
duke@435 | 470 | virtual int Opcode() const; |
duke@435 | 471 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 472 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 473 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 474 | }; |
duke@435 | 475 | |
duke@435 | 476 | //------------------------------ExpDNode--------------------------------------- |
duke@435 | 477 | // Exponentiate a double |
duke@435 | 478 | class ExpDNode : public Node { |
duke@435 | 479 | public: |
roland@4589 | 480 | ExpDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { |
roland@4589 | 481 | init_flags(Flag_is_expensive); |
roland@4589 | 482 | C->add_expensive_node(this); |
roland@4589 | 483 | } |
duke@435 | 484 | virtual int Opcode() const; |
duke@435 | 485 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 486 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 487 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 488 | }; |
duke@435 | 489 | |
duke@435 | 490 | //------------------------------LogDNode--------------------------------------- |
duke@435 | 491 | // Log_e of a double |
duke@435 | 492 | class LogDNode : public Node { |
duke@435 | 493 | public: |
roland@4617 | 494 | LogDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { |
roland@4617 | 495 | init_flags(Flag_is_expensive); |
roland@4617 | 496 | C->add_expensive_node(this); |
roland@4617 | 497 | } |
duke@435 | 498 | virtual int Opcode() const; |
duke@435 | 499 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 500 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 501 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 502 | }; |
duke@435 | 503 | |
duke@435 | 504 | //------------------------------Log10DNode--------------------------------------- |
duke@435 | 505 | // Log_10 of a double |
duke@435 | 506 | class Log10DNode : public Node { |
duke@435 | 507 | public: |
roland@4617 | 508 | Log10DNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { |
roland@4617 | 509 | init_flags(Flag_is_expensive); |
roland@4617 | 510 | C->add_expensive_node(this); |
roland@4617 | 511 | } |
duke@435 | 512 | virtual int Opcode() const; |
duke@435 | 513 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 514 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 515 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 516 | }; |
duke@435 | 517 | |
duke@435 | 518 | //------------------------------PowDNode--------------------------------------- |
duke@435 | 519 | // Raise a double to a double power |
duke@435 | 520 | class PowDNode : public Node { |
duke@435 | 521 | public: |
roland@4589 | 522 | PowDNode(Compile* C, Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) { |
roland@4589 | 523 | init_flags(Flag_is_expensive); |
roland@4589 | 524 | C->add_expensive_node(this); |
roland@4589 | 525 | } |
duke@435 | 526 | virtual int Opcode() const; |
duke@435 | 527 | const Type *bottom_type() const { return Type::DOUBLE; } |
duke@435 | 528 | virtual uint ideal_reg() const { return Op_RegD; } |
duke@435 | 529 | virtual const Type *Value( PhaseTransform *phase ) const; |
duke@435 | 530 | }; |
duke@435 | 531 | |
duke@435 | 532 | //-------------------------------ReverseBytesINode-------------------------------- |
duke@435 | 533 | // reverse bytes of an integer |
duke@435 | 534 | class ReverseBytesINode : public Node { |
duke@435 | 535 | public: |
duke@435 | 536 | ReverseBytesINode(Node *c, Node *in1) : Node(c, in1) {} |
duke@435 | 537 | virtual int Opcode() const; |
duke@435 | 538 | const Type *bottom_type() const { return TypeInt::INT; } |
duke@435 | 539 | virtual uint ideal_reg() const { return Op_RegI; } |
duke@435 | 540 | }; |
duke@435 | 541 | |
duke@435 | 542 | //-------------------------------ReverseBytesLNode-------------------------------- |
duke@435 | 543 | // reverse bytes of a long |
duke@435 | 544 | class ReverseBytesLNode : public Node { |
duke@435 | 545 | public: |
duke@435 | 546 | ReverseBytesLNode(Node *c, Node *in1) : Node(c, in1) {} |
duke@435 | 547 | virtual int Opcode() const; |
duke@435 | 548 | const Type *bottom_type() const { return TypeLong::LONG; } |
duke@435 | 549 | virtual uint ideal_reg() const { return Op_RegL; } |
duke@435 | 550 | }; |
never@1831 | 551 | |
never@1831 | 552 | //-------------------------------ReverseBytesUSNode-------------------------------- |
never@1831 | 553 | // reverse bytes of an unsigned short / char |
never@1831 | 554 | class ReverseBytesUSNode : public Node { |
never@1831 | 555 | public: |
never@1831 | 556 | ReverseBytesUSNode(Node *c, Node *in1) : Node(c, in1) {} |
never@1831 | 557 | virtual int Opcode() const; |
never@1831 | 558 | const Type *bottom_type() const { return TypeInt::CHAR; } |
never@1831 | 559 | virtual uint ideal_reg() const { return Op_RegI; } |
never@1831 | 560 | }; |
never@1831 | 561 | |
never@1831 | 562 | //-------------------------------ReverseBytesSNode-------------------------------- |
never@1831 | 563 | // reverse bytes of a short |
never@1831 | 564 | class ReverseBytesSNode : public Node { |
never@1831 | 565 | public: |
never@1831 | 566 | ReverseBytesSNode(Node *c, Node *in1) : Node(c, in1) {} |
never@1831 | 567 | virtual int Opcode() const; |
never@1831 | 568 | const Type *bottom_type() const { return TypeInt::SHORT; } |
never@1831 | 569 | virtual uint ideal_reg() const { return Op_RegI; } |
never@1831 | 570 | }; |
stefank@2314 | 571 | |
stefank@2314 | 572 | #endif // SHARE_VM_OPTO_SUBNODE_HPP |