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

Side by Side Diff: src/compiler/mips/code-generator-mips.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
« no previous file with comments | « no previous file | src/compiler/mips/instruction-selector-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
paul.l... 2015/09/03 22:27:39 It took me some staring at the code to figure out
paul.l... 2015/09/04 03:33:58 OK, I think we both overcomplicated this. When I s
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 lt; 272 return lt;
254 case kNotOverflow: 273 case kNotOverflow:
274 predicate = false;
255 return ge; 275 return ge;
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 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, 284 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
264 FlagsCondition condition) { 285 FlagsCondition condition) {
265 switch (condition) { 286 switch (condition) {
266 case kEqual: 287 case kEqual:
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 return false; 904 return false;
884 } 905 }
885 906
886 907
887 // Assembles branches after an instruction. 908 // Assembles branches after an instruction.
888 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { 909 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
889 MipsOperandConverter i(this, instr); 910 MipsOperandConverter i(this, instr);
890 Label* tlabel = branch->true_label; 911 Label* tlabel = branch->true_label;
891 Label* flabel = branch->false_label; 912 Label* flabel = branch->false_label;
892 Condition cc = kNoCondition; 913 Condition cc = kNoCondition;
893 914 bool predicate;
894 // MIPS does not have condition code flags, so compare and branch are 915 // MIPS does not have condition code flags, so compare and branch are
895 // implemented differently than on the other arch's. The compare operations 916 // implemented differently than on the other arch's. The compare operations
896 // emit mips pseudo-instructions, which are handled here by branch 917 // emit mips pseudo-instructions, which are handled here by branch
897 // instructions that do the actual comparison. Essential that the input 918 // instructions that do the actual comparison. Essential that the input
898 // registers to compare pseudo-op are not modified before this branch op, as 919 // registers to compare pseudo-op are not modified before this branch op, as
899 // they are tested here. 920 // they are tested here.
900 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were 921 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were
901 // not separated by other instructions. 922 // not separated by other instructions.
902 923
903 if (instr->arch_opcode() == kMipsTst) { 924 if (instr->arch_opcode() == kMipsTst) {
904 cc = FlagsConditionToConditionTst(branch->condition); 925 cc = FlagsConditionToConditionTst(predicate, branch->condition);
905 __ And(at, i.InputRegister(0), i.InputOperand(1)); 926 __ And(at, i.InputRegister(0), i.InputOperand(1));
906 __ Branch(tlabel, cc, at, Operand(zero_reg)); 927 __ Branch(tlabel, cc, at, Operand(zero_reg));
907 } else if (instr->arch_opcode() == kMipsAddOvf || 928 } else if (instr->arch_opcode() == kMipsAddOvf ||
908 instr->arch_opcode() == kMipsSubOvf) { 929 instr->arch_opcode() == kMipsSubOvf) {
909 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. 930 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow.
910 cc = FlagsConditionToConditionOvf(branch->condition); 931 cc = FlagsConditionToConditionOvf(predicate, branch->condition);
911 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); 932 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg));
912 } else if (instr->arch_opcode() == kMipsCmp) { 933 } else if (instr->arch_opcode() == kMipsCmp) {
913 cc = FlagsConditionToConditionCmp(branch->condition); 934 cc = FlagsConditionToConditionCmp(predicate, branch->condition);
914 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); 935 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1));
915 } else if (instr->arch_opcode() == kMipsCmpS) { 936 } else if (instr->arch_opcode() == kMipsCmpS) {
916 if (!convertCondition(branch->condition, cc)) { 937 if (!convertCondition(branch->condition, cc)) {
917 UNSUPPORTED_COND(kMips64CmpS, branch->condition); 938 UNSUPPORTED_COND(kMips64CmpS, branch->condition);
918 } 939 }
919 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), 940 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0),
920 i.InputSingleRegister(1)); 941 i.InputSingleRegister(1));
921 } else if (instr->arch_opcode() == kMipsCmpD) { 942 } else if (instr->arch_opcode() == kMipsCmpD) {
922 if (!convertCondition(branch->condition, cc)) { 943 if (!convertCondition(branch->condition, cc)) {
923 UNSUPPORTED_COND(kMips64CmpD, branch->condition); 944 UNSUPPORTED_COND(kMips64CmpD, branch->condition);
(...skipping 19 matching lines...) Expand all
943 FlagsCondition condition) { 964 FlagsCondition condition) {
944 MipsOperandConverter i(this, instr); 965 MipsOperandConverter i(this, instr);
945 Label done; 966 Label done;
946 967
947 // Materialize a full 32-bit 1 or 0 value. The result register is always the 968 // Materialize a full 32-bit 1 or 0 value. The result register is always the
948 // last output of the instruction. 969 // last output of the instruction.
949 Label false_value; 970 Label false_value;
950 DCHECK_NE(0u, instr->OutputCount()); 971 DCHECK_NE(0u, instr->OutputCount());
951 Register result = i.OutputRegister(instr->OutputCount() - 1); 972 Register result = i.OutputRegister(instr->OutputCount() - 1);
952 Condition cc = kNoCondition; 973 Condition cc = kNoCondition;
953 974 bool predicate;
954 // MIPS does not have condition code flags, so compare and branch are 975 // MIPS does not have condition code flags, so compare and branch are
955 // implemented differently than on the other arch's. The compare operations 976 // implemented differently than on the other arch's. The compare operations
956 // emit mips psuedo-instructions, which are checked and handled here. 977 // emit mips psuedo-instructions, which are checked and handled here.
957 978
958 // For materializations, we use delay slot to set the result true, and
959 // in the false case, where we fall thru the branch, we reset the result
960 // false.
961
962 if (instr->arch_opcode() == kMipsTst) { 979 if (instr->arch_opcode() == kMipsTst) {
963 cc = FlagsConditionToConditionTst(condition); 980 cc = FlagsConditionToConditionTst(predicate, condition);
964 __ And(at, i.InputRegister(0), i.InputOperand(1)); 981 __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1));
965 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); 982 __ xori(kScratchReg2, zero_reg, 1); // Create 1 for true.
paul.l... 2015/09/03 22:27:39 Prefer li(kScratchReg2, 1) here, for readability.
966 __ li(result, Operand(1)); // In delay slot. 983 if (!IsMipsArchVariant(kMips32r6)) {
paul.l... 2015/09/03 22:27:39 I find that 'negative-conditions' -- if (not-somet
967 984 if (predicate) {
985 __ Movn(result, zero_reg, kScratchReg);
986 __ Movz(result, kScratchReg2, kScratchReg);
paul.l... 2015/09/03 22:27:39 If you refactor the code a bit, you can get by wit
paul.l... 2015/09/04 03:33:58 Never mind the last paragraph of prev comment (quo
987 } else {
988 __ Movz(result, zero_reg, kScratchReg);
989 __ Movn(result, kScratchReg2, kScratchReg);
990 }
991 } else {
992 if (predicate) {
993 __ seleqz(result, kScratchReg2, kScratchReg);
994 } else {
995 __ selnez(result, kScratchReg2, kScratchReg);
996 }
997 }
998 return;
968 } else if (instr->arch_opcode() == kMipsAddOvf || 999 } else if (instr->arch_opcode() == kMipsAddOvf ||
969 instr->arch_opcode() == kMipsSubOvf) { 1000 instr->arch_opcode() == kMipsSubOvf) {
970 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. 1001 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow.
971 cc = FlagsConditionToConditionOvf(condition); 1002 cc = FlagsConditionToConditionOvf(predicate, condition);
972 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); 1003 // Return 1 on overflow.
973 __ li(result, Operand(1)); // In delay slot. 1004 __ Slt(result, kCompareReg, Operand(zero_reg));
974 1005 if (!predicate) // Invert result on not overflow.
1006 __ xori(result, result, 1);
1007 return;
975 } else if (instr->arch_opcode() == kMipsCmp) { 1008 } else if (instr->arch_opcode() == kMipsCmp) {
976 Register left = i.InputRegister(0); 1009 cc = FlagsConditionToConditionCmp(predicate, condition);
977 Operand right = i.InputOperand(1); 1010 switch (cc) {
978 cc = FlagsConditionToConditionCmp(condition); 1011 case eq:
979 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); 1012 case ne: {
980 __ li(result, Operand(1)); // In delay slot. 1013 Register left = i.InputRegister(0);
981 1014 Operand right = i.InputOperand(1);
1015 __ Subu(kScratchReg, left, right);
1016 __ xori(kScratchReg2, zero_reg, 1);
1017 if (!IsMipsArchVariant(kMips32r6)) {
1018 if (predicate) {
1019 __ Movn(result, zero_reg, kScratchReg);
1020 __ Movz(result, kScratchReg2, kScratchReg);
1021 } else {
1022 __ Movz(result, zero_reg, kScratchReg);
1023 __ Movn(result, kScratchReg2, kScratchReg);
1024 }
1025 } else {
1026 if (predicate) {
1027 __ seleqz(result, kScratchReg2, kScratchReg);
1028 } else {
1029 __ selnez(result, kScratchReg2, kScratchReg);
1030 }
1031 }
1032 } break;
1033 case lt:
1034 case ge: {
1035 Register left = i.InputRegister(0);
1036 Operand right = i.InputOperand(1);
1037 __ Slt(result, left, right);
1038 if (!predicate) {
1039 __ xori(result, result, 1);
1040 }
1041 } break;
1042 case gt:
1043 case le: {
1044 Register left = i.InputRegister(1);
1045 Operand right = i.InputOperand(0);
1046 __ Slt(result, left, right);
1047 if (!predicate) {
1048 __ xori(result, result, 1);
1049 }
1050 } break;
1051 case lo:
1052 case hs: {
1053 Register left = i.InputRegister(0);
1054 Operand right = i.InputOperand(1);
1055 __ Sltu(result, left, right);
1056 if (!predicate) {
1057 __ xori(result, result, 1);
1058 }
1059 } break;
1060 case hi:
1061 case ls: {
1062 Register left = i.InputRegister(1);
1063 Operand right = i.InputOperand(0);
1064 __ Sltu(result, left, right);
1065 if (!predicate) {
1066 __ xori(result, result, 1);
1067 }
1068 } break;
1069 default:
1070 UNREACHABLE();
1071 }
1072 return;
982 } else if (instr->arch_opcode() == kMipsCmpD || 1073 } else if (instr->arch_opcode() == kMipsCmpD ||
983 instr->arch_opcode() == kMipsCmpS) { 1074 instr->arch_opcode() == kMipsCmpS) {
984 FPURegister left = i.InputDoubleRegister(0); 1075 FPURegister left = i.InputDoubleRegister(0);
985 FPURegister right = i.InputDoubleRegister(1); 1076 FPURegister right = i.InputDoubleRegister(1);
986 1077
987 bool predicate;
988 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); 1078 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition);
989 if (!IsMipsArchVariant(kMips32r6)) { 1079 if (!IsMipsArchVariant(kMips32r6)) {
990 __ li(result, Operand(1)); 1080 __ li(result, Operand(1));
991 if (instr->arch_opcode() == kMipsCmpD) { 1081 if (instr->arch_opcode() == kMipsCmpD) {
992 __ c(cc, D, left, right); 1082 __ c(cc, D, left, right);
993 } else { 1083 } else {
994 DCHECK(instr->arch_opcode() == kMipsCmpS); 1084 DCHECK(instr->arch_opcode() == kMipsCmpS);
995 __ c(cc, S, left, right); 1085 __ c(cc, S, left, right);
996 } 1086 }
997 if (predicate) { 1087 if (predicate) {
(...skipping 13 matching lines...) Expand all
1011 if (!predicate) // Toggle result for not equal. 1101 if (!predicate) // Toggle result for not equal.
1012 __ xori(result, result, 1); 1102 __ xori(result, result, 1);
1013 } 1103 }
1014 return; 1104 return;
1015 } else { 1105 } else {
1016 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", 1106 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n",
1017 instr->arch_opcode()); 1107 instr->arch_opcode());
1018 TRACE_UNIMPL(); 1108 TRACE_UNIMPL();
1019 UNIMPLEMENTED(); 1109 UNIMPLEMENTED();
1020 } 1110 }
1021
1022 // Fallthrough case is the false materialization.
1023 __ bind(&false_value);
1024 __ li(result, Operand(0));
1025 __ bind(&done);
1026 } 1111 }
1027 1112
1028 1113
1029 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { 1114 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
1030 MipsOperandConverter i(this, instr); 1115 MipsOperandConverter i(this, instr);
1031 Register input = i.InputRegister(0); 1116 Register input = i.InputRegister(0);
1032 for (size_t index = 2; index < instr->InputCount(); index += 2) { 1117 for (size_t index = 2; index < instr->InputCount(); index += 2) {
1033 __ li(at, Operand(i.InputInt32(index + 0))); 1118 __ li(at, Operand(i.InputInt32(index + 0)));
1034 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); 1119 __ beq(input, at, GetLabel(i.InputRpo(index + 1)));
1035 } 1120 }
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 } 1452 }
1368 } 1453 }
1369 } 1454 }
1370 } 1455 }
1371 1456
1372 #undef __ 1457 #undef __
1373 1458
1374 } // namespace compiler 1459 } // namespace compiler
1375 } // namespace internal 1460 } // namespace internal
1376 } // namespace v8 1461 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/mips/instruction-selector-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698