1 /* 2 * Copyright (c) 1997, 2025, 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_DIVNODE_HPP 26 #define SHARE_OPTO_DIVNODE_HPP 27 28 #include "opto/callnode.hpp" 29 #include "opto/multnode.hpp" 30 #include "opto/node.hpp" 31 #include "opto/opcodes.hpp" 32 #include "opto/type.hpp" 33 34 // Portions of code courtesy of Clifford Click 35 36 // Optimization - Graph Style 37 38 39 //------------------------------DivINode--------------------------------------- 40 // Integer division 41 // Note: this is division as defined by JVMS, i.e., MinInt/-1 == MinInt. 42 // On processors which don't naturally support this special case (e.g., x86), 43 // the matcher or runtime system must take care of this. 44 class DivINode : public Node { 45 public: 46 DivINode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {} 47 virtual int Opcode() const; 48 virtual Node* Identity(PhaseGVN* phase); 49 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 50 virtual const Type* Value(PhaseGVN* phase) const; 51 virtual const Type *bottom_type() const { return TypeInt::INT; } 52 virtual uint ideal_reg() const { return Op_RegI; } 53 }; 54 55 //------------------------------DivLNode--------------------------------------- 56 // Long division 57 class DivLNode : public Node { 58 public: 59 DivLNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {} 60 virtual int Opcode() const; 61 virtual Node* Identity(PhaseGVN* phase); 62 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 63 virtual const Type* Value(PhaseGVN* phase) const; 64 virtual const Type *bottom_type() const { return TypeLong::LONG; } 65 virtual uint ideal_reg() const { return Op_RegL; } 66 }; 67 68 //------------------------------DivFNode--------------------------------------- 69 // Float division 70 class DivFNode : public Node { 71 public: 72 DivFNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor) {} 73 virtual int Opcode() const; 74 virtual Node* Identity(PhaseGVN* phase); 75 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 76 virtual const Type* Value(PhaseGVN* phase) const; 77 virtual const Type *bottom_type() const { return Type::FLOAT; } 78 virtual uint ideal_reg() const { return Op_RegF; } 79 }; 80 81 82 //------------------------------DivHFNode-------------------------------------- 83 // Half float division 84 class DivHFNode : public Node { 85 public: 86 DivHFNode(Node* c, Node* dividend, Node* divisor) : Node(c, dividend, divisor) {} 87 virtual int Opcode() const; 88 virtual Node* Identity(PhaseGVN* phase); 89 virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 90 virtual const Type* Value(PhaseGVN* phase) const; 91 virtual const Type* bottom_type() const { return Type::HALF_FLOAT; } 92 virtual uint ideal_reg() const { return Op_RegF; } 93 }; 94 95 //------------------------------DivDNode--------------------------------------- 96 // Double division 97 class DivDNode : public Node { 98 public: 99 DivDNode( Node *c, Node *dividend, Node *divisor ) : Node(c,dividend, divisor) {} 100 virtual int Opcode() const; 101 virtual Node* Identity(PhaseGVN* phase); 102 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 103 virtual const Type* Value(PhaseGVN* phase) const; 104 virtual const Type *bottom_type() const { return Type::DOUBLE; } 105 virtual uint ideal_reg() const { return Op_RegD; } 106 }; 107 108 //------------------------------UDivINode--------------------------------------- 109 // Unsigned integer division 110 class UDivINode : public Node { 111 public: 112 UDivINode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {} 113 virtual int Opcode() const; 114 virtual Node* Identity(PhaseGVN* phase); 115 virtual const Type* Value(PhaseGVN* phase) const; 116 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 117 virtual const Type *bottom_type() const { return TypeInt::INT; } 118 virtual uint ideal_reg() const { return Op_RegI; } 119 }; 120 121 //------------------------------UDivLNode--------------------------------------- 122 // Unsigned long division 123 class UDivLNode : public Node { 124 public: 125 UDivLNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {} 126 virtual int Opcode() const; 127 virtual Node* Identity(PhaseGVN* phase); 128 virtual const Type* Value(PhaseGVN* phase) const; 129 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 130 virtual const Type *bottom_type() const { return TypeLong::LONG; } 131 virtual uint ideal_reg() const { return Op_RegL; } 132 }; 133 134 //------------------------------ModINode--------------------------------------- 135 // Integer modulus 136 class ModINode : public Node { 137 public: 138 ModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {} 139 virtual int Opcode() const; 140 virtual const Type* Value(PhaseGVN* phase) const; 141 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 142 virtual const Type *bottom_type() const { return TypeInt::INT; } 143 virtual uint ideal_reg() const { return Op_RegI; } 144 }; 145 146 //------------------------------ModLNode--------------------------------------- 147 // Long modulus 148 class ModLNode : public Node { 149 public: 150 ModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {} 151 virtual int Opcode() const; 152 virtual const Type* Value(PhaseGVN* phase) const; 153 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 154 virtual const Type *bottom_type() const { return TypeLong::LONG; } 155 virtual uint ideal_reg() const { return Op_RegL; } 156 }; 157 158 // Base class for float and double modulus 159 class ModFloatingNode : public CallLeafPureNode { 160 TupleNode* make_tuple_of_input_state_and_constant_result(PhaseIterGVN* phase, const Type* con) const; 161 162 protected: 163 virtual Node* dividend() const = 0; 164 virtual Node* divisor() const = 0; 165 virtual const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const = 0; 166 167 public: 168 ModFloatingNode(Compile* C, const TypeFunc* tf, address addr, const char* name); 169 Node* Ideal(PhaseGVN* phase, bool can_reshape) override; 170 }; 171 172 // Float Modulus 173 class ModFNode : public ModFloatingNode { 174 private: 175 Node* dividend() const override { return in(TypeFunc::Parms + 0); } 176 Node* divisor() const override { return in(TypeFunc::Parms + 1); } 177 const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const override; 178 179 public: 180 ModFNode(Compile* C, Node* a, Node* b); 181 int Opcode() const override; 182 uint ideal_reg() const override { return Op_RegF; } 183 uint size_of() const override { return sizeof(*this); } 184 }; 185 186 // Double Modulus 187 class ModDNode : public ModFloatingNode { 188 private: 189 Node* dividend() const override { return in(TypeFunc::Parms + 0); } 190 Node* divisor() const override { return in(TypeFunc::Parms + 2); } 191 const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const override; 192 193 public: 194 ModDNode(Compile* C, Node* a, Node* b); 195 int Opcode() const override; 196 uint ideal_reg() const override { return Op_RegD; } 197 uint size_of() const override { return sizeof(*this); } 198 }; 199 200 //------------------------------UModINode--------------------------------------- 201 // Unsigned integer modulus 202 class UModINode : public Node { 203 public: 204 UModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {} 205 virtual int Opcode() const; 206 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 207 virtual const Type *bottom_type() const { return TypeInt::INT; } 208 virtual uint ideal_reg() const { return Op_RegI; } 209 virtual const Type* Value(PhaseGVN* phase) const; 210 }; 211 212 //------------------------------UModLNode--------------------------------------- 213 // Unsigned long modulus 214 class UModLNode : public Node { 215 public: 216 UModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {} 217 virtual int Opcode() const; 218 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 219 virtual const Type *bottom_type() const { return TypeLong::LONG; } 220 virtual uint ideal_reg() const { return Op_RegL; } 221 virtual const Type* Value(PhaseGVN* phase) const; 222 }; 223 224 //------------------------------DivModNode--------------------------------------- 225 // Division with remainder result. 226 class DivModNode : public MultiNode { 227 protected: 228 DivModNode( Node *c, Node *dividend, Node *divisor ); 229 public: 230 enum { 231 div_proj_num = 0, // quotient 232 mod_proj_num = 1 // remainder 233 }; 234 virtual int Opcode() const; 235 virtual Node* Identity(PhaseGVN* phase) { return this; } 236 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { return nullptr; } 237 virtual const Type* Value(PhaseGVN* phase) const { return bottom_type(); } 238 virtual uint hash() const { return Node::hash(); } 239 virtual bool is_CFG() const { return false; } 240 virtual uint ideal_reg() const { return NotAMachineReg; } 241 242 static DivModNode* make(Node* div_or_mod, BasicType bt, bool is_unsigned); 243 244 ProjNode* div_proj() { return proj_out_or_null(div_proj_num); } 245 ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); } 246 }; 247 248 //------------------------------DivModINode--------------------------------------- 249 // Integer division with remainder result. 250 class DivModINode : public DivModNode { 251 public: 252 DivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {} 253 virtual int Opcode() const; 254 virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; } 255 virtual Node *match( const ProjNode *proj, const Matcher *m ); 256 257 // Make a divmod and associated projections from a div or mod. 258 static DivModINode* make(Node* div_or_mod); 259 }; 260 261 //------------------------------DivModLNode--------------------------------------- 262 // Long division with remainder result. 263 class DivModLNode : public DivModNode { 264 public: 265 DivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {} 266 virtual int Opcode() const; 267 virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; } 268 virtual Node *match( const ProjNode *proj, const Matcher *m ); 269 270 // Make a divmod and associated projections from a div or mod. 271 static DivModLNode* make(Node* div_or_mod); 272 }; 273 274 275 //------------------------------UDivModINode--------------------------------------- 276 // Unsigend integer division with remainder result. 277 class UDivModINode : public DivModNode { 278 public: 279 UDivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {} 280 virtual int Opcode() const; 281 virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; } 282 virtual Node *match( const ProjNode *proj, const Matcher *m ); 283 284 // Make a divmod and associated projections from a div or mod. 285 static UDivModINode* make(Node* div_or_mod); 286 }; 287 288 //------------------------------UDivModLNode--------------------------------------- 289 // Unsigned long division with remainder result. 290 class UDivModLNode : public DivModNode { 291 public: 292 UDivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {} 293 virtual int Opcode() const; 294 virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; } 295 virtual Node *match( const ProjNode *proj, const Matcher *m ); 296 297 // Make a divmod and associated projections from a div or mod. 298 static UDivModLNode* make(Node* div_or_mod); 299 }; 300 301 #endif // SHARE_OPTO_DIVNODE_HPP