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 |