src/hotspot/share/c1/c1_RangeCheckElimination.hpp
changeset 47216 71c04702a3d5
parent 38031 e0b822facc03
child 49373 47b5652f2928
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2012, 2016, 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_VM_C1_C1_RANGECHECKELIMINATION_HPP
       
    26 #define SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP
       
    27 
       
    28 #include "c1/c1_Instruction.hpp"
       
    29 
       
    30 // Base class for range check elimination
       
    31 class RangeCheckElimination : AllStatic {
       
    32 public:
       
    33   static void eliminate(IR *ir);
       
    34 };
       
    35 
       
    36 // Implementation
       
    37 class RangeCheckEliminator VALUE_OBJ_CLASS_SPEC {
       
    38 private:
       
    39   int _number_of_instructions;
       
    40   bool _optimistic; // Insert predicates and deoptimize when they fail
       
    41   IR *_ir;
       
    42 
       
    43   typedef GrowableArray<BlockBegin*> BlockBeginList;
       
    44   typedef GrowableArray<int> IntegerStack;
       
    45 
       
    46   class Verification : public BlockClosure {
       
    47   // RangeCheckEliminator::Verification should never get instatiated on the heap.
       
    48   private:
       
    49     void* operator new(size_t size) throw();
       
    50     void* operator new[](size_t size) throw();
       
    51     void operator delete(void* p) { ShouldNotReachHere(); }
       
    52     void operator delete[](void* p) { ShouldNotReachHere(); }
       
    53 
       
    54     IR *_ir;
       
    55     boolArray _used;
       
    56     BlockBeginList _current;
       
    57     BlockBeginList _successors;
       
    58 
       
    59   public:
       
    60     Verification(IR *ir);
       
    61     virtual void block_do(BlockBegin *block);
       
    62     bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL);
       
    63     bool dominates(BlockBegin *dominator, BlockBegin *block);
       
    64   };
       
    65 
       
    66 public:
       
    67   // Bounds for an instruction in the form x + c which c integer
       
    68   // constant and x another instruction
       
    69   class Bound : public CompilationResourceObj {
       
    70   private:
       
    71     int _upper;
       
    72     Value _upper_instr;
       
    73     int _lower;
       
    74     Value _lower_instr;
       
    75 
       
    76   public:
       
    77     Bound();
       
    78     Bound(Value v);
       
    79     Bound(Instruction::Condition cond, Value v, int constant = 0);
       
    80     Bound(int lower, Value lower_instr, int upper, Value upper_instr);
       
    81     ~Bound();
       
    82 
       
    83 #ifdef ASSERT
       
    84     void add_assertion(Instruction *instruction, Instruction *position, int i, Value instr, Instruction::Condition cond);
       
    85 #endif
       
    86     int upper();
       
    87     Value upper_instr();
       
    88     int lower();
       
    89     Value lower_instr();
       
    90     void print();
       
    91     bool check_no_overflow(int const_value);
       
    92     void or_op(Bound *b);
       
    93     void and_op(Bound *b);
       
    94     bool has_upper();
       
    95     bool has_lower();
       
    96     void set_upper(int upper, Value upper_instr);
       
    97     void set_lower(int lower, Value lower_instr);
       
    98     bool is_smaller(Bound *b);
       
    99     void remove_upper();
       
   100     void remove_lower();
       
   101     void add_constant(int value);
       
   102     Bound *copy();
       
   103 
       
   104   private:
       
   105     void init();
       
   106   };
       
   107 
       
   108 
       
   109   class Visitor : public InstructionVisitor {
       
   110   private:
       
   111     Bound *_bound;
       
   112     RangeCheckEliminator *_rce;
       
   113 
       
   114   public:
       
   115     void set_range_check_eliminator(RangeCheckEliminator *rce) { _rce = rce; }
       
   116     Bound *bound() const { return _bound; }
       
   117     void clear_bound() { _bound = NULL; }
       
   118 
       
   119   protected:
       
   120     // visitor functions
       
   121     void do_Constant       (Constant*        x);
       
   122     void do_IfOp           (IfOp*            x);
       
   123     void do_LogicOp        (LogicOp*         x);
       
   124     void do_ArithmeticOp   (ArithmeticOp*    x);
       
   125     void do_Phi            (Phi*             x);
       
   126 
       
   127     void do_StoreField     (StoreField*      x) { /* nothing to do */ };
       
   128     void do_StoreIndexed   (StoreIndexed*    x) { /* nothing to do */ };
       
   129     void do_MonitorEnter   (MonitorEnter*    x) { /* nothing to do */ };
       
   130     void do_MonitorExit    (MonitorExit*     x) { /* nothing to do */ };
       
   131     void do_Invoke         (Invoke*          x) { /* nothing to do */ };
       
   132     void do_UnsafePutRaw   (UnsafePutRaw*    x) { /* nothing to do */ };
       
   133     void do_UnsafePutObject(UnsafePutObject* x) { /* nothing to do */ };
       
   134     void do_Intrinsic      (Intrinsic*       x) { /* nothing to do */ };
       
   135     void do_Local          (Local*           x) { /* nothing to do */ };
       
   136     void do_LoadField      (LoadField*       x) { /* nothing to do */ };
       
   137     void do_ArrayLength    (ArrayLength*     x) { /* nothing to do */ };
       
   138     void do_LoadIndexed    (LoadIndexed*     x) { /* nothing to do */ };
       
   139     void do_NegateOp       (NegateOp*        x) { /* nothing to do */ };
       
   140     void do_ShiftOp        (ShiftOp*         x) { /* nothing to do */ };
       
   141     void do_CompareOp      (CompareOp*       x) { /* nothing to do */ };
       
   142     void do_Convert        (Convert*         x) { /* nothing to do */ };
       
   143     void do_NullCheck      (NullCheck*       x) { /* nothing to do */ };
       
   144     void do_TypeCast       (TypeCast*        x) { /* nothing to do */ };
       
   145     void do_NewInstance    (NewInstance*     x) { /* nothing to do */ };
       
   146     void do_NewTypeArray   (NewTypeArray*    x) { /* nothing to do */ };
       
   147     void do_NewObjectArray (NewObjectArray*  x) { /* nothing to do */ };
       
   148     void do_NewMultiArray  (NewMultiArray*   x) { /* nothing to do */ };
       
   149     void do_CheckCast      (CheckCast*       x) { /* nothing to do */ };
       
   150     void do_InstanceOf     (InstanceOf*      x) { /* nothing to do */ };
       
   151     void do_BlockBegin     (BlockBegin*      x) { /* nothing to do */ };
       
   152     void do_Goto           (Goto*            x) { /* nothing to do */ };
       
   153     void do_If             (If*              x) { /* nothing to do */ };
       
   154     void do_IfInstanceOf   (IfInstanceOf*    x) { /* nothing to do */ };
       
   155     void do_TableSwitch    (TableSwitch*     x) { /* nothing to do */ };
       
   156     void do_LookupSwitch   (LookupSwitch*    x) { /* nothing to do */ };
       
   157     void do_Return         (Return*          x) { /* nothing to do */ };
       
   158     void do_Throw          (Throw*           x) { /* nothing to do */ };
       
   159     void do_Base           (Base*            x) { /* nothing to do */ };
       
   160     void do_OsrEntry       (OsrEntry*        x) { /* nothing to do */ };
       
   161     void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ };
       
   162     void do_RoundFP        (RoundFP*         x) { /* nothing to do */ };
       
   163     void do_UnsafeGetRaw   (UnsafeGetRaw*    x) { /* nothing to do */ };
       
   164     void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ };
       
   165     void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { /* nothing to do */ };
       
   166     void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ };
       
   167     void do_ProfileReturnType (ProfileReturnType*  x) { /* nothing to do */ };
       
   168     void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
       
   169     void do_RuntimeCall    (RuntimeCall*     x) { /* nothing to do */ };
       
   170     void do_MemBar         (MemBar*          x) { /* nothing to do */ };
       
   171     void do_RangeCheckPredicate(RangeCheckPredicate* x) { /* nothing to do */ };
       
   172 #ifdef ASSERT
       
   173     void do_Assert         (Assert*          x) { /* nothing to do */ };
       
   174 #endif
       
   175   };
       
   176 
       
   177 #ifdef ASSERT
       
   178   void add_assertions(Bound *bound, Instruction *instruction, Instruction *position);
       
   179 #endif
       
   180 
       
   181   typedef GrowableArray<Bound*> BoundStack;
       
   182   typedef GrowableArray<BoundStack*> BoundMap;
       
   183   typedef GrowableArray<AccessIndexed*> AccessIndexedList;
       
   184   typedef GrowableArray<Instruction*> InstructionList;
       
   185 
       
   186   class AccessIndexedInfo : public CompilationResourceObj  {
       
   187   public:
       
   188     AccessIndexedList *_list;
       
   189     int _min;
       
   190     int _max;
       
   191   };
       
   192 
       
   193   typedef GrowableArray<AccessIndexedInfo*> AccessIndexedInfoArray;
       
   194   BoundMap _bounds; // Mapping from Instruction's id to current bound
       
   195   AccessIndexedInfoArray _access_indexed_info; // Mapping from Instruction's id to AccessIndexedInfo for in block motion
       
   196   Visitor _visitor;
       
   197 
       
   198 public:
       
   199   RangeCheckEliminator(IR *ir);
       
   200 
       
   201   IR *ir() const { return _ir; }
       
   202 
       
   203   // Pass over the dominator tree to identify blocks where there's an oppportunity for optimization
       
   204   bool set_process_block_flags(BlockBegin *block);
       
   205   // The core of the optimization work: pass over the dominator tree
       
   206   // to propagate bound information, insert predicate out of loops,
       
   207   // eliminate bound checks when possible and perform in block motion
       
   208   void calc_bounds(BlockBegin *block, BlockBegin *loop_header);
       
   209   // reorder bound checks within a block in order to eliminate some of them
       
   210   void in_block_motion(BlockBegin *block, AccessIndexedList &accessIndexed, InstructionList &arrays);
       
   211 
       
   212   // update/access current bound
       
   213   void update_bound(IntegerStack &pushed, Value v, Instruction::Condition cond, Value value, int constant);
       
   214   void update_bound(IntegerStack &pushed, Value v, Bound *bound);
       
   215   Bound *get_bound(Value v);
       
   216 
       
   217   bool loop_invariant(BlockBegin *loop_header, Instruction *instruction);                                    // check for loop invariance
       
   218   void add_access_indexed_info(InstructionList &indices, int i, Value instruction, AccessIndexed *ai); // record indexed access for in block motion
       
   219   void remove_range_check(AccessIndexed *ai);                                                                // Mark this instructions as not needing a range check
       
   220   void add_if_condition(IntegerStack &pushed, Value x, Value y, Instruction::Condition condition);           // Update bound for an If
       
   221   bool in_array_bound(Bound *bound, Value array);                                                            // Check whether bound is known to fall within array
       
   222 
       
   223   // helper functions to work with predicates
       
   224   Instruction* insert_after(Instruction* insert_position, Instruction* instr, int bci);
       
   225   Instruction* predicate(Instruction* left, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1);
       
   226   Instruction* predicate_cmp_with_const(Instruction* instr, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=1);
       
   227   Instruction* predicate_add(Instruction* left, int left_const, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1);
       
   228   Instruction* predicate_add_cmp_with_const(Instruction* left, int left_const, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=-1);
       
   229 
       
   230   void insert_deoptimization(ValueStack *state, Instruction *insert_position, Instruction *array_instr,      // Add predicate
       
   231                              Instruction *length_instruction, Instruction *lower_instr, int lower,
       
   232                              Instruction *upper_instr, int upper, AccessIndexed *ai);
       
   233   bool is_ok_for_deoptimization(Instruction *insert_position, Instruction *array_instr,                      // Can we safely add a predicate?
       
   234                                 Instruction *length_instr, Instruction *lower_instr,
       
   235                                 int lower, Instruction *upper_instr, int upper);
       
   236   void process_if(IntegerStack &pushed, BlockBegin *block, If *cond);                                        // process If Instruction
       
   237   void process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai);                // process indexed access
       
   238 
       
   239   void dump_condition_stack(BlockBegin *cur_block);
       
   240   static void print_statistics();
       
   241 };
       
   242 
       
   243 #endif // SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP