@@ -2774,12 +2774,33 @@ class MergePrimitiveStores : public StackObj {
27742774private:
27752775 PhaseGVN* const _phase;
27762776 StoreNode* const _store;
2777+ // State machine with initial state Unknown
2778+ // Allowed transitions:
2779+ // Unknown -> Const
2780+ // Unknown -> Platform
2781+ // Unknown -> Reverse
2782+ // Unknown -> NotAdjacent
2783+ // Const -> Const
2784+ // Const -> NotAdjacent
2785+ // Platform -> Platform
2786+ // Platform -> NotAdjacent
2787+ // Reverse -> Reverse
2788+ // Reverse -> NotAdjacent
2789+ // NotAdjacent -> NotAdjacent
2790+ enum ValueOrder : uint8_t {
2791+ Unknown, // Initial state
2792+ Const, // Input values are const
2793+ Platform, // Platform order
2794+ Reverse, // Reverse platform order
2795+ NotAdjacent // Not adjacent
2796+ };
2797+ ValueOrder _value_order;
27772798
27782799 NOT_PRODUCT ( const CHeapBitMap &_trace_tags; )
27792800
27802801public:
27812802 MergePrimitiveStores (PhaseGVN* phase, StoreNode* store) :
2782- _phase (phase), _store(store)
2803+ _phase (phase), _store(store), _value_order(ValueOrder::Unknown)
27832804 NOT_PRODUCT ( COMMA _trace_tags (Compile::current()->directive()->trace_merge_stores_tags()) )
27842805 {}
27852806
@@ -2789,7 +2810,7 @@ class MergePrimitiveStores : public StackObj {
27892810 bool is_compatible_store (const StoreNode* other_store) const ;
27902811 bool is_adjacent_pair (const StoreNode* use_store, const StoreNode* def_store) const ;
27912812 bool is_adjacent_input_pair (const Node* n1, const Node* n2, const int memory_size) const ;
2792- static bool is_con_RShift (const Node* n, Node const *& base_out, jint& shift_out);
2813+ static bool is_con_RShift (const Node* n, Node const *& base_out, jint& shift_out, PhaseGVN* phase );
27932814 enum CFGStatus { SuccessNoRangeCheck, SuccessWithRangeCheck, Failure };
27942815 static CFGStatus cfg_status_for_pair (const StoreNode* use_store, const StoreNode* def_store);
27952816
@@ -2825,6 +2846,7 @@ class MergePrimitiveStores : public StackObj {
28252846#endif
28262847 };
28272848
2849+ enum ValueOrder find_adjacent_input_value_order (const Node* n1, const Node* n2, const int memory_size) const ;
28282850 Status find_adjacent_use_store (const StoreNode* def_store) const ;
28292851 Status find_adjacent_def_store (const StoreNode* use_store) const ;
28302852 Status find_use_store (const StoreNode* def_store) const ;
@@ -2886,10 +2908,17 @@ StoreNode* MergePrimitiveStores::run() {
28862908 // Check if we can merge with at least one def, so that we have at least 2 stores to merge.
28872909 Status status_def = find_adjacent_def_store (_store);
28882910 NOT_PRODUCT ( if (is_trace_basic ()) { tty->print (" [TraceMergeStores] expect def: " ); status_def.print_on (tty); })
2889- if (status_def.found_store () == nullptr ) {
2911+ Node* def_store = status_def.found_store ();
2912+ if (def_store == nullptr ) {
28902913 return nullptr ;
28912914 }
28922915
2916+ // Initialize value order
2917+ _value_order = find_adjacent_input_value_order (def_store->in (MemNode::ValueIn),
2918+ _store->in (MemNode::ValueIn),
2919+ _store->memory_size ());
2920+ assert (_value_order != ValueOrder::NotAdjacent && _value_order != ValueOrder::Unknown, " Order should be checked" );
2921+
28932922 ResourceMark rm;
28942923 Node_List merge_list;
28952924 collect_merge_list (merge_list);
@@ -2936,49 +2965,75 @@ bool MergePrimitiveStores::is_adjacent_pair(const StoreNode* use_store, const St
29362965 return pointer_def.is_adjacent_to_and_before (pointer_use);
29372966}
29382967
2939- bool MergePrimitiveStores::is_adjacent_input_pair (const Node* n1, const Node* n2, const int memory_size) const {
2968+ // Check input values n1 and n2 can be merged and return the value order
2969+ MergePrimitiveStores::ValueOrder MergePrimitiveStores::find_adjacent_input_value_order (const Node* n1, const Node* n2,
2970+ const int memory_size) const {
29402971 // Pattern: [n1 = ConI, n2 = ConI]
2941- if (n1->Opcode () == Op_ConI) {
2942- return n2-> Opcode () == Op_ConI ;
2972+ if (n1->Opcode () == Op_ConI && n2-> Opcode () == Op_ConI ) {
2973+ return ValueOrder::Const ;
29432974 }
29442975
2945- // Pattern: [n1 = base >> shift, n2 = base >> (shift + memory_size)]
2946- #ifndef VM_LITTLE_ENDIAN
2947- // Pattern: [n1 = base >> (shift + memory_size), n2 = base >> shift]
2948- // Swapping n1 with n2 gives same pattern as on little endian platforms.
2949- swap (n1, n2);
2950- #endif // !VM_LITTLE_ENDIAN
2951- Node const * base_n2;
2976+ Node const *base_n2;
29522977 jint shift_n2;
2953- if (!is_con_RShift (n2, base_n2, shift_n2)) {
2954- return false ;
2978+ if (!is_con_RShift (n2, base_n2, shift_n2, _phase )) {
2979+ return ValueOrder::NotAdjacent ;
29552980 }
2956- if (n1->Opcode () == Op_ConvL2I) {
2957- // look through
2958- n1 = n1->in (1 );
2959- }
2960- Node const * base_n1;
2981+ Node const *base_n1;
29612982 jint shift_n1;
2962- if (n1 == base_n2) {
2963- // n1 = base = base >> 0
2964- base_n1 = n1;
2965- shift_n1 = 0 ;
2966- } else if (!is_con_RShift (n1, base_n1, shift_n1)) {
2967- return false ;
2983+ if (!is_con_RShift (n1, base_n1, shift_n1, _phase)) {
2984+ return ValueOrder::NotAdjacent;
29682985 }
2986+
29692987 int bits_per_store = memory_size * 8 ;
29702988 if (base_n1 != base_n2 ||
2971- shift_n1 + bits_per_store != shift_n2 ||
2989+ abs ( shift_n1 - shift_n2) != bits_per_store ||
29722990 shift_n1 % bits_per_store != 0 ) {
2973- return false ;
2991+ // Values are not adjacent
2992+ return ValueOrder::NotAdjacent;
29742993 }
29752994
2976- // both load from same value with correct shift
2977- return true ;
2995+ // Detect value order
2996+ #ifdef VM_LITTLE_ENDIAN
2997+ return shift_n1 < shift_n2 ? ValueOrder::Platform // Pattern: [n1 = base >> shift, n2 = base >> (shift + memory_size)]
2998+ : ValueOrder::Reverse; // Pattern: [n1 = base >> (shift + memory_size), n2 = base >> shift]
2999+ #else
3000+ return shift_n1 > shift_n2 ? ValueOrder::Platform // Pattern: [n1 = base >> (shift + memory_size), n2 = base >> shift]
3001+ : ValueOrder::Reverse; // Pattern: [n1 = base >> shift, n2 = base >> (shift + memory_size)]
3002+ #endif
3003+ }
3004+
3005+ bool MergePrimitiveStores::is_adjacent_input_pair (const Node* n1, const Node* n2, const int memory_size) const {
3006+ ValueOrder input_value_order = find_adjacent_input_value_order (n1, n2, memory_size);
3007+
3008+ switch (input_value_order) {
3009+ case ValueOrder::NotAdjacent:
3010+ return false ;
3011+ case ValueOrder::Reverse:
3012+ if (memory_size != 1 ||
3013+ !Matcher::match_rule_supported (Op_ReverseBytesS) ||
3014+ !Matcher::match_rule_supported (Op_ReverseBytesI) ||
3015+ !Matcher::match_rule_supported (Op_ReverseBytesL)) {
3016+ // ReverseBytes are not supported by platform
3017+ return false ;
3018+ }
3019+ // fall-through.
3020+ case ValueOrder::Const:
3021+ case ValueOrder::Platform:
3022+ if (_value_order == ValueOrder::Unknown) {
3023+ // Initial state is Unknown, and we find a valid input value order
3024+ return true ;
3025+ }
3026+ // The value order can not be changed
3027+ return _value_order == input_value_order;
3028+ case ValueOrder::Unknown:
3029+ default :
3030+ ShouldNotReachHere ();
3031+ }
3032+ return false ;
29783033}
29793034
29803035// Detect pattern: n = base_out >> shift_out
2981- bool MergePrimitiveStores::is_con_RShift (const Node* n, Node const *& base_out, jint& shift_out) {
3036+ bool MergePrimitiveStores::is_con_RShift (const Node* n, Node const *& base_out, jint& shift_out, PhaseGVN* phase ) {
29823037 assert (n != nullptr , " precondition" );
29833038
29843039 int opc = n->Opcode ();
@@ -2997,6 +3052,14 @@ bool MergePrimitiveStores::is_con_RShift(const Node* n, Node const*& base_out, j
29973052 // The shift must be positive:
29983053 return shift_out >= 0 ;
29993054 }
3055+
3056+ if (phase->type (n)->isa_int () != nullptr ||
3057+ phase->type (n)->isa_long () != nullptr ) {
3058+ // (base >> 0)
3059+ base_out = n;
3060+ shift_out = 0 ;
3061+ return true ;
3062+ }
30003063 return false ;
30013064}
30023065
@@ -3163,6 +3226,7 @@ Node* MergePrimitiveStores::make_merged_input_value(const Node_List& merge_list)
31633226 Node* first = merge_list.at (merge_list.size ()-1 );
31643227 Node* merged_input_value = nullptr ;
31653228 if (_store->in (MemNode::ValueIn)->Opcode () == Op_ConI) {
3229+ assert (_value_order == ValueOrder::Const, " must match" );
31663230 // Pattern: [ConI, ConI, ...] -> new constant
31673231 jlong con = 0 ;
31683232 jlong bits_per_store = _store->memory_size () * 8 ;
@@ -3179,6 +3243,7 @@ Node* MergePrimitiveStores::make_merged_input_value(const Node_List& merge_list)
31793243 }
31803244 merged_input_value = _phase->longcon (con);
31813245 } else {
3246+ assert (_value_order == ValueOrder::Platform || _value_order == ValueOrder::Reverse, " must match" );
31823247 // Pattern: [base >> 24, base >> 16, base >> 8, base] -> base
31833248 // | |
31843249 // _store first
@@ -3189,10 +3254,13 @@ Node* MergePrimitiveStores::make_merged_input_value(const Node_List& merge_list)
31893254 // `_store` and `first` are swapped in the diagram above
31903255 swap (hi, lo);
31913256#endif // !VM_LITTLE_ENDIAN
3257+ if (_value_order == ValueOrder::Reverse) {
3258+ swap (hi, lo);
3259+ }
31923260 Node const * hi_base;
31933261 jint hi_shift;
31943262 merged_input_value = lo;
3195- bool is_true = is_con_RShift (hi, hi_base, hi_shift);
3263+ bool is_true = is_con_RShift (hi, hi_base, hi_shift, _phase );
31963264 assert (is_true, " must detect con RShift" );
31973265 if (merged_input_value != hi_base && merged_input_value->Opcode () == Op_ConvL2I) {
31983266 // look through
@@ -3218,6 +3286,17 @@ Node* MergePrimitiveStores::make_merged_input_value(const Node_List& merge_list)
32183286 (_phase->type (merged_input_value)->isa_long () != nullptr && new_memory_size == 8 ),
32193287 " merged_input_value is either int or long, and new_memory_size is small enough" );
32203288
3289+ if (_value_order == ValueOrder::Reverse) {
3290+ assert (_store->memory_size () == 1 , " only implemented for bytes" );
3291+ if (new_memory_size == 8 ) {
3292+ merged_input_value = _phase->transform (new ReverseBytesLNode (merged_input_value));
3293+ } else if (new_memory_size == 4 ) {
3294+ merged_input_value = _phase->transform (new ReverseBytesINode (merged_input_value));
3295+ } else {
3296+ assert (new_memory_size == 2 , " sanity check" );
3297+ merged_input_value = _phase->transform (new ReverseBytesSNode (merged_input_value));
3298+ }
3299+ }
32213300 return merged_input_value;
32223301}
32233302
0 commit comments