OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 } | 80 } |
81 | 81 |
82 private: | 82 private: |
83 bool IsLoadStoreImmediate(int64_t value, LSDataSize size) { | 83 bool IsLoadStoreImmediate(int64_t value, LSDataSize size) { |
84 return Assembler::IsImmLSScaled(value, size) || | 84 return Assembler::IsImmLSScaled(value, size) || |
85 Assembler::IsImmLSUnscaled(value); | 85 Assembler::IsImmLSUnscaled(value); |
86 } | 86 } |
87 }; | 87 }; |
88 | 88 |
89 | 89 |
90 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 90 namespace { |
91 Node* node) { | 91 |
| 92 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { |
92 Arm64OperandGenerator g(selector); | 93 Arm64OperandGenerator g(selector); |
93 selector->Emit(opcode, g.DefineAsRegister(node), | 94 selector->Emit(opcode, g.DefineAsRegister(node), |
94 g.UseRegister(node->InputAt(0))); | 95 g.UseRegister(node->InputAt(0))); |
95 } | 96 } |
96 | 97 |
97 | 98 |
98 static void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, | 99 void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { |
99 Node* node) { | |
100 Arm64OperandGenerator g(selector); | 100 Arm64OperandGenerator g(selector); |
101 selector->Emit(opcode, g.DefineAsRegister(node), | 101 selector->Emit(opcode, g.DefineAsRegister(node), |
102 g.UseRegister(node->InputAt(0)), | 102 g.UseRegister(node->InputAt(0)), |
103 g.UseRegister(node->InputAt(1))); | |
104 } | |
105 | |
106 | |
107 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | |
108 Node* node) { | |
109 Arm64OperandGenerator g(selector); | |
110 selector->Emit(opcode, g.DefineAsRegister(node), | |
111 g.UseRegister(node->InputAt(0)), | |
112 g.UseRegister(node->InputAt(1))); | 103 g.UseRegister(node->InputAt(1))); |
113 } | 104 } |
114 | 105 |
115 | 106 |
116 static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, | 107 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, |
117 Node* node, ImmediateMode operand_mode) { | 108 ImmediateMode operand_mode) { |
118 Arm64OperandGenerator g(selector); | 109 Arm64OperandGenerator g(selector); |
119 selector->Emit(opcode, g.DefineAsRegister(node), | 110 selector->Emit(opcode, g.DefineAsRegister(node), |
120 g.UseRegister(node->InputAt(0)), | 111 g.UseRegister(node->InputAt(0)), |
121 g.UseOperand(node->InputAt(1), operand_mode)); | 112 g.UseOperand(node->InputAt(1), operand_mode)); |
122 } | 113 } |
123 | 114 |
124 | 115 |
125 template <typename Matcher> | 116 template <typename Matcher> |
126 static bool TryMatchShift(InstructionSelector* selector, Node* node, | 117 bool TryMatchShift(InstructionSelector* selector, Node* node, |
127 InstructionCode* opcode, IrOpcode::Value shift_opcode, | 118 InstructionCode* opcode, IrOpcode::Value shift_opcode, |
128 ImmediateMode imm_mode, | 119 ImmediateMode imm_mode, AddressingMode addressing_mode) { |
129 AddressingMode addressing_mode) { | |
130 if (node->opcode() != shift_opcode) return false; | 120 if (node->opcode() != shift_opcode) return false; |
131 Arm64OperandGenerator g(selector); | 121 Arm64OperandGenerator g(selector); |
132 Matcher m(node); | 122 Matcher m(node); |
133 if (g.CanBeImmediate(m.right().node(), imm_mode)) { | 123 if (g.CanBeImmediate(m.right().node(), imm_mode)) { |
134 *opcode |= AddressingModeField::encode(addressing_mode); | 124 *opcode |= AddressingModeField::encode(addressing_mode); |
135 return true; | 125 return true; |
136 } | 126 } |
137 return false; | 127 return false; |
138 } | 128 } |
139 | 129 |
140 | 130 |
141 static bool TryMatchAnyShift(InstructionSelector* selector, Node* node, | 131 bool TryMatchAnyShift(InstructionSelector* selector, Node* node, |
142 InstructionCode* opcode, bool try_ror) { | 132 InstructionCode* opcode, bool try_ror) { |
143 return TryMatchShift<Int32BinopMatcher>(selector, node, opcode, | 133 return TryMatchShift<Int32BinopMatcher>(selector, node, opcode, |
144 IrOpcode::kWord32Shl, kShift32Imm, | 134 IrOpcode::kWord32Shl, kShift32Imm, |
145 kMode_Operand2_R_LSL_I) || | 135 kMode_Operand2_R_LSL_I) || |
146 TryMatchShift<Int32BinopMatcher>(selector, node, opcode, | 136 TryMatchShift<Int32BinopMatcher>(selector, node, opcode, |
147 IrOpcode::kWord32Shr, kShift32Imm, | 137 IrOpcode::kWord32Shr, kShift32Imm, |
148 kMode_Operand2_R_LSR_I) || | 138 kMode_Operand2_R_LSR_I) || |
149 TryMatchShift<Int32BinopMatcher>(selector, node, opcode, | 139 TryMatchShift<Int32BinopMatcher>(selector, node, opcode, |
150 IrOpcode::kWord32Sar, kShift32Imm, | 140 IrOpcode::kWord32Sar, kShift32Imm, |
151 kMode_Operand2_R_ASR_I) || | 141 kMode_Operand2_R_ASR_I) || |
152 (try_ror && TryMatchShift<Int32BinopMatcher>( | 142 (try_ror && TryMatchShift<Int32BinopMatcher>( |
153 selector, node, opcode, IrOpcode::kWord32Ror, | 143 selector, node, opcode, IrOpcode::kWord32Ror, |
154 kShift32Imm, kMode_Operand2_R_ROR_I)) || | 144 kShift32Imm, kMode_Operand2_R_ROR_I)) || |
155 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, | 145 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, |
156 IrOpcode::kWord64Shl, kShift64Imm, | 146 IrOpcode::kWord64Shl, kShift64Imm, |
157 kMode_Operand2_R_LSL_I) || | 147 kMode_Operand2_R_LSL_I) || |
158 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, | 148 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, |
159 IrOpcode::kWord64Shr, kShift64Imm, | 149 IrOpcode::kWord64Shr, kShift64Imm, |
160 kMode_Operand2_R_LSR_I) || | 150 kMode_Operand2_R_LSR_I) || |
161 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, | 151 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, |
162 IrOpcode::kWord64Sar, kShift64Imm, | 152 IrOpcode::kWord64Sar, kShift64Imm, |
163 kMode_Operand2_R_ASR_I) || | 153 kMode_Operand2_R_ASR_I) || |
164 (try_ror && TryMatchShift<Int64BinopMatcher>( | 154 (try_ror && TryMatchShift<Int64BinopMatcher>( |
165 selector, node, opcode, IrOpcode::kWord64Ror, | 155 selector, node, opcode, IrOpcode::kWord64Ror, |
166 kShift64Imm, kMode_Operand2_R_ROR_I)); | 156 kShift64Imm, kMode_Operand2_R_ROR_I)); |
167 } | 157 } |
168 | 158 |
169 | 159 |
170 static bool TryMatchAnyExtend(InstructionSelector* selector, Node* node, | 160 bool TryMatchAnyExtend(InstructionSelector* selector, Node* node, |
171 InstructionCode* opcode) { | 161 InstructionCode* opcode) { |
172 NodeMatcher nm(node); | 162 NodeMatcher nm(node); |
173 if (nm.IsWord32And()) { | 163 if (nm.IsWord32And()) { |
174 Int32BinopMatcher m(node); | 164 Int32BinopMatcher m(node); |
175 if (m.right().HasValue()) { | 165 if (m.right().HasValue()) { |
176 if (m.right().Value() == 0xff) { | 166 if (m.right().Value() == 0xff) { |
177 *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTB); | 167 *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTB); |
178 return true; | 168 return true; |
179 } else if (m.right().Value() == 0xffff) { | 169 } else if (m.right().Value() == 0xffff) { |
180 *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTH); | 170 *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTH); |
181 return true; | 171 return true; |
182 } | 172 } |
183 } | 173 } |
184 } | 174 } |
185 return false; | 175 return false; |
186 } | 176 } |
187 | 177 |
188 | 178 |
189 // Shared routine for multiple binary operations. | 179 // Shared routine for multiple binary operations. |
190 template <typename Matcher> | 180 template <typename Matcher> |
191 static void VisitBinop(InstructionSelector* selector, Node* node, | 181 void VisitBinop(InstructionSelector* selector, Node* node, |
192 InstructionCode opcode, ImmediateMode operand_mode, | 182 InstructionCode opcode, ImmediateMode operand_mode, |
193 FlagsContinuation* cont) { | 183 FlagsContinuation* cont) { |
194 Arm64OperandGenerator g(selector); | 184 Arm64OperandGenerator g(selector); |
195 Matcher m(node); | 185 Matcher m(node); |
196 InstructionOperand inputs[4]; | 186 InstructionOperand inputs[4]; |
197 size_t input_count = 0; | 187 size_t input_count = 0; |
198 InstructionOperand outputs[2]; | 188 InstructionOperand outputs[2]; |
199 size_t output_count = 0; | 189 size_t output_count = 0; |
200 bool is_add_sub = false; | 190 bool is_add_sub = false; |
201 | 191 |
202 if (m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || m.IsInt64Sub()) { | 192 if (m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || m.IsInt64Sub()) { |
203 is_add_sub = true; | 193 is_add_sub = true; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 DCHECK_GE(arraysize(inputs), input_count); | 239 DCHECK_GE(arraysize(inputs), input_count); |
250 DCHECK_GE(arraysize(outputs), output_count); | 240 DCHECK_GE(arraysize(outputs), output_count); |
251 | 241 |
252 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, | 242 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, |
253 inputs); | 243 inputs); |
254 } | 244 } |
255 | 245 |
256 | 246 |
257 // Shared routine for multiple binary operations. | 247 // Shared routine for multiple binary operations. |
258 template <typename Matcher> | 248 template <typename Matcher> |
259 static void VisitBinop(InstructionSelector* selector, Node* node, | 249 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
260 ArchOpcode opcode, ImmediateMode operand_mode) { | 250 ImmediateMode operand_mode) { |
261 FlagsContinuation cont; | 251 FlagsContinuation cont; |
262 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); | 252 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); |
263 } | 253 } |
264 | 254 |
265 | 255 |
266 template <typename Matcher> | 256 template <typename Matcher> |
267 static void VisitAddSub(InstructionSelector* selector, Node* node, | 257 void VisitAddSub(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
268 ArchOpcode opcode, ArchOpcode negate_opcode) { | 258 ArchOpcode negate_opcode) { |
269 Arm64OperandGenerator g(selector); | 259 Arm64OperandGenerator g(selector); |
270 Matcher m(node); | 260 Matcher m(node); |
271 if (m.right().HasValue() && (m.right().Value() < 0) && | 261 if (m.right().HasValue() && (m.right().Value() < 0) && |
272 g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { | 262 g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { |
273 selector->Emit(negate_opcode, g.DefineAsRegister(node), | 263 selector->Emit(negate_opcode, g.DefineAsRegister(node), |
274 g.UseRegister(m.left().node()), | 264 g.UseRegister(m.left().node()), |
275 g.TempImmediate(-m.right().Value())); | 265 g.TempImmediate(-m.right().Value())); |
276 } else { | 266 } else { |
277 VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); | 267 VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); |
278 } | 268 } |
279 } | 269 } |
280 | 270 |
| 271 } // namespace |
| 272 |
281 | 273 |
282 void InstructionSelector::VisitLoad(Node* node) { | 274 void InstructionSelector::VisitLoad(Node* node) { |
283 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 275 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
284 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 276 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
285 Arm64OperandGenerator g(this); | 277 Arm64OperandGenerator g(this); |
286 Node* base = node->InputAt(0); | 278 Node* base = node->InputAt(0); |
287 Node* index = node->InputAt(1); | 279 Node* index = node->InputAt(1); |
288 ArchOpcode opcode; | 280 ArchOpcode opcode; |
289 ImmediateMode immediate_mode = kNoImmediate; | 281 ImmediateMode immediate_mode = kNoImmediate; |
290 switch (rep) { | 282 switch (rep) { |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 VisitRRR(this, kArm64Umod32, node); | 941 VisitRRR(this, kArm64Umod32, node); |
950 } | 942 } |
951 | 943 |
952 | 944 |
953 void InstructionSelector::VisitUint64Mod(Node* node) { | 945 void InstructionSelector::VisitUint64Mod(Node* node) { |
954 VisitRRR(this, kArm64Umod, node); | 946 VisitRRR(this, kArm64Umod, node); |
955 } | 947 } |
956 | 948 |
957 | 949 |
958 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { | 950 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { |
959 Arm64OperandGenerator g(this); | 951 VisitRR(this, kArm64Float32ToFloat64, node); |
960 Emit(kArm64Float32ToFloat64, g.DefineAsRegister(node), | |
961 g.UseRegister(node->InputAt(0))); | |
962 } | 952 } |
963 | 953 |
964 | 954 |
965 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { | 955 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { |
966 Arm64OperandGenerator g(this); | 956 VisitRR(this, kArm64Int32ToFloat64, node); |
967 Emit(kArm64Int32ToFloat64, g.DefineAsRegister(node), | |
968 g.UseRegister(node->InputAt(0))); | |
969 } | 957 } |
970 | 958 |
971 | 959 |
972 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { | 960 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { |
973 Arm64OperandGenerator g(this); | 961 VisitRR(this, kArm64Uint32ToFloat64, node); |
974 Emit(kArm64Uint32ToFloat64, g.DefineAsRegister(node), | |
975 g.UseRegister(node->InputAt(0))); | |
976 } | 962 } |
977 | 963 |
978 | 964 |
979 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { | 965 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { |
980 Arm64OperandGenerator g(this); | 966 VisitRR(this, kArm64Float64ToInt32, node); |
981 Emit(kArm64Float64ToInt32, g.DefineAsRegister(node), | |
982 g.UseRegister(node->InputAt(0))); | |
983 } | 967 } |
984 | 968 |
985 | 969 |
986 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { | 970 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { |
987 Arm64OperandGenerator g(this); | 971 VisitRR(this, kArm64Float64ToUint32, node); |
988 Emit(kArm64Float64ToUint32, g.DefineAsRegister(node), | |
989 g.UseRegister(node->InputAt(0))); | |
990 } | 972 } |
991 | 973 |
992 | 974 |
993 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { | 975 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
994 Arm64OperandGenerator g(this); | 976 VisitRR(this, kArm64Sxtw, node); |
995 Emit(kArm64Sxtw, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); | |
996 } | 977 } |
997 | 978 |
998 | 979 |
999 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { | 980 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { |
1000 Arm64OperandGenerator g(this); | 981 Arm64OperandGenerator g(this); |
1001 Node* value = node->InputAt(0); | 982 Node* value = node->InputAt(0); |
1002 switch (value->opcode()) { | 983 switch (value->opcode()) { |
1003 case IrOpcode::kWord32And: | 984 case IrOpcode::kWord32And: |
1004 case IrOpcode::kWord32Or: | 985 case IrOpcode::kWord32Or: |
1005 case IrOpcode::kWord32Xor: | 986 case IrOpcode::kWord32Xor: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 Emit(kArm64Lsr, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 1035 Emit(kArm64Lsr, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
1055 g.UseImmediate(m.right().node())); | 1036 g.UseImmediate(m.right().node())); |
1056 return; | 1037 return; |
1057 } | 1038 } |
1058 } | 1039 } |
1059 | 1040 |
1060 Emit(kArm64Mov32, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); | 1041 Emit(kArm64Mov32, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); |
1061 } | 1042 } |
1062 | 1043 |
1063 | 1044 |
| 1045 void InstructionSelector::VisitFloat32Add(Node* node) { |
| 1046 VisitRRR(this, kArm64Float32Add, node); |
| 1047 } |
| 1048 |
| 1049 |
1064 void InstructionSelector::VisitFloat64Add(Node* node) { | 1050 void InstructionSelector::VisitFloat64Add(Node* node) { |
1065 VisitRRRFloat64(this, kArm64Float64Add, node); | 1051 VisitRRR(this, kArm64Float64Add, node); |
1066 } | 1052 } |
1067 | 1053 |
1068 | 1054 |
| 1055 void InstructionSelector::VisitFloat32Sub(Node* node) { |
| 1056 VisitRRR(this, kArm64Float32Sub, node); |
| 1057 } |
| 1058 |
| 1059 |
1069 void InstructionSelector::VisitFloat64Sub(Node* node) { | 1060 void InstructionSelector::VisitFloat64Sub(Node* node) { |
1070 Arm64OperandGenerator g(this); | 1061 Arm64OperandGenerator g(this); |
1071 Float64BinopMatcher m(node); | 1062 Float64BinopMatcher m(node); |
1072 if (m.left().IsMinusZero() && m.right().IsFloat64RoundDown() && | 1063 if (m.left().IsMinusZero() && m.right().IsFloat64RoundDown() && |
1073 CanCover(m.node(), m.right().node())) { | 1064 CanCover(m.node(), m.right().node())) { |
1074 if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub && | 1065 if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub && |
1075 CanCover(m.right().node(), m.right().InputAt(0))) { | 1066 CanCover(m.right().node(), m.right().InputAt(0))) { |
1076 Float64BinopMatcher mright0(m.right().InputAt(0)); | 1067 Float64BinopMatcher mright0(m.right().InputAt(0)); |
1077 if (mright0.left().IsMinusZero()) { | 1068 if (mright0.left().IsMinusZero()) { |
1078 Emit(kArm64Float64RoundUp, g.DefineAsRegister(node), | 1069 Emit(kArm64Float64RoundUp, g.DefineAsRegister(node), |
1079 g.UseRegister(mright0.right().node())); | 1070 g.UseRegister(mright0.right().node())); |
1080 return; | 1071 return; |
1081 } | 1072 } |
1082 } | 1073 } |
1083 } | 1074 } |
1084 VisitRRRFloat64(this, kArm64Float64Sub, node); | 1075 VisitRRR(this, kArm64Float64Sub, node); |
| 1076 } |
| 1077 |
| 1078 |
| 1079 void InstructionSelector::VisitFloat32Mul(Node* node) { |
| 1080 VisitRRR(this, kArm64Float32Mul, node); |
1085 } | 1081 } |
1086 | 1082 |
1087 | 1083 |
1088 void InstructionSelector::VisitFloat64Mul(Node* node) { | 1084 void InstructionSelector::VisitFloat64Mul(Node* node) { |
1089 VisitRRRFloat64(this, kArm64Float64Mul, node); | 1085 VisitRRR(this, kArm64Float64Mul, node); |
| 1086 } |
| 1087 |
| 1088 |
| 1089 void InstructionSelector::VisitFloat32Div(Node* node) { |
| 1090 VisitRRR(this, kArm64Float32Div, node); |
1090 } | 1091 } |
1091 | 1092 |
1092 | 1093 |
1093 void InstructionSelector::VisitFloat64Div(Node* node) { | 1094 void InstructionSelector::VisitFloat64Div(Node* node) { |
1094 VisitRRRFloat64(this, kArm64Float64Div, node); | 1095 VisitRRR(this, kArm64Float64Div, node); |
1095 } | 1096 } |
1096 | 1097 |
1097 | 1098 |
1098 void InstructionSelector::VisitFloat64Mod(Node* node) { | 1099 void InstructionSelector::VisitFloat64Mod(Node* node) { |
1099 Arm64OperandGenerator g(this); | 1100 Arm64OperandGenerator g(this); |
1100 Emit(kArm64Float64Mod, g.DefineAsFixed(node, d0), | 1101 Emit(kArm64Float64Mod, g.DefineAsFixed(node, d0), |
1101 g.UseFixed(node->InputAt(0), d0), | 1102 g.UseFixed(node->InputAt(0), d0), |
1102 g.UseFixed(node->InputAt(1), d1))->MarkAsCall(); | 1103 g.UseFixed(node->InputAt(1), d1))->MarkAsCall(); |
1103 } | 1104 } |
1104 | 1105 |
1105 | 1106 |
| 1107 void InstructionSelector::VisitFloat32Max(Node* node) { |
| 1108 VisitRRR(this, kArm64Float32Max, node); |
| 1109 } |
| 1110 |
| 1111 |
1106 void InstructionSelector::VisitFloat64Max(Node* node) { | 1112 void InstructionSelector::VisitFloat64Max(Node* node) { |
1107 Arm64OperandGenerator g(this); | 1113 VisitRRR(this, kArm64Float64Max, node); |
1108 Node* left = node->InputAt(0); | 1114 } |
1109 Node* right = node->InputAt(1); | 1115 |
1110 Emit(kArm64Float64Max, g.DefineAsRegister(node), g.UseRegister(left), | 1116 |
1111 g.UseRegister(right)); | 1117 void InstructionSelector::VisitFloat32Min(Node* node) { |
| 1118 VisitRRR(this, kArm64Float32Min, node); |
1112 } | 1119 } |
1113 | 1120 |
1114 | 1121 |
1115 void InstructionSelector::VisitFloat64Min(Node* node) { | 1122 void InstructionSelector::VisitFloat64Min(Node* node) { |
1116 Arm64OperandGenerator g(this); | 1123 VisitRRR(this, kArm64Float64Min, node); |
1117 Node* left = node->InputAt(0); | 1124 } |
1118 Node* right = node->InputAt(1); | 1125 |
1119 Emit(kArm64Float64Min, g.DefineAsRegister(node), g.UseRegister(left), | 1126 |
1120 g.UseRegister(right)); | 1127 void InstructionSelector::VisitFloat32Sqrt(Node* node) { |
| 1128 VisitRR(this, kArm64Float32Sqrt, node); |
1121 } | 1129 } |
1122 | 1130 |
1123 | 1131 |
1124 void InstructionSelector::VisitFloat64Sqrt(Node* node) { | 1132 void InstructionSelector::VisitFloat64Sqrt(Node* node) { |
1125 VisitRRFloat64(this, kArm64Float64Sqrt, node); | 1133 VisitRR(this, kArm64Float64Sqrt, node); |
1126 } | 1134 } |
1127 | 1135 |
1128 | 1136 |
1129 void InstructionSelector::VisitFloat64RoundDown(Node* node) { | 1137 void InstructionSelector::VisitFloat64RoundDown(Node* node) { |
1130 VisitRRFloat64(this, kArm64Float64RoundDown, node); | 1138 VisitRR(this, kArm64Float64RoundDown, node); |
1131 } | 1139 } |
1132 | 1140 |
1133 | 1141 |
1134 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { | 1142 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { |
1135 VisitRRFloat64(this, kArm64Float64RoundTruncate, node); | 1143 VisitRR(this, kArm64Float64RoundTruncate, node); |
1136 } | 1144 } |
1137 | 1145 |
1138 | 1146 |
1139 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { | 1147 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { |
1140 VisitRRFloat64(this, kArm64Float64RoundTiesAway, node); | 1148 VisitRR(this, kArm64Float64RoundTiesAway, node); |
1141 } | 1149 } |
1142 | 1150 |
1143 | 1151 |
1144 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { | 1152 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
1145 Arm64OperandGenerator g(this); | 1153 Arm64OperandGenerator g(this); |
1146 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | 1154 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); |
1147 | 1155 |
1148 FrameStateDescriptor* frame_state_descriptor = NULL; | 1156 FrameStateDescriptor* frame_state_descriptor = NULL; |
1149 if (descriptor->NeedsFrameState()) { | 1157 if (descriptor->NeedsFrameState()) { |
1150 frame_state_descriptor = | 1158 frame_state_descriptor = |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1215 // Emit the call instruction. | 1223 // Emit the call instruction. |
1216 InstructionOperand* first_output = | 1224 InstructionOperand* first_output = |
1217 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; | 1225 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; |
1218 Instruction* call_instr = | 1226 Instruction* call_instr = |
1219 Emit(opcode, buffer.outputs.size(), first_output, | 1227 Emit(opcode, buffer.outputs.size(), first_output, |
1220 buffer.instruction_args.size(), &buffer.instruction_args.front()); | 1228 buffer.instruction_args.size(), &buffer.instruction_args.front()); |
1221 call_instr->MarkAsCall(); | 1229 call_instr->MarkAsCall(); |
1222 } | 1230 } |
1223 | 1231 |
1224 | 1232 |
| 1233 namespace { |
| 1234 |
1225 // Shared routine for multiple compare operations. | 1235 // Shared routine for multiple compare operations. |
1226 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1236 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1227 InstructionOperand left, InstructionOperand right, | 1237 InstructionOperand left, InstructionOperand right, |
1228 FlagsContinuation* cont) { | 1238 FlagsContinuation* cont) { |
1229 Arm64OperandGenerator g(selector); | 1239 Arm64OperandGenerator g(selector); |
1230 opcode = cont->Encode(opcode); | 1240 opcode = cont->Encode(opcode); |
1231 if (cont->IsBranch()) { | 1241 if (cont->IsBranch()) { |
1232 selector->Emit(opcode, g.NoOutput(), left, right, | 1242 selector->Emit(opcode, g.NoOutput(), left, right, |
1233 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1243 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1234 } else { | 1244 } else { |
1235 DCHECK(cont->IsSet()); | 1245 DCHECK(cont->IsSet()); |
1236 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1246 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1237 } | 1247 } |
1238 } | 1248 } |
1239 | 1249 |
1240 | 1250 |
1241 // Shared routine for multiple word compare operations. | 1251 // Shared routine for multiple word compare operations. |
1242 static void VisitWordCompare(InstructionSelector* selector, Node* node, | 1252 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1243 InstructionCode opcode, FlagsContinuation* cont, | 1253 InstructionCode opcode, FlagsContinuation* cont, |
1244 bool commutative, ImmediateMode immediate_mode) { | 1254 bool commutative, ImmediateMode immediate_mode) { |
1245 Arm64OperandGenerator g(selector); | 1255 Arm64OperandGenerator g(selector); |
1246 Node* left = node->InputAt(0); | 1256 Node* left = node->InputAt(0); |
1247 Node* right = node->InputAt(1); | 1257 Node* right = node->InputAt(1); |
1248 | 1258 |
1249 // Match immediates on left or right side of comparison. | 1259 // Match immediates on left or right side of comparison. |
1250 if (g.CanBeImmediate(right, immediate_mode)) { | 1260 if (g.CanBeImmediate(right, immediate_mode)) { |
1251 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), | 1261 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), |
1252 cont); | 1262 cont); |
1253 } else if (g.CanBeImmediate(left, immediate_mode)) { | 1263 } else if (g.CanBeImmediate(left, immediate_mode)) { |
1254 if (!commutative) cont->Commute(); | 1264 if (!commutative) cont->Commute(); |
1255 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), | 1265 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), |
1256 cont); | 1266 cont); |
1257 } else { | 1267 } else { |
1258 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 1268 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), |
1259 cont); | 1269 cont); |
1260 } | 1270 } |
1261 } | 1271 } |
1262 | 1272 |
1263 | 1273 |
1264 static void VisitWord32Compare(InstructionSelector* selector, Node* node, | 1274 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
1265 FlagsContinuation* cont) { | 1275 FlagsContinuation* cont) { |
1266 VisitWordCompare(selector, node, kArm64Cmp32, cont, false, kArithmeticImm); | 1276 VisitWordCompare(selector, node, kArm64Cmp32, cont, false, kArithmeticImm); |
1267 } | 1277 } |
1268 | 1278 |
1269 | 1279 |
1270 static void VisitWordTest(InstructionSelector* selector, Node* node, | 1280 void VisitWordTest(InstructionSelector* selector, Node* node, |
1271 InstructionCode opcode, FlagsContinuation* cont) { | 1281 InstructionCode opcode, FlagsContinuation* cont) { |
1272 Arm64OperandGenerator g(selector); | 1282 Arm64OperandGenerator g(selector); |
1273 VisitCompare(selector, opcode, g.UseRegister(node), g.UseRegister(node), | 1283 VisitCompare(selector, opcode, g.UseRegister(node), g.UseRegister(node), |
1274 cont); | 1284 cont); |
1275 } | 1285 } |
1276 | 1286 |
1277 | 1287 |
1278 static void VisitWord32Test(InstructionSelector* selector, Node* node, | 1288 void VisitWord32Test(InstructionSelector* selector, Node* node, |
1279 FlagsContinuation* cont) { | 1289 FlagsContinuation* cont) { |
1280 VisitWordTest(selector, node, kArm64Tst32, cont); | 1290 VisitWordTest(selector, node, kArm64Tst32, cont); |
1281 } | 1291 } |
1282 | 1292 |
1283 | 1293 |
1284 static void VisitWord64Test(InstructionSelector* selector, Node* node, | 1294 void VisitWord64Test(InstructionSelector* selector, Node* node, |
1285 FlagsContinuation* cont) { | 1295 FlagsContinuation* cont) { |
1286 VisitWordTest(selector, node, kArm64Tst, cont); | 1296 VisitWordTest(selector, node, kArm64Tst, cont); |
1287 } | 1297 } |
1288 | 1298 |
1289 | 1299 |
1290 // Shared routine for multiple float compare operations. | 1300 // Shared routine for multiple float64 compare operations. |
1291 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1301 void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
1292 FlagsContinuation* cont) { | 1302 FlagsContinuation* cont) { |
| 1303 Arm64OperandGenerator g(selector); |
| 1304 Float32BinopMatcher m(node); |
| 1305 if (m.right().Is(0.0f)) { |
| 1306 VisitCompare(selector, kArm64Float32Cmp, g.UseRegister(m.left().node()), |
| 1307 g.UseImmediate(m.right().node()), cont); |
| 1308 } else { |
| 1309 VisitCompare(selector, kArm64Float32Cmp, g.UseRegister(m.left().node()), |
| 1310 g.UseRegister(m.right().node()), cont); |
| 1311 } |
| 1312 } |
| 1313 |
| 1314 |
| 1315 // Shared routine for multiple float64 compare operations. |
| 1316 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
| 1317 FlagsContinuation* cont) { |
1293 Arm64OperandGenerator g(selector); | 1318 Arm64OperandGenerator g(selector); |
1294 Float64BinopMatcher m(node); | 1319 Float64BinopMatcher m(node); |
1295 if (m.right().Is(0.0)) { | 1320 if (m.right().Is(0.0)) { |
1296 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()), | 1321 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()), |
1297 g.UseImmediate(m.right().node()), cont); | 1322 g.UseImmediate(m.right().node()), cont); |
1298 } else { | 1323 } else { |
1299 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()), | 1324 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()), |
1300 g.UseRegister(m.right().node()), cont); | 1325 g.UseRegister(m.right().node()), cont); |
1301 } | 1326 } |
1302 } | 1327 } |
1303 | 1328 |
| 1329 } // namespace |
| 1330 |
1304 | 1331 |
1305 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1332 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
1306 BasicBlock* fbranch) { | 1333 BasicBlock* fbranch) { |
1307 OperandGenerator g(this); | 1334 OperandGenerator g(this); |
1308 Node* user = branch; | 1335 Node* user = branch; |
1309 Node* value = branch->InputAt(0); | 1336 Node* value = branch->InputAt(0); |
1310 | 1337 |
1311 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 1338 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
1312 | 1339 |
1313 // Try to combine with comparisons against 0 by simply inverting the branch. | 1340 // Try to combine with comparisons against 0 by simply inverting the branch. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1349 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1376 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, |
1350 kArithmeticImm); | 1377 kArithmeticImm); |
1351 case IrOpcode::kInt64LessThanOrEqual: | 1378 case IrOpcode::kInt64LessThanOrEqual: |
1352 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1379 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
1353 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1380 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, |
1354 kArithmeticImm); | 1381 kArithmeticImm); |
1355 case IrOpcode::kUint64LessThan: | 1382 case IrOpcode::kUint64LessThan: |
1356 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1383 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
1357 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1384 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, |
1358 kArithmeticImm); | 1385 kArithmeticImm); |
| 1386 case IrOpcode::kFloat32Equal: |
| 1387 cont.OverwriteAndNegateIfEqual(kEqual); |
| 1388 return VisitFloat32Compare(this, value, &cont); |
| 1389 case IrOpcode::kFloat32LessThan: |
| 1390 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
| 1391 return VisitFloat32Compare(this, value, &cont); |
| 1392 case IrOpcode::kFloat32LessThanOrEqual: |
| 1393 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
| 1394 return VisitFloat32Compare(this, value, &cont); |
1359 case IrOpcode::kFloat64Equal: | 1395 case IrOpcode::kFloat64Equal: |
1360 cont.OverwriteAndNegateIfEqual(kEqual); | 1396 cont.OverwriteAndNegateIfEqual(kEqual); |
1361 return VisitFloat64Compare(this, value, &cont); | 1397 return VisitFloat64Compare(this, value, &cont); |
1362 case IrOpcode::kFloat64LessThan: | 1398 case IrOpcode::kFloat64LessThan: |
1363 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1399 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
1364 return VisitFloat64Compare(this, value, &cont); | 1400 return VisitFloat64Compare(this, value, &cont); |
1365 case IrOpcode::kFloat64LessThanOrEqual: | 1401 case IrOpcode::kFloat64LessThanOrEqual: |
1366 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 1402 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
1367 return VisitFloat64Compare(this, value, &cont); | 1403 return VisitFloat64Compare(this, value, &cont); |
1368 case IrOpcode::kProjection: | 1404 case IrOpcode::kProjection: |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1577 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); | 1613 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
1578 } | 1614 } |
1579 | 1615 |
1580 | 1616 |
1581 void InstructionSelector::VisitUint64LessThan(Node* node) { | 1617 void InstructionSelector::VisitUint64LessThan(Node* node) { |
1582 FlagsContinuation cont(kUnsignedLessThan, node); | 1618 FlagsContinuation cont(kUnsignedLessThan, node); |
1583 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); | 1619 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
1584 } | 1620 } |
1585 | 1621 |
1586 | 1622 |
| 1623 void InstructionSelector::VisitFloat32Equal(Node* node) { |
| 1624 FlagsContinuation cont(kEqual, node); |
| 1625 VisitFloat32Compare(this, node, &cont); |
| 1626 } |
| 1627 |
| 1628 |
| 1629 void InstructionSelector::VisitFloat32LessThan(Node* node) { |
| 1630 FlagsContinuation cont(kUnsignedLessThan, node); |
| 1631 VisitFloat32Compare(this, node, &cont); |
| 1632 } |
| 1633 |
| 1634 |
| 1635 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { |
| 1636 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); |
| 1637 VisitFloat32Compare(this, node, &cont); |
| 1638 } |
| 1639 |
| 1640 |
1587 void InstructionSelector::VisitFloat64Equal(Node* node) { | 1641 void InstructionSelector::VisitFloat64Equal(Node* node) { |
1588 FlagsContinuation cont(kEqual, node); | 1642 FlagsContinuation cont(kEqual, node); |
1589 VisitFloat64Compare(this, node, &cont); | 1643 VisitFloat64Compare(this, node, &cont); |
1590 } | 1644 } |
1591 | 1645 |
1592 | 1646 |
1593 void InstructionSelector::VisitFloat64LessThan(Node* node) { | 1647 void InstructionSelector::VisitFloat64LessThan(Node* node) { |
1594 FlagsContinuation cont(kUnsignedLessThan, node); | 1648 FlagsContinuation cont(kUnsignedLessThan, node); |
1595 VisitFloat64Compare(this, node, &cont); | 1649 VisitFloat64Compare(this, node, &cont); |
1596 } | 1650 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1647 return; | 1701 return; |
1648 } | 1702 } |
1649 Emit(kArm64Float64InsertHighWord32, g.DefineAsRegister(node), | 1703 Emit(kArm64Float64InsertHighWord32, g.DefineAsRegister(node), |
1650 g.UseRegister(left), g.UseRegister(right)); | 1704 g.UseRegister(left), g.UseRegister(right)); |
1651 } | 1705 } |
1652 | 1706 |
1653 | 1707 |
1654 // static | 1708 // static |
1655 MachineOperatorBuilder::Flags | 1709 MachineOperatorBuilder::Flags |
1656 InstructionSelector::SupportedMachineOperatorFlags() { | 1710 InstructionSelector::SupportedMachineOperatorFlags() { |
1657 return MachineOperatorBuilder::kFloat64RoundDown | | 1711 return MachineOperatorBuilder::kFloat32Max | |
| 1712 MachineOperatorBuilder::kFloat32Min | |
| 1713 MachineOperatorBuilder::kFloat64Max | |
| 1714 MachineOperatorBuilder::kFloat64Min | |
| 1715 MachineOperatorBuilder::kFloat64RoundDown | |
1658 MachineOperatorBuilder::kFloat64RoundTruncate | | 1716 MachineOperatorBuilder::kFloat64RoundTruncate | |
1659 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1717 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1660 MachineOperatorBuilder::kFloat64Max | | |
1661 MachineOperatorBuilder::kFloat64Min | | |
1662 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1718 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1663 MachineOperatorBuilder::kInt32DivIsSafe | | 1719 MachineOperatorBuilder::kInt32DivIsSafe | |
1664 MachineOperatorBuilder::kUint32DivIsSafe; | 1720 MachineOperatorBuilder::kUint32DivIsSafe; |
1665 } | 1721 } |
1666 | 1722 |
1667 } // namespace compiler | 1723 } // namespace compiler |
1668 } // namespace internal | 1724 } // namespace internal |
1669 } // namespace v8 | 1725 } // namespace v8 |
OLD | NEW |