@@ -847,21 +847,74 @@ Node *LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
847
847
}
848
848
}
849
849
850
- // Check for "(x>>c0)<<c0" which just masks off low bits
851
- if ( (add1_op == Op_RShiftI || add1_op == Op_URShiftI ) &&
852
- add1->in (2 ) == in (2 ) )
853
- // Convert to "(x & -(1<<c0))"
854
- return new AndINode (add1->in (1 ),phase->intcon ( -(1 <<con)));
855
-
856
- // Check for "((x>>c0) & Y)<<c0" which just masks off more low bits
857
- if ( add1_op == Op_AndI ) {
850
+ // Check for "(x >> C1) << C2"
851
+ if (add1_op == Op_RShiftI || add1_op == Op_URShiftI) {
852
+ // Special case C1 == C2, which just masks off low bits
853
+ if (add1->in (2 ) == in (2 )) {
854
+ // Convert to "(x & -(1 << C2))"
855
+ return new AndINode (add1->in (1 ), phase->intcon (-(1 << con)));
856
+ } else {
857
+ int add1Con = 0 ;
858
+ const_shift_count (phase, add1, &add1Con);
859
+
860
+ // Wait until the right shift has been sharpened to the correct count
861
+ if (add1Con > 0 && add1Con < BitsPerJavaInteger) {
862
+ // As loop parsing can produce LShiftI nodes, we should wait until the graph is fully formed
863
+ // to apply optimizations, otherwise we can inadvertently stop vectorization opportunities.
864
+ if (phase->is_IterGVN ()) {
865
+ if (con > add1Con) {
866
+ // Creates "(x << (C2 - C1)) & -(1 << C2)"
867
+ Node* lshift = phase->transform (new LShiftINode (add1->in (1 ), phase->intcon (con - add1Con)));
868
+ return new AndINode (lshift, phase->intcon (-(1 << con)));
869
+ } else {
870
+ assert (con < add1Con, " must be (%d < %d)" , con, add1Con);
871
+ // Creates "(x >> (C1 - C2)) & -(1 << C2)"
872
+
873
+ // Handle logical and arithmetic shifts
874
+ Node* rshift;
875
+ if (add1_op == Op_RShiftI) {
876
+ rshift = phase->transform (new RShiftINode (add1->in (1 ), phase->intcon (add1Con - con)));
877
+ } else {
878
+ rshift = phase->transform (new URShiftINode (add1->in (1 ), phase->intcon (add1Con - con)));
879
+ }
880
+
881
+ return new AndINode (rshift, phase->intcon (-(1 << con)));
882
+ }
883
+ } else {
884
+ phase->record_for_igvn (this );
885
+ }
886
+ }
887
+ }
888
+ }
889
+
890
+ // Check for "((x >> C1) & Y) << C2"
891
+ if (add1_op == Op_AndI) {
858
892
Node *add2 = add1->in (1 );
859
893
int add2_op = add2->Opcode ();
860
- if ( (add2_op == Op_RShiftI || add2_op == Op_URShiftI ) &&
861
- add2->in (2 ) == in (2 ) ) {
862
- // Convert to "(x & (Y<<c0))"
863
- Node *y_sh = phase->transform ( new LShiftINode ( add1->in (2 ), in (2 ) ) );
864
- return new AndINode ( add2->in (1 ), y_sh );
894
+ if (add2_op == Op_RShiftI || add2_op == Op_URShiftI) {
895
+ // Special case C1 == C2, which just masks off low bits
896
+ if (add2->in (2 ) == in (2 )) {
897
+ // Convert to "(x & (Y << C2))"
898
+ Node* y_sh = phase->transform (new LShiftINode (add1->in (2 ), phase->intcon (con)));
899
+ return new AndINode (add2->in (1 ), y_sh);
900
+ }
901
+
902
+ int add2Con = 0 ;
903
+ const_shift_count (phase, add2, &add2Con);
904
+ if (add2Con > 0 && add2Con < BitsPerJavaInteger) {
905
+ if (phase->is_IterGVN ()) {
906
+ // Convert to "((x >> C1) << C2) & (Y << C2)"
907
+
908
+ // Make "(x >> C1) << C2", which will get folded away by the rule above
909
+ Node* x_sh = phase->transform (new LShiftINode (add2, phase->intcon (con)));
910
+ // Make "Y << C2", which will simplify when Y is a constant
911
+ Node* y_sh = phase->transform (new LShiftINode (add1->in (2 ), phase->intcon (con)));
912
+
913
+ return new AndINode (x_sh, y_sh);
914
+ } else {
915
+ phase->record_for_igvn (this );
916
+ }
917
+ }
865
918
}
866
919
}
867
920
@@ -970,21 +1023,74 @@ Node *LShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
970
1023
}
971
1024
}
972
1025
973
- // Check for "(x>>c0)<<c0" which just masks off low bits
974
- if ( (add1_op == Op_RShiftL || add1_op == Op_URShiftL ) &&
975
- add1->in (2 ) == in (2 ) )
976
- // Convert to "(x & -(1<<c0))"
977
- return new AndLNode (add1->in (1 ),phase->longcon ( -(CONST64 (1 )<<con)));
1026
+ // Check for "(x >> C1) << C2"
1027
+ if (add1_op == Op_RShiftL || add1_op == Op_URShiftL) {
1028
+ // Special case C1 == C2, which just masks off low bits
1029
+ if (add1->in (2 ) == in (2 )) {
1030
+ // Convert to "(x & -(1 << C2))"
1031
+ return new AndLNode (add1->in (1 ), phase->longcon (-(CONST64 (1 ) << con)));
1032
+ } else {
1033
+ int add1Con = 0 ;
1034
+ const_shift_count (phase, add1, &add1Con);
1035
+
1036
+ // Wait until the right shift has been sharpened to the correct count
1037
+ if (add1Con > 0 && add1Con < BitsPerJavaLong) {
1038
+ // As loop parsing can produce LShiftI nodes, we should wait until the graph is fully formed
1039
+ // to apply optimizations, otherwise we can inadvertently stop vectorization opportunities.
1040
+ if (phase->is_IterGVN ()) {
1041
+ if (con > add1Con) {
1042
+ // Creates "(x << (C2 - C1)) & -(1 << C2)"
1043
+ Node* lshift = phase->transform (new LShiftLNode (add1->in (1 ), phase->intcon (con - add1Con)));
1044
+ return new AndLNode (lshift, phase->longcon (-(CONST64 (1 ) << con)));
1045
+ } else {
1046
+ assert (con < add1Con, " must be (%d < %d)" , con, add1Con);
1047
+ // Creates "(x >> (C1 - C2)) & -(1 << C2)"
1048
+
1049
+ // Handle logical and arithmetic shifts
1050
+ Node* rshift;
1051
+ if (add1_op == Op_RShiftL) {
1052
+ rshift = phase->transform (new RShiftLNode (add1->in (1 ), phase->intcon (add1Con - con)));
1053
+ } else {
1054
+ rshift = phase->transform (new URShiftLNode (add1->in (1 ), phase->intcon (add1Con - con)));
1055
+ }
1056
+
1057
+ return new AndLNode (rshift, phase->longcon (-(CONST64 (1 ) << con)));
1058
+ }
1059
+ } else {
1060
+ phase->record_for_igvn (this );
1061
+ }
1062
+ }
1063
+ }
1064
+ }
978
1065
979
- // Check for "((x>>c0 ) & Y)<<c0" which just masks off more low bits
980
- if ( add1_op == Op_AndL ) {
981
- Node * add2 = add1->in (1 );
1066
+ // Check for "((x >> C1 ) & Y) << C2"
1067
+ if ( add1_op == Op_AndL) {
1068
+ Node* add2 = add1->in (1 );
982
1069
int add2_op = add2->Opcode ();
983
- if ( (add2_op == Op_RShiftL || add2_op == Op_URShiftL ) &&
984
- add2->in (2 ) == in (2 ) ) {
985
- // Convert to "(x & (Y<<c0))"
986
- Node *y_sh = phase->transform ( new LShiftLNode ( add1->in (2 ), in (2 ) ) );
987
- return new AndLNode ( add2->in (1 ), y_sh );
1070
+ if (add2_op == Op_RShiftL || add2_op == Op_URShiftL) {
1071
+ // Special case C1 == C2, which just masks off low bits
1072
+ if (add2->in (2 ) == in (2 )) {
1073
+ // Convert to "(x & (Y << C2))"
1074
+ Node* y_sh = phase->transform (new LShiftLNode (add1->in (2 ), phase->intcon (con)));
1075
+ return new AndLNode (add2->in (1 ), y_sh);
1076
+ }
1077
+
1078
+ int add2Con = 0 ;
1079
+ const_shift_count (phase, add2, &add2Con);
1080
+ if (add2Con > 0 && add2Con < BitsPerJavaLong) {
1081
+ if (phase->is_IterGVN ()) {
1082
+ // Convert to "((x >> C1) << C2) & (Y << C2)"
1083
+
1084
+ // Make "(x >> C1) << C2", which will get folded away by the rule above
1085
+ Node* x_sh = phase->transform (new LShiftLNode (add2, phase->intcon (con)));
1086
+ // Make "Y << C2", which will simplify when Y is a constant
1087
+ Node* y_sh = phase->transform (new LShiftLNode (add1->in (2 ), phase->intcon (con)));
1088
+
1089
+ return new AndLNode (x_sh, y_sh);
1090
+ } else {
1091
+ phase->record_for_igvn (this );
1092
+ }
1093
+ }
988
1094
}
989
1095
}
990
1096
0 commit comments