| 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 /// \file | 10 /// \file |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 if (Var->getIsArg()) { | 856 if (Var->getIsArg()) { |
| 857 Lo->setIsArg(); | 857 Lo->setIsArg(); |
| 858 Hi->setIsArg(); | 858 Hi->setIsArg(); |
| 859 } | 859 } |
| 860 } | 860 } |
| 861 | 861 |
| 862 Operand *TargetARM32::loOperand(Operand *Operand) { | 862 Operand *TargetARM32::loOperand(Operand *Operand) { |
| 863 assert(Operand->getType() == IceType_i64); | 863 assert(Operand->getType() == IceType_i64); |
| 864 if (Operand->getType() != IceType_i64) | 864 if (Operand->getType() != IceType_i64) |
| 865 return Operand; | 865 return Operand; |
| 866 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 866 if (auto *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 867 split64(Var); | 867 split64(Var); |
| 868 return Var->getLo(); | 868 return Var->getLo(); |
| 869 } | 869 } |
| 870 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 870 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 871 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | 871 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
| 872 } | 872 } |
| 873 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | 873 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
| 874 // Conservatively disallow memory operands with side-effects (pre/post | 874 // Conservatively disallow memory operands with side-effects (pre/post |
| 875 // increment) in case of duplication. | 875 // increment) in case of duplication. |
| 876 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | 876 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
| 877 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | 877 Mem->getAddrMode() == OperandARM32Mem::NegOffset); |
| 878 if (Mem->isRegReg()) { | 878 if (Mem->isRegReg()) { |
| 879 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | 879 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), |
| 880 Mem->getIndex(), Mem->getShiftOp(), | 880 Mem->getIndex(), Mem->getShiftOp(), |
| 881 Mem->getShiftAmt(), Mem->getAddrMode()); | 881 Mem->getShiftAmt(), Mem->getAddrMode()); |
| 882 } else { | 882 } else { |
| 883 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | 883 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), |
| 884 Mem->getOffset(), Mem->getAddrMode()); | 884 Mem->getOffset(), Mem->getAddrMode()); |
| 885 } | 885 } |
| 886 } | 886 } |
| 887 llvm_unreachable("Unsupported operand type"); | 887 llvm_unreachable("Unsupported operand type"); |
| 888 return nullptr; | 888 return nullptr; |
| 889 } | 889 } |
| 890 | 890 |
| 891 Operand *TargetARM32::hiOperand(Operand *Operand) { | 891 Operand *TargetARM32::hiOperand(Operand *Operand) { |
| 892 assert(Operand->getType() == IceType_i64); | 892 assert(Operand->getType() == IceType_i64); |
| 893 if (Operand->getType() != IceType_i64) | 893 if (Operand->getType() != IceType_i64) |
| 894 return Operand; | 894 return Operand; |
| 895 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 895 if (auto *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 896 split64(Var); | 896 split64(Var); |
| 897 return Var->getHi(); | 897 return Var->getHi(); |
| 898 } | 898 } |
| 899 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 899 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 900 return Ctx->getConstantInt32( | 900 return Ctx->getConstantInt32( |
| 901 static_cast<uint32_t>(Const->getValue() >> 32)); | 901 static_cast<uint32_t>(Const->getValue() >> 32)); |
| 902 } | 902 } |
| 903 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | 903 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
| 904 // Conservatively disallow memory operands with side-effects | 904 // Conservatively disallow memory operands with side-effects |
| 905 // in case of duplication. | 905 // in case of duplication. |
| 906 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | 906 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
| 907 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | 907 Mem->getAddrMode() == OperandARM32Mem::NegOffset); |
| 908 const Type SplitType = IceType_i32; | 908 const Type SplitType = IceType_i32; |
| 909 if (Mem->isRegReg()) { | 909 if (Mem->isRegReg()) { |
| 910 // We have to make a temp variable T, and add 4 to either Base or Index. | 910 // We have to make a temp variable T, and add 4 to either Base or Index. |
| 911 // The Index may be shifted, so adding 4 can mean something else. | 911 // The Index may be shifted, so adding 4 can mean something else. |
| 912 // Thus, prefer T := Base + 4, and use T as the new Base. | 912 // Thus, prefer T := Base + 4, and use T as the new Base. |
| 913 Variable *Base = Mem->getBase(); | 913 Variable *Base = Mem->getBase(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 Operand *TotalSize = Inst->getSizeInBytes(); | 1005 Operand *TotalSize = Inst->getSizeInBytes(); |
| 1006 if (const auto *ConstantTotalSize = | 1006 if (const auto *ConstantTotalSize = |
| 1007 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { | 1007 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
| 1008 uint32_t Value = ConstantTotalSize->getValue(); | 1008 uint32_t Value = ConstantTotalSize->getValue(); |
| 1009 Value = Utils::applyAlignment(Value, Alignment); | 1009 Value = Utils::applyAlignment(Value, Alignment); |
| 1010 Operand *SubAmount = legalize(Ctx->getConstantInt32(Value)); | 1010 Operand *SubAmount = legalize(Ctx->getConstantInt32(Value)); |
| 1011 _sub(SP, SP, SubAmount); | 1011 _sub(SP, SP, SubAmount); |
| 1012 } else { | 1012 } else { |
| 1013 // Non-constant sizes need to be adjusted to the next highest | 1013 // Non-constant sizes need to be adjusted to the next highest |
| 1014 // multiple of the required alignment at runtime. | 1014 // multiple of the required alignment at runtime. |
| 1015 TotalSize = legalize(TotalSize); | 1015 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); |
| 1016 Variable *T = makeReg(IceType_i32); | 1016 Variable *T = makeReg(IceType_i32); |
| 1017 _mov(T, TotalSize); | 1017 _mov(T, TotalSize); |
| 1018 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); | 1018 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); |
| 1019 _add(T, T, AddAmount); | 1019 _add(T, T, AddAmount); |
| 1020 alignRegisterPow2(T, Alignment); | 1020 alignRegisterPow2(T, Alignment); |
| 1021 _sub(SP, SP, T); | 1021 _sub(SP, SP, T); |
| 1022 } | 1022 } |
| 1023 _mov(Dest, SP); | 1023 _mov(Dest, SP); |
| 1024 } | 1024 } |
| 1025 | 1025 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1094 | 1094 |
| 1095 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { | 1095 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
| 1096 Variable *Dest = Inst->getDest(); | 1096 Variable *Dest = Inst->getDest(); |
| 1097 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier | 1097 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier |
| 1098 // to legalize Src0 to flex or Src1 to flex and there is a reversible | 1098 // to legalize Src0 to flex or Src1 to flex and there is a reversible |
| 1099 // instruction. E.g., reverse subtract with immediate, register vs | 1099 // instruction. E.g., reverse subtract with immediate, register vs |
| 1100 // register, immediate. | 1100 // register, immediate. |
| 1101 // Or it may be the case that the operands aren't swapped, but the | 1101 // Or it may be the case that the operands aren't swapped, but the |
| 1102 // bits can be flipped and a different operation applied. | 1102 // bits can be flipped and a different operation applied. |
| 1103 // E.g., use BIC (bit clear) instead of AND for some masks. | 1103 // E.g., use BIC (bit clear) instead of AND for some masks. |
| 1104 Operand *Src0 = Inst->getSrc(0); | 1104 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 1105 Operand *Src1 = Inst->getSrc(1); | 1105 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| 1106 if (Dest->getType() == IceType_i64) { | 1106 if (Dest->getType() == IceType_i64) { |
| 1107 // These helper-call-involved instructions are lowered in this | 1107 // These helper-call-involved instructions are lowered in this |
| 1108 // separate switch. This is because we would otherwise assume that | 1108 // separate switch. This is because we would otherwise assume that |
| 1109 // we need to legalize Src0 to Src0RLo and Src0Hi. However, those go unused | 1109 // we need to legalize Src0 to Src0RLo and Src0Hi. However, those go unused |
| 1110 // with helper calls, and such unused/redundant instructions will fail | 1110 // with helper calls, and such unused/redundant instructions will fail |
| 1111 // liveness analysis under -Om1 setting. | 1111 // liveness analysis under -Om1 setting. |
| 1112 switch (Inst->getOp()) { | 1112 switch (Inst->getOp()) { |
| 1113 default: | 1113 default: |
| 1114 break; | 1114 break; |
| 1115 case InstArithmetic::Udiv: | 1115 case InstArithmetic::Udiv: |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 UnimplementedError(Func->getContext()->getFlags()); | 1451 UnimplementedError(Func->getContext()->getFlags()); |
| 1452 return; | 1452 return; |
| 1453 } | 1453 } |
| 1454 } | 1454 } |
| 1455 | 1455 |
| 1456 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 1456 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
| 1457 Variable *Dest = Inst->getDest(); | 1457 Variable *Dest = Inst->getDest(); |
| 1458 Operand *Src0 = Inst->getSrc(0); | 1458 Operand *Src0 = Inst->getSrc(0); |
| 1459 assert(Dest->getType() == Src0->getType()); | 1459 assert(Dest->getType() == Src0->getType()); |
| 1460 if (Dest->getType() == IceType_i64) { | 1460 if (Dest->getType() == IceType_i64) { |
| 1461 Src0 = legalize(Src0); | 1461 Src0 = legalizeUndef(Src0); |
| 1462 Operand *Src0Lo = loOperand(Src0); | 1462 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); |
| 1463 Operand *Src0Hi = hiOperand(Src0); | 1463 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex); |
| 1464 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1464 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1465 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1465 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1466 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 1466 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 1467 _mov(T_Lo, Src0Lo); | 1467 _mov(T_Lo, Src0Lo); |
| 1468 _mov(DestLo, T_Lo); | 1468 _mov(DestLo, T_Lo); |
| 1469 _mov(T_Hi, Src0Hi); | 1469 _mov(T_Hi, Src0Hi); |
| 1470 _mov(DestHi, T_Hi); | 1470 _mov(DestHi, T_Hi); |
| 1471 } else { | 1471 } else { |
| 1472 Operand *SrcR; | 1472 Operand *SrcR; |
| 1473 if (Dest->hasReg()) { | 1473 if (Dest->hasReg()) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 // Pair of Arg Operand -> GPR number assignments. | 1516 // Pair of Arg Operand -> GPR number assignments. |
| 1517 llvm::SmallVector<std::pair<Operand *, int32_t>, | 1517 llvm::SmallVector<std::pair<Operand *, int32_t>, |
| 1518 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; | 1518 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; |
| 1519 // Pair of Arg Operand -> stack offset. | 1519 // Pair of Arg Operand -> stack offset. |
| 1520 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | 1520 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; |
| 1521 int32_t ParameterAreaSizeBytes = 0; | 1521 int32_t ParameterAreaSizeBytes = 0; |
| 1522 | 1522 |
| 1523 // Classify each argument operand according to the location where the | 1523 // Classify each argument operand according to the location where the |
| 1524 // argument is passed. | 1524 // argument is passed. |
| 1525 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 1525 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
| 1526 Operand *Arg = Instr->getArg(i); | 1526 Operand *Arg = legalizeUndef(Instr->getArg(i)); |
| 1527 Type Ty = Arg->getType(); | 1527 Type Ty = Arg->getType(); |
| 1528 bool InRegs = false; | 1528 bool InRegs = false; |
| 1529 if (isVectorType(Ty)) { | 1529 if (isVectorType(Ty)) { |
| 1530 UnimplementedError(Func->getContext()->getFlags()); | 1530 UnimplementedError(Func->getContext()->getFlags()); |
| 1531 } else if (isFloatingType(Ty)) { | 1531 } else if (isFloatingType(Ty)) { |
| 1532 UnimplementedError(Func->getContext()->getFlags()); | 1532 UnimplementedError(Func->getContext()->getFlags()); |
| 1533 } else if (Ty == IceType_i64) { | 1533 } else if (Ty == IceType_i64) { |
| 1534 std::pair<int32_t, int32_t> Regs; | 1534 std::pair<int32_t, int32_t> Regs; |
| 1535 if (CC.I64InRegs(&Regs)) { | 1535 if (CC.I64InRegs(&Regs)) { |
| 1536 InRegs = true; | 1536 InRegs = true; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1696 } else { | 1696 } else { |
| 1697 _mov(Dest, ReturnReg); | 1697 _mov(Dest, ReturnReg); |
| 1698 } | 1698 } |
| 1699 } | 1699 } |
| 1700 } | 1700 } |
| 1701 } | 1701 } |
| 1702 | 1702 |
| 1703 void TargetARM32::lowerCast(const InstCast *Inst) { | 1703 void TargetARM32::lowerCast(const InstCast *Inst) { |
| 1704 InstCast::OpKind CastKind = Inst->getCastKind(); | 1704 InstCast::OpKind CastKind = Inst->getCastKind(); |
| 1705 Variable *Dest = Inst->getDest(); | 1705 Variable *Dest = Inst->getDest(); |
| 1706 Operand *Src0 = Inst->getSrc(0); | 1706 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 1707 switch (CastKind) { | 1707 switch (CastKind) { |
| 1708 default: | 1708 default: |
| 1709 Func->setError("Cast type not supported"); | 1709 Func->setError("Cast type not supported"); |
| 1710 return; | 1710 return; |
| 1711 case InstCast::Sext: { | 1711 case InstCast::Sext: { |
| 1712 if (isVectorType(Dest->getType())) { | 1712 if (isVectorType(Dest->getType())) { |
| 1713 UnimplementedError(Func->getContext()->getFlags()); | 1713 UnimplementedError(Func->getContext()->getFlags()); |
| 1714 } else if (Dest->getType() == IceType_i64) { | 1714 } else if (Dest->getType() == IceType_i64) { |
| 1715 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 | 1715 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 |
| 1716 Constant *ShiftAmt = Ctx->getConstantInt32(31); | 1716 Constant *ShiftAmt = Ctx->getConstantInt32(31); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1801 Variable *T = makeReg(Dest->getType()); | 1801 Variable *T = makeReg(Dest->getType()); |
| 1802 _uxt(T, Src0R); | 1802 _uxt(T, Src0R); |
| 1803 _mov(Dest, T); | 1803 _mov(Dest, T); |
| 1804 } | 1804 } |
| 1805 break; | 1805 break; |
| 1806 } | 1806 } |
| 1807 case InstCast::Trunc: { | 1807 case InstCast::Trunc: { |
| 1808 if (isVectorType(Dest->getType())) { | 1808 if (isVectorType(Dest->getType())) { |
| 1809 UnimplementedError(Func->getContext()->getFlags()); | 1809 UnimplementedError(Func->getContext()->getFlags()); |
| 1810 } else { | 1810 } else { |
| 1811 Operand *Src0 = Inst->getSrc(0); | |
| 1812 if (Src0->getType() == IceType_i64) | 1811 if (Src0->getType() == IceType_i64) |
| 1813 Src0 = loOperand(Src0); | 1812 Src0 = loOperand(Src0); |
| 1814 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 1813 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 1815 // t1 = trunc Src0RF; Dest = t1 | 1814 // t1 = trunc Src0RF; Dest = t1 |
| 1816 Variable *T = makeReg(Dest->getType()); | 1815 Variable *T = makeReg(Dest->getType()); |
| 1817 _mov(T, Src0RF); | 1816 _mov(T, Src0RF); |
| 1818 if (Dest->getType() == IceType_i1) | 1817 if (Dest->getType() == IceType_i1) |
| 1819 _and(T, T, Ctx->getConstantInt1(1)); | 1818 _and(T, T, Ctx->getConstantInt1(1)); |
| 1820 _mov(Dest, T); | 1819 _mov(Dest, T); |
| 1821 } | 1820 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1859 UnimplementedError(Func->getContext()->getFlags()); | 1858 UnimplementedError(Func->getContext()->getFlags()); |
| 1860 } | 1859 } |
| 1861 | 1860 |
| 1862 void TargetARM32::lowerFcmp(const InstFcmp *Inst) { | 1861 void TargetARM32::lowerFcmp(const InstFcmp *Inst) { |
| 1863 (void)Inst; | 1862 (void)Inst; |
| 1864 UnimplementedError(Func->getContext()->getFlags()); | 1863 UnimplementedError(Func->getContext()->getFlags()); |
| 1865 } | 1864 } |
| 1866 | 1865 |
| 1867 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { | 1866 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
| 1868 Variable *Dest = Inst->getDest(); | 1867 Variable *Dest = Inst->getDest(); |
| 1869 Operand *Src0 = Inst->getSrc(0); | 1868 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 1870 Operand *Src1 = Inst->getSrc(1); | 1869 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| 1871 | 1870 |
| 1872 if (isVectorType(Dest->getType())) { | 1871 if (isVectorType(Dest->getType())) { |
| 1873 UnimplementedError(Func->getContext()->getFlags()); | 1872 UnimplementedError(Func->getContext()->getFlags()); |
| 1874 return; | 1873 return; |
| 1875 } | 1874 } |
| 1876 | 1875 |
| 1877 // a=icmp cond, b, c ==> | 1876 // a=icmp cond, b, c ==> |
| 1878 // GCC does: | 1877 // GCC does: |
| 1879 // cmp b.hi, c.hi or cmp b.lo, c.lo | 1878 // cmp b.hi, c.hi or cmp b.lo, c.lo |
| 1880 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi | 1879 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2029 return; | 2028 return; |
| 2030 case Intrinsics::AtomicStore: { | 2029 case Intrinsics::AtomicStore: { |
| 2031 UnimplementedError(Func->getContext()->getFlags()); | 2030 UnimplementedError(Func->getContext()->getFlags()); |
| 2032 return; | 2031 return; |
| 2033 } | 2032 } |
| 2034 case Intrinsics::Bswap: { | 2033 case Intrinsics::Bswap: { |
| 2035 Variable *Dest = Instr->getDest(); | 2034 Variable *Dest = Instr->getDest(); |
| 2036 Operand *Val = Instr->getArg(0); | 2035 Operand *Val = Instr->getArg(0); |
| 2037 Type Ty = Val->getType(); | 2036 Type Ty = Val->getType(); |
| 2038 if (Ty == IceType_i64) { | 2037 if (Ty == IceType_i64) { |
| 2038 Val = legalizeUndef(Val); |
| 2039 Variable *Val_Lo = legalizeToVar(loOperand(Val)); | 2039 Variable *Val_Lo = legalizeToVar(loOperand(Val)); |
| 2040 Variable *Val_Hi = legalizeToVar(hiOperand(Val)); | 2040 Variable *Val_Hi = legalizeToVar(hiOperand(Val)); |
| 2041 Variable *T_Lo = makeReg(IceType_i32); | 2041 Variable *T_Lo = makeReg(IceType_i32); |
| 2042 Variable *T_Hi = makeReg(IceType_i32); | 2042 Variable *T_Hi = makeReg(IceType_i32); |
| 2043 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2043 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2044 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2044 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2045 _rev(T_Lo, Val_Lo); | 2045 _rev(T_Lo, Val_Lo); |
| 2046 _rev(T_Hi, Val_Hi); | 2046 _rev(T_Hi, Val_Hi); |
| 2047 _mov(DestLo, T_Hi); | 2047 _mov(DestLo, T_Hi); |
| 2048 _mov(DestHi, T_Lo); | 2048 _mov(DestHi, T_Lo); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 } | 2081 } |
| 2082 return; | 2082 return; |
| 2083 } | 2083 } |
| 2084 case Intrinsics::Ctlz: { | 2084 case Intrinsics::Ctlz: { |
| 2085 // The "is zero undef" parameter is ignored and we always return | 2085 // The "is zero undef" parameter is ignored and we always return |
| 2086 // a well-defined value. | 2086 // a well-defined value. |
| 2087 Operand *Val = Instr->getArg(0); | 2087 Operand *Val = Instr->getArg(0); |
| 2088 Variable *ValLoR; | 2088 Variable *ValLoR; |
| 2089 Variable *ValHiR = nullptr; | 2089 Variable *ValHiR = nullptr; |
| 2090 if (Val->getType() == IceType_i64) { | 2090 if (Val->getType() == IceType_i64) { |
| 2091 Val = legalizeUndef(Val); |
| 2091 ValLoR = legalizeToVar(loOperand(Val)); | 2092 ValLoR = legalizeToVar(loOperand(Val)); |
| 2092 ValHiR = legalizeToVar(hiOperand(Val)); | 2093 ValHiR = legalizeToVar(hiOperand(Val)); |
| 2093 } else { | 2094 } else { |
| 2094 ValLoR = legalizeToVar(Val); | 2095 ValLoR = legalizeToVar(Val); |
| 2095 } | 2096 } |
| 2096 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); | 2097 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); |
| 2097 return; | 2098 return; |
| 2098 } | 2099 } |
| 2099 case Intrinsics::Cttz: { | 2100 case Intrinsics::Cttz: { |
| 2100 // Essentially like Clz, but reverse the bits first. | 2101 // Essentially like Clz, but reverse the bits first. |
| 2101 Operand *Val = Instr->getArg(0); | 2102 Operand *Val = Instr->getArg(0); |
| 2102 Variable *ValLoR; | 2103 Variable *ValLoR; |
| 2103 Variable *ValHiR = nullptr; | 2104 Variable *ValHiR = nullptr; |
| 2104 if (Val->getType() == IceType_i64) { | 2105 if (Val->getType() == IceType_i64) { |
| 2106 Val = legalizeUndef(Val); |
| 2105 ValLoR = legalizeToVar(loOperand(Val)); | 2107 ValLoR = legalizeToVar(loOperand(Val)); |
| 2106 ValHiR = legalizeToVar(hiOperand(Val)); | 2108 ValHiR = legalizeToVar(hiOperand(Val)); |
| 2107 Variable *TLo = makeReg(IceType_i32); | 2109 Variable *TLo = makeReg(IceType_i32); |
| 2108 Variable *THi = makeReg(IceType_i32); | 2110 Variable *THi = makeReg(IceType_i32); |
| 2109 _rbit(TLo, ValLoR); | 2111 _rbit(TLo, ValLoR); |
| 2110 _rbit(THi, ValHiR); | 2112 _rbit(THi, ValHiR); |
| 2111 ValLoR = THi; | 2113 ValLoR = THi; |
| 2112 ValHiR = TLo; | 2114 ValHiR = TLo; |
| 2113 } else { | 2115 } else { |
| 2114 ValLoR = legalizeToVar(Val); | 2116 ValLoR = legalizeToVar(Val); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2261 | 2263 |
| 2262 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 2264 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
| 2263 Func->setError("Phi found in regular instruction list"); | 2265 Func->setError("Phi found in regular instruction list"); |
| 2264 } | 2266 } |
| 2265 | 2267 |
| 2266 void TargetARM32::lowerRet(const InstRet *Inst) { | 2268 void TargetARM32::lowerRet(const InstRet *Inst) { |
| 2267 Variable *Reg = nullptr; | 2269 Variable *Reg = nullptr; |
| 2268 if (Inst->hasRetValue()) { | 2270 if (Inst->hasRetValue()) { |
| 2269 Operand *Src0 = Inst->getRetValue(); | 2271 Operand *Src0 = Inst->getRetValue(); |
| 2270 if (Src0->getType() == IceType_i64) { | 2272 if (Src0->getType() == IceType_i64) { |
| 2273 Src0 = legalizeUndef(Src0); |
| 2271 Variable *R0 = legalizeToVar(loOperand(Src0), RegARM32::Reg_r0); | 2274 Variable *R0 = legalizeToVar(loOperand(Src0), RegARM32::Reg_r0); |
| 2272 Variable *R1 = legalizeToVar(hiOperand(Src0), RegARM32::Reg_r1); | 2275 Variable *R1 = legalizeToVar(hiOperand(Src0), RegARM32::Reg_r1); |
| 2273 Reg = R0; | 2276 Reg = R0; |
| 2274 Context.insert(InstFakeUse::create(Func, R1)); | 2277 Context.insert(InstFakeUse::create(Func, R1)); |
| 2275 } else if (isScalarFloatingType(Src0->getType())) { | 2278 } else if (isScalarFloatingType(Src0->getType())) { |
| 2276 UnimplementedError(Func->getContext()->getFlags()); | 2279 UnimplementedError(Func->getContext()->getFlags()); |
| 2277 } else if (isVectorType(Src0->getType())) { | 2280 } else if (isVectorType(Src0->getType())) { |
| 2278 UnimplementedError(Func->getContext()->getFlags()); | 2281 UnimplementedError(Func->getContext()->getFlags()); |
| 2279 } else { | 2282 } else { |
| 2280 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 2283 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2311 UnimplementedError(Func->getContext()->getFlags()); | 2314 UnimplementedError(Func->getContext()->getFlags()); |
| 2312 return; | 2315 return; |
| 2313 } | 2316 } |
| 2314 // TODO(jvoung): handle folding opportunities. | 2317 // TODO(jvoung): handle folding opportunities. |
| 2315 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t | 2318 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t |
| 2316 Variable *CmpOpnd0 = legalizeToVar(Condition); | 2319 Variable *CmpOpnd0 = legalizeToVar(Condition); |
| 2317 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); | 2320 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); |
| 2318 _cmp(CmpOpnd0, CmpOpnd1); | 2321 _cmp(CmpOpnd0, CmpOpnd1); |
| 2319 CondARM32::Cond Cond = CondARM32::NE; | 2322 CondARM32::Cond Cond = CondARM32::NE; |
| 2320 if (DestTy == IceType_i64) { | 2323 if (DestTy == IceType_i64) { |
| 2324 SrcT = legalizeUndef(SrcT); |
| 2325 SrcF = legalizeUndef(SrcF); |
| 2321 // Set the low portion. | 2326 // Set the low portion. |
| 2322 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2327 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2323 Variable *TLo = nullptr; | 2328 Variable *TLo = nullptr; |
| 2324 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); | 2329 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); |
| 2325 _mov(TLo, SrcFLo); | 2330 _mov(TLo, SrcFLo); |
| 2326 Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex); | 2331 Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex); |
| 2327 _mov_nonkillable(TLo, SrcTLo, Cond); | 2332 _mov_nonkillable(TLo, SrcTLo, Cond); |
| 2328 _mov(DestLo, TLo); | 2333 _mov(DestLo, TLo); |
| 2329 // Set the high portion. | 2334 // Set the high portion. |
| 2330 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2335 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2344 _mov(Dest, T); | 2349 _mov(Dest, T); |
| 2345 } | 2350 } |
| 2346 | 2351 |
| 2347 void TargetARM32::lowerStore(const InstStore *Inst) { | 2352 void TargetARM32::lowerStore(const InstStore *Inst) { |
| 2348 Operand *Value = Inst->getData(); | 2353 Operand *Value = Inst->getData(); |
| 2349 Operand *Addr = Inst->getAddr(); | 2354 Operand *Addr = Inst->getAddr(); |
| 2350 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); | 2355 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
| 2351 Type Ty = NewAddr->getType(); | 2356 Type Ty = NewAddr->getType(); |
| 2352 | 2357 |
| 2353 if (Ty == IceType_i64) { | 2358 if (Ty == IceType_i64) { |
| 2359 Value = legalizeUndef(Value); |
| 2354 Variable *ValueHi = legalizeToVar(hiOperand(Value)); | 2360 Variable *ValueHi = legalizeToVar(hiOperand(Value)); |
| 2355 Variable *ValueLo = legalizeToVar(loOperand(Value)); | 2361 Variable *ValueLo = legalizeToVar(loOperand(Value)); |
| 2356 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); | 2362 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); |
| 2357 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); | 2363 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); |
| 2358 } else if (isVectorType(Ty)) { | 2364 } else if (isVectorType(Ty)) { |
| 2359 UnimplementedError(Func->getContext()->getFlags()); | 2365 UnimplementedError(Func->getContext()->getFlags()); |
| 2360 } else { | 2366 } else { |
| 2361 Variable *ValueR = legalizeToVar(Value); | 2367 Variable *ValueR = legalizeToVar(Value); |
| 2362 _str(ValueR, NewAddr); | 2368 _str(ValueR, NewAddr); |
| 2363 } | 2369 } |
| 2364 } | 2370 } |
| 2365 | 2371 |
| 2366 void TargetARM32::doAddressOptStore() { | 2372 void TargetARM32::doAddressOptStore() { |
| 2367 UnimplementedError(Func->getContext()->getFlags()); | 2373 UnimplementedError(Func->getContext()->getFlags()); |
| 2368 } | 2374 } |
| 2369 | 2375 |
| 2370 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 2376 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
| 2371 // This implements the most naive possible lowering. | 2377 // This implements the most naive possible lowering. |
| 2372 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default | 2378 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default |
| 2373 Operand *Src0 = Inst->getComparison(); | 2379 Operand *Src0 = Inst->getComparison(); |
| 2374 SizeT NumCases = Inst->getNumCases(); | 2380 SizeT NumCases = Inst->getNumCases(); |
| 2375 if (Src0->getType() == IceType_i64) { | 2381 if (Src0->getType() == IceType_i64) { |
| 2376 // TODO(jvoung): handle and test undef for Src0 | 2382 Src0 = legalizeUndef(Src0); |
| 2377 Variable *Src0Lo = legalizeToVar(loOperand(Src0)); | 2383 Variable *Src0Lo = legalizeToVar(loOperand(Src0)); |
| 2378 Variable *Src0Hi = legalizeToVar(hiOperand(Src0)); | 2384 Variable *Src0Hi = legalizeToVar(hiOperand(Src0)); |
| 2379 for (SizeT I = 0; I < NumCases; ++I) { | 2385 for (SizeT I = 0; I < NumCases; ++I) { |
| 2380 Operand *ValueLo = Ctx->getConstantInt32(Inst->getValue(I)); | 2386 Operand *ValueLo = Ctx->getConstantInt32(Inst->getValue(I)); |
| 2381 Operand *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32); | 2387 Operand *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32); |
| 2382 ValueLo = legalize(ValueLo, Legal_Reg | Legal_Flex); | 2388 ValueLo = legalize(ValueLo, Legal_Reg | Legal_Flex); |
| 2383 ValueHi = legalize(ValueHi, Legal_Reg | Legal_Flex); | 2389 ValueHi = legalize(ValueHi, Legal_Reg | Legal_Flex); |
| 2384 _cmp(Src0Lo, ValueLo); | 2390 _cmp(Src0Lo, ValueLo); |
| 2385 _cmp(Src0Hi, ValueHi, CondARM32::EQ); | 2391 _cmp(Src0Hi, ValueHi, CondARM32::EQ); |
| 2386 _br(Inst->getLabel(I), CondARM32::EQ); | 2392 _br(Inst->getLabel(I), CondARM32::EQ); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2437 } else { | 2443 } else { |
| 2438 // Mov's Src operand can really only be the flexible second operand type | 2444 // Mov's Src operand can really only be the flexible second operand type |
| 2439 // or a register. Users should guarantee that. | 2445 // or a register. Users should guarantee that. |
| 2440 _mov(Reg, Src); | 2446 _mov(Reg, Src); |
| 2441 } | 2447 } |
| 2442 return Reg; | 2448 return Reg; |
| 2443 } | 2449 } |
| 2444 | 2450 |
| 2445 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 2451 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
| 2446 int32_t RegNum) { | 2452 int32_t RegNum) { |
| 2453 Type Ty = From->getType(); |
| 2447 // Assert that a physical register is allowed. To date, all calls | 2454 // Assert that a physical register is allowed. To date, all calls |
| 2448 // to legalize() allow a physical register. Legal_Flex converts | 2455 // to legalize() allow a physical register. Legal_Flex converts |
| 2449 // registers to the right type OperandARM32FlexReg as needed. | 2456 // registers to the right type OperandARM32FlexReg as needed. |
| 2450 assert(Allowed & Legal_Reg); | 2457 assert(Allowed & Legal_Reg); |
| 2451 // Go through the various types of operands: | 2458 // Go through the various types of operands: |
| 2452 // OperandARM32Mem, OperandARM32Flex, Constant, and Variable. | 2459 // OperandARM32Mem, OperandARM32Flex, Constant, and Variable. |
| 2453 // Given the above assertion, if type of operand is not legal | 2460 // Given the above assertion, if type of operand is not legal |
| 2454 // (e.g., OperandARM32Mem and !Legal_Mem), we can always copy | 2461 // (e.g., OperandARM32Mem and !Legal_Mem), we can always copy |
| 2455 // to a register. | 2462 // to a register. |
| 2456 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { | 2463 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { |
| 2457 // Before doing anything with a Mem operand, we need to ensure | 2464 // Before doing anything with a Mem operand, we need to ensure |
| 2458 // that the Base and Index components are in physical registers. | 2465 // that the Base and Index components are in physical registers. |
| 2459 Variable *Base = Mem->getBase(); | 2466 Variable *Base = Mem->getBase(); |
| 2460 Variable *Index = Mem->getIndex(); | 2467 Variable *Index = Mem->getIndex(); |
| 2461 Variable *RegBase = nullptr; | 2468 Variable *RegBase = nullptr; |
| 2462 Variable *RegIndex = nullptr; | 2469 Variable *RegIndex = nullptr; |
| 2463 if (Base) { | 2470 if (Base) { |
| 2464 RegBase = legalizeToVar(Base); | 2471 RegBase = legalizeToVar(Base); |
| 2465 } | 2472 } |
| 2466 if (Index) { | 2473 if (Index) { |
| 2467 RegIndex = legalizeToVar(Index); | 2474 RegIndex = legalizeToVar(Index); |
| 2468 } | 2475 } |
| 2469 // Create a new operand if there was a change. | 2476 // Create a new operand if there was a change. |
| 2470 if (Base != RegBase || Index != RegIndex) { | 2477 if (Base != RegBase || Index != RegIndex) { |
| 2471 // There is only a reg +/- reg or reg + imm form. | 2478 // There is only a reg +/- reg or reg + imm form. |
| 2472 // Figure out which to re-create. | 2479 // Figure out which to re-create. |
| 2473 if (Mem->isRegReg()) { | 2480 if (Mem->isRegReg()) { |
| 2474 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, RegIndex, | 2481 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, |
| 2475 Mem->getShiftOp(), Mem->getShiftAmt(), | 2482 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 2476 Mem->getAddrMode()); | 2483 Mem->getAddrMode()); |
| 2477 } else { | 2484 } else { |
| 2478 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, | 2485 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Mem->getOffset(), |
| 2479 Mem->getOffset(), Mem->getAddrMode()); | 2486 Mem->getAddrMode()); |
| 2480 } | 2487 } |
| 2481 } | 2488 } |
| 2482 if (!(Allowed & Legal_Mem)) { | 2489 if (!(Allowed & Legal_Mem)) { |
| 2483 Type Ty = Mem->getType(); | |
| 2484 Variable *Reg = makeReg(Ty, RegNum); | 2490 Variable *Reg = makeReg(Ty, RegNum); |
| 2485 _ldr(Reg, Mem); | 2491 _ldr(Reg, Mem); |
| 2486 From = Reg; | 2492 From = Reg; |
| 2487 } else { | 2493 } else { |
| 2488 From = Mem; | 2494 From = Mem; |
| 2489 } | 2495 } |
| 2490 return From; | 2496 return From; |
| 2491 } | 2497 } |
| 2492 | 2498 |
| 2493 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { | 2499 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { |
| 2494 if (!(Allowed & Legal_Flex)) { | 2500 if (!(Allowed & Legal_Flex)) { |
| 2495 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { | 2501 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { |
| 2496 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { | 2502 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { |
| 2497 From = FlexReg->getReg(); | 2503 From = FlexReg->getReg(); |
| 2498 // Fall through and let From be checked as a Variable below, | 2504 // Fall through and let From be checked as a Variable below, |
| 2499 // where it may or may not need a register. | 2505 // where it may or may not need a register. |
| 2500 } else { | 2506 } else { |
| 2501 return copyToReg(Flex, RegNum); | 2507 return copyToReg(Flex, RegNum); |
| 2502 } | 2508 } |
| 2503 } else { | 2509 } else { |
| 2504 return copyToReg(Flex, RegNum); | 2510 return copyToReg(Flex, RegNum); |
| 2505 } | 2511 } |
| 2506 } else { | 2512 } else { |
| 2507 return From; | 2513 return From; |
| 2508 } | 2514 } |
| 2509 } | 2515 } |
| 2510 | 2516 |
| 2511 if (llvm::isa<Constant>(From)) { | 2517 if (llvm::isa<Constant>(From)) { |
| 2512 if (llvm::isa<ConstantUndef>(From)) { | 2518 if (llvm::isa<ConstantUndef>(From)) { |
| 2513 // Lower undefs to zero. Another option is to lower undefs to an | 2519 From = legalizeUndef(From, RegNum); |
| 2514 // uninitialized register; however, using an uninitialized register | 2520 if (isVectorType(Ty)) |
| 2515 // results in less predictable code. | 2521 return From; |
| 2516 if (isVectorType(From->getType())) | |
| 2517 return makeVectorOfZeros(From->getType(), RegNum); | |
| 2518 From = Ctx->getConstantZero(From->getType()); | |
| 2519 } | 2522 } |
| 2520 // There should be no constants of vector type (other than undef). | 2523 // There should be no constants of vector type (other than undef). |
| 2521 assert(!isVectorType(From->getType())); | 2524 assert(!isVectorType(Ty)); |
| 2522 bool CanBeFlex = Allowed & Legal_Flex; | 2525 bool CanBeFlex = Allowed & Legal_Flex; |
| 2523 if (auto C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | 2526 if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
| 2524 uint32_t RotateAmt; | 2527 uint32_t RotateAmt; |
| 2525 uint32_t Immed_8; | 2528 uint32_t Immed_8; |
| 2526 uint32_t Value = static_cast<uint32_t>(C32->getValue()); | 2529 uint32_t Value = static_cast<uint32_t>(C32->getValue()); |
| 2527 // Check if the immediate will fit in a Flexible second operand, | 2530 // Check if the immediate will fit in a Flexible second operand, |
| 2528 // if a Flexible second operand is allowed. We need to know the exact | 2531 // if a Flexible second operand is allowed. We need to know the exact |
| 2529 // value, so that rules out relocatable constants. | 2532 // value, so that rules out relocatable constants. |
| 2530 // Also try the inverse and use MVN if possible. | 2533 // Also try the inverse and use MVN if possible. |
| 2531 if (CanBeFlex && | 2534 if (CanBeFlex && |
| 2532 OperandARM32FlexImm::canHoldImm(Value, &RotateAmt, &Immed_8)) { | 2535 OperandARM32FlexImm::canHoldImm(Value, &RotateAmt, &Immed_8)) { |
| 2533 return OperandARM32FlexImm::create(Func, From->getType(), Immed_8, | 2536 return OperandARM32FlexImm::create(Func, Ty, Immed_8, RotateAmt); |
| 2534 RotateAmt); | |
| 2535 } else if (CanBeFlex && OperandARM32FlexImm::canHoldImm( | 2537 } else if (CanBeFlex && OperandARM32FlexImm::canHoldImm( |
| 2536 ~Value, &RotateAmt, &Immed_8)) { | 2538 ~Value, &RotateAmt, &Immed_8)) { |
| 2537 auto InvertedFlex = OperandARM32FlexImm::create(Func, From->getType(), | 2539 auto InvertedFlex = |
| 2538 Immed_8, RotateAmt); | 2540 OperandARM32FlexImm::create(Func, Ty, Immed_8, RotateAmt); |
| 2539 Type Ty = From->getType(); | |
| 2540 Variable *Reg = makeReg(Ty, RegNum); | 2541 Variable *Reg = makeReg(Ty, RegNum); |
| 2541 _mvn(Reg, InvertedFlex); | 2542 _mvn(Reg, InvertedFlex); |
| 2542 return Reg; | 2543 return Reg; |
| 2543 } else { | 2544 } else { |
| 2544 // Do a movw/movt to a register. | 2545 // Do a movw/movt to a register. |
| 2545 Type Ty = From->getType(); | |
| 2546 Variable *Reg = makeReg(Ty, RegNum); | 2546 Variable *Reg = makeReg(Ty, RegNum); |
| 2547 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | 2547 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
| 2548 _movw(Reg, | 2548 _movw(Reg, |
| 2549 UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32); | 2549 UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32); |
| 2550 if (UpperBits != 0) { | 2550 if (UpperBits != 0) { |
| 2551 _movt(Reg, Ctx->getConstantInt32(UpperBits)); | 2551 _movt(Reg, Ctx->getConstantInt32(UpperBits)); |
| 2552 } | 2552 } |
| 2553 return Reg; | 2553 return Reg; |
| 2554 } | 2554 } |
| 2555 } else if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) { | 2555 } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
| 2556 Type Ty = From->getType(); | |
| 2557 Variable *Reg = makeReg(Ty, RegNum); | 2556 Variable *Reg = makeReg(Ty, RegNum); |
| 2558 _movw(Reg, C); | 2557 _movw(Reg, C); |
| 2559 _movt(Reg, C); | 2558 _movt(Reg, C); |
| 2560 return Reg; | 2559 return Reg; |
| 2561 } else { | 2560 } else { |
| 2562 // Load floats/doubles from literal pool. | 2561 // Load floats/doubles from literal pool. |
| 2563 UnimplementedError(Func->getContext()->getFlags()); | 2562 UnimplementedError(Func->getContext()->getFlags()); |
| 2564 From = copyToReg(From, RegNum); | 2563 From = copyToReg(From, RegNum); |
| 2565 } | 2564 } |
| 2566 return From; | 2565 return From; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2579 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | 2578 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { |
| 2580 From = copyToReg(From, RegNum); | 2579 From = copyToReg(From, RegNum); |
| 2581 } | 2580 } |
| 2582 return From; | 2581 return From; |
| 2583 } | 2582 } |
| 2584 llvm_unreachable("Unhandled operand kind in legalize()"); | 2583 llvm_unreachable("Unhandled operand kind in legalize()"); |
| 2585 | 2584 |
| 2586 return From; | 2585 return From; |
| 2587 } | 2586 } |
| 2588 | 2587 |
| 2589 // Provide a trivial wrapper to legalize() for this common usage. | 2588 /// Provide a trivial wrapper to legalize() for this common usage. |
| 2590 Variable *TargetARM32::legalizeToVar(Operand *From, int32_t RegNum) { | 2589 Variable *TargetARM32::legalizeToVar(Operand *From, int32_t RegNum) { |
| 2591 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 2590 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
| 2592 } | 2591 } |
| 2593 | 2592 |
| 2593 /// Legalize undef values to concrete values. |
| 2594 Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) { |
| 2595 Type Ty = From->getType(); |
| 2596 if (llvm::isa<ConstantUndef>(From)) { |
| 2597 // Lower undefs to zero. Another option is to lower undefs to an |
| 2598 // uninitialized register; however, using an uninitialized register |
| 2599 // results in less predictable code. |
| 2600 // |
| 2601 // If in the future the implementation is changed to lower undef |
| 2602 // values to uninitialized registers, a FakeDef will be needed: |
| 2603 // Context.insert(InstFakeDef::create(Func, Reg)); |
| 2604 // This is in order to ensure that the live range of Reg is not |
| 2605 // overestimated. If the constant being lowered is a 64 bit value, |
| 2606 // then the result should be split and the lo and hi components will |
| 2607 // need to go in uninitialized registers. |
| 2608 if (isVectorType(Ty)) |
| 2609 return makeVectorOfZeros(Ty, RegNum); |
| 2610 return Ctx->getConstantZero(Ty); |
| 2611 } |
| 2612 return From; |
| 2613 } |
| 2614 |
| 2594 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) { | 2615 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) { |
| 2595 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); | 2616 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); |
| 2596 // It may be the case that address mode optimization already creates | 2617 // It may be the case that address mode optimization already creates |
| 2597 // an OperandARM32Mem, so in that case it wouldn't need another level | 2618 // an OperandARM32Mem, so in that case it wouldn't need another level |
| 2598 // of transformation. | 2619 // of transformation. |
| 2599 if (Mem) { | 2620 if (Mem) { |
| 2600 return llvm::cast<OperandARM32Mem>(legalize(Mem)); | 2621 return llvm::cast<OperandARM32Mem>(legalize(Mem)); |
| 2601 } | 2622 } |
| 2602 // If we didn't do address mode optimization, then we only | 2623 // If we didn't do address mode optimization, then we only |
| 2603 // have a base/offset to work with. ARM always requires a base | 2624 // have a base/offset to work with. ARM always requires a base |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2746 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; | 2767 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
| 2747 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 2768 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
| 2748 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 2769 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
| 2749 } | 2770 } |
| 2750 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 2771 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 2751 // However, for compatibility with current NaCl LLVM, don't claim that. | 2772 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 2752 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 2773 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 2753 } | 2774 } |
| 2754 | 2775 |
| 2755 } // end of namespace Ice | 2776 } // end of namespace Ice |
| OLD | NEW |