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 |