| 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 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 Context.setInsertPoint(Context.getCur()); | 521 Context.setInsertPoint(Context.getCur()); |
| 522 | 522 |
| 523 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 523 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
| 524 Variable *Arg = Args[I]; | 524 Variable *Arg = Args[I]; |
| 525 Type Ty = Arg->getType(); | 525 Type Ty = Arg->getType(); |
| 526 if (Ty == IceType_i64) { | 526 if (Ty == IceType_i64) { |
| 527 std::pair<int32_t, int32_t> RegPair; | 527 std::pair<int32_t, int32_t> RegPair; |
| 528 if (!CC.I64InRegs(&RegPair)) | 528 if (!CC.I64InRegs(&RegPair)) |
| 529 continue; | 529 continue; |
| 530 Variable *RegisterArg = Func->makeVariable(Ty); | 530 Variable *RegisterArg = Func->makeVariable(Ty); |
| 531 Variable *RegisterLo = Func->makeVariable(IceType_i32); | 531 auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg); |
| 532 Variable *RegisterHi = Func->makeVariable(IceType_i32); | 532 if (BuildDefs::dump()) |
| 533 if (BuildDefs::dump()) { | 533 RegisterArg64On32->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 534 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 534 RegisterArg64On32->initHiLo(Func); |
| 535 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func)); | 535 RegisterArg64On32->setIsArg(); |
| 536 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func)); | 536 RegisterArg64On32->getLo()->setRegNum(RegPair.first); |
| 537 } | 537 RegisterArg64On32->getHi()->setRegNum(RegPair.second); |
| 538 RegisterLo->setRegNum(RegPair.first); | |
| 539 RegisterLo->setIsArg(); | |
| 540 RegisterHi->setRegNum(RegPair.second); | |
| 541 RegisterHi->setIsArg(); | |
| 542 RegisterArg->setLoHi(RegisterLo, RegisterHi); | |
| 543 RegisterArg->setIsArg(); | |
| 544 Arg->setIsArg(false); | 538 Arg->setIsArg(false); |
| 545 | 539 |
| 546 Args[I] = RegisterArg; | 540 Args[I] = RegisterArg64On32; |
| 547 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 541 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 548 continue; | 542 continue; |
| 549 } else { | 543 } else { |
| 550 int32_t RegNum; | 544 int32_t RegNum; |
| 551 if (isVectorType(Ty) || isFloatingType(Ty)) { | 545 if (isVectorType(Ty) || isFloatingType(Ty)) { |
| 552 if (!CC.FPInReg(Ty, &RegNum)) | 546 if (!CC.FPInReg(Ty, &RegNum)) |
| 553 continue; | 547 continue; |
| 554 } else { | 548 } else { |
| 555 assert(Ty == IceType_i32); | 549 assert(Ty == IceType_i32); |
| 556 if (!CC.I32InReg(&RegNum)) | 550 if (!CC.I32InReg(&RegNum)) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 575 // | 569 // |
| 576 // This assumes Arg is an argument passed on the stack. This sets the frame | 570 // This assumes Arg is an argument passed on the stack. This sets the frame |
| 577 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 571 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
| 578 // I64 arg that has been split into Lo and Hi components, it calls itself | 572 // I64 arg that has been split into Lo and Hi components, it calls itself |
| 579 // recursively on the components, taking care to handle Lo first because of the | 573 // recursively on the components, taking care to handle Lo first because of the |
| 580 // little-endian architecture. Lastly, this function generates an instruction | 574 // little-endian architecture. Lastly, this function generates an instruction |
| 581 // to copy Arg into its assigned register if applicable. | 575 // to copy Arg into its assigned register if applicable. |
| 582 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 576 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 583 size_t BasicFrameOffset, | 577 size_t BasicFrameOffset, |
| 584 size_t &InArgsSizeBytes) { | 578 size_t &InArgsSizeBytes) { |
| 585 Variable *Lo = Arg->getLo(); | 579 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { |
| 586 Variable *Hi = Arg->getHi(); | 580 Variable *Lo = Arg64On32->getLo(); |
| 587 Type Ty = Arg->getType(); | 581 Variable *Hi = Arg64On32->getHi(); |
| 588 if (Lo && Hi && Ty == IceType_i64) { | |
| 589 assert(Lo->getType() != IceType_i64); // don't want infinite recursion | |
| 590 assert(Hi->getType() != IceType_i64); // don't want infinite recursion | |
| 591 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 582 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 592 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 583 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 593 return; | 584 return; |
| 594 } | 585 } |
| 586 Type Ty = Arg->getType(); |
| 595 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); | 587 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); |
| 596 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); | 588 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); |
| 597 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 589 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 598 // If the argument variable has been assigned a register, we need to load the | 590 // If the argument variable has been assigned a register, we need to load the |
| 599 // value from the stack slot. | 591 // value from the stack slot. |
| 600 if (Arg->hasReg()) { | 592 if (Arg->hasReg()) { |
| 601 assert(Ty != IceType_i64); | 593 assert(Ty != IceType_i64); |
| 602 OperandARM32Mem *Mem = OperandARM32Mem::create( | 594 OperandARM32Mem *Mem = OperandARM32Mem::create( |
| 603 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( | 595 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( |
| 604 Ctx->getConstantInt32(Arg->getStackOffset()))); | 596 Ctx->getConstantInt32(Arg->getStackOffset()))); |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1045 MovInst->setDeleted(); | 1037 MovInst->setDeleted(); |
| 1046 NewBaseReg = LegalVar; | 1038 NewBaseReg = LegalVar; |
| 1047 NewBaseOffset = Offset; | 1039 NewBaseOffset = Offset; |
| 1048 continue; | 1040 continue; |
| 1049 } | 1041 } |
| 1050 } | 1042 } |
| 1051 } | 1043 } |
| 1052 } | 1044 } |
| 1053 } | 1045 } |
| 1054 | 1046 |
| 1055 void TargetARM32::split64(Variable *Var) { | |
| 1056 assert(Var->getType() == IceType_i64); | |
| 1057 Variable *Lo = Var->getLo(); | |
| 1058 Variable *Hi = Var->getHi(); | |
| 1059 if (Lo) { | |
| 1060 assert(Hi); | |
| 1061 return; | |
| 1062 } | |
| 1063 assert(Hi == nullptr); | |
| 1064 Lo = Func->makeVariable(IceType_i32); | |
| 1065 Hi = Func->makeVariable(IceType_i32); | |
| 1066 if (BuildDefs::dump()) { | |
| 1067 Lo->setName(Func, Var->getName(Func) + "__lo"); | |
| 1068 Hi->setName(Func, Var->getName(Func) + "__hi"); | |
| 1069 } | |
| 1070 Var->setLoHi(Lo, Hi); | |
| 1071 if (Var->getIsArg()) { | |
| 1072 Lo->setIsArg(); | |
| 1073 Hi->setIsArg(); | |
| 1074 } | |
| 1075 } | |
| 1076 | |
| 1077 Operand *TargetARM32::loOperand(Operand *Operand) { | 1047 Operand *TargetARM32::loOperand(Operand *Operand) { |
| 1078 assert(Operand->getType() == IceType_i64); | 1048 assert(Operand->getType() == IceType_i64); |
| 1079 if (Operand->getType() != IceType_i64) | 1049 if (Operand->getType() != IceType_i64) |
| 1080 return Operand; | 1050 return Operand; |
| 1081 if (auto *Var = llvm::dyn_cast<Variable>(Operand)) { | 1051 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
| 1082 split64(Var); | 1052 return Var64On32->getLo(); |
| 1083 return Var->getLo(); | 1053 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) |
| 1084 } | |
| 1085 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
| 1086 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | 1054 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
| 1087 } | |
| 1088 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | 1055 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
| 1089 // Conservatively disallow memory operands with side-effects (pre/post | 1056 // Conservatively disallow memory operands with side-effects (pre/post |
| 1090 // increment) in case of duplication. | 1057 // increment) in case of duplication. |
| 1091 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | 1058 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
| 1092 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | 1059 Mem->getAddrMode() == OperandARM32Mem::NegOffset); |
| 1093 if (Mem->isRegReg()) { | 1060 if (Mem->isRegReg()) { |
| 1094 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | 1061 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), |
| 1095 Mem->getIndex(), Mem->getShiftOp(), | 1062 Mem->getIndex(), Mem->getShiftOp(), |
| 1096 Mem->getShiftAmt(), Mem->getAddrMode()); | 1063 Mem->getShiftAmt(), Mem->getAddrMode()); |
| 1097 } else { | 1064 } else { |
| 1098 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | 1065 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), |
| 1099 Mem->getOffset(), Mem->getAddrMode()); | 1066 Mem->getOffset(), Mem->getAddrMode()); |
| 1100 } | 1067 } |
| 1101 } | 1068 } |
| 1102 llvm_unreachable("Unsupported operand type"); | 1069 llvm_unreachable("Unsupported operand type"); |
| 1103 return nullptr; | 1070 return nullptr; |
| 1104 } | 1071 } |
| 1105 | 1072 |
| 1106 Operand *TargetARM32::hiOperand(Operand *Operand) { | 1073 Operand *TargetARM32::hiOperand(Operand *Operand) { |
| 1107 assert(Operand->getType() == IceType_i64); | 1074 assert(Operand->getType() == IceType_i64); |
| 1108 if (Operand->getType() != IceType_i64) | 1075 if (Operand->getType() != IceType_i64) |
| 1109 return Operand; | 1076 return Operand; |
| 1110 if (auto *Var = llvm::dyn_cast<Variable>(Operand)) { | 1077 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
| 1111 split64(Var); | 1078 return Var64On32->getHi(); |
| 1112 return Var->getHi(); | |
| 1113 } | |
| 1114 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1079 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 1115 return Ctx->getConstantInt32( | 1080 return Ctx->getConstantInt32( |
| 1116 static_cast<uint32_t>(Const->getValue() >> 32)); | 1081 static_cast<uint32_t>(Const->getValue() >> 32)); |
| 1117 } | 1082 } |
| 1118 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | 1083 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
| 1119 // Conservatively disallow memory operands with side-effects in case of | 1084 // Conservatively disallow memory operands with side-effects in case of |
| 1120 // duplication. | 1085 // duplication. |
| 1121 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | 1086 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
| 1122 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | 1087 Mem->getAddrMode() == OperandARM32Mem::NegOffset); |
| 1123 const Type SplitType = IceType_i32; | 1088 const Type SplitType = IceType_i32; |
| (...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 1893 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
| 1929 Context.insert(FakeUse); | 1894 Context.insert(FakeUse); |
| 1930 } | 1895 } |
| 1931 | 1896 |
| 1932 if (!Dest) | 1897 if (!Dest) |
| 1933 return; | 1898 return; |
| 1934 | 1899 |
| 1935 // Assign the result of the call to Dest. | 1900 // Assign the result of the call to Dest. |
| 1936 if (ReturnReg) { | 1901 if (ReturnReg) { |
| 1937 if (ReturnRegHi) { | 1902 if (ReturnRegHi) { |
| 1938 assert(Dest->getType() == IceType_i64); | 1903 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 1939 split64(Dest); | 1904 Variable *DestLo = Dest64On32->getLo(); |
| 1940 Variable *DestLo = Dest->getLo(); | 1905 Variable *DestHi = Dest64On32->getHi(); |
| 1941 Variable *DestHi = Dest->getHi(); | |
| 1942 _mov(DestLo, ReturnReg); | 1906 _mov(DestLo, ReturnReg); |
| 1943 _mov(DestHi, ReturnRegHi); | 1907 _mov(DestHi, ReturnRegHi); |
| 1944 } else { | 1908 } else { |
| 1945 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | 1909 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { |
| 1946 _vmov(Dest, ReturnReg); | 1910 _vmov(Dest, ReturnReg); |
| 1947 } else { | 1911 } else { |
| 1948 assert(isIntegerType(Dest->getType()) && | 1912 assert(isIntegerType(Dest->getType()) && |
| 1949 typeWidthInBytes(Dest->getType()) <= 4); | 1913 typeWidthInBytes(Dest->getType()) <= 4); |
| 1950 _mov(Dest, ReturnReg); | 1914 _mov(Dest, ReturnReg); |
| 1951 } | 1915 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2096 // t1.fp = vcvt src0.fp | 2060 // t1.fp = vcvt src0.fp |
| 2097 // t2.i32 = vmov t1.fp | 2061 // t2.i32 = vmov t1.fp |
| 2098 // dest.int = conv t2.i32 @ Truncates the result if needed. | 2062 // dest.int = conv t2.i32 @ Truncates the result if needed. |
| 2099 // fptoui: | 2063 // fptoui: |
| 2100 // t1.fp = vcvt src0.fp | 2064 // t1.fp = vcvt src0.fp |
| 2101 // t2.u32 = vmov t1.fp | 2065 // t2.u32 = vmov t1.fp |
| 2102 // dest.uint = conv t2.u32 @ Truncates the result if needed. | 2066 // dest.uint = conv t2.u32 @ Truncates the result if needed. |
| 2103 if (isVectorType(Dest->getType())) { | 2067 if (isVectorType(Dest->getType())) { |
| 2104 UnimplementedError(Func->getContext()->getFlags()); | 2068 UnimplementedError(Func->getContext()->getFlags()); |
| 2105 break; | 2069 break; |
| 2106 } else if (Dest->getType() == IceType_i64) { | 2070 } |
| 2107 split64(Dest); | 2071 if (auto *Dest64On32 = llvm::dyn_cast<Variable64On32>(Dest)) { |
| 2108 Context.insert(InstFakeDef::create(Func, Dest->getLo())); | 2072 Context.insert(InstFakeDef::create(Func, Dest64On32->getLo())); |
| 2109 Context.insert(InstFakeDef::create(Func, Dest->getHi())); | 2073 Context.insert(InstFakeDef::create(Func, Dest64On32->getHi())); |
| 2110 UnimplementedError(Func->getContext()->getFlags()); | 2074 UnimplementedError(Func->getContext()->getFlags()); |
| 2111 break; | 2075 break; |
| 2112 } | 2076 } |
| 2113 const bool DestIsSigned = CastKind == InstCast::Fptosi; | 2077 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
| 2114 Variable *Src0R = legalizeToReg(Src0); | 2078 Variable *Src0R = legalizeToReg(Src0); |
| 2115 Variable *T_fp = makeReg(IceType_f32); | 2079 Variable *T_fp = makeReg(IceType_f32); |
| 2116 if (isFloat32Asserting32Or64(Src0->getType())) { | 2080 if (isFloat32Asserting32Or64(Src0->getType())) { |
| 2117 _vcvt(T_fp, Src0R, | 2081 _vcvt(T_fp, Src0R, |
| 2118 DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui); | 2082 DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui); |
| 2119 } else { | 2083 } else { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2206 break; | 2170 break; |
| 2207 } | 2171 } |
| 2208 case IceType_i64: { | 2172 case IceType_i64: { |
| 2209 // t0, t1 <- src0 | 2173 // t0, t1 <- src0 |
| 2210 // dest[31..0] = t0 | 2174 // dest[31..0] = t0 |
| 2211 // dest[63..32] = t1 | 2175 // dest[63..32] = t1 |
| 2212 assert(Src0->getType() == IceType_f64); | 2176 assert(Src0->getType() == IceType_f64); |
| 2213 Variable *T0 = makeReg(IceType_i32); | 2177 Variable *T0 = makeReg(IceType_i32); |
| 2214 Variable *T1 = makeReg(IceType_i32); | 2178 Variable *T1 = makeReg(IceType_i32); |
| 2215 Variable *Src0R = legalizeToReg(Src0); | 2179 Variable *Src0R = legalizeToReg(Src0); |
| 2216 split64(Dest); | |
| 2217 _vmov(InstARM32Vmov::RegisterPair(T0, T1), Src0R); | 2180 _vmov(InstARM32Vmov::RegisterPair(T0, T1), Src0R); |
| 2218 lowerAssign(InstAssign::create(Func, Dest->getLo(), T0)); | 2181 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 2219 lowerAssign(InstAssign::create(Func, Dest->getHi(), T1)); | 2182 lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T0)); |
| 2183 lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T1)); |
| 2220 break; | 2184 break; |
| 2221 } | 2185 } |
| 2222 case IceType_f64: { | 2186 case IceType_f64: { |
| 2223 // T0 <- lo(src) | 2187 // T0 <- lo(src) |
| 2224 // T1 <- hi(src) | 2188 // T1 <- hi(src) |
| 2225 // vmov T2, T0, T1 | 2189 // vmov T2, T0, T1 |
| 2226 // Dest <- T2 | 2190 // Dest <- T2 |
| 2227 assert(Src0->getType() == IceType_i64); | 2191 assert(Src0->getType() == IceType_i64); |
| 2228 Variable *SrcLo = legalizeToReg(loOperand(Src0)); | 2192 Variable *SrcLo = legalizeToReg(loOperand(Src0)); |
| 2229 Variable *SrcHi = legalizeToReg(hiOperand(Src0)); | 2193 Variable *SrcHi = legalizeToReg(hiOperand(Src0)); |
| (...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3203 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; | 3167 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
| 3204 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 3168 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
| 3205 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 3169 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
| 3206 } | 3170 } |
| 3207 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 3171 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 3208 // However, for compatibility with current NaCl LLVM, don't claim that. | 3172 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 3209 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 3173 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 3210 } | 3174 } |
| 3211 | 3175 |
| 3212 } // end of namespace Ice | 3176 } // end of namespace Ice |
| OLD | NEW |