| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_inliner.h" | 5 #include "vm/flow_graph_inliner.h" |
| 6 | 6 |
| 7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
| 8 #include "vm/block_scheduler.h" | 8 #include "vm/block_scheduler.h" |
| 9 #include "vm/branch_optimizer.h" | 9 #include "vm/branch_optimizer.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 2829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2840 FlowGraph* flow_graph, | 2840 FlowGraph* flow_graph, |
| 2841 ForwardInstructionIterator* iterator, | 2841 ForwardInstructionIterator* iterator, |
| 2842 InstanceCallInstr* call) { | 2842 InstanceCallInstr* call) { |
| 2843 Function& target = Function::Handle(Z); | 2843 Function& target = Function::Handle(Z); |
| 2844 GrowableArray<intptr_t> class_ids; | 2844 GrowableArray<intptr_t> class_ids; |
| 2845 call->ic_data()->GetCheckAt(0, &class_ids, &target); | 2845 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2846 const intptr_t receiver_cid = class_ids[0]; | 2846 const intptr_t receiver_cid = class_ids[0]; |
| 2847 | 2847 |
| 2848 TargetEntryInstr* entry; | 2848 TargetEntryInstr* entry; |
| 2849 Definition* last; | 2849 Definition* last; |
| 2850 if (!FlowGraphInliner::TryInlineRecognizedMethod(flow_graph, | 2850 if (FlowGraphInliner::TryInlineRecognizedMethod(flow_graph, |
| 2851 receiver_cid, | 2851 receiver_cid, |
| 2852 target, | 2852 target, |
| 2853 call, | 2853 call, |
| 2854 call->ArgumentAt(0), | 2854 call->ArgumentAt(0), |
| 2855 call->token_pos(), | 2855 call->token_pos(), |
| 2856 *call->ic_data(), | 2856 *call->ic_data(), |
| 2857 &entry, &last)) { | 2857 &entry, &last)) { |
| 2858 return false; | 2858 // Insert receiver class check if needed. |
| 2859 } | 2859 if (MethodRecognizer::PolymorphicTarget(target) || |
| 2860 | 2860 flow_graph->InstanceCallNeedsClassCheck(call, target.kind())) { |
| 2861 // Insert receiver class check if needed. | 2861 Instruction* check = GetCheckClass( |
| 2862 if (MethodRecognizer::PolymorphicTarget(target) || | 2862 flow_graph, |
| 2863 flow_graph->InstanceCallNeedsClassCheck(call, target.kind())) { | 2863 call->ArgumentAt(0), |
| 2864 Instruction* check = GetCheckClass( | 2864 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()), |
| 2865 flow_graph, | 2865 call->deopt_id(), |
| 2866 call->ArgumentAt(0), | 2866 call->token_pos()); |
| 2867 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()), | 2867 flow_graph->InsertBefore(call, check, call->env(), FlowGraph::kEffect); |
| 2868 call->deopt_id(), | 2868 } |
| 2869 call->token_pos()); | 2869 |
| 2870 flow_graph->InsertBefore(call, check, call->env(), FlowGraph::kEffect); | 2870 // Remove the original push arguments. |
| 2871 } | 2871 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 2872 | 2872 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 2873 // Remove the original push arguments. | 2873 push->ReplaceUsesWith(push->value()->definition()); |
| 2874 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 2874 push->RemoveFromGraph(); |
| 2875 PushArgumentInstr* push = call->PushArgumentAt(i); | 2875 } |
| 2876 push->ReplaceUsesWith(push->value()->definition()); | 2876 // Replace all uses of this definition with the result. |
| 2877 push->RemoveFromGraph(); | 2877 call->ReplaceUsesWith(last); |
| 2878 } | 2878 // Finally insert the sequence other definition in place of this one in the |
| 2879 // Replace all uses of this definition with the result. | 2879 // graph. |
| 2880 call->ReplaceUsesWith(last); | 2880 call->previous()->LinkTo(entry->next()); |
| 2881 // Finally insert the sequence other definition in place of this one in the | 2881 entry->UnuseAllInputs(); // Entry block is not in the graph. |
| 2882 // graph. | 2882 last->LinkTo(call); |
| 2883 call->previous()->LinkTo(entry->next()); | 2883 // Remove through the iterator. |
| 2884 entry->UnuseAllInputs(); // Entry block is not in the graph. | 2884 ASSERT(iterator->Current() == call); |
| 2885 last->LinkTo(call); | 2885 iterator->RemoveCurrentFromGraph(); |
| 2886 // Remove through the iterator. | 2886 call->set_previous(NULL); |
| 2887 ASSERT(iterator->Current() == call); | 2887 call->set_next(NULL); |
| 2888 iterator->RemoveCurrentFromGraph(); | 2888 return true; |
| 2889 call->set_previous(NULL); | 2889 } |
| 2890 call->set_next(NULL); | 2890 return false; |
| 2891 return true; | 2891 } |
| 2892 } | 2892 |
| 2893 | 2893 |
| 2894 bool FlowGraphInliner::TryReplaceStaticCallWithInline( |
| 2895 FlowGraph* flow_graph, |
| 2896 ForwardInstructionIterator* iterator, |
| 2897 StaticCallInstr* call) { |
| 2898 TargetEntryInstr* entry; |
| 2899 Definition* last; |
| 2900 if (FlowGraphInliner::TryInlineRecognizedMethod(flow_graph, |
| 2901 kIllegalCid, |
| 2902 call->function(), |
| 2903 call, |
| 2904 call->ArgumentAt(0), |
| 2905 call->token_pos(), |
| 2906 *call->ic_data(), |
| 2907 &entry, &last)) { |
| 2908 // Remove the original push arguments. |
| 2909 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 2910 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 2911 push->ReplaceUsesWith(push->value()->definition()); |
| 2912 push->RemoveFromGraph(); |
| 2913 } |
| 2914 // Replace all uses of this definition with the result. |
| 2915 call->ReplaceUsesWith(last); |
| 2916 // Finally insert the sequence other definition in place of this one in the |
| 2917 // graph. |
| 2918 call->previous()->LinkTo(entry->next()); |
| 2919 entry->UnuseAllInputs(); // Entry block is not in the graph. |
| 2920 last->LinkTo(call); |
| 2921 // Remove through the iterator. |
| 2922 ASSERT(iterator->Current() == call); |
| 2923 iterator->RemoveCurrentFromGraph(); |
| 2924 call->set_previous(NULL); |
| 2925 call->set_next(NULL); |
| 2926 return true; |
| 2927 } |
| 2928 return false; |
| 2929 } |
| 2930 |
| 2931 |
| 2932 static bool InlineFloat32x4Method(FlowGraph* flow_graph, |
| 2933 Instruction* call, |
| 2934 MethodRecognizer::Kind kind, |
| 2935 TargetEntryInstr** entry, |
| 2936 Definition** last) { |
| 2937 if (!ShouldInlineSimd()) { |
| 2938 return false; |
| 2939 } |
| 2940 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2941 call->GetBlock()->try_index()); |
| 2942 (*entry)->InheritDeoptTarget(Z, call); |
| 2943 Instruction* cursor = *entry; |
| 2944 switch (kind) { |
| 2945 case MethodRecognizer::kFloat32x4ShuffleX: |
| 2946 case MethodRecognizer::kFloat32x4ShuffleY: |
| 2947 case MethodRecognizer::kFloat32x4ShuffleZ: |
| 2948 case MethodRecognizer::kFloat32x4ShuffleW: { |
| 2949 *last = new(Z) Simd32x4ShuffleInstr(kind, |
| 2950 new(Z) Value(call->ArgumentAt(0)), |
| 2951 0, // mask ignored. |
| 2952 call->deopt_id()); |
| 2953 break; |
| 2954 } |
| 2955 case MethodRecognizer::kFloat32x4GetSignMask: { |
| 2956 *last = new(Z) Simd32x4GetSignMaskInstr(kind, |
| 2957 new(Z) Value(call->ArgumentAt(0)), |
| 2958 call->deopt_id()); |
| 2959 break; |
| 2960 } |
| 2961 case MethodRecognizer::kFloat32x4Equal: |
| 2962 case MethodRecognizer::kFloat32x4GreaterThan: |
| 2963 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
| 2964 case MethodRecognizer::kFloat32x4LessThan: |
| 2965 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 2966 case MethodRecognizer::kFloat32x4NotEqual: { |
| 2967 Definition* left = call->ArgumentAt(0); |
| 2968 Definition* right = call->ArgumentAt(1); |
| 2969 *last = new(Z) Float32x4ComparisonInstr(kind, |
| 2970 new(Z) Value(left), |
| 2971 new(Z) Value(right), |
| 2972 call->deopt_id()); |
| 2973 break; |
| 2974 } |
| 2975 case MethodRecognizer::kFloat32x4Min: |
| 2976 case MethodRecognizer::kFloat32x4Max: { |
| 2977 Definition* left = call->ArgumentAt(0); |
| 2978 Definition* right = call->ArgumentAt(1); |
| 2979 *last = new(Z) Float32x4MinMaxInstr(kind, |
| 2980 new(Z) Value(left), |
| 2981 new(Z) Value(right), |
| 2982 call->deopt_id()); |
| 2983 break; |
| 2984 } |
| 2985 case MethodRecognizer::kFloat32x4Scale: { |
| 2986 Definition* left = call->ArgumentAt(0); |
| 2987 Definition* right = call->ArgumentAt(1); |
| 2988 // Left and right values are swapped when handed to the instruction, |
| 2989 // this is done so that the double value is loaded into the output |
| 2990 // register and can be destroyed. |
| 2991 *last = new(Z) Float32x4ScaleInstr(kind, |
| 2992 new(Z) Value(right), |
| 2993 new(Z) Value(left), |
| 2994 call->deopt_id()); |
| 2995 break; |
| 2996 } |
| 2997 case MethodRecognizer::kFloat32x4Sqrt: |
| 2998 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 2999 case MethodRecognizer::kFloat32x4Reciprocal: { |
| 3000 Definition* left = call->ArgumentAt(0); |
| 3001 *last = new(Z) Float32x4SqrtInstr(kind, |
| 3002 new(Z) Value(left), |
| 3003 call->deopt_id()); |
| 3004 break; |
| 3005 } |
| 3006 case MethodRecognizer::kFloat32x4WithX: |
| 3007 case MethodRecognizer::kFloat32x4WithY: |
| 3008 case MethodRecognizer::kFloat32x4WithZ: |
| 3009 case MethodRecognizer::kFloat32x4WithW: { |
| 3010 Definition* left = call->ArgumentAt(0); |
| 3011 Definition* right = call->ArgumentAt(1); |
| 3012 *last = new(Z) Float32x4WithInstr(kind, |
| 3013 new(Z) Value(left), |
| 3014 new(Z) Value(right), |
| 3015 call->deopt_id()); |
| 3016 break; |
| 3017 } |
| 3018 case MethodRecognizer::kFloat32x4Absolute: |
| 3019 case MethodRecognizer::kFloat32x4Negate: { |
| 3020 Definition* left = call->ArgumentAt(0); |
| 3021 *last = new(Z) Float32x4ZeroArgInstr(kind, |
| 3022 new(Z) Value(left), |
| 3023 call->deopt_id()); |
| 3024 break; |
| 3025 } |
| 3026 case MethodRecognizer::kFloat32x4Clamp: { |
| 3027 Definition* left = call->ArgumentAt(0); |
| 3028 Definition* lower = call->ArgumentAt(1); |
| 3029 Definition* upper = call->ArgumentAt(2); |
| 3030 *last = new(Z) Float32x4ClampInstr( |
| 3031 new(Z) Value(left), |
| 3032 new(Z) Value(lower), |
| 3033 new(Z) Value(upper), |
| 3034 call->deopt_id()); |
| 3035 break; |
| 3036 } |
| 3037 default: |
| 3038 UNREACHABLE(); |
| 3039 return false; |
| 3040 } |
| 3041 flow_graph->AppendTo(cursor, *last, |
| 3042 call->deopt_id() != Thread::kNoDeoptId ? |
| 3043 call->env() : NULL, |
| 3044 FlowGraph::kValue); |
| 3045 return true; |
| 3046 } |
| 3047 |
| 3048 |
| 3049 static bool CheckMask(Definition* definition, intptr_t* mask_ptr) { |
| 3050 if (!definition->IsConstant()) return false; |
| 3051 ConstantInstr* constant_instruction = definition->AsConstant(); |
| 3052 const Object& constant_mask = constant_instruction->value(); |
| 3053 if (!constant_mask.IsSmi()) return false; |
| 3054 const intptr_t mask = Smi::Cast(constant_mask).Value(); |
| 3055 if ((mask < 0) || (mask > 255)) { |
| 3056 return false; // Not a valid mask. |
| 3057 } |
| 3058 *mask_ptr = mask; |
| 3059 return true; |
| 3060 } |
| 3061 |
| 3062 |
| 3063 static bool InlineSimdShuffleMethod(FlowGraph* flow_graph, |
| 3064 Instruction* call, |
| 3065 MethodRecognizer::Kind kind, |
| 3066 TargetEntryInstr** entry, |
| 3067 Definition** last) { |
| 3068 if (!ShouldInlineSimd()) { |
| 3069 return false; |
| 3070 } |
| 3071 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3072 call->GetBlock()->try_index()); |
| 3073 (*entry)->InheritDeoptTarget(Z, call); |
| 3074 Instruction* cursor = *entry; |
| 3075 Definition* mask_definition = call->ArgumentAt(1); |
| 3076 intptr_t mask = 0; |
| 3077 if (!CheckMask(mask_definition, &mask)) { |
| 3078 return false; |
| 3079 } |
| 3080 *last = new(Z) Simd32x4ShuffleInstr( |
| 3081 kind, |
| 3082 new(Z) Value(call->ArgumentAt(0)), |
| 3083 mask, |
| 3084 call->deopt_id()); |
| 3085 flow_graph->AppendTo(cursor, *last, |
| 3086 call->deopt_id() != Thread::kNoDeoptId ? |
| 3087 call->env() : NULL, |
| 3088 FlowGraph::kValue); |
| 3089 return true; |
| 3090 } |
| 3091 |
| 3092 |
| 3093 static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph, |
| 3094 Instruction* call, |
| 3095 MethodRecognizer::Kind kind, |
| 3096 TargetEntryInstr** entry, |
| 3097 Definition** last) { |
| 3098 if (!ShouldInlineSimd()) { |
| 3099 return false; |
| 3100 } |
| 3101 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3102 call->GetBlock()->try_index()); |
| 3103 (*entry)->InheritDeoptTarget(Z, call); |
| 3104 Instruction* cursor = *entry; |
| 3105 Definition* mask_definition = call->ArgumentAt(2); |
| 3106 intptr_t mask = 0; |
| 3107 if (!CheckMask(mask_definition, &mask)) { |
| 3108 return false; |
| 3109 } |
| 3110 *last = new(Z) Simd32x4ShuffleMixInstr( |
| 3111 kind, |
| 3112 new(Z) Value(call->ArgumentAt(0)), |
| 3113 new(Z) Value(call->ArgumentAt(1)), |
| 3114 mask, |
| 3115 call->deopt_id()); |
| 3116 flow_graph->AppendTo(cursor, *last, |
| 3117 call->deopt_id() != Thread::kNoDeoptId ? |
| 3118 call->env() : NULL, |
| 3119 FlowGraph::kValue); |
| 3120 return true; |
| 3121 } |
| 3122 |
| 3123 |
| 3124 |
| 3125 static bool InlineInt32x4Method(FlowGraph* flow_graph, |
| 3126 Instruction* call, |
| 3127 MethodRecognizer::Kind kind, |
| 3128 TargetEntryInstr** entry, |
| 3129 Definition** last) { |
| 3130 if (!ShouldInlineSimd()) { |
| 3131 return false; |
| 3132 } |
| 3133 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3134 call->GetBlock()->try_index()); |
| 3135 (*entry)->InheritDeoptTarget(Z, call); |
| 3136 Instruction* cursor = *entry; |
| 3137 switch (kind) { |
| 3138 case MethodRecognizer::kInt32x4GetFlagX: |
| 3139 case MethodRecognizer::kInt32x4GetFlagY: |
| 3140 case MethodRecognizer::kInt32x4GetFlagZ: |
| 3141 case MethodRecognizer::kInt32x4GetFlagW: { |
| 3142 *last = new(Z) Int32x4GetFlagInstr( |
| 3143 kind, |
| 3144 new(Z) Value(call->ArgumentAt(0)), |
| 3145 call->deopt_id()); |
| 3146 break; |
| 3147 } |
| 3148 case MethodRecognizer::kInt32x4GetSignMask: { |
| 3149 *last = new(Z) Simd32x4GetSignMaskInstr( |
| 3150 kind, |
| 3151 new(Z) Value(call->ArgumentAt(0)), |
| 3152 call->deopt_id()); |
| 3153 break; |
| 3154 } |
| 3155 case MethodRecognizer::kInt32x4Select: { |
| 3156 Definition* mask = call->ArgumentAt(0); |
| 3157 Definition* trueValue = call->ArgumentAt(1); |
| 3158 Definition* falseValue = call->ArgumentAt(2); |
| 3159 *last = new(Z) Int32x4SelectInstr( |
| 3160 new(Z) Value(mask), |
| 3161 new(Z) Value(trueValue), |
| 3162 new(Z) Value(falseValue), |
| 3163 call->deopt_id()); |
| 3164 break; |
| 3165 } |
| 3166 case MethodRecognizer::kInt32x4WithFlagX: |
| 3167 case MethodRecognizer::kInt32x4WithFlagY: |
| 3168 case MethodRecognizer::kInt32x4WithFlagZ: |
| 3169 case MethodRecognizer::kInt32x4WithFlagW: { |
| 3170 *last = new(Z) Int32x4SetFlagInstr( |
| 3171 kind, |
| 3172 new(Z) Value(call->ArgumentAt(0)), |
| 3173 new(Z) Value(call->ArgumentAt(1)), |
| 3174 call->deopt_id()); |
| 3175 break; |
| 3176 } |
| 3177 default: |
| 3178 return false; |
| 3179 } |
| 3180 flow_graph->AppendTo(cursor, *last, |
| 3181 call->deopt_id() != Thread::kNoDeoptId ? |
| 3182 call->env() : NULL, |
| 3183 FlowGraph::kValue); |
| 3184 return true; |
| 3185 } |
| 3186 |
| 3187 |
| 3188 static bool InlineFloat64x2Method(FlowGraph* flow_graph, |
| 3189 Instruction* call, |
| 3190 MethodRecognizer::Kind kind, |
| 3191 TargetEntryInstr** entry, |
| 3192 Definition** last) { |
| 3193 if (!ShouldInlineSimd()) { |
| 3194 return false; |
| 3195 } |
| 3196 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3197 call->GetBlock()->try_index()); |
| 3198 (*entry)->InheritDeoptTarget(Z, call); |
| 3199 Instruction* cursor = *entry; |
| 3200 switch (kind) { |
| 3201 case MethodRecognizer::kFloat64x2GetX: |
| 3202 case MethodRecognizer::kFloat64x2GetY: { |
| 3203 *last = new(Z) Simd64x2ShuffleInstr( |
| 3204 kind, |
| 3205 new(Z) Value(call->ArgumentAt(0)), |
| 3206 0, // mask is ignored. |
| 3207 call->deopt_id()); |
| 3208 break; |
| 3209 } |
| 3210 case MethodRecognizer::kFloat64x2Negate: |
| 3211 case MethodRecognizer::kFloat64x2Abs: |
| 3212 case MethodRecognizer::kFloat64x2Sqrt: |
| 3213 case MethodRecognizer::kFloat64x2GetSignMask: { |
| 3214 *last = new(Z) Float64x2ZeroArgInstr( |
| 3215 kind, new(Z) Value(call->ArgumentAt(0)), call->deopt_id()); |
| 3216 break; |
| 3217 } |
| 3218 case MethodRecognizer::kFloat64x2Scale: |
| 3219 case MethodRecognizer::kFloat64x2WithX: |
| 3220 case MethodRecognizer::kFloat64x2WithY: |
| 3221 case MethodRecognizer::kFloat64x2Min: |
| 3222 case MethodRecognizer::kFloat64x2Max: { |
| 3223 Definition* left = call->ArgumentAt(0); |
| 3224 Definition* right = call->ArgumentAt(1); |
| 3225 *last = new(Z) Float64x2OneArgInstr(kind, |
| 3226 new(Z) Value(left), |
| 3227 new(Z) Value(right), |
| 3228 call->deopt_id()); |
| 3229 break; |
| 3230 } |
| 3231 default: |
| 3232 UNREACHABLE(); |
| 3233 return false; |
| 3234 } |
| 3235 flow_graph->AppendTo(cursor, *last, |
| 3236 call->deopt_id() != Thread::kNoDeoptId ? |
| 3237 call->env() : NULL, |
| 3238 FlowGraph::kValue); |
| 3239 return true; |
| 3240 } |
| 3241 |
| 3242 |
| 3243 static bool InlineSimdConstructor(FlowGraph* flow_graph, |
| 3244 Instruction* call, |
| 3245 MethodRecognizer::Kind kind, |
| 3246 TargetEntryInstr** entry, |
| 3247 Definition** last) { |
| 3248 if (!ShouldInlineSimd()) { |
| 3249 return false; |
| 3250 } |
| 3251 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3252 call->GetBlock()->try_index()); |
| 3253 (*entry)->InheritDeoptTarget(Z, call); |
| 3254 Instruction* cursor = *entry; |
| 3255 switch (kind) { |
| 3256 case MethodRecognizer::kFloat32x4Zero: |
| 3257 *last = new(Z) Float32x4ZeroInstr(); |
| 3258 break; |
| 3259 case MethodRecognizer::kFloat32x4Splat: |
| 3260 *last = new(Z) Float32x4SplatInstr(new(Z) Value(call->ArgumentAt(1)), |
| 3261 call->deopt_id()); |
| 3262 break; |
| 3263 case MethodRecognizer::kFloat32x4Constructor: |
| 3264 *last = new(Z) Float32x4ConstructorInstr( |
| 3265 new(Z) Value(call->ArgumentAt(1)), |
| 3266 new(Z) Value(call->ArgumentAt(2)), |
| 3267 new(Z) Value(call->ArgumentAt(3)), |
| 3268 new(Z) Value(call->ArgumentAt(4)), |
| 3269 call->deopt_id()); |
| 3270 break; |
| 3271 case MethodRecognizer::kFloat32x4FromInt32x4Bits: |
| 3272 *last = new(Z) Int32x4ToFloat32x4Instr(new(Z) Value(call->ArgumentAt(1)), |
| 3273 call->deopt_id()); |
| 3274 break; |
| 3275 case MethodRecognizer::kFloat32x4FromFloat64x2: |
| 3276 *last = new(Z) Float64x2ToFloat32x4Instr( |
| 3277 new(Z) Value(call->ArgumentAt(1)), |
| 3278 call->deopt_id()); |
| 3279 break; |
| 3280 case MethodRecognizer::kFloat64x2Zero: |
| 3281 *last = new(Z) Float64x2ZeroInstr(); |
| 3282 break; |
| 3283 case MethodRecognizer::kFloat64x2Splat: |
| 3284 *last = new(Z) Float64x2SplatInstr(new(Z) Value(call->ArgumentAt(1)), |
| 3285 call->deopt_id()); |
| 3286 break; |
| 3287 case MethodRecognizer::kFloat64x2Constructor: |
| 3288 *last = new(Z) Float64x2ConstructorInstr( |
| 3289 new(Z) Value(call->ArgumentAt(1)), |
| 3290 new(Z) Value(call->ArgumentAt(2)), |
| 3291 call->deopt_id()); |
| 3292 break; |
| 3293 case MethodRecognizer::kFloat64x2FromFloat32x4: |
| 3294 *last = new(Z) Float32x4ToFloat64x2Instr( |
| 3295 new(Z) Value(call->ArgumentAt(1)), |
| 3296 call->deopt_id()); |
| 3297 break; |
| 3298 case MethodRecognizer::kInt32x4BoolConstructor: |
| 3299 *last = new(Z) Int32x4BoolConstructorInstr( |
| 3300 new(Z) Value(call->ArgumentAt(1)), |
| 3301 new(Z) Value(call->ArgumentAt(2)), |
| 3302 new(Z) Value(call->ArgumentAt(3)), |
| 3303 new(Z) Value(call->ArgumentAt(4)), |
| 3304 call->deopt_id()); |
| 3305 break; |
| 3306 case MethodRecognizer::kInt32x4Constructor: |
| 3307 *last = new(Z) Int32x4ConstructorInstr( |
| 3308 new(Z) Value(call->ArgumentAt(1)), |
| 3309 new(Z) Value(call->ArgumentAt(2)), |
| 3310 new(Z) Value(call->ArgumentAt(3)), |
| 3311 new(Z) Value(call->ArgumentAt(4)), |
| 3312 call->deopt_id()); |
| 3313 break; |
| 3314 case MethodRecognizer::kInt32x4FromFloat32x4Bits: |
| 3315 *last = new(Z) Float32x4ToInt32x4Instr(new(Z) Value(call->ArgumentAt(1)), |
| 3316 call->deopt_id()); |
| 3317 break; |
| 3318 default: |
| 3319 UNREACHABLE(); |
| 3320 return false; |
| 3321 } |
| 3322 flow_graph->AppendTo(cursor, *last, |
| 3323 call->deopt_id() != Thread::kNoDeoptId ? |
| 3324 call->env() : NULL, |
| 3325 FlowGraph::kValue); |
| 3326 return true; |
| 3327 } |
| 3328 |
| 2894 | 3329 |
| 2895 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph, | 3330 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph, |
| 2896 intptr_t receiver_cid, | 3331 intptr_t receiver_cid, |
| 2897 const Function& target, | 3332 const Function& target, |
| 2898 Instruction* call, | 3333 Instruction* call, |
| 2899 Definition* receiver, | 3334 Definition* receiver, |
| 2900 TokenPosition token_pos, | 3335 TokenPosition token_pos, |
| 2901 const ICData& ic_data, | 3336 const ICData& ic_data, |
| 2902 TargetEntryInstr** entry, | 3337 TargetEntryInstr** entry, |
| 2903 Definition** last) { | 3338 Definition** last) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3138 flow_graph, GrowableObjectArray::data_offset(), kEmitStoreBarrier, | 3573 flow_graph, GrowableObjectArray::data_offset(), kEmitStoreBarrier, |
| 3139 call, entry, last); | 3574 call, entry, last); |
| 3140 case MethodRecognizer::kGrowableArraySetLength: | 3575 case MethodRecognizer::kGrowableArraySetLength: |
| 3141 ASSERT(receiver_cid == kGrowableObjectArrayCid); | 3576 ASSERT(receiver_cid == kGrowableObjectArrayCid); |
| 3142 ASSERT(ic_data.NumberOfChecks() == 1); | 3577 ASSERT(ic_data.NumberOfChecks() == 1); |
| 3143 return InlineGrowableArraySetter( | 3578 return InlineGrowableArraySetter( |
| 3144 flow_graph, GrowableObjectArray::length_offset(), kNoStoreBarrier, | 3579 flow_graph, GrowableObjectArray::length_offset(), kNoStoreBarrier, |
| 3145 call, entry, last); | 3580 call, entry, last); |
| 3146 case MethodRecognizer::kSmi_bitAndFromSmi: | 3581 case MethodRecognizer::kSmi_bitAndFromSmi: |
| 3147 return InlineSmiBitAndFromSmi(flow_graph, call, entry, last); | 3582 return InlineSmiBitAndFromSmi(flow_graph, call, entry, last); |
| 3583 |
| 3584 case MethodRecognizer::kFloat32x4ShuffleX: |
| 3585 case MethodRecognizer::kFloat32x4ShuffleY: |
| 3586 case MethodRecognizer::kFloat32x4ShuffleZ: |
| 3587 case MethodRecognizer::kFloat32x4ShuffleW: |
| 3588 case MethodRecognizer::kFloat32x4GetSignMask: |
| 3589 case MethodRecognizer::kFloat32x4Equal: |
| 3590 case MethodRecognizer::kFloat32x4GreaterThan: |
| 3591 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
| 3592 case MethodRecognizer::kFloat32x4LessThan: |
| 3593 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 3594 case MethodRecognizer::kFloat32x4NotEqual: |
| 3595 case MethodRecognizer::kFloat32x4Min: |
| 3596 case MethodRecognizer::kFloat32x4Max: |
| 3597 case MethodRecognizer::kFloat32x4Scale: |
| 3598 case MethodRecognizer::kFloat32x4Sqrt: |
| 3599 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 3600 case MethodRecognizer::kFloat32x4Reciprocal: |
| 3601 case MethodRecognizer::kFloat32x4WithX: |
| 3602 case MethodRecognizer::kFloat32x4WithY: |
| 3603 case MethodRecognizer::kFloat32x4WithZ: |
| 3604 case MethodRecognizer::kFloat32x4WithW: |
| 3605 case MethodRecognizer::kFloat32x4Absolute: |
| 3606 case MethodRecognizer::kFloat32x4Negate: |
| 3607 case MethodRecognizer::kFloat32x4Clamp: |
| 3608 return InlineFloat32x4Method(flow_graph, call, kind, entry, last); |
| 3609 |
| 3610 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 3611 case MethodRecognizer::kInt32x4ShuffleMix: |
| 3612 return InlineSimdShuffleMixMethod(flow_graph, call, kind, entry, last); |
| 3613 |
| 3614 case MethodRecognizer::kFloat32x4Shuffle: |
| 3615 case MethodRecognizer::kInt32x4Shuffle: |
| 3616 return InlineSimdShuffleMethod(flow_graph, call, kind, entry, last); |
| 3617 |
| 3618 case MethodRecognizer::kInt32x4GetFlagX: |
| 3619 case MethodRecognizer::kInt32x4GetFlagY: |
| 3620 case MethodRecognizer::kInt32x4GetFlagZ: |
| 3621 case MethodRecognizer::kInt32x4GetFlagW: |
| 3622 case MethodRecognizer::kInt32x4GetSignMask: |
| 3623 case MethodRecognizer::kInt32x4Select: |
| 3624 case MethodRecognizer::kInt32x4WithFlagX: |
| 3625 case MethodRecognizer::kInt32x4WithFlagY: |
| 3626 case MethodRecognizer::kInt32x4WithFlagZ: |
| 3627 case MethodRecognizer::kInt32x4WithFlagW: |
| 3628 return InlineInt32x4Method(flow_graph, call, kind, entry, last); |
| 3629 |
| 3630 case MethodRecognizer::kFloat64x2GetX: |
| 3631 case MethodRecognizer::kFloat64x2GetY: |
| 3632 case MethodRecognizer::kFloat64x2Negate: |
| 3633 case MethodRecognizer::kFloat64x2Abs: |
| 3634 case MethodRecognizer::kFloat64x2Sqrt: |
| 3635 case MethodRecognizer::kFloat64x2GetSignMask: |
| 3636 case MethodRecognizer::kFloat64x2Scale: |
| 3637 case MethodRecognizer::kFloat64x2WithX: |
| 3638 case MethodRecognizer::kFloat64x2WithY: |
| 3639 case MethodRecognizer::kFloat64x2Min: |
| 3640 case MethodRecognizer::kFloat64x2Max: |
| 3641 return InlineFloat64x2Method(flow_graph, call, kind, entry, last); |
| 3642 |
| 3643 case MethodRecognizer::kFloat32x4Zero: |
| 3644 case MethodRecognizer::kFloat32x4Splat: |
| 3645 case MethodRecognizer::kFloat32x4Constructor: |
| 3646 case MethodRecognizer::kFloat32x4FromFloat64x2: |
| 3647 case MethodRecognizer::kFloat64x2Constructor: |
| 3648 case MethodRecognizer::kFloat64x2Zero: |
| 3649 case MethodRecognizer::kFloat64x2Splat: |
| 3650 case MethodRecognizer::kFloat64x2FromFloat32x4: |
| 3651 case MethodRecognizer::kInt32x4BoolConstructor: |
| 3652 case MethodRecognizer::kInt32x4Constructor: |
| 3653 case MethodRecognizer::kInt32x4FromFloat32x4Bits: |
| 3654 return InlineSimdConstructor(flow_graph, call, kind, entry, last); |
| 3655 |
| 3148 default: | 3656 default: |
| 3149 return false; | 3657 return false; |
| 3150 } | 3658 } |
| 3151 } | 3659 } |
| 3152 | 3660 |
| 3153 | 3661 |
| 3154 } // namespace dart | 3662 } // namespace dart |
| OLD | NEW |