OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the TargetLoweringARM32 class, which consists almost | 10 // This file implements the TargetLoweringARM32 class, which consists almost |
(...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1062 Variable *T_Hi1 = makeReg(IceType_i32); | 1062 Variable *T_Hi1 = makeReg(IceType_i32); |
1063 Variable *Src1RLo = legalizeToVar(Src1Lo); | 1063 Variable *Src1RLo = legalizeToVar(Src1Lo); |
1064 Variable *Src1RHi = legalizeToVar(Src1Hi); | 1064 Variable *Src1RHi = legalizeToVar(Src1Hi); |
1065 _mul(T_Acc, Src0RLo, Src1RHi); | 1065 _mul(T_Acc, Src0RLo, Src1RHi); |
1066 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); | 1066 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); |
1067 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); | 1067 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); |
1068 _add(T_Hi, T_Hi1, T_Acc1); | 1068 _add(T_Hi, T_Hi1, T_Acc1); |
1069 _mov(DestLo, T_Lo); | 1069 _mov(DestLo, T_Lo); |
1070 _mov(DestHi, T_Hi); | 1070 _mov(DestHi, T_Hi); |
1071 } break; | 1071 } break; |
1072 case InstArithmetic::Shl: | 1072 case InstArithmetic::Shl: { |
1073 // a=b<<c ==> | |
1074 // GCC 4.8 does: | |
1075 // sub t_c1, c.lo, #32 | |
1076 // lsl t_hi, b.hi, c.lo | |
1077 // orr t_hi, t_hi, b.lo, lsl t_c1 | |
1078 // rsb t_c2, c.lo, #32 | |
1079 // orr t_hi, t_hi, b.lo, lsr t_c2 | |
1080 // lsl t_lo, b.lo, c.lo | |
1081 // a.lo = t_lo | |
1082 // a.hi = t_hi | |
1083 // Can be strength-reduced for constant-shifts, but we don't do | |
1084 // that for now. | |
1085 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. | |
1086 // On ARM, shifts only take the lower 8 bits of the shift register, | |
1087 // and saturate to the range 0-32, so the negative value will | |
1088 // saturate to 32. | |
1089 Variable *T_Hi = makeReg(IceType_i32); | |
1090 Variable *Src1RLo = legalizeToVar(Src1Lo); | |
1091 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | |
1092 Variable *T_C1 = makeReg(IceType_i32); | |
1093 Variable *T_C2 = makeReg(IceType_i32); | |
1094 _sub(T_C1, Src1RLo, ThirtyTwo); | |
1095 _lsl(T_Hi, Src0RHi, Src1RLo); | |
1096 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | |
1097 OperandARM32::LSL, T_C1)); | |
1098 _rsb(T_C2, Src1RLo, ThirtyTwo); | |
1099 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | |
1100 OperandARM32::LSR, T_C2)); | |
1101 _mov(DestHi, T_Hi); | |
1102 Variable *T_Lo = makeReg(IceType_i32); | |
1103 // _mov seems to sometimes have better register preferencing than lsl. | |
1104 // Otherwise mov w/ lsl shifted register is a pseudo-instruction | |
1105 // that maps to lsl. | |
1106 _mov(T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | |
1107 OperandARM32::LSL, Src1RLo)); | |
1108 _mov(DestLo, T_Lo); | |
1109 } break; | |
Jim Stichnoth
2015/06/04 22:10:59
I've been thinking (in the x86-32 version and also
jvoung (off chromium)
2015/06/04 23:15:14
That sounds good to me, but will leave for a separ
| |
1073 case InstArithmetic::Lshr: | 1110 case InstArithmetic::Lshr: |
1074 case InstArithmetic::Ashr: | 1111 // a=b>>c (unsigned) ==> |
1112 // GCC 4.8 does: | |
1113 // rsb t_c1, c.lo, #32 | |
1114 // lsr t_lo, b.lo, c.lo | |
1115 // orr t_lo, t_lo, b.hi, lsl t_c1 | |
1116 // sub t_c2, c.lo, #32 | |
1117 // orr t_lo, t_lo, b.hi, lsr t_c2 | |
1118 // lsr t_hi, b.hi, c.lo | |
1119 // a.lo = t_lo | |
1120 // a.hi = t_hi | |
1121 case InstArithmetic::Ashr: { | |
1122 // a=b>>c (signed) ==> ... | |
1123 // Ashr is similar, but the sub t_c2, c.lo, #32 should set flags, | |
1124 // and the next orr should be conditioned on PLUS. The last two | |
1125 // right shifts should also be arithmetic. | |
1126 bool IsAshr = Inst->getOp() == InstArithmetic::Ashr; | |
1127 Variable *T_Lo = makeReg(IceType_i32); | |
1128 Variable *Src1RLo = legalizeToVar(Src1Lo); | |
1129 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | |
1130 Variable *T_C1 = makeReg(IceType_i32); | |
1131 Variable *T_C2 = makeReg(IceType_i32); | |
1132 _rsb(T_C1, Src1RLo, ThirtyTwo); | |
1133 _lsr(T_Lo, Src0RLo, Src1RLo); | |
1134 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | |
1135 OperandARM32::LSL, T_C1)); | |
1136 OperandARM32::ShiftKind RShiftKind; | |
1137 CondARM32::Cond Pred; | |
1138 if (IsAshr) { | |
1139 _subs(T_C2, Src1RLo, ThirtyTwo); | |
1140 RShiftKind = OperandARM32::ASR; | |
1141 Pred = CondARM32::PL; | |
1142 } else { | |
1143 _sub(T_C2, Src1RLo, ThirtyTwo); | |
1144 RShiftKind = OperandARM32::LSR; | |
1145 Pred = CondARM32::AL; | |
1146 } | |
1147 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | |
1148 RShiftKind, T_C2), | |
1149 Pred); | |
1150 _mov(DestLo, T_Lo); | |
1151 Variable *T_Hi = makeReg(IceType_i32); | |
1152 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | |
1153 RShiftKind, Src1RLo)); | |
1154 _mov(DestHi, T_Hi); | |
1155 } break; | |
1075 case InstArithmetic::Udiv: | 1156 case InstArithmetic::Udiv: |
1076 case InstArithmetic::Sdiv: | 1157 case InstArithmetic::Sdiv: |
1077 case InstArithmetic::Urem: | 1158 case InstArithmetic::Urem: |
1078 case InstArithmetic::Srem: | 1159 case InstArithmetic::Srem: |
1079 UnimplementedError(Func->getContext()->getFlags()); | 1160 UnimplementedError(Func->getContext()->getFlags()); |
1080 break; | 1161 break; |
1081 case InstArithmetic::Fadd: | 1162 case InstArithmetic::Fadd: |
1082 case InstArithmetic::Fsub: | 1163 case InstArithmetic::Fsub: |
1083 case InstArithmetic::Fmul: | 1164 case InstArithmetic::Fmul: |
1084 case InstArithmetic::Fdiv: | 1165 case InstArithmetic::Fdiv: |
(...skipping 30 matching lines...) Expand all Loading... | |
1115 case InstArithmetic::Sub: { | 1196 case InstArithmetic::Sub: { |
1116 _sub(T, Src0R, Src1); | 1197 _sub(T, Src0R, Src1); |
1117 _mov(Dest, T); | 1198 _mov(Dest, T); |
1118 } break; | 1199 } break; |
1119 case InstArithmetic::Mul: { | 1200 case InstArithmetic::Mul: { |
1120 Variable *Src1R = legalizeToVar(Src1); | 1201 Variable *Src1R = legalizeToVar(Src1); |
1121 _mul(T, Src0R, Src1R); | 1202 _mul(T, Src0R, Src1R); |
1122 _mov(Dest, T); | 1203 _mov(Dest, T); |
1123 } break; | 1204 } break; |
1124 case InstArithmetic::Shl: | 1205 case InstArithmetic::Shl: |
1125 UnimplementedError(Func->getContext()->getFlags()); | 1206 _lsl(T, Src0R, Src1); |
1207 _mov(Dest, T); | |
1126 break; | 1208 break; |
1127 case InstArithmetic::Lshr: | 1209 case InstArithmetic::Lshr: |
1128 UnimplementedError(Func->getContext()->getFlags()); | 1210 _lsr(T, Src0R, Src1); |
1211 _mov(Dest, T); | |
1129 break; | 1212 break; |
1130 case InstArithmetic::Ashr: | 1213 case InstArithmetic::Ashr: |
1131 UnimplementedError(Func->getContext()->getFlags()); | 1214 _asr(T, Src0R, Src1); |
1215 _mov(Dest, T); | |
1132 break; | 1216 break; |
1133 case InstArithmetic::Udiv: | 1217 case InstArithmetic::Udiv: |
1134 UnimplementedError(Func->getContext()->getFlags()); | 1218 UnimplementedError(Func->getContext()->getFlags()); |
1135 break; | 1219 break; |
1136 case InstArithmetic::Sdiv: | 1220 case InstArithmetic::Sdiv: |
1137 UnimplementedError(Func->getContext()->getFlags()); | 1221 UnimplementedError(Func->getContext()->getFlags()); |
1138 break; | 1222 break; |
1139 case InstArithmetic::Urem: | 1223 case InstArithmetic::Urem: |
1140 UnimplementedError(Func->getContext()->getFlags()); | 1224 UnimplementedError(Func->getContext()->getFlags()); |
1141 break; | 1225 break; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1304 UnimplementedError(Func->getContext()->getFlags()); | 1388 UnimplementedError(Func->getContext()->getFlags()); |
1305 } else { | 1389 } else { |
1306 _mov(Dest, ReturnReg); | 1390 _mov(Dest, ReturnReg); |
1307 } | 1391 } |
1308 } | 1392 } |
1309 } | 1393 } |
1310 } | 1394 } |
1311 | 1395 |
1312 void TargetARM32::lowerCast(const InstCast *Inst) { | 1396 void TargetARM32::lowerCast(const InstCast *Inst) { |
1313 InstCast::OpKind CastKind = Inst->getCastKind(); | 1397 InstCast::OpKind CastKind = Inst->getCastKind(); |
1398 Variable *Dest = Inst->getDest(); | |
1399 Operand *Src0 = Inst->getSrc(0); | |
1314 switch (CastKind) { | 1400 switch (CastKind) { |
1315 default: | 1401 default: |
1316 Func->setError("Cast type not supported"); | 1402 Func->setError("Cast type not supported"); |
1317 return; | 1403 return; |
1318 case InstCast::Sext: { | 1404 case InstCast::Sext: { |
1319 UnimplementedError(Func->getContext()->getFlags()); | 1405 if (isVectorType(Dest->getType())) { |
1406 UnimplementedError(Func->getContext()->getFlags()); | |
1407 } else if (Dest->getType() == IceType_i64) { | |
1408 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 | |
1409 Constant *Shift = Ctx->getConstantInt32(31); | |
1410 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | |
1411 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | |
1412 Variable *T_Lo = makeReg(DestLo->getType()); | |
1413 if (Src0->getType() == IceType_i32) { | |
1414 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | |
1415 _mov(T_Lo, Src0RF); | |
1416 } else if (Src0->getType() == IceType_i1) { | |
1417 Variable *Src0R = legalizeToVar(Src0); | |
1418 _lsl(T_Lo, Src0R, Shift); | |
1419 _asr(T_Lo, T_Lo, Shift); | |
1420 } else { | |
1421 Variable *Src0R = legalizeToVar(Src0); | |
1422 _sxt(T_Lo, Src0R); | |
1423 } | |
1424 _mov(DestLo, T_Lo); | |
1425 Variable *T_Hi = makeReg(DestHi->getType()); | |
1426 if (Src0->getType() != IceType_i1) { | |
1427 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, | |
1428 OperandARM32::ASR, Shift)); | |
1429 } else { | |
1430 // For i1, the asr instruction is already done above. | |
1431 _mov(T_Hi, T_Lo); | |
1432 } | |
1433 _mov(DestHi, T_Hi); | |
1434 } else if (Src0->getType() == IceType_i1) { | |
1435 // GPR registers are 32-bit, so just use 31 as dst_bitwidth - 1. | |
1436 // lsl t1, src_reg, 31 | |
1437 // asr t1, t1, 31 | |
1438 // dst = t1 | |
1439 Variable *Src0R = legalizeToVar(Src0); | |
1440 Constant *ShiftAmount = Ctx->getConstantInt32(31); | |
Jim Stichnoth
2015/06/04 22:10:59
Maybe use the same variable name for ShiftAmount a
jvoung (off chromium)
2015/06/04 23:15:14
Done -- picked middle ground of ShiftAmt =)
| |
1441 Variable *T = makeReg(Dest->getType()); | |
1442 _lsl(T, Src0R, ShiftAmount); | |
1443 _asr(T, T, ShiftAmount); | |
1444 _mov(Dest, T); | |
1445 } else { | |
1446 // t1 = sxt src; dst = t1 | |
1447 Variable *Src0R = legalizeToVar(Src0); | |
1448 Variable *T = makeReg(Dest->getType()); | |
1449 _sxt(T, Src0R); | |
1450 _mov(Dest, T); | |
1451 } | |
1320 break; | 1452 break; |
1321 } | 1453 } |
1322 case InstCast::Zext: { | 1454 case InstCast::Zext: { |
1323 UnimplementedError(Func->getContext()->getFlags()); | 1455 if (isVectorType(Dest->getType())) { |
1456 UnimplementedError(Func->getContext()->getFlags()); | |
1457 } else if (Dest->getType() == IceType_i64) { | |
1458 // t1=uxtb src; dst.lo=t1; dst.hi=0 | |
1459 Constant *Zero = Ctx->getConstantZero(IceType_i32); | |
1460 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | |
1461 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | |
1462 Variable *T_Lo = makeReg(DestLo->getType()); | |
1463 // i32 and i1 can just take up the whole register. | |
1464 // i32 doesn't need uxt, while i1 will have an and mask later anyway. | |
1465 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) { | |
1466 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | |
1467 _mov(T_Lo, Src0RF); | |
1468 } else { | |
1469 Variable *Src0R = legalizeToVar(Src0); | |
1470 _uxt(T_Lo, Src0R); | |
1471 } | |
1472 if (Src0->getType() == IceType_i1) { | |
1473 Constant *One = Ctx->getConstantInt32(1); | |
1474 _and(T_Lo, T_Lo, One); | |
1475 } | |
1476 _mov(DestLo, T_Lo); | |
1477 Variable *T_Hi = makeReg(DestLo->getType()); | |
1478 _mov(T_Hi, Zero); | |
1479 _mov(DestHi, T_Hi); | |
1480 } else if (Src0->getType() == IceType_i1) { | |
1481 // t = Src0; t &= 1; Dest = t | |
1482 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | |
1483 Constant *One = Ctx->getConstantInt32(1); | |
1484 Variable *T = makeReg(Dest->getType()); | |
1485 // Just use _mov instead of _uxt since all registers are 32-bit. | |
1486 // _uxt requires the source to be a register so could have required | |
1487 // a _mov from legalize anyway. | |
1488 _mov(T, Src0RF); | |
1489 _and(T, T, One); | |
1490 _mov(Dest, T); | |
1491 } else { | |
1492 // t1 = uxt src; dst = t1 | |
1493 Variable *Src0R = legalizeToVar(Src0); | |
1494 Variable *T = makeReg(Dest->getType()); | |
1495 _uxt(T, Src0R); | |
1496 _mov(Dest, T); | |
1497 } | |
1324 break; | 1498 break; |
1325 } | 1499 } |
1326 case InstCast::Trunc: { | 1500 case InstCast::Trunc: { |
1327 UnimplementedError(Func->getContext()->getFlags()); | 1501 if (isVectorType(Dest->getType())) { |
1502 UnimplementedError(Func->getContext()->getFlags()); | |
1503 } else { | |
1504 Operand *Src0 = Inst->getSrc(0); | |
1505 if (Src0->getType() == IceType_i64) | |
1506 Src0 = loOperand(Src0); | |
1507 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | |
1508 // t1 = trunc Src0RF; Dest = t1 | |
1509 Variable *T = makeReg(Dest->getType()); | |
1510 _mov(T, Src0RF); | |
1511 if (Dest->getType() == IceType_i1) | |
1512 _and(T, T, Ctx->getConstantInt1(1)); | |
1513 _mov(Dest, T); | |
1514 } | |
1328 break; | 1515 break; |
1329 } | 1516 } |
1330 case InstCast::Fptrunc: | 1517 case InstCast::Fptrunc: |
1331 UnimplementedError(Func->getContext()->getFlags()); | 1518 UnimplementedError(Func->getContext()->getFlags()); |
1332 break; | 1519 break; |
1333 case InstCast::Fpext: { | 1520 case InstCast::Fpext: { |
1334 UnimplementedError(Func->getContext()->getFlags()); | 1521 UnimplementedError(Func->getContext()->getFlags()); |
1335 break; | 1522 break; |
1336 } | 1523 } |
1337 case InstCast::Fptosi: | 1524 case InstCast::Fptosi: |
1338 UnimplementedError(Func->getContext()->getFlags()); | 1525 UnimplementedError(Func->getContext()->getFlags()); |
1339 break; | 1526 break; |
1340 case InstCast::Fptoui: | 1527 case InstCast::Fptoui: |
1341 UnimplementedError(Func->getContext()->getFlags()); | 1528 UnimplementedError(Func->getContext()->getFlags()); |
1342 break; | 1529 break; |
1343 case InstCast::Sitofp: | 1530 case InstCast::Sitofp: |
1344 UnimplementedError(Func->getContext()->getFlags()); | 1531 UnimplementedError(Func->getContext()->getFlags()); |
1345 break; | 1532 break; |
1346 case InstCast::Uitofp: { | 1533 case InstCast::Uitofp: { |
1347 UnimplementedError(Func->getContext()->getFlags()); | 1534 UnimplementedError(Func->getContext()->getFlags()); |
1348 break; | 1535 break; |
1349 } | 1536 } |
1350 case InstCast::Bitcast: { | 1537 case InstCast::Bitcast: { |
1538 Operand *Src0 = Inst->getSrc(0); | |
1539 if (Dest->getType() == Src0->getType()) { | |
1540 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); | |
1541 lowerAssign(Assign); | |
1542 return; | |
1543 } | |
1351 UnimplementedError(Func->getContext()->getFlags()); | 1544 UnimplementedError(Func->getContext()->getFlags()); |
1352 break; | 1545 break; |
1353 } | 1546 } |
1354 } | 1547 } |
1355 } | 1548 } |
1356 | 1549 |
1357 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { | 1550 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { |
1358 (void)Inst; | 1551 (void)Inst; |
1359 UnimplementedError(Func->getContext()->getFlags()); | 1552 UnimplementedError(Func->getContext()->getFlags()); |
1360 } | 1553 } |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2026 } | 2219 } |
2027 } | 2220 } |
2028 | 2221 |
2029 void TargetDataARM32::lowerConstants() const { | 2222 void TargetDataARM32::lowerConstants() const { |
2030 if (Ctx->getFlags().getDisableTranslation()) | 2223 if (Ctx->getFlags().getDisableTranslation()) |
2031 return; | 2224 return; |
2032 UnimplementedError(Ctx->getFlags()); | 2225 UnimplementedError(Ctx->getFlags()); |
2033 } | 2226 } |
2034 | 2227 |
2035 } // end of namespace Ice | 2228 } // end of namespace Ice |
OLD | NEW |