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

Side by Side Diff: runtime/vm/assembler_mips.h

Issue 817593002: Improve generated MIPS code for conditional expressions and branches by delaying (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/assembler_mips.cc » ('j') | runtime/vm/constants_mips.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_ASSEMBLER_MIPS_H_ 5 #ifndef VM_ASSEMBLER_MIPS_H_
6 #define VM_ASSEMBLER_MIPS_H_ 6 #define VM_ASSEMBLER_MIPS_H_
7 7
8 #ifndef VM_ASSEMBLER_H_ 8 #ifndef VM_ASSEMBLER_H_
9 #error Do not include assembler_mips.h directly; use assembler.h instead. 9 #error Do not include assembler_mips.h directly; use assembler.h instead.
10 #endif 10 #endif
(...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 } 927 }
928 928
929 if (Utils::IsUint(kImmBits, imm)) { 929 if (Utils::IsUint(kImmBits, imm)) {
930 andi(rd, rs, Immediate(imm)); 930 andi(rd, rs, Immediate(imm));
931 } else { 931 } else {
932 LoadImmediate(TMP, imm); 932 LoadImmediate(TMP, imm);
933 and_(rd, rs, TMP); 933 and_(rd, rs, TMP);
934 } 934 }
935 } 935 }
936 936
937 void OrImmediate(Register rd, Register rs, int32_t imm) {
938 ASSERT(!in_delay_slot_);
939 if (imm == 0) {
940 mov(rd, rs);
941 return;
942 }
943
944 if (Utils::IsUint(kImmBits, imm)) {
945 ori(rd, rs, Immediate(imm));
946 } else {
947 LoadImmediate(TMP, imm);
948 or_(rd, rs, TMP);
949 }
950 }
951
952 void XorImmediate(Register rd, Register rs, int32_t imm) {
953 ASSERT(!in_delay_slot_);
954 if (imm == 0) {
955 mov(rd, rs);
956 return;
957 }
958
959 if (Utils::IsUint(kImmBits, imm)) {
960 xori(rd, rs, Immediate(imm));
961 } else {
962 LoadImmediate(TMP, imm);
963 xor_(rd, rs, TMP);
964 }
965 }
966
967 // Branch to label if condition is true.
968 void BranchOnCondition(Condition cond, Label* l) {
969 ASSERT(!in_delay_slot_);
970 Register left = cond.left();
971 Register right = cond.right();
972 RelationOperator rel_op = cond.rel_op();
973 switch (rel_op) {
974 case NV: return;
975 case AL: b(l); return;
976 case EQ: // fall through.
977 case NE: {
978 if (left == IMM) {
979 addiu(AT, ZR, Immediate(cond.imm()));
zra 2014/12/19 17:49:47 Why not LoadImmediate?
regis 2014/12/22 20:17:34 I like to see exactly what instruction we generate
980 left = AT;
981 } else if (right == IMM) {
982 addiu(AT, ZR, Immediate(cond.imm()));
983 right = AT;
984 }
985 if (rel_op == EQ) {
986 beq(left, right, l);
987 } else {
988 bne(left, right, l);
989 }
990 break;
991 }
992 case GT: {
993 if (left == ZR) {
994 bltz(right, l);
995 } else if (right == ZR) {
996 bgtz(left, l);
997 } else if (left == IMM) {
998 slti(AT, right, Immediate(cond.imm()));
999 bne(AT, ZR, l);
1000 } else if (right == IMM) {
1001 slti(AT, left, Immediate(cond.imm() + 1));
1002 beq(AT, ZR, l);
1003 } else {
1004 slt(AT, right, left);
1005 bne(AT, ZR, l);
1006 }
1007 break;
1008 }
1009 case GE: {
1010 if (left == ZR) {
1011 blez(right, l);
1012 } else if (right == ZR) {
1013 bgez(left, l);
1014 } else if (left == IMM) {
1015 slti(AT, right, Immediate(cond.imm() + 1));
1016 bne(AT, ZR, l);
1017 } else if (right == IMM) {
1018 slti(AT, left, Immediate(cond.imm()));
1019 beq(AT, ZR, l);
1020 } else {
1021 slt(AT, left, right);
1022 beq(AT, ZR, l);
1023 }
1024 break;
1025 }
1026 case LT: {
1027 if (left == ZR) {
1028 bgtz(right, l);
1029 } else if (right == ZR) {
1030 bltz(left, l);
1031 } else if (left == IMM) {
1032 slti(AT, right, Immediate(cond.imm() + 1));
1033 beq(AT, ZR, l);
1034 } else if (right == IMM) {
1035 slti(AT, left, Immediate(cond.imm()));
1036 bne(AT, ZR, l);
1037 } else {
1038 slt(AT, left, right);
1039 bne(AT, ZR, l);
1040 }
1041 break;
1042 }
1043 case LE: {
1044 if (left == ZR) {
1045 bgez(right, l);
1046 } else if (right == ZR) {
1047 blez(left, l);
1048 } else if (left == IMM) {
1049 slti(AT, right, Immediate(cond.imm()));
1050 beq(AT, ZR, l);
1051 } else if (right == IMM) {
1052 slti(AT, left, Immediate(cond.imm() + 1));
1053 bne(AT, ZR, l);
1054 } else {
1055 slt(AT, right, left);
1056 beq(AT, ZR, l);
1057 }
1058 break;
1059 }
1060 case UGT: {
1061 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used.
zra 2014/12/19 17:49:47 What do you do if you want to branch on an unsigne
regis 2014/12/22 20:17:34 This does not come up. The compiler will always al
1062 if (left == ZR) {
1063 // NV: Never branch. Fall through.
1064 } else if (right == ZR) {
1065 bne(left, ZR, l);
1066 } else {
1067 sltu(AT, right, left);
1068 bne(AT, ZR, l);
1069 }
1070 break;
1071 }
1072 case UGE: {
1073 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used.
1074 if (left == ZR) {
1075 beq(right, ZR, l);
1076 } else if (right == ZR) {
1077 // AL: Always branch to l.
1078 beq(ZR, ZR, l);
1079 } else {
1080 sltu(AT, left, right);
1081 beq(AT, ZR, l);
1082 }
1083 break;
1084 }
1085 case ULT: {
1086 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used.
1087 if (left == ZR) {
1088 bne(right, ZR, l);
1089 } else if (right == ZR) {
1090 // NV: Never branch. Fall through.
1091 } else {
1092 sltu(AT, left, right);
1093 bne(AT, ZR, l);
1094 }
1095 break;
1096 }
1097 case ULE: {
1098 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used.
1099 if (left == ZR) {
1100 // AL: Always branch to l.
1101 beq(ZR, ZR, l);
1102 } else if (right == ZR) {
1103 beq(left, ZR, l);
1104 } else {
1105 sltu(AT, right, left);
1106 beq(AT, ZR, l);
1107 }
1108 break;
1109 }
1110 default:
1111 UNREACHABLE();
1112 }
1113 }
1114
937 void BranchEqual(Register rd, Register rn, Label* l) { 1115 void BranchEqual(Register rd, Register rn, Label* l) {
938 beq(rd, rn, l); 1116 beq(rd, rn, l);
939 } 1117 }
940 1118
941 void BranchEqual(Register rd, const Immediate& imm, Label* l) { 1119 void BranchEqual(Register rd, const Immediate& imm, Label* l) {
942 ASSERT(!in_delay_slot_); 1120 ASSERT(!in_delay_slot_);
943 if (imm.value() == 0) { 1121 if (imm.value() == 0) {
944 beq(rd, ZR, l); 1122 beq(rd, ZR, l);
945 } else { 1123 } else {
946 ASSERT(rd != CMPRES2); 1124 ASSERT(rd != CMPRES2);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 ASSERT(!in_delay_slot_); 1160 ASSERT(!in_delay_slot_);
983 slt(CMPRES2, rs, rd); // CMPRES2 = rd > rs ? 1 : 0. 1161 slt(CMPRES2, rs, rd); // CMPRES2 = rd > rs ? 1 : 0.
984 bne(CMPRES2, ZR, l); 1162 bne(CMPRES2, ZR, l);
985 } 1163 }
986 1164
987 void BranchSignedGreater(Register rd, const Immediate& imm, Label* l) { 1165 void BranchSignedGreater(Register rd, const Immediate& imm, Label* l) {
988 ASSERT(!in_delay_slot_); 1166 ASSERT(!in_delay_slot_);
989 if (imm.value() == 0) { 1167 if (imm.value() == 0) {
990 bgtz(rd, l); 1168 bgtz(rd, l);
991 } else { 1169 } else {
992 ASSERT(rd != CMPRES2); 1170 if (Utils::IsInt(kImmBits, imm.value() + 1)) {
993 LoadImmediate(CMPRES2, imm.value()); 1171 slti(CMPRES2, rd, Immediate(imm.value() + 1));
994 BranchSignedGreater(rd, CMPRES2, l); 1172 beq(CMPRES2, ZR, l);
1173 } else {
1174 ASSERT(rd != CMPRES2);
1175 LoadImmediate(CMPRES2, imm.value());
1176 BranchSignedGreater(rd, CMPRES2, l);
1177 }
995 } 1178 }
996 } 1179 }
997 1180
998 void BranchUnsignedGreater(Register rd, Register rs, Label* l) { 1181 void BranchUnsignedGreater(Register rd, Register rs, Label* l) {
999 ASSERT(!in_delay_slot_); 1182 ASSERT(!in_delay_slot_);
1000 sltu(CMPRES2, rs, rd); 1183 sltu(CMPRES2, rs, rd);
1001 bne(CMPRES2, ZR, l); 1184 bne(CMPRES2, ZR, l);
1002 } 1185 }
1003 1186
1004 void BranchUnsignedGreater(Register rd, const Immediate& imm, Label* l) { 1187 void BranchUnsignedGreater(Register rd, const Immediate& imm, Label* l) {
1005 ASSERT(!in_delay_slot_); 1188 ASSERT(!in_delay_slot_);
1006 if (imm.value() == 0) { 1189 if (imm.value() == 0) {
1007 BranchNotEqual(rd, Immediate(0), l); 1190 BranchNotEqual(rd, Immediate(0), l);
1008 } else { 1191 } else {
1009 ASSERT(rd != CMPRES2); 1192 if ((imm.value() != -1) && Utils::IsInt(kImmBits, imm.value() + 1)) {
1010 LoadImmediate(CMPRES2, imm.value()); 1193 sltiu(CMPRES2, rd, Immediate(imm.value() + 1));
1011 BranchUnsignedGreater(rd, CMPRES2, l); 1194 beq(CMPRES2, ZR, l);
1195 } else {
1196 ASSERT(rd != CMPRES2);
1197 LoadImmediate(CMPRES2, imm.value());
1198 BranchUnsignedGreater(rd, CMPRES2, l);
1199 }
1012 } 1200 }
1013 } 1201 }
1014 1202
1015 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { 1203 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) {
1016 ASSERT(!in_delay_slot_); 1204 ASSERT(!in_delay_slot_);
1017 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. 1205 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0.
1018 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs. 1206 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs.
1019 } 1207 }
1020 1208
1021 void BranchSignedGreaterEqual(Register rd, const Immediate& imm, Label* l) { 1209 void BranchSignedGreaterEqual(Register rd, const Immediate& imm, Label* l) {
(...skipping 16 matching lines...) Expand all
1038 ASSERT(!in_delay_slot_); 1226 ASSERT(!in_delay_slot_);
1039 sltu(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. 1227 sltu(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0.
1040 beq(CMPRES2, ZR, l); 1228 beq(CMPRES2, ZR, l);
1041 } 1229 }
1042 1230
1043 void BranchUnsignedGreaterEqual(Register rd, const Immediate& imm, Label* l) { 1231 void BranchUnsignedGreaterEqual(Register rd, const Immediate& imm, Label* l) {
1044 ASSERT(!in_delay_slot_); 1232 ASSERT(!in_delay_slot_);
1045 if (imm.value() == 0) { 1233 if (imm.value() == 0) {
1046 b(l); 1234 b(l);
1047 } else { 1235 } else {
1048 if (Utils::IsUint(kImmBits, imm.value())) { 1236 if (Utils::IsInt(kImmBits, imm.value())) {
1049 sltiu(CMPRES2, rd, imm); 1237 sltiu(CMPRES2, rd, imm);
1050 beq(CMPRES2, ZR, l); 1238 beq(CMPRES2, ZR, l);
1051 } else { 1239 } else {
1052 ASSERT(rd != CMPRES2); 1240 ASSERT(rd != CMPRES2);
1053 LoadImmediate(CMPRES2, imm.value()); 1241 LoadImmediate(CMPRES2, imm.value());
1054 BranchUnsignedGreaterEqual(rd, CMPRES2, l); 1242 BranchUnsignedGreaterEqual(rd, CMPRES2, l);
1055 } 1243 }
1056 } 1244 }
1057 } 1245 }
1058 1246
(...skipping 18 matching lines...) Expand all
1077 } 1265 }
1078 } 1266 }
1079 1267
1080 void BranchUnsignedLess(Register rd, Register rs, Label* l) { 1268 void BranchUnsignedLess(Register rd, Register rs, Label* l) {
1081 ASSERT(!in_delay_slot_); 1269 ASSERT(!in_delay_slot_);
1082 BranchUnsignedGreater(rs, rd, l); 1270 BranchUnsignedGreater(rs, rd, l);
1083 } 1271 }
1084 1272
1085 void BranchUnsignedLess(Register rd, const Immediate& imm, Label* l) { 1273 void BranchUnsignedLess(Register rd, const Immediate& imm, Label* l) {
1086 ASSERT(!in_delay_slot_); 1274 ASSERT(!in_delay_slot_);
1087 ASSERT(imm.value() != 0); 1275 if (imm.value() == 0) {
1088 if (Utils::IsInt(kImmBits, imm.value())) { 1276 // Never branch. Fall through.
1089 sltiu(CMPRES2, rd, imm);
1090 bne(CMPRES2, ZR, l);
1091 } else { 1277 } else {
1092 ASSERT(rd != CMPRES2); 1278 if (Utils::IsInt(kImmBits, imm.value())) {
1093 LoadImmediate(CMPRES2, imm.value()); 1279 sltiu(CMPRES2, rd, imm);
1094 BranchUnsignedGreater(CMPRES2, rd, l); 1280 bne(CMPRES2, ZR, l);
1281 } else {
1282 ASSERT(rd != CMPRES2);
1283 LoadImmediate(CMPRES2, imm.value());
1284 BranchUnsignedGreater(CMPRES2, rd, l);
1285 }
1095 } 1286 }
1096 } 1287 }
1097 1288
1098 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { 1289 void BranchSignedLessEqual(Register rd, Register rs, Label* l) {
1099 ASSERT(!in_delay_slot_); 1290 ASSERT(!in_delay_slot_);
1100 BranchSignedGreaterEqual(rs, rd, l); 1291 BranchSignedGreaterEqual(rs, rd, l);
1101 } 1292 }
1102 1293
1103 void BranchSignedLessEqual(Register rd, const Immediate& imm, Label* l) { 1294 void BranchSignedLessEqual(Register rd, const Immediate& imm, Label* l) {
1104 ASSERT(!in_delay_slot_); 1295 ASSERT(!in_delay_slot_);
1105 if (imm.value() == 0) { 1296 if (imm.value() == 0) {
1106 blez(rd, l); 1297 blez(rd, l);
1107 } else { 1298 } else {
1108 ASSERT(rd != CMPRES2); 1299 if (Utils::IsInt(kImmBits, imm.value() + 1)) {
1109 LoadImmediate(CMPRES2, imm.value()); 1300 slti(CMPRES2, rd, Immediate(imm.value() + 1));
1110 BranchSignedGreaterEqual(CMPRES2, rd, l); 1301 bne(CMPRES2, ZR, l);
1302 } else {
1303 ASSERT(rd != CMPRES2);
1304 LoadImmediate(CMPRES2, imm.value());
1305 BranchSignedGreaterEqual(CMPRES2, rd, l);
1306 }
1111 } 1307 }
1112 } 1308 }
1113 1309
1114 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) { 1310 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) {
1115 ASSERT(!in_delay_slot_); 1311 ASSERT(!in_delay_slot_);
1116 BranchUnsignedGreaterEqual(rs, rd, l); 1312 BranchUnsignedGreaterEqual(rs, rd, l);
1117 } 1313 }
1118 1314
1119 void BranchUnsignedLessEqual(Register rd, const Immediate& imm, Label* l) { 1315 void BranchUnsignedLessEqual(Register rd, const Immediate& imm, Label* l) {
1120 ASSERT(!in_delay_slot_); 1316 ASSERT(!in_delay_slot_);
1121 ASSERT(rd != CMPRES2); 1317 if (imm.value() == 0) {
1122 LoadImmediate(CMPRES2, imm.value()); 1318 beq(rd, ZR, l);
1123 BranchUnsignedGreaterEqual(CMPRES2, rd, l); 1319 } else {
1320 if ((imm.value() != -1) && Utils::IsInt(kImmBits, imm.value() + 1)) {
1321 sltiu(CMPRES2, rd, Immediate(imm.value() + 1));
1322 bne(CMPRES2, ZR, l);
1323 } else {
1324 ASSERT(rd != CMPRES2);
1325 LoadImmediate(CMPRES2, imm.value());
1326 BranchUnsignedGreaterEqual(CMPRES2, rd, l);
1327 }
1328 }
1124 } 1329 }
1125 1330
1126 void Push(Register rt) { 1331 void Push(Register rt) {
1127 ASSERT(!in_delay_slot_); 1332 ASSERT(!in_delay_slot_);
1128 addiu(SP, SP, Immediate(-kWordSize)); 1333 addiu(SP, SP, Immediate(-kWordSize));
1129 sw(rt, Address(SP)); 1334 sw(rt, Address(SP));
1130 } 1335 }
1131 1336
1132 void Pop(Register rt) { 1337 void Pop(Register rt) {
1133 ASSERT(!in_delay_slot_); 1338 ASSERT(!in_delay_slot_);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 // Create a frame for calling into runtime that preserves all volatile 1416 // Create a frame for calling into runtime that preserves all volatile
1212 // registers. Frame's SP is guaranteed to be correctly aligned and 1417 // registers. Frame's SP is guaranteed to be correctly aligned and
1213 // frame_space bytes are reserved under it. 1418 // frame_space bytes are reserved under it.
1214 void EnterCallRuntimeFrame(intptr_t frame_space); 1419 void EnterCallRuntimeFrame(intptr_t frame_space);
1215 void LeaveCallRuntimeFrame(); 1420 void LeaveCallRuntimeFrame();
1216 1421
1217 void LoadWordFromPoolOffset(Register rd, int32_t offset); 1422 void LoadWordFromPoolOffset(Register rd, int32_t offset);
1218 void LoadObject(Register rd, const Object& object); 1423 void LoadObject(Register rd, const Object& object);
1219 void PushObject(const Object& object); 1424 void PushObject(const Object& object);
1220 1425
1221 // Compares rn with the object. Returns results in rd1 and rd2.
1222 // rd1 is 1 if rn < object. rd2 is 1 if object < rn. Since both cannot be
1223 // 1, rd1 == rd2 (== 0) iff rn == object.
1224 void CompareObject(Register rd1, Register rd2,
1225 Register rn, const Object& object);
1226
1227 void LoadIsolate(Register result); 1426 void LoadIsolate(Register result);
1228 1427
1229 void LoadClassId(Register result, Register object); 1428 void LoadClassId(Register result, Register object);
1230 void LoadClassById(Register result, Register class_id); 1429 void LoadClassById(Register result, Register class_id);
1231 void LoadClass(Register result, Register object); 1430 void LoadClass(Register result, Register object);
1232 void LoadTaggedClassIdMayBeSmi(Register result, Register object); 1431 void LoadTaggedClassIdMayBeSmi(Register result, Register object);
1233 1432
1234 void ComputeRange(Register result, 1433 void ComputeRange(Register result,
1235 Register value, 1434 Register value,
1236 Label* miss); 1435 Label* miss);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 Register value, 1630 Register value,
1432 Label* no_update); 1631 Label* no_update);
1433 1632
1434 DISALLOW_ALLOCATION(); 1633 DISALLOW_ALLOCATION();
1435 DISALLOW_COPY_AND_ASSIGN(Assembler); 1634 DISALLOW_COPY_AND_ASSIGN(Assembler);
1436 }; 1635 };
1437 1636
1438 } // namespace dart 1637 } // namespace dart
1439 1638
1440 #endif // VM_ASSEMBLER_MIPS_H_ 1639 #endif // VM_ASSEMBLER_MIPS_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_mips.cc » ('j') | runtime/vm/constants_mips.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698