src/share/vm/opto/mathexactnode.cpp

Tue, 14 Jan 2014 17:46:48 -0800

author
kvn
date
Tue, 14 Jan 2014 17:46:48 -0800
changeset 6312
04d32e7fad07
parent 5997
59e8ad757e19
child 6375
085b304a1cc5
permissions
-rw-r--r--

8002074: Support for AES on SPARC
Summary: Add intrinsics/stub routines support for single-block and multi-block (as used by Cipher Block Chaining mode) AES encryption and decryption operations on the SPARC platform.
Reviewed-by: kvn, roland
Contributed-by: shrinivas.joshi@oracle.com

rbackman@5791 1 /*
rbackman@5791 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
rbackman@5791 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
rbackman@5791 4 *
rbackman@5791 5 * This code is free software; you can redistribute it and/or modify it
rbackman@5791 6 * under the terms of the GNU General Public License version 2 only, as
rbackman@5791 7 * published by the Free Software Foundation.
rbackman@5791 8 *
rbackman@5791 9 * This code is distributed in the hope that it will be useful, but WITHOUT
rbackman@5791 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
rbackman@5791 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
rbackman@5791 12 * version 2 for more details (a copy is included in the LICENSE file that
rbackman@5791 13 * accompanied this code).
rbackman@5791 14 *
rbackman@5791 15 * You should have received a copy of the GNU General Public License version
rbackman@5791 16 * 2 along with this work; if not, write to the Free Software Foundation,
rbackman@5791 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
rbackman@5791 18 *
rbackman@5791 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
rbackman@5791 20 * or visit www.oracle.com if you need additional information or have any
rbackman@5791 21 * questions.
rbackman@5791 22 *
rbackman@5791 23 */
rbackman@5791 24
rbackman@5791 25 #include "precompiled.hpp"
rbackman@5791 26 #include "memory/allocation.inline.hpp"
rbackman@5791 27 #include "opto/addnode.hpp"
rbackman@5927 28 #include "opto/cfgnode.hpp"
rbackman@5791 29 #include "opto/machnode.hpp"
rbackman@5927 30 #include "opto/matcher.hpp"
rbackman@5791 31 #include "opto/mathexactnode.hpp"
rbackman@5791 32 #include "opto/subnode.hpp"
rbackman@5791 33
rbackman@5997 34 MathExactNode::MathExactNode(Node* ctrl, Node* in1) : MultiNode(2) {
rbackman@5997 35 init_class_id(Class_MathExact);
rbackman@5791 36 init_req(0, ctrl);
rbackman@5997 37 init_req(1, in1);
rbackman@5997 38 }
rbackman@5997 39
rbackman@5997 40 MathExactNode::MathExactNode(Node* ctrl, Node* in1, Node* in2) : MultiNode(3) {
rbackman@5997 41 init_class_id(Class_MathExact);
rbackman@5997 42 init_req(0, ctrl);
rbackman@5997 43 init_req(1, in1);
rbackman@5997 44 init_req(2, in2);
rbackman@5791 45 }
rbackman@5791 46
rbackman@5927 47 BoolNode* MathExactNode::bool_node() const {
rbackman@5927 48 Node* flags = flags_node();
rbackman@5927 49 BoolNode* boolnode = flags->unique_out()->as_Bool();
rbackman@5927 50 assert(boolnode != NULL, "must have BoolNode");
rbackman@5927 51 return boolnode;
rbackman@5927 52 }
rbackman@5927 53
rbackman@5927 54 IfNode* MathExactNode::if_node() const {
rbackman@5927 55 BoolNode* boolnode = bool_node();
rbackman@5927 56 IfNode* ifnode = boolnode->unique_out()->as_If();
rbackman@5927 57 assert(ifnode != NULL, "must have IfNode");
rbackman@5927 58 return ifnode;
rbackman@5927 59 }
rbackman@5927 60
rbackman@5927 61 Node* MathExactNode::control_node() const {
rbackman@5927 62 IfNode* ifnode = if_node();
rbackman@5927 63 return ifnode->in(0);
rbackman@5927 64 }
rbackman@5927 65
rbackman@5927 66 Node* MathExactNode::non_throwing_branch() const {
rbackman@5927 67 IfNode* ifnode = if_node();
rbackman@5927 68 if (bool_node()->_test._test == BoolTest::overflow) {
rbackman@5927 69 return ifnode->proj_out(0);
rbackman@5927 70 }
rbackman@5927 71 return ifnode->proj_out(1);
rbackman@5927 72 }
rbackman@5927 73
rbackman@5791 74 // If the MathExactNode won't overflow we have to replace the
rbackman@5791 75 // FlagsProjNode and ProjNode that is generated by the MathExactNode
rbackman@5997 76 Node* MathExactNode::no_overflow(PhaseGVN* phase, Node* new_result) {
rbackman@5997 77 PhaseIterGVN* igvn = phase->is_IterGVN();
rbackman@5791 78 if (igvn) {
rbackman@5791 79 ProjNode* result = result_node();
rbackman@5791 80 ProjNode* flags = flags_node();
rbackman@5791 81
rbackman@5791 82 if (result != NULL) {
rbackman@5791 83 igvn->replace_node(result, new_result);
rbackman@5791 84 }
rbackman@5791 85
rbackman@5791 86 if (flags != NULL) {
rbackman@5927 87 BoolNode* boolnode = bool_node();
rbackman@5927 88 switch (boolnode->_test._test) {
rbackman@5791 89 case BoolTest::overflow:
rbackman@5791 90 // if the check is for overflow - never taken
rbackman@5927 91 igvn->replace_node(boolnode, phase->intcon(0));
rbackman@5791 92 break;
rbackman@5791 93 case BoolTest::no_overflow:
rbackman@5791 94 // if the check is for no overflow - always taken
rbackman@5927 95 igvn->replace_node(boolnode, phase->intcon(1));
rbackman@5791 96 break;
rbackman@5791 97 default:
rbackman@5791 98 fatal("Unexpected value of BoolTest");
rbackman@5791 99 break;
rbackman@5791 100 }
rbackman@5791 101 flags->del_req(0);
rbackman@5791 102 }
rbackman@5791 103 }
rbackman@5791 104 return new_result;
rbackman@5791 105 }
rbackman@5791 106
rbackman@5997 107 Node* MathExactINode::match(const ProjNode* proj, const Matcher* m) {
rbackman@5997 108 uint ideal_reg = proj->ideal_reg();
rbackman@5997 109 RegMask rm;
rbackman@5997 110 if (proj->_con == result_proj_node) {
rbackman@5997 111 rm = m->mathExactI_result_proj_mask();
rbackman@5997 112 } else {
rbackman@5997 113 assert(proj->_con == flags_proj_node, "must be result or flags");
rbackman@5997 114 assert(ideal_reg == Op_RegFlags, "sanity");
rbackman@5997 115 rm = m->mathExactI_flags_proj_mask();
rbackman@5997 116 }
rbackman@5997 117 return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
rbackman@5997 118 }
rbackman@5997 119
rbackman@5997 120 Node* MathExactLNode::match(const ProjNode* proj, const Matcher* m) {
rbackman@5997 121 uint ideal_reg = proj->ideal_reg();
rbackman@5997 122 RegMask rm;
rbackman@5997 123 if (proj->_con == result_proj_node) {
rbackman@5997 124 rm = m->mathExactL_result_proj_mask();
rbackman@5997 125 } else {
rbackman@5997 126 assert(proj->_con == flags_proj_node, "must be result or flags");
rbackman@5997 127 assert(ideal_reg == Op_RegFlags, "sanity");
rbackman@5997 128 rm = m->mathExactI_flags_proj_mask();
rbackman@5997 129 }
rbackman@5997 130 return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
rbackman@5997 131 }
rbackman@5997 132
rbackman@5997 133 Node* AddExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 134 Node* arg1 = in(1);
rbackman@5997 135 Node* arg2 = in(2);
rbackman@5791 136
rbackman@5791 137 const Type* type1 = phase->type(arg1);
rbackman@5791 138 const Type* type2 = phase->type(arg2);
rbackman@5791 139
rbackman@5791 140 if (type1 != Type::TOP && type1->singleton() &&
rbackman@5791 141 type2 != Type::TOP && type2->singleton()) {
rbackman@5791 142 jint val1 = arg1->get_int();
rbackman@5791 143 jint val2 = arg2->get_int();
rbackman@5791 144 jint result = val1 + val2;
rbackman@5791 145 // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result
rbackman@5791 146 if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) {
rbackman@5791 147 Node* con_result = ConINode::make(phase->C, result);
rbackman@5791 148 return no_overflow(phase, con_result);
rbackman@5791 149 }
rbackman@5791 150 return NULL;
rbackman@5791 151 }
rbackman@5791 152
rbackman@5997 153 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { // (Add 0 x) == x
rbackman@5791 154 Node* add_result = new (phase->C) AddINode(arg1, arg2);
rbackman@5791 155 return no_overflow(phase, add_result);
rbackman@5791 156 }
rbackman@5791 157
rbackman@5791 158 if (type2->singleton()) {
rbackman@5791 159 return NULL; // no change - keep constant on the right
rbackman@5791 160 }
rbackman@5791 161
rbackman@5791 162 if (type1->singleton()) {
rbackman@5791 163 // Make it x + Constant - move constant to the right
rbackman@5791 164 swap_edges(1, 2);
rbackman@5791 165 return this;
rbackman@5791 166 }
rbackman@5791 167
rbackman@5791 168 if (arg2->is_Load()) {
rbackman@5791 169 return NULL; // no change - keep load on the right
rbackman@5791 170 }
rbackman@5791 171
rbackman@5791 172 if (arg1->is_Load()) {
rbackman@5791 173 // Make it x + Load - move load to the right
rbackman@5791 174 swap_edges(1, 2);
rbackman@5791 175 return this;
rbackman@5791 176 }
rbackman@5791 177
rbackman@5791 178 if (arg1->_idx > arg2->_idx) {
rbackman@5791 179 // Sort the edges
rbackman@5791 180 swap_edges(1, 2);
rbackman@5791 181 return this;
rbackman@5791 182 }
rbackman@5791 183
rbackman@5791 184 return NULL;
rbackman@5791 185 }
rbackman@5791 186
rbackman@5997 187 Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 188 Node* arg1 = in(1);
rbackman@5997 189 Node* arg2 = in(2);
rbackman@5997 190
rbackman@5997 191 const Type* type1 = phase->type(arg1);
rbackman@5997 192 const Type* type2 = phase->type(arg2);
rbackman@5997 193
rbackman@5997 194 if (type1 != Type::TOP && type1->singleton() &&
rbackman@5997 195 type2 != Type::TOP && type2->singleton()) {
rbackman@5997 196 jlong val1 = arg1->get_long();
rbackman@5997 197 jlong val2 = arg2->get_long();
rbackman@5997 198 jlong result = val1 + val2;
rbackman@5997 199 // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result
rbackman@5997 200 if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) {
rbackman@5997 201 Node* con_result = ConLNode::make(phase->C, result);
rbackman@5997 202 return no_overflow(phase, con_result);
rbackman@5997 203 }
rbackman@5997 204 return NULL;
rbackman@5997 205 }
rbackman@5997 206
rbackman@5997 207 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x
rbackman@5997 208 Node* add_result = new (phase->C) AddLNode(arg1, arg2);
rbackman@5997 209 return no_overflow(phase, add_result);
rbackman@5997 210 }
rbackman@5997 211
rbackman@5997 212 if (type2->singleton()) {
rbackman@5997 213 return NULL; // no change - keep constant on the right
rbackman@5997 214 }
rbackman@5997 215
rbackman@5997 216 if (type1->singleton()) {
rbackman@5997 217 // Make it x + Constant - move constant to the right
rbackman@5997 218 swap_edges(1, 2);
rbackman@5997 219 return this;
rbackman@5997 220 }
rbackman@5997 221
rbackman@5997 222 if (arg2->is_Load()) {
rbackman@5997 223 return NULL; // no change - keep load on the right
rbackman@5997 224 }
rbackman@5997 225
rbackman@5997 226 if (arg1->is_Load()) {
rbackman@5997 227 // Make it x + Load - move load to the right
rbackman@5997 228 swap_edges(1, 2);
rbackman@5997 229 return this;
rbackman@5997 230 }
rbackman@5997 231
rbackman@5997 232 if (arg1->_idx > arg2->_idx) {
rbackman@5997 233 // Sort the edges
rbackman@5997 234 swap_edges(1, 2);
rbackman@5997 235 return this;
rbackman@5997 236 }
rbackman@5997 237
rbackman@5997 238 return NULL;
rbackman@5997 239 }
rbackman@5997 240
rbackman@5997 241 Node* SubExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 242 Node* arg1 = in(1);
rbackman@5997 243 Node* arg2 = in(2);
rbackman@5997 244
rbackman@5997 245 const Type* type1 = phase->type(arg1);
rbackman@5997 246 const Type* type2 = phase->type(arg2);
rbackman@5997 247
rbackman@5997 248 if (type1 != Type::TOP && type1->singleton() &&
rbackman@5997 249 type2 != Type::TOP && type2->singleton()) {
rbackman@5997 250 jint val1 = arg1->get_int();
rbackman@5997 251 jint val2 = arg2->get_int();
rbackman@5997 252 jint result = val1 - val2;
rbackman@5997 253
rbackman@5997 254 // Hacker's Delight 2-12 Overflow iff the arguments have different signs and
rbackman@5997 255 // the sign of the result is different than the sign of arg1
rbackman@5997 256 if (((val1 ^ val2) & (val1 ^ result)) >= 0) {
rbackman@5997 257 Node* con_result = ConINode::make(phase->C, result);
rbackman@5997 258 return no_overflow(phase, con_result);
rbackman@5997 259 }
rbackman@5997 260 return NULL;
rbackman@5997 261 }
rbackman@5997 262
rbackman@5997 263 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) {
rbackman@5997 264 // Sub with zero is the same as add with zero
rbackman@5997 265 Node* add_result = new (phase->C) AddINode(arg1, arg2);
rbackman@5997 266 return no_overflow(phase, add_result);
rbackman@5997 267 }
rbackman@5997 268
rbackman@5997 269 return NULL;
rbackman@5997 270 }
rbackman@5997 271
rbackman@5997 272 Node* SubExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 273 Node* arg1 = in(1);
rbackman@5997 274 Node* arg2 = in(2);
rbackman@5997 275
rbackman@5997 276 const Type* type1 = phase->type(arg1);
rbackman@5997 277 const Type* type2 = phase->type(arg2);
rbackman@5997 278
rbackman@5997 279 if (type1 != Type::TOP && type1->singleton() &&
rbackman@5997 280 type2 != Type::TOP && type2->singleton()) {
rbackman@5997 281 jlong val1 = arg1->get_long();
rbackman@5997 282 jlong val2 = arg2->get_long();
rbackman@5997 283 jlong result = val1 - val2;
rbackman@5997 284
rbackman@5997 285 // Hacker's Delight 2-12 Overflow iff the arguments have different signs and
rbackman@5997 286 // the sign of the result is different than the sign of arg1
rbackman@5997 287 if (((val1 ^ val2) & (val1 ^ result)) >= 0) {
rbackman@5997 288 Node* con_result = ConLNode::make(phase->C, result);
rbackman@5997 289 return no_overflow(phase, con_result);
rbackman@5997 290 }
rbackman@5997 291 return NULL;
rbackman@5997 292 }
rbackman@5997 293
rbackman@5997 294 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) {
rbackman@5997 295 // Sub with zero is the same as add with zero
rbackman@5997 296 Node* add_result = new (phase->C) AddLNode(arg1, arg2);
rbackman@5997 297 return no_overflow(phase, add_result);
rbackman@5997 298 }
rbackman@5997 299
rbackman@5997 300 return NULL;
rbackman@5997 301 }
rbackman@5997 302
rbackman@5997 303 Node* NegExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 304 Node *arg = in(1);
rbackman@5997 305
rbackman@5997 306 const Type* type = phase->type(arg);
rbackman@5997 307 if (type != Type::TOP && type->singleton()) {
rbackman@5997 308 jint value = arg->get_int();
rbackman@5997 309 if (value != min_jint) {
rbackman@5997 310 Node* neg_result = ConINode::make(phase->C, -value);
rbackman@5997 311 return no_overflow(phase, neg_result);
rbackman@5997 312 }
rbackman@5997 313 }
rbackman@5997 314 return NULL;
rbackman@5997 315 }
rbackman@5997 316
rbackman@5997 317 Node* NegExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 318 Node *arg = in(1);
rbackman@5997 319
rbackman@5997 320 const Type* type = phase->type(arg);
rbackman@5997 321 if (type != Type::TOP && type->singleton()) {
rbackman@5997 322 jlong value = arg->get_long();
rbackman@5997 323 if (value != min_jlong) {
rbackman@5997 324 Node* neg_result = ConLNode::make(phase->C, -value);
rbackman@5997 325 return no_overflow(phase, neg_result);
rbackman@5997 326 }
rbackman@5997 327 }
rbackman@5997 328 return NULL;
rbackman@5997 329 }
rbackman@5997 330
rbackman@5997 331 Node* MulExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 332 Node* arg1 = in(1);
rbackman@5997 333 Node* arg2 = in(2);
rbackman@5997 334
rbackman@5997 335 const Type* type1 = phase->type(arg1);
rbackman@5997 336 const Type* type2 = phase->type(arg2);
rbackman@5997 337
rbackman@5997 338 if (type1 != Type::TOP && type1->singleton() &&
rbackman@5997 339 type2 != Type::TOP && type2->singleton()) {
rbackman@5997 340 jint val1 = arg1->get_int();
rbackman@5997 341 jint val2 = arg2->get_int();
rbackman@5997 342 jlong result = (jlong) val1 * (jlong) val2;
rbackman@5997 343 if ((jint) result == result) {
rbackman@5997 344 // no overflow
rbackman@5997 345 Node* mul_result = ConINode::make(phase->C, result);
rbackman@5997 346 return no_overflow(phase, mul_result);
rbackman@5997 347 }
rbackman@5997 348 }
rbackman@5997 349
rbackman@5997 350 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) {
rbackman@5997 351 return no_overflow(phase, ConINode::make(phase->C, 0));
rbackman@5997 352 }
rbackman@5997 353
rbackman@5997 354 if (type1 == TypeInt::ONE) {
rbackman@5997 355 Node* mul_result = new (phase->C) AddINode(arg2, phase->intcon(0));
rbackman@5997 356 return no_overflow(phase, mul_result);
rbackman@5997 357 }
rbackman@5997 358 if (type2 == TypeInt::ONE) {
rbackman@5997 359 Node* mul_result = new (phase->C) AddINode(arg1, phase->intcon(0));
rbackman@5997 360 return no_overflow(phase, mul_result);
rbackman@5997 361 }
rbackman@5997 362
rbackman@5997 363 if (type1 == TypeInt::MINUS_1) {
rbackman@5997 364 return new (phase->C) NegExactINode(NULL, arg2);
rbackman@5997 365 }
rbackman@5997 366
rbackman@5997 367 if (type2 == TypeInt::MINUS_1) {
rbackman@5997 368 return new (phase->C) NegExactINode(NULL, arg1);
rbackman@5997 369 }
rbackman@5997 370
rbackman@5997 371 return NULL;
rbackman@5997 372 }
rbackman@5997 373
rbackman@5997 374 Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
rbackman@5997 375 Node* arg1 = in(1);
rbackman@5997 376 Node* arg2 = in(2);
rbackman@5997 377
rbackman@5997 378 const Type* type1 = phase->type(arg1);
rbackman@5997 379 const Type* type2 = phase->type(arg2);
rbackman@5997 380
rbackman@5997 381 if (type1 != Type::TOP && type1->singleton() &&
rbackman@5997 382 type2 != Type::TOP && type2->singleton()) {
rbackman@5997 383 jlong val1 = arg1->get_long();
rbackman@5997 384 jlong val2 = arg2->get_long();
rbackman@5997 385
rbackman@5997 386 jlong result = val1 * val2;
rbackman@5997 387 jlong ax = (val1 < 0 ? -val1 : val1);
rbackman@5997 388 jlong ay = (val2 < 0 ? -val2 : val2);
rbackman@5997 389
rbackman@5997 390 bool overflow = false;
rbackman@5997 391 if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) {
rbackman@5997 392 // potential overflow if any bit in upper 32 bits are set
rbackman@5997 393 if ((val1 == min_jlong && val2 == -1) || (val2 == min_jlong && val1 == -1)) {
rbackman@5997 394 // -1 * Long.MIN_VALUE will overflow
rbackman@5997 395 overflow = true;
rbackman@5997 396 } else if (val2 != 0 && (result / val2 != val1)) {
rbackman@5997 397 overflow = true;
rbackman@5997 398 }
rbackman@5997 399 }
rbackman@5997 400
rbackman@5997 401 if (!overflow) {
rbackman@5997 402 Node* mul_result = ConLNode::make(phase->C, result);
rbackman@5997 403 return no_overflow(phase, mul_result);
rbackman@5997 404 }
rbackman@5997 405 }
rbackman@5997 406
rbackman@5997 407 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) {
rbackman@5997 408 return no_overflow(phase, ConLNode::make(phase->C, 0));
rbackman@5997 409 }
rbackman@5997 410
rbackman@5997 411 if (type1 == TypeLong::ONE) {
rbackman@5997 412 Node* mul_result = new (phase->C) AddLNode(arg2, phase->longcon(0));
rbackman@5997 413 return no_overflow(phase, mul_result);
rbackman@5997 414 }
rbackman@5997 415 if (type2 == TypeLong::ONE) {
rbackman@5997 416 Node* mul_result = new (phase->C) AddLNode(arg1, phase->longcon(0));
rbackman@5997 417 return no_overflow(phase, mul_result);
rbackman@5997 418 }
rbackman@5997 419
rbackman@5997 420 if (type1 == TypeLong::MINUS_1) {
rbackman@5997 421 return new (phase->C) NegExactLNode(NULL, arg2);
rbackman@5997 422 }
rbackman@5997 423
rbackman@5997 424 if (type2 == TypeLong::MINUS_1) {
rbackman@5997 425 return new (phase->C) NegExactLNode(NULL, arg1);
rbackman@5997 426 }
rbackman@5997 427
rbackman@5997 428 return NULL;
rbackman@5997 429 }
rbackman@5997 430

mercurial