Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/compiler/arm64/instruction-selector-arm64.cc

Issue 1044793002: [turbofan] Add backend support for float32 operations. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add MachineOperator unit tests. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698