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