< prev index next >

src/hotspot/share/c1/c1_Canonicalizer.cpp

Print this page

  1 /*
  2  * Copyright (c) 1999, 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  *

263     ciField* field = lf->field();
264     if (field->is_static_constant()) {
265       // Constant field loads are usually folded during parsing.
266       // But it doesn't happen with PatchALot, ScavengeRootsInCode < 2, or when
267       // holder class is being initialized during parsing (for static fields).
268       ciObject* c = field->constant_value().as_object();
269       if (!c->is_null_object()) {
270         set_constant(c->as_array()->length());
271       }
272     }
273   }
274 }
275 
276 void Canonicalizer::do_LoadIndexed    (LoadIndexed*     x) {
277   StableArrayConstant* array = x->array()->type()->as_StableArrayConstant();
278   IntConstant* index = x->index()->type()->as_IntConstant();
279 
280   assert(array == nullptr || FoldStableValues, "not enabled");
281 
282   // Constant fold loads from stable arrays.
283   if (!x->mismatched() && array != nullptr && index != nullptr) {
284     jint idx = index->value();
285     if (idx < 0 || idx >= array->value()->length()) {
286       // Leave the load as is. The range check will handle it.
287       return;
288     }
289 
290     ciConstant field_val = array->value()->element_value(idx);
291     if (!field_val.is_null_or_zero()) {
292       jint dimension = array->dimension();
293       assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info");
294       ValueType* value = nullptr;
295       if (dimension > 1) {
296         // Preserve information about the dimension for the element.
297         assert(field_val.as_object()->is_array(), "not an array");
298         value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1);
299       } else {
300         assert(dimension == 1, "sanity");
301         value = as_ValueType(field_val);
302       }
303       set_canonical(new Constant(value));

451         double vy = x->y()->type()->as_DoubleConstant()->value();
452         if (g_isnan(vx) || g_isnan(vy))
453           set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1);
454         else if (vx == vy)
455           set_constant(0);
456         else if (vx < vy)
457           set_constant(-1);
458         else
459           set_constant(1);
460         break;
461       }
462 
463       default:
464         break;
465     }
466   }
467 }
468 
469 
470 void Canonicalizer::do_IfOp(IfOp* x) {
471   // Currently, Canonicalizer is only used by GraphBuilder,
472   // and IfOp is not created by GraphBuilder but only later
473   // when eliminating conditional expressions with CE_Eliminator,
474   // so this method will not be called.
475   ShouldNotReachHere();
476 }
477 
478 
479 void Canonicalizer::do_Intrinsic      (Intrinsic*       x) {
480   switch (x->id()) {
481   case vmIntrinsics::_floatToRawIntBits   : {
482     FloatConstant* c = x->argument_at(0)->type()->as_FloatConstant();
483     if (c != nullptr) {
484       JavaValue v;
485       v.set_jfloat(c->value());
486       set_constant(v.get_jint());
487     }
488     break;
489   }
490   case vmIntrinsics::_intBitsToFloat      : {
491     IntConstant* c = x->argument_at(0)->type()->as_IntConstant();
492     if (c != nullptr) {
493       JavaValue v;
494       v.set_jint(c->value());
495       set_constant(v.get_jfloat());

631 }
632 
633 void Canonicalizer::do_TypeCast       (TypeCast*        x) {}
634 void Canonicalizer::do_Invoke         (Invoke*          x) {}
635 void Canonicalizer::do_NewInstance    (NewInstance*     x) {}
636 void Canonicalizer::do_NewTypeArray   (NewTypeArray*    x) {}
637 void Canonicalizer::do_NewObjectArray (NewObjectArray*  x) {}
638 void Canonicalizer::do_NewMultiArray  (NewMultiArray*   x) {}
639 void Canonicalizer::do_CheckCast      (CheckCast*       x) {
640   if (x->klass()->is_loaded()) {
641     Value obj = x->obj();
642     ciType* klass = obj->exact_type();
643     if (klass == nullptr) {
644       klass = obj->declared_type();
645     }
646     if (klass != nullptr && klass->is_loaded()) {
647       bool is_interface = klass->is_instance_klass() &&
648                           klass->as_instance_klass()->is_interface();
649       // Interface casts can't be statically optimized away since verifier doesn't
650       // enforce interface types in bytecode.
651       if (!is_interface && klass->is_subtype_of(x->klass())) {

652         set_canonical(obj);
653         return;
654       }
655     }
656     // checkcast of null returns null
657     if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) {
658       set_canonical(obj);
659     }
660   }
661 }
662 void Canonicalizer::do_InstanceOf     (InstanceOf*      x) {
663   if (x->klass()->is_loaded()) {
664     Value obj = x->obj();
665     ciType* exact = obj->exact_type();
666     if (exact != nullptr && exact->is_loaded() && (obj->as_NewInstance() || obj->as_NewArray())) {
667       set_constant(exact->is_subtype_of(x->klass()) ? 1 : 0);
668       return;
669     }
670     // instanceof null returns false
671     if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) {
672       set_constant(0);
673     }
674   }
675 
676 }
677 void Canonicalizer::do_MonitorEnter   (MonitorEnter*    x) {}
678 void Canonicalizer::do_MonitorExit    (MonitorExit*     x) {}
679 void Canonicalizer::do_BlockBegin     (BlockBegin*      x) {}
680 void Canonicalizer::do_Goto           (Goto*            x) {}
681 
682 
683 static bool is_true(jlong x, If::Condition cond, jlong y) {
684   switch (cond) {
685     case If::eql: return x == y;
686     case If::neq: return x != y;
687     case If::lss: return x <  y;
688     case If::leq: return x <= y;
689     case If::gtr: return x >  y;
690     case If::geq: return x >= y;
691     default:

828         high = mid - 1;
829       } else {
830         low = mid + 1;
831       }
832     }
833     set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
834   }
835 }
836 
837 
838 void Canonicalizer::do_Return         (Return*          x) {}
839 void Canonicalizer::do_Throw          (Throw*           x) {}
840 void Canonicalizer::do_Base           (Base*            x) {}
841 void Canonicalizer::do_OsrEntry       (OsrEntry*        x) {}
842 void Canonicalizer::do_ExceptionObject(ExceptionObject* x) {}
843 void Canonicalizer::do_UnsafeGet      (UnsafeGet*       x) {}
844 void Canonicalizer::do_UnsafePut      (UnsafePut*       x) {}
845 void Canonicalizer::do_UnsafeGetAndSet(UnsafeGetAndSet* x) {}
846 void Canonicalizer::do_ProfileCall    (ProfileCall*     x) {}
847 void Canonicalizer::do_ProfileReturnType(ProfileReturnType* x) {}
848 void Canonicalizer::do_ProfileInvoke  (ProfileInvoke*   x) {}
849 void Canonicalizer::do_RuntimeCall    (RuntimeCall*     x) {}

850 void Canonicalizer::do_RangeCheckPredicate(RangeCheckPredicate* x) {}
851 #ifdef ASSERT
852 void Canonicalizer::do_Assert         (Assert*          x) {}
853 #endif
854 void Canonicalizer::do_MemBar         (MemBar*          x) {}

  1 /*
  2  * Copyright (c) 1999, 2026, 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  *

263     ciField* field = lf->field();
264     if (field->is_static_constant()) {
265       // Constant field loads are usually folded during parsing.
266       // But it doesn't happen with PatchALot, ScavengeRootsInCode < 2, or when
267       // holder class is being initialized during parsing (for static fields).
268       ciObject* c = field->constant_value().as_object();
269       if (!c->is_null_object()) {
270         set_constant(c->as_array()->length());
271       }
272     }
273   }
274 }
275 
276 void Canonicalizer::do_LoadIndexed    (LoadIndexed*     x) {
277   StableArrayConstant* array = x->array()->type()->as_StableArrayConstant();
278   IntConstant* index = x->index()->type()->as_IntConstant();
279 
280   assert(array == nullptr || FoldStableValues, "not enabled");
281 
282   // Constant fold loads from stable arrays.
283   if (!x->should_profile() && !x->mismatched() && array != nullptr && index != nullptr) {
284     jint idx = index->value();
285     if (idx < 0 || idx >= array->value()->length()) {
286       // Leave the load as is. The range check will handle it.
287       return;
288     }
289 
290     ciConstant field_val = array->value()->element_value(idx);
291     if (!field_val.is_null_or_zero()) {
292       jint dimension = array->dimension();
293       assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info");
294       ValueType* value = nullptr;
295       if (dimension > 1) {
296         // Preserve information about the dimension for the element.
297         assert(field_val.as_object()->is_array(), "not an array");
298         value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1);
299       } else {
300         assert(dimension == 1, "sanity");
301         value = as_ValueType(field_val);
302       }
303       set_canonical(new Constant(value));

451         double vy = x->y()->type()->as_DoubleConstant()->value();
452         if (g_isnan(vx) || g_isnan(vy))
453           set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1);
454         else if (vx == vy)
455           set_constant(0);
456         else if (vx < vy)
457           set_constant(-1);
458         else
459           set_constant(1);
460         break;
461       }
462 
463       default:
464         break;
465     }
466   }
467 }
468 
469 
470 void Canonicalizer::do_IfOp(IfOp* x) {
471   // Currently, Canonicalizer is only used by GraphBuilder, and IfOp is only created by
472   // GraphBuilder when loading/storing flat fields, do nothing for now.



473 }
474 
475 
476 void Canonicalizer::do_Intrinsic      (Intrinsic*       x) {
477   switch (x->id()) {
478   case vmIntrinsics::_floatToRawIntBits   : {
479     FloatConstant* c = x->argument_at(0)->type()->as_FloatConstant();
480     if (c != nullptr) {
481       JavaValue v;
482       v.set_jfloat(c->value());
483       set_constant(v.get_jint());
484     }
485     break;
486   }
487   case vmIntrinsics::_intBitsToFloat      : {
488     IntConstant* c = x->argument_at(0)->type()->as_IntConstant();
489     if (c != nullptr) {
490       JavaValue v;
491       v.set_jint(c->value());
492       set_constant(v.get_jfloat());

628 }
629 
630 void Canonicalizer::do_TypeCast       (TypeCast*        x) {}
631 void Canonicalizer::do_Invoke         (Invoke*          x) {}
632 void Canonicalizer::do_NewInstance    (NewInstance*     x) {}
633 void Canonicalizer::do_NewTypeArray   (NewTypeArray*    x) {}
634 void Canonicalizer::do_NewObjectArray (NewObjectArray*  x) {}
635 void Canonicalizer::do_NewMultiArray  (NewMultiArray*   x) {}
636 void Canonicalizer::do_CheckCast      (CheckCast*       x) {
637   if (x->klass()->is_loaded()) {
638     Value obj = x->obj();
639     ciType* klass = obj->exact_type();
640     if (klass == nullptr) {
641       klass = obj->declared_type();
642     }
643     if (klass != nullptr && klass->is_loaded()) {
644       bool is_interface = klass->is_instance_klass() &&
645                           klass->as_instance_klass()->is_interface();
646       // Interface casts can't be statically optimized away since verifier doesn't
647       // enforce interface types in bytecode.
648       if (!is_interface && klass->is_subtype_of(x->klass()) && (!x->is_null_free() || obj->is_null_free())) {
649         assert(!x->klass()->is_inlinetype() || x->klass() == klass, "Inline klasses can't have subtypes");
650         set_canonical(obj);
651         return;
652       }
653     }
654     // checkcast of null returns null for non null-free klasses
655     if (!x->is_null_free() && obj->is_null_obj()) {
656       set_canonical(obj);
657     }
658   }
659 }
660 void Canonicalizer::do_InstanceOf     (InstanceOf*      x) {
661   if (x->klass()->is_loaded()) {
662     Value obj = x->obj();
663     ciType* exact = obj->exact_type();
664     if (exact != nullptr && exact->is_loaded() && (obj->as_NewInstance() || obj->as_NewArray())) {
665       set_constant(exact->is_subtype_of(x->klass()) ? 1 : 0);
666       return;
667     }
668     // instanceof null returns false
669     if (obj->as_Constant() && obj->is_null_obj()) {
670       set_constant(0);
671     }
672   }
673 
674 }
675 void Canonicalizer::do_MonitorEnter   (MonitorEnter*    x) {}
676 void Canonicalizer::do_MonitorExit    (MonitorExit*     x) {}
677 void Canonicalizer::do_BlockBegin     (BlockBegin*      x) {}
678 void Canonicalizer::do_Goto           (Goto*            x) {}
679 
680 
681 static bool is_true(jlong x, If::Condition cond, jlong y) {
682   switch (cond) {
683     case If::eql: return x == y;
684     case If::neq: return x != y;
685     case If::lss: return x <  y;
686     case If::leq: return x <= y;
687     case If::gtr: return x >  y;
688     case If::geq: return x >= y;
689     default:

826         high = mid - 1;
827       } else {
828         low = mid + 1;
829       }
830     }
831     set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
832   }
833 }
834 
835 
836 void Canonicalizer::do_Return         (Return*          x) {}
837 void Canonicalizer::do_Throw          (Throw*           x) {}
838 void Canonicalizer::do_Base           (Base*            x) {}
839 void Canonicalizer::do_OsrEntry       (OsrEntry*        x) {}
840 void Canonicalizer::do_ExceptionObject(ExceptionObject* x) {}
841 void Canonicalizer::do_UnsafeGet      (UnsafeGet*       x) {}
842 void Canonicalizer::do_UnsafePut      (UnsafePut*       x) {}
843 void Canonicalizer::do_UnsafeGetAndSet(UnsafeGetAndSet* x) {}
844 void Canonicalizer::do_ProfileCall    (ProfileCall*     x) {}
845 void Canonicalizer::do_ProfileReturnType(ProfileReturnType* x) {}
846 void Canonicalizer::do_ProfileInvoke    (ProfileInvoke* x) {}
847 void Canonicalizer::do_ProfileACmpTypes (ProfileACmpTypes* x) {}
848 void Canonicalizer::do_RuntimeCall      (RuntimeCall* x) {}
849 void Canonicalizer::do_RangeCheckPredicate(RangeCheckPredicate* x) {}
850 #ifdef ASSERT
851 void Canonicalizer::do_Assert         (Assert*          x) {}
852 #endif
853 void Canonicalizer::do_MemBar         (MemBar*          x) {}
< prev index next >