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

Side by Side Diff: src/compiler/mips64/code-generator-mips64.cc

Issue 1294933003: MIPS:[turbofan] Improve boolean materialization compares. Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add mips32 port. Created 5 years, 4 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/code-generator.h" 5 #include "src/compiler/code-generator.h"
6 #include "src/compiler/code-generator-impl.h" 6 #include "src/compiler/code-generator-impl.h"
7 #include "src/compiler/gap-resolver.h" 7 #include "src/compiler/gap-resolver.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/mips/macro-assembler-mips.h" 9 #include "src/mips/macro-assembler-mips.h"
10 #include "src/scopes.h" 10 #include "src/scopes.h"
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 }; 193 };
194 194
195 195
196 class OutOfLineCeil final : public OutOfLineRound { 196 class OutOfLineCeil final : public OutOfLineRound {
197 public: 197 public:
198 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) 198 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result)
199 : OutOfLineRound(gen, result) {} 199 : OutOfLineRound(gen, result) {}
200 }; 200 };
201 201
202 202
203 Condition FlagsConditionToConditionCmp(FlagsCondition condition) { 203 Condition FlagsConditionToConditionCmp(bool& predicate,
204 FlagsCondition condition) {
204 switch (condition) { 205 switch (condition) {
205 case kEqual: 206 case kEqual:
207 predicate = true;
206 return eq; 208 return eq;
207 case kNotEqual: 209 case kNotEqual:
210 predicate = false;
208 return ne; 211 return ne;
209 case kSignedLessThan: 212 case kSignedLessThan:
213 predicate = true;
210 return lt; 214 return lt;
211 case kSignedGreaterThanOrEqual: 215 case kSignedGreaterThanOrEqual:
216 predicate = false;
212 return ge; 217 return ge;
213 case kSignedLessThanOrEqual: 218 case kSignedLessThanOrEqual:
219 predicate = false;
214 return le; 220 return le;
215 case kSignedGreaterThan: 221 case kSignedGreaterThan:
222 predicate = true;
216 return gt; 223 return gt;
217 case kUnsignedLessThan: 224 case kUnsignedLessThan:
225 predicate = true;
218 return lo; 226 return lo;
219 case kUnsignedGreaterThanOrEqual: 227 case kUnsignedGreaterThanOrEqual:
228 predicate = false;
220 return hs; 229 return hs;
221 case kUnsignedLessThanOrEqual: 230 case kUnsignedLessThanOrEqual:
231 predicate = false;
222 return ls; 232 return ls;
223 case kUnsignedGreaterThan: 233 case kUnsignedGreaterThan:
234 predicate = true;
224 return hi; 235 return hi;
225 case kUnorderedEqual: 236 case kUnorderedEqual:
226 case kUnorderedNotEqual: 237 case kUnorderedNotEqual:
238 predicate = true;
227 break; 239 break;
228 default: 240 default:
241 predicate = true;
229 break; 242 break;
230 } 243 }
231 UNREACHABLE(); 244 UNREACHABLE();
232 return kNoCondition; 245 return kNoCondition;
233 } 246 }
234 247
235 248
236 Condition FlagsConditionToConditionTst(FlagsCondition condition) { 249 Condition FlagsConditionToConditionTst(bool& predicate,
250 FlagsCondition condition) {
237 switch (condition) { 251 switch (condition) {
238 case kNotEqual: 252 case kNotEqual:
253 predicate = false;
239 return ne; 254 return ne;
240 case kEqual: 255 case kEqual:
256 predicate = true;
241 return eq; 257 return eq;
242 default: 258 default:
259 predicate = true;
243 break; 260 break;
244 } 261 }
245 UNREACHABLE(); 262 UNREACHABLE();
246 return kNoCondition; 263 return kNoCondition;
247 } 264 }
248 265
249 266
250 Condition FlagsConditionToConditionOvf(FlagsCondition condition) { 267 Condition FlagsConditionToConditionOvf(bool& predicate,
268 FlagsCondition condition) {
251 switch (condition) { 269 switch (condition) {
252 case kOverflow: 270 case kOverflow:
271 predicate = true;
253 return ne; 272 return ne;
254 case kNotOverflow: 273 case kNotOverflow:
274 predicate = false;
255 return eq; 275 return eq;
256 default: 276 default:
277 predicate = true;
257 break; 278 break;
258 } 279 }
259 UNREACHABLE(); 280 UNREACHABLE();
260 return kNoCondition; 281 return kNoCondition;
261 } 282 }
262 283
263 284
264 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, 285 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
265 FlagsCondition condition) { 286 FlagsCondition condition) {
266 switch (condition) { 287 switch (condition) {
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 return false; 979 return false;
959 } 980 }
960 981
961 982
962 // Assembles branches after an instruction. 983 // Assembles branches after an instruction.
963 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { 984 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
964 MipsOperandConverter i(this, instr); 985 MipsOperandConverter i(this, instr);
965 Label* tlabel = branch->true_label; 986 Label* tlabel = branch->true_label;
966 Label* flabel = branch->false_label; 987 Label* flabel = branch->false_label;
967 Condition cc = kNoCondition; 988 Condition cc = kNoCondition;
968 989 bool predicate;
969 // MIPS does not have condition code flags, so compare and branch are 990 // MIPS does not have condition code flags, so compare and branch are
970 // implemented differently than on the other arch's. The compare operations 991 // implemented differently than on the other arch's. The compare operations
971 // emit mips psuedo-instructions, which are handled here by branch 992 // emit mips psuedo-instructions, which are handled here by branch
972 // instructions that do the actual comparison. Essential that the input 993 // instructions that do the actual comparison. Essential that the input
973 // registers to compare pseudo-op are not modified before this branch op, as 994 // registers to compare pseudo-op are not modified before this branch op, as
974 // they are tested here. 995 // they are tested here.
975 996
976 if (instr->arch_opcode() == kMips64Tst) { 997 if (instr->arch_opcode() == kMips64Tst) {
977 cc = FlagsConditionToConditionTst(branch->condition); 998 cc = FlagsConditionToConditionTst(predicate, branch->condition);
978 __ And(at, i.InputRegister(0), i.InputOperand(1)); 999 __ And(at, i.InputRegister(0), i.InputOperand(1));
979 __ Branch(tlabel, cc, at, Operand(zero_reg)); 1000 __ Branch(tlabel, cc, at, Operand(zero_reg));
980 } else if (instr->arch_opcode() == kMips64Dadd || 1001 } else if (instr->arch_opcode() == kMips64Dadd ||
981 instr->arch_opcode() == kMips64Dsub) { 1002 instr->arch_opcode() == kMips64Dsub) {
982 cc = FlagsConditionToConditionOvf(branch->condition); 1003 cc = FlagsConditionToConditionOvf(predicate, branch->condition);
983 __ dsra32(kScratchReg, i.OutputRegister(), 0); 1004 __ dsra32(kScratchReg, i.OutputRegister(), 0);
984 __ sra(at, i.OutputRegister(), 31); 1005 __ sra(at, i.OutputRegister(), 31);
985 __ Branch(tlabel, cc, at, Operand(kScratchReg)); 1006 __ Branch(tlabel, cc, at, Operand(kScratchReg));
986 } else if (instr->arch_opcode() == kMips64Cmp) { 1007 } else if (instr->arch_opcode() == kMips64Cmp) {
987 cc = FlagsConditionToConditionCmp(branch->condition); 1008 cc = FlagsConditionToConditionCmp(predicate, branch->condition);
988 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); 1009 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1));
989 } else if (instr->arch_opcode() == kMips64CmpS) { 1010 } else if (instr->arch_opcode() == kMips64CmpS) {
990 if (!convertCondition(branch->condition, cc)) { 1011 if (!convertCondition(branch->condition, cc)) {
991 UNSUPPORTED_COND(kMips64CmpS, branch->condition); 1012 UNSUPPORTED_COND(kMips64CmpS, branch->condition);
992 } 1013 }
993 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), 1014 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0),
994 i.InputSingleRegister(1)); 1015 i.InputSingleRegister(1));
995 } else if (instr->arch_opcode() == kMips64CmpD) { 1016 } else if (instr->arch_opcode() == kMips64CmpD) {
996 if (!convertCondition(branch->condition, cc)) { 1017 if (!convertCondition(branch->condition, cc)) {
997 UNSUPPORTED_COND(kMips64CmpD, branch->condition); 1018 UNSUPPORTED_COND(kMips64CmpD, branch->condition);
(...skipping 19 matching lines...) Expand all
1017 FlagsCondition condition) { 1038 FlagsCondition condition) {
1018 MipsOperandConverter i(this, instr); 1039 MipsOperandConverter i(this, instr);
1019 Label done; 1040 Label done;
1020 1041
1021 // Materialize a full 32-bit 1 or 0 value. The result register is always the 1042 // Materialize a full 32-bit 1 or 0 value. The result register is always the
1022 // last output of the instruction. 1043 // last output of the instruction.
1023 Label false_value; 1044 Label false_value;
1024 DCHECK_NE(0u, instr->OutputCount()); 1045 DCHECK_NE(0u, instr->OutputCount());
1025 Register result = i.OutputRegister(instr->OutputCount() - 1); 1046 Register result = i.OutputRegister(instr->OutputCount() - 1);
1026 Condition cc = kNoCondition; 1047 Condition cc = kNoCondition;
1027 1048 bool predicate;
1028 // MIPS does not have condition code flags, so compare and branch are 1049 // MIPS does not have condition code flags, so compare and branch are
1029 // implemented differently than on the other arch's. The compare operations 1050 // implemented differently than on the other arch's. The compare operations
1030 // emit mips pseudo-instructions, which are checked and handled here. 1051 // emit mips pseudo-instructions, which are checked and handled here.
1031 1052
1032 // For materializations, we use delay slot to set the result true, and
1033 // in the false case, where we fall through the branch, we reset the result
1034 // false.
1035
1036 if (instr->arch_opcode() == kMips64Tst) { 1053 if (instr->arch_opcode() == kMips64Tst) {
1037 cc = FlagsConditionToConditionTst(condition); 1054 cc = FlagsConditionToConditionTst(predicate, condition);
1038 __ And(at, i.InputRegister(0), i.InputOperand(1)); 1055 __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1));
1039 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); 1056 __ xori(kScratchReg2, zero_reg, 1); // Create 1 for true.
1040 __ li(result, Operand(1)); // In delay slot. 1057 if (kArchVariant != kMips64r6) {
1058 if (predicate) {
1059 __ Movn(result, zero_reg, kScratchReg);
1060 __ Movz(result, kScratchReg2, kScratchReg);
1061 } else {
1062 __ Movz(result, zero_reg, kScratchReg);
1063 __ Movn(result, kScratchReg2, kScratchReg);
1064 }
1065 } else {
1066 if (predicate) {
1067 __ seleqz(result, kScratchReg2, kScratchReg);
1068 } else {
1069 __ selnez(result, kScratchReg2, kScratchReg);
1070 }
1071 }
1072 return;
1041 } else if (instr->arch_opcode() == kMips64Dadd || 1073 } else if (instr->arch_opcode() == kMips64Dadd ||
1042 instr->arch_opcode() == kMips64Dsub) { 1074 instr->arch_opcode() == kMips64Dsub) {
1043 cc = FlagsConditionToConditionOvf(condition); 1075 FlagsConditionToConditionOvf(predicate, condition);
1044 __ dsra32(kScratchReg, i.OutputRegister(), 0); 1076 // Check for overflow creates 1 or 0 for result.
1045 __ sra(at, i.OutputRegister(), 31); 1077 __ dsrl32(kScratchReg, i.OutputRegister(), 31);
1046 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(kScratchReg)); 1078 __ srl(at, i.OutputRegister(), 31);
1047 __ li(result, Operand(1)); // In delay slot. 1079 __ xor_(result, kScratchReg, at);
1080 if (!predicate) // Toggle result for not overflow.
1081 __ xori(result, result, 1);
1082 return;
1048 } else if (instr->arch_opcode() == kMips64Cmp) { 1083 } else if (instr->arch_opcode() == kMips64Cmp) {
1049 Register left = i.InputRegister(0); 1084 cc = FlagsConditionToConditionCmp(predicate, condition);
1050 Operand right = i.InputOperand(1); 1085 switch (cc) {
1051 cc = FlagsConditionToConditionCmp(condition); 1086 case eq:
1052 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); 1087 case ne: {
1053 __ li(result, Operand(1)); // In delay slot. 1088 Register left = i.InputRegister(0);
1089 Operand right = i.InputOperand(1);
1090 __ Dsubu(kScratchReg, left, right);
1091 __ xori(kScratchReg2, zero_reg, 1);
1092 if (kArchVariant != kMips64r6) {
1093 if (predicate) {
1094 __ Movn(result, zero_reg, kScratchReg);
1095 __ Movz(result, kScratchReg2, kScratchReg);
1096 } else {
1097 __ Movz(result, zero_reg, kScratchReg);
1098 __ Movn(result, kScratchReg2, kScratchReg);
1099 }
1100 } else {
1101 if (predicate) {
1102 __ seleqz(result, kScratchReg2, kScratchReg);
1103 } else {
1104 __ selnez(result, kScratchReg2, kScratchReg);
1105 }
1106 }
1107 } break;
1108 case lt:
1109 case ge: {
1110 Register left = i.InputRegister(0);
1111 Operand right = i.InputOperand(1);
1112 __ Slt(result, left, right);
1113 if (!predicate) {
1114 __ xori(result, result, 1);
1115 }
1116 } break;
1117 case gt:
1118 case le: {
1119 Register left = i.InputRegister(1);
1120 Operand right = i.InputOperand(0);
1121 __ Slt(result, left, right);
1122 if (!predicate) {
1123 __ xori(result, result, 1);
1124 }
1125 } break;
1126 case lo:
1127 case hs: {
1128 Register left = i.InputRegister(0);
1129 Operand right = i.InputOperand(1);
1130 __ Sltu(result, left, right);
1131 if (!predicate) {
1132 __ xori(result, result, 1);
1133 }
1134 } break;
1135 case hi:
1136 case ls: {
1137 Register left = i.InputRegister(1);
1138 Operand right = i.InputOperand(0);
1139 __ Sltu(result, left, right);
1140 if (!predicate) {
1141 __ xori(result, result, 1);
1142 }
1143 } break;
1144 default:
1145 UNREACHABLE();
1146 }
1147 return;
1054 } else if (instr->arch_opcode() == kMips64CmpD || 1148 } else if (instr->arch_opcode() == kMips64CmpD ||
1055 instr->arch_opcode() == kMips64CmpS) { 1149 instr->arch_opcode() == kMips64CmpS) {
1056 FPURegister left = i.InputDoubleRegister(0); 1150 FPURegister left = i.InputDoubleRegister(0);
1057 FPURegister right = i.InputDoubleRegister(1); 1151 FPURegister right = i.InputDoubleRegister(1);
1058 1152
1059 bool predicate;
1060 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); 1153 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition);
1061 if (kArchVariant != kMips64r6) { 1154 if (kArchVariant != kMips64r6) {
1062 __ li(result, Operand(1)); 1155 __ li(result, Operand(1));
1063 if (instr->arch_opcode() == kMips64CmpD) { 1156 if (instr->arch_opcode() == kMips64CmpD) {
1064 __ c(cc, D, left, right); 1157 __ c(cc, D, left, right);
1065 } else { 1158 } else {
1066 DCHECK(instr->arch_opcode() == kMips64CmpS); 1159 DCHECK(instr->arch_opcode() == kMips64CmpS);
1067 __ c(cc, S, left, right); 1160 __ c(cc, S, left, right);
1068 } 1161 }
1069 if (predicate) { 1162 if (predicate) {
(...skipping 13 matching lines...) Expand all
1083 if (!predicate) // Toggle result for not equal. 1176 if (!predicate) // Toggle result for not equal.
1084 __ xori(result, result, 1); 1177 __ xori(result, result, 1);
1085 } 1178 }
1086 return; 1179 return;
1087 } else { 1180 } else {
1088 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", 1181 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n",
1089 instr->arch_opcode()); 1182 instr->arch_opcode());
1090 TRACE_UNIMPL(); 1183 TRACE_UNIMPL();
1091 UNIMPLEMENTED(); 1184 UNIMPLEMENTED();
1092 } 1185 }
1093 // Fallthru case is the false materialization.
1094 __ bind(&false_value);
1095 __ li(result, Operand(static_cast<int64_t>(0)));
1096 __ bind(&done);
1097 } 1186 }
1098 1187
1099 1188
1100 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { 1189 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
1101 MipsOperandConverter i(this, instr); 1190 MipsOperandConverter i(this, instr);
1102 Register input = i.InputRegister(0); 1191 Register input = i.InputRegister(0);
1103 for (size_t index = 2; index < instr->InputCount(); index += 2) { 1192 for (size_t index = 2; index < instr->InputCount(); index += 2) {
1104 __ li(at, Operand(i.InputInt32(index + 0))); 1193 __ li(at, Operand(i.InputInt32(index + 0)));
1105 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); 1194 __ beq(input, at, GetLabel(i.InputRpo(index + 1)));
1106 } 1195 }
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1443 } 1532 }
1444 } 1533 }
1445 } 1534 }
1446 } 1535 }
1447 1536
1448 #undef __ 1537 #undef __
1449 1538
1450 } // namespace compiler 1539 } // namespace compiler
1451 } // namespace internal 1540 } // namespace internal
1452 } // namespace v8 1541 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698