1 /* 2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_OPTO_SUBNODE_HPP 26 #define SHARE_OPTO_SUBNODE_HPP 27 28 #include "opto/node.hpp" 29 #include "opto/opcodes.hpp" 30 #include "opto/type.hpp" 31 32 // Portions of code courtesy of Clifford Click 33 34 //------------------------------SUBNode---------------------------------------- 35 // Class SUBTRACTION functionality. This covers all the usual 'subtract' 36 // behaviors. Subtract-integer, -float, -double, binary xor, compare-integer, 37 // -float, and -double are all inherited from this class. The compare 38 // functions behave like subtract functions, except that all negative answers 39 // are compressed into -1, and all positive answers compressed to 1. 40 class SubNode : public Node { 41 public: SubNode(Node * in1,Node * in2)42 SubNode( Node *in1, Node *in2 ) : Node(0,in1,in2) { 43 init_class_id(Class_Sub); 44 } 45 46 // Handle algebraic identities here. If we have an identity, return the Node 47 // we are equivalent to. We look for "add of zero" as an identity. 48 virtual Node* Identity(PhaseGVN* phase); 49 50 // Compute a new Type for this node. Basically we just do the pre-check, 51 // then call the virtual add() to set the type. 52 virtual const Type* Value(PhaseGVN* phase) const; 53 const Type* Value_common( PhaseTransform *phase ) const; 54 55 // Supplied function returns the subtractend of the inputs. 56 // This also type-checks the inputs for sanity. Guaranteed never to 57 // be passed a TOP or BOTTOM type, these are filtered out by a pre-check. 58 virtual const Type *sub( const Type *, const Type * ) const = 0; 59 60 // Supplied function to return the additive identity type. 61 // This is returned whenever the subtracts inputs are the same. 62 virtual const Type *add_id() const = 0; 63 }; 64 65 66 // NOTE: SubINode should be taken away and replaced by add and negate 67 //------------------------------SubINode--------------------------------------- 68 // Subtract 2 integers 69 class SubINode : public SubNode { 70 public: SubINode(Node * in1,Node * in2)71 SubINode( Node *in1, Node *in2 ) : SubNode(in1,in2) {} 72 virtual int Opcode() const; 73 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 74 virtual const Type *sub( const Type *, const Type * ) const; add_id() const75 const Type *add_id() const { return TypeInt::ZERO; } bottom_type() const76 const Type *bottom_type() const { return TypeInt::INT; } ideal_reg() const77 virtual uint ideal_reg() const { return Op_RegI; } 78 }; 79 80 //------------------------------SubLNode--------------------------------------- 81 // Subtract 2 integers 82 class SubLNode : public SubNode { 83 public: SubLNode(Node * in1,Node * in2)84 SubLNode( Node *in1, Node *in2 ) : SubNode(in1,in2) {} 85 virtual int Opcode() const; 86 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 87 virtual const Type *sub( const Type *, const Type * ) const; add_id() const88 const Type *add_id() const { return TypeLong::ZERO; } bottom_type() const89 const Type *bottom_type() const { return TypeLong::LONG; } ideal_reg() const90 virtual uint ideal_reg() const { return Op_RegL; } 91 }; 92 93 // NOTE: SubFPNode should be taken away and replaced by add and negate 94 //------------------------------SubFPNode-------------------------------------- 95 // Subtract 2 floats or doubles 96 class SubFPNode : public SubNode { 97 protected: SubFPNode(Node * in1,Node * in2)98 SubFPNode( Node *in1, Node *in2 ) : SubNode(in1,in2) {} 99 public: 100 const Type* Value(PhaseGVN* phase) const; 101 }; 102 103 // NOTE: SubFNode should be taken away and replaced by add and negate 104 //------------------------------SubFNode--------------------------------------- 105 // Subtract 2 doubles 106 class SubFNode : public SubFPNode { 107 public: SubFNode(Node * in1,Node * in2)108 SubFNode( Node *in1, Node *in2 ) : SubFPNode(in1,in2) {} 109 virtual int Opcode() const; 110 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 111 virtual const Type *sub( const Type *, const Type * ) const; add_id() const112 const Type *add_id() const { return TypeF::ZERO; } bottom_type() const113 const Type *bottom_type() const { return Type::FLOAT; } ideal_reg() const114 virtual uint ideal_reg() const { return Op_RegF; } 115 }; 116 117 // NOTE: SubDNode should be taken away and replaced by add and negate 118 //------------------------------SubDNode--------------------------------------- 119 // Subtract 2 doubles 120 class SubDNode : public SubFPNode { 121 public: SubDNode(Node * in1,Node * in2)122 SubDNode( Node *in1, Node *in2 ) : SubFPNode(in1,in2) {} 123 virtual int Opcode() const; 124 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 125 virtual const Type *sub( const Type *, const Type * ) const; add_id() const126 const Type *add_id() const { return TypeD::ZERO; } bottom_type() const127 const Type *bottom_type() const { return Type::DOUBLE; } ideal_reg() const128 virtual uint ideal_reg() const { return Op_RegD; } 129 }; 130 131 //------------------------------CmpNode--------------------------------------- 132 // Compare 2 values, returning condition codes (-1, 0 or 1). 133 class CmpNode : public SubNode { 134 public: CmpNode(Node * in1,Node * in2)135 CmpNode( Node *in1, Node *in2 ) : SubNode(in1,in2) { 136 init_class_id(Class_Cmp); 137 } 138 virtual Node* Identity(PhaseGVN* phase); add_id() const139 const Type *add_id() const { return TypeInt::ZERO; } bottom_type() const140 const Type *bottom_type() const { return TypeInt::CC; } ideal_reg() const141 virtual uint ideal_reg() const { return Op_RegFlags; } 142 143 #ifndef PRODUCT 144 // CmpNode and subclasses include all data inputs (until hitting a control 145 // boundary) in their related node set, as well as all outputs until and 146 // including eventual control nodes and their projections. 147 virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const; 148 #endif 149 }; 150 151 //------------------------------CmpINode--------------------------------------- 152 // Compare 2 signed values, returning condition codes (-1, 0 or 1). 153 class CmpINode : public CmpNode { 154 public: CmpINode(Node * in1,Node * in2)155 CmpINode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} 156 virtual int Opcode() const; 157 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 158 virtual const Type *sub( const Type *, const Type * ) const; 159 }; 160 161 //------------------------------CmpUNode--------------------------------------- 162 // Compare 2 unsigned values (integer or pointer), returning condition codes (-1, 0 or 1). 163 class CmpUNode : public CmpNode { 164 public: CmpUNode(Node * in1,Node * in2)165 CmpUNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} 166 virtual int Opcode() const; 167 virtual const Type *sub( const Type *, const Type * ) const; 168 const Type* Value(PhaseGVN* phase) const; 169 bool is_index_range_check() const; 170 }; 171 172 //------------------------------CmpPNode--------------------------------------- 173 // Compare 2 pointer values, returning condition codes (-1, 0 or 1). 174 class CmpPNode : public CmpNode { 175 public: CmpPNode(Node * in1,Node * in2)176 CmpPNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} 177 virtual int Opcode() const; 178 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 179 virtual const Type *sub( const Type *, const Type * ) const; 180 }; 181 182 //------------------------------CmpNNode-------------------------------------- 183 // Compare 2 narrow oop values, returning condition codes (-1, 0 or 1). 184 class CmpNNode : public CmpNode { 185 public: CmpNNode(Node * in1,Node * in2)186 CmpNNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} 187 virtual int Opcode() const; 188 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 189 virtual const Type *sub( const Type *, const Type * ) const; 190 }; 191 192 //------------------------------CmpLNode--------------------------------------- 193 // Compare 2 long values, returning condition codes (-1, 0 or 1). 194 class CmpLNode : public CmpNode { 195 public: CmpLNode(Node * in1,Node * in2)196 CmpLNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} 197 virtual int Opcode() const; 198 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 199 virtual const Type *sub( const Type *, const Type * ) const; 200 }; 201 202 //------------------------------CmpULNode--------------------------------------- 203 // Compare 2 unsigned long values, returning condition codes (-1, 0 or 1). 204 class CmpULNode : public CmpNode { 205 public: CmpULNode(Node * in1,Node * in2)206 CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { } 207 virtual int Opcode() const; 208 virtual const Type* sub(const Type*, const Type*) const; 209 }; 210 211 //------------------------------CmpL3Node-------------------------------------- 212 // Compare 2 long values, returning integer value (-1, 0 or 1). 213 class CmpL3Node : public CmpLNode { 214 public: CmpL3Node(Node * in1,Node * in2)215 CmpL3Node( Node *in1, Node *in2 ) : CmpLNode(in1,in2) { 216 // Since it is not consumed by Bools, it is not really a Cmp. 217 init_class_id(Class_Sub); 218 } 219 virtual int Opcode() const; ideal_reg() const220 virtual uint ideal_reg() const { return Op_RegI; } 221 }; 222 223 //------------------------------CmpFNode--------------------------------------- 224 // Compare 2 float values, returning condition codes (-1, 0 or 1). 225 // This implements the Java bytecode fcmpl, so unordered returns -1. 226 // Operands may not commute. 227 class CmpFNode : public CmpNode { 228 public: CmpFNode(Node * in1,Node * in2)229 CmpFNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} 230 virtual int Opcode() const; sub(const Type *,const Type *) const231 virtual const Type *sub( const Type *, const Type * ) const { ShouldNotReachHere(); return NULL; } 232 const Type* Value(PhaseGVN* phase) const; 233 }; 234 235 //------------------------------CmpF3Node-------------------------------------- 236 // Compare 2 float values, returning integer value (-1, 0 or 1). 237 // This implements the Java bytecode fcmpl, so unordered returns -1. 238 // Operands may not commute. 239 class CmpF3Node : public CmpFNode { 240 public: CmpF3Node(Node * in1,Node * in2)241 CmpF3Node( Node *in1, Node *in2 ) : CmpFNode(in1,in2) { 242 // Since it is not consumed by Bools, it is not really a Cmp. 243 init_class_id(Class_Sub); 244 } 245 virtual int Opcode() const; 246 // Since it is not consumed by Bools, it is not really a Cmp. ideal_reg() const247 virtual uint ideal_reg() const { return Op_RegI; } 248 }; 249 250 251 //------------------------------CmpDNode--------------------------------------- 252 // Compare 2 double values, returning condition codes (-1, 0 or 1). 253 // This implements the Java bytecode dcmpl, so unordered returns -1. 254 // Operands may not commute. 255 class CmpDNode : public CmpNode { 256 public: CmpDNode(Node * in1,Node * in2)257 CmpDNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} 258 virtual int Opcode() const; sub(const Type *,const Type *) const259 virtual const Type *sub( const Type *, const Type * ) const { ShouldNotReachHere(); return NULL; } 260 const Type* Value(PhaseGVN* phase) const; 261 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 262 }; 263 264 //------------------------------CmpD3Node-------------------------------------- 265 // Compare 2 double values, returning integer value (-1, 0 or 1). 266 // This implements the Java bytecode dcmpl, so unordered returns -1. 267 // Operands may not commute. 268 class CmpD3Node : public CmpDNode { 269 public: CmpD3Node(Node * in1,Node * in2)270 CmpD3Node( Node *in1, Node *in2 ) : CmpDNode(in1,in2) { 271 // Since it is not consumed by Bools, it is not really a Cmp. 272 init_class_id(Class_Sub); 273 } 274 virtual int Opcode() const; ideal_reg() const275 virtual uint ideal_reg() const { return Op_RegI; } 276 }; 277 278 279 //------------------------------BoolTest--------------------------------------- 280 // Convert condition codes to a boolean test value (0 or -1). 281 // We pick the values as 3 bits; the low order 2 bits we compare against the 282 // condition codes, the high bit flips the sense of the result. 283 struct BoolTest { 284 enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, overflow = 2, no_overflow = 6, never = 8, illegal = 9 }; 285 mask _test; BoolTestBoolTest286 BoolTest( mask btm ) : _test(btm) {} 287 const Type *cc2logical( const Type *CC ) const; 288 // Commute the test. I use a small table lookup. The table is created as 289 // a simple char array where each element is the ASCII version of a 'mask' 290 // enum from above. commuteBoolTest291 mask commute( ) const { return mask("032147658"[_test]-'0'); } negateBoolTest292 mask negate( ) const { return mask(_test^4); } is_canonicalBoolTest293 bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le || _test == BoolTest::overflow); } is_lessBoolTest294 bool is_less( ) const { return _test == BoolTest::lt || _test == BoolTest::le; } is_greaterBoolTest295 bool is_greater( ) const { return _test == BoolTest::gt || _test == BoolTest::ge; } 296 void dump_on(outputStream *st) const; 297 mask merge(BoolTest other) const; 298 }; 299 300 //------------------------------BoolNode--------------------------------------- 301 // A Node to convert a Condition Codes to a Logical result. 302 class BoolNode : public Node { 303 virtual uint hash() const; 304 virtual bool cmp( const Node &n ) const; 305 virtual uint size_of() const; 306 307 // Try to optimize signed integer comparison 308 Node* fold_cmpI(PhaseGVN* phase, SubNode* cmp, Node* cmp1, int cmp_op, 309 int cmp1_op, const TypeInt* cmp2_type); 310 public: 311 const BoolTest _test; BoolNode(Node * cc,BoolTest::mask t)312 BoolNode( Node *cc, BoolTest::mask t): Node(0,cc), _test(t) { 313 init_class_id(Class_Bool); 314 } 315 // Convert an arbitrary int value to a Bool or other suitable predicate. 316 static Node* make_predicate(Node* test_value, PhaseGVN* phase); 317 // Convert self back to an integer value. 318 Node* as_int_value(PhaseGVN* phase); 319 // Invert sense of self, returning new Bool. 320 BoolNode* negate(PhaseGVN* phase); 321 virtual int Opcode() const; 322 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 323 virtual const Type* Value(PhaseGVN* phase) const; bottom_type() const324 virtual const Type *bottom_type() const { return TypeInt::BOOL; } match_edge(uint idx) const325 uint match_edge(uint idx) const { return 0; } ideal_reg() const326 virtual uint ideal_reg() const { return Op_RegI; } 327 328 bool is_counted_loop_exit_test(); 329 #ifndef PRODUCT 330 virtual void dump_spec(outputStream *st) const; 331 virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const; 332 #endif 333 }; 334 335 //------------------------------AbsNode---------------------------------------- 336 // Abstract class for absolute value. Mostly used to get a handy wrapper 337 // for finding this pattern in the graph. 338 class AbsNode : public Node { 339 public: AbsNode(Node * value)340 AbsNode( Node *value ) : Node(0,value) {} 341 }; 342 343 //------------------------------AbsINode--------------------------------------- 344 // Absolute value an integer. Since a naive graph involves control flow, we 345 // "match" it in the ideal world (so the control flow can be removed). 346 class AbsINode : public AbsNode { 347 public: AbsINode(Node * in1)348 AbsINode( Node *in1 ) : AbsNode(in1) {} 349 virtual int Opcode() const; bottom_type() const350 const Type *bottom_type() const { return TypeInt::INT; } ideal_reg() const351 virtual uint ideal_reg() const { return Op_RegI; } 352 }; 353 354 //------------------------------AbsLNode--------------------------------------- 355 // Absolute value a long. Since a naive graph involves control flow, we 356 // "match" it in the ideal world (so the control flow can be removed). 357 class AbsLNode : public AbsNode { 358 public: AbsLNode(Node * in1)359 AbsLNode( Node *in1 ) : AbsNode(in1) {} 360 virtual int Opcode() const; bottom_type() const361 const Type *bottom_type() const { return TypeLong::LONG; } ideal_reg() const362 virtual uint ideal_reg() const { return Op_RegL; } 363 }; 364 365 //------------------------------AbsFNode--------------------------------------- 366 // Absolute value a float, a common float-point idiom with a cheap hardware 367 // implemention on most chips. Since a naive graph involves control flow, we 368 // "match" it in the ideal world (so the control flow can be removed). 369 class AbsFNode : public AbsNode { 370 public: AbsFNode(Node * in1)371 AbsFNode( Node *in1 ) : AbsNode(in1) {} 372 virtual int Opcode() const; bottom_type() const373 const Type *bottom_type() const { return Type::FLOAT; } ideal_reg() const374 virtual uint ideal_reg() const { return Op_RegF; } 375 }; 376 377 //------------------------------AbsDNode--------------------------------------- 378 // Absolute value a double, a common float-point idiom with a cheap hardware 379 // implemention on most chips. Since a naive graph involves control flow, we 380 // "match" it in the ideal world (so the control flow can be removed). 381 class AbsDNode : public AbsNode { 382 public: AbsDNode(Node * in1)383 AbsDNode( Node *in1 ) : AbsNode(in1) {} 384 virtual int Opcode() const; bottom_type() const385 const Type *bottom_type() const { return Type::DOUBLE; } ideal_reg() const386 virtual uint ideal_reg() const { return Op_RegD; } 387 }; 388 389 390 //------------------------------CmpLTMaskNode---------------------------------- 391 // If p < q, return -1 else return 0. Nice for flow-free idioms. 392 class CmpLTMaskNode : public Node { 393 public: CmpLTMaskNode(Node * p,Node * q)394 CmpLTMaskNode( Node *p, Node *q ) : Node(0, p, q) {} 395 virtual int Opcode() const; bottom_type() const396 const Type *bottom_type() const { return TypeInt::INT; } ideal_reg() const397 virtual uint ideal_reg() const { return Op_RegI; } 398 }; 399 400 401 //------------------------------NegNode---------------------------------------- 402 class NegNode : public Node { 403 public: NegNode(Node * in1)404 NegNode( Node *in1 ) : Node(0,in1) {} 405 }; 406 407 //------------------------------NegFNode--------------------------------------- 408 // Negate value a float. Negating 0.0 returns -0.0, but subtracting from 409 // zero returns +0.0 (per JVM spec on 'fneg' bytecode). As subtraction 410 // cannot be used to replace negation we have to implement negation as ideal 411 // node; note that negation and addition can replace subtraction. 412 class NegFNode : public NegNode { 413 public: NegFNode(Node * in1)414 NegFNode( Node *in1 ) : NegNode(in1) {} 415 virtual int Opcode() const; bottom_type() const416 const Type *bottom_type() const { return Type::FLOAT; } ideal_reg() const417 virtual uint ideal_reg() const { return Op_RegF; } 418 }; 419 420 //------------------------------NegDNode--------------------------------------- 421 // Negate value a double. Negating 0.0 returns -0.0, but subtracting from 422 // zero returns +0.0 (per JVM spec on 'dneg' bytecode). As subtraction 423 // cannot be used to replace negation we have to implement negation as ideal 424 // node; note that negation and addition can replace subtraction. 425 class NegDNode : public NegNode { 426 public: NegDNode(Node * in1)427 NegDNode( Node *in1 ) : NegNode(in1) {} 428 virtual int Opcode() const; bottom_type() const429 const Type *bottom_type() const { return Type::DOUBLE; } ideal_reg() const430 virtual uint ideal_reg() const { return Op_RegD; } 431 }; 432 433 //------------------------------AtanDNode-------------------------------------- 434 // arcus tangens of a double 435 class AtanDNode : public Node { 436 public: AtanDNode(Node * c,Node * in1,Node * in2)437 AtanDNode(Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {} 438 virtual int Opcode() const; bottom_type() const439 const Type *bottom_type() const { return Type::DOUBLE; } ideal_reg() const440 virtual uint ideal_reg() const { return Op_RegD; } 441 }; 442 443 444 //------------------------------SqrtDNode-------------------------------------- 445 // square root a double 446 class SqrtDNode : public Node { 447 public: SqrtDNode(Compile * C,Node * c,Node * in1)448 SqrtDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { 449 init_flags(Flag_is_expensive); 450 C->add_expensive_node(this); 451 } 452 virtual int Opcode() const; bottom_type() const453 const Type *bottom_type() const { return Type::DOUBLE; } ideal_reg() const454 virtual uint ideal_reg() const { return Op_RegD; } 455 virtual const Type* Value(PhaseGVN* phase) const; 456 }; 457 458 //------------------------------SqrtFNode-------------------------------------- 459 // square root a float 460 class SqrtFNode : public Node { 461 public: SqrtFNode(Compile * C,Node * c,Node * in1)462 SqrtFNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { 463 init_flags(Flag_is_expensive); 464 if (c != NULL) { 465 // Treat node only as expensive if a control input is set because it might 466 // be created from a SqrtDNode in ConvD2FNode::Ideal() that was found to 467 // be unique and therefore has no control input. 468 C->add_expensive_node(this); 469 } 470 } 471 virtual int Opcode() const; bottom_type() const472 const Type *bottom_type() const { return Type::FLOAT; } ideal_reg() const473 virtual uint ideal_reg() const { return Op_RegF; } 474 virtual const Type* Value(PhaseGVN* phase) const; 475 }; 476 477 //-------------------------------ReverseBytesINode-------------------------------- 478 // reverse bytes of an integer 479 class ReverseBytesINode : public Node { 480 public: ReverseBytesINode(Node * c,Node * in1)481 ReverseBytesINode(Node *c, Node *in1) : Node(c, in1) {} 482 virtual int Opcode() const; bottom_type() const483 const Type *bottom_type() const { return TypeInt::INT; } ideal_reg() const484 virtual uint ideal_reg() const { return Op_RegI; } 485 }; 486 487 //-------------------------------ReverseBytesLNode-------------------------------- 488 // reverse bytes of a long 489 class ReverseBytesLNode : public Node { 490 public: ReverseBytesLNode(Node * c,Node * in1)491 ReverseBytesLNode(Node *c, Node *in1) : Node(c, in1) {} 492 virtual int Opcode() const; bottom_type() const493 const Type *bottom_type() const { return TypeLong::LONG; } ideal_reg() const494 virtual uint ideal_reg() const { return Op_RegL; } 495 }; 496 497 //-------------------------------ReverseBytesUSNode-------------------------------- 498 // reverse bytes of an unsigned short / char 499 class ReverseBytesUSNode : public Node { 500 public: ReverseBytesUSNode(Node * c,Node * in1)501 ReverseBytesUSNode(Node *c, Node *in1) : Node(c, in1) {} 502 virtual int Opcode() const; bottom_type() const503 const Type *bottom_type() const { return TypeInt::CHAR; } ideal_reg() const504 virtual uint ideal_reg() const { return Op_RegI; } 505 }; 506 507 //-------------------------------ReverseBytesSNode-------------------------------- 508 // reverse bytes of a short 509 class ReverseBytesSNode : public Node { 510 public: ReverseBytesSNode(Node * c,Node * in1)511 ReverseBytesSNode(Node *c, Node *in1) : Node(c, in1) {} 512 virtual int Opcode() const; bottom_type() const513 const Type *bottom_type() const { return TypeInt::SHORT; } ideal_reg() const514 virtual uint ideal_reg() const { return Op_RegI; } 515 }; 516 517 #endif // SHARE_OPTO_SUBNODE_HPP 518