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

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

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

Powered by Google App Engine
This is Rietveld 408576698