| 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 |
| 11 /// This file implements the TargetLoweringARM32 class, which consists almost | 11 /// This file implements the TargetLoweringARM32 class, which consists almost |
| 12 /// entirely of the lowering sequence for each high-level instruction. | 12 /// entirely of the lowering sequence for each high-level instruction. |
| 13 /// | 13 /// |
| 14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
| 15 #include "IceTargetLoweringARM32.h" | 15 #include "IceTargetLoweringARM32.h" |
| 16 | 16 |
| 17 #include "IceCfg.h" | 17 #include "IceCfg.h" |
| 18 #include "IceCfgNode.h" | 18 #include "IceCfgNode.h" |
| 19 #include "IceClFlags.h" | 19 #include "IceClFlags.h" |
| 20 #include "IceDefs.h" | 20 #include "IceDefs.h" |
| 21 #include "IceELFObjectWriter.h" | 21 #include "IceELFObjectWriter.h" |
| 22 #include "IceGlobalInits.h" | 22 #include "IceGlobalInits.h" |
| 23 #include "IceInstARM32.def" |
| 23 #include "IceInstARM32.h" | 24 #include "IceInstARM32.h" |
| 24 #include "IceLiveness.h" | 25 #include "IceLiveness.h" |
| 25 #include "IceOperand.h" | 26 #include "IceOperand.h" |
| 26 #include "IcePhiLoweringImpl.h" | 27 #include "IcePhiLoweringImpl.h" |
| 27 #include "IceRegistersARM32.h" | 28 #include "IceRegistersARM32.h" |
| 28 #include "IceTargetLoweringARM32.def" | 29 #include "IceTargetLoweringARM32.def" |
| 29 #include "IceUtils.h" | 30 #include "IceUtils.h" |
| 30 #include "llvm/Support/MathExtras.h" | 31 #include "llvm/Support/MathExtras.h" |
| 31 | 32 |
| 32 #include <algorithm> | 33 #include <algorithm> |
| 34 #include <utility> |
| 33 | 35 |
| 34 namespace Ice { | 36 namespace Ice { |
| 35 | 37 |
| 36 namespace { | 38 namespace { |
| 37 | 39 |
| 38 // UnimplementedError is defined as a macro so that we can get actual line | 40 // UnimplementedError is defined as a macro so that we can get actual line |
| 39 // numbers. | 41 // numbers. |
| 40 #define UnimplementedError(Flags) \ | 42 #define UnimplementedError(Flags) \ |
| 41 do { \ | 43 do { \ |
| 42 if (!static_cast<const ClFlags &>(Flags).getSkipUnimplemented()) { \ | 44 if (!static_cast<const ClFlags &>(Flags).getSkipUnimplemented()) { \ |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 isFP32, isFP64, isVec128, alias_init) \ | 375 isFP32, isFP64, isVec128, alias_init) \ |
| 374 name, | 376 name, |
| 375 REGARM32_TABLE | 377 REGARM32_TABLE |
| 376 #undef X | 378 #undef X |
| 377 }; | 379 }; |
| 378 | 380 |
| 379 return RegNames[RegNum]; | 381 return RegNames[RegNum]; |
| 380 } | 382 } |
| 381 | 383 |
| 382 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { | 384 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { |
| 383 if (Ty == IceType_void) | 385 static const Type DefaultType[] = { |
| 384 Ty = IceType_i32; | 386 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
| 387 isFP32, isFP64, isVec128, alias_init) \ |
| 388 (isFP32) \ |
| 389 ? IceType_f32 \ |
| 390 : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))), |
| 391 REGARM32_TABLE |
| 392 #undef X |
| 393 }; |
| 394 |
| 395 assert(RegNum < RegARM32::Reg_NUM); |
| 396 if (Ty == IceType_void) { |
| 397 assert(RegNum < llvm::array_lengthof(DefaultType)); |
| 398 Ty = DefaultType[RegNum]; |
| 399 } |
| 385 if (PhysicalRegisters[Ty].empty()) | 400 if (PhysicalRegisters[Ty].empty()) |
| 386 PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM); | 401 PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM); |
| 387 assert(RegNum < PhysicalRegisters[Ty].size()); | 402 assert(RegNum < PhysicalRegisters[Ty].size()); |
| 388 Variable *Reg = PhysicalRegisters[Ty][RegNum]; | 403 Variable *Reg = PhysicalRegisters[Ty][RegNum]; |
| 389 if (Reg == nullptr) { | 404 if (Reg == nullptr) { |
| 390 Reg = Func->makeVariable(Ty); | 405 Reg = Func->makeVariable(Ty); |
| 391 Reg->setRegNum(RegNum); | 406 Reg->setRegNum(RegNum); |
| 392 PhysicalRegisters[Ty][RegNum] = Reg; | 407 PhysicalRegisters[Ty][RegNum] = Reg; |
| 393 // Specially mark a named physical register as an "argument" so that it is | 408 // Specially mark a named physical register as an "argument" so that it is |
| 394 // considered live upon function entry. Otherwise it's possible to get | 409 // considered live upon function entry. Otherwise it's possible to get |
| (...skipping 23 matching lines...) Expand all Loading... |
| 418 llvm::report_fatal_error( | 433 llvm::report_fatal_error( |
| 419 "Infinite-weight Variable has no register assigned"); | 434 "Infinite-weight Variable has no register assigned"); |
| 420 } | 435 } |
| 421 int32_t Offset = Var->getStackOffset(); | 436 int32_t Offset = Var->getStackOffset(); |
| 422 int32_t BaseRegNum = Var->getBaseRegNum(); | 437 int32_t BaseRegNum = Var->getBaseRegNum(); |
| 423 if (BaseRegNum == Variable::NoRegister) { | 438 if (BaseRegNum == Variable::NoRegister) { |
| 424 BaseRegNum = getFrameOrStackReg(); | 439 BaseRegNum = getFrameOrStackReg(); |
| 425 if (!hasFramePointer()) | 440 if (!hasFramePointer()) |
| 426 Offset += getStackAdjustment(); | 441 Offset += getStackAdjustment(); |
| 427 } | 442 } |
| 428 if (!isLegalVariableStackOffset(Offset)) { | 443 const Type VarTy = Var->getType(); |
| 444 // In general, no Variable64On32 should be emited in textual asm output. It |
| 445 // turns out that some lowering sequences Fake-Def/Fake-Use such a variables. |
| 446 // If they end up being assigned an illegal offset we get a runtime error. We |
| 447 // liberally allow Variable64On32 to have illegal offsets because offsets |
| 448 // don't matter in FakeDefs/FakeUses. |
| 449 if (!llvm::isa<Variable64On32>(Var) && |
| 450 !isLegalVariableStackOffset(VarTy, Offset)) { |
| 429 llvm::report_fatal_error("Illegal stack offset"); | 451 llvm::report_fatal_error("Illegal stack offset"); |
| 430 } | 452 } |
| 431 const Type FrameSPTy = stackSlotType(); | 453 Str << "[" << getRegName(BaseRegNum, VarTy); |
| 432 Str << "[" << getRegName(BaseRegNum, FrameSPTy); | |
| 433 if (Offset != 0) { | 454 if (Offset != 0) { |
| 434 Str << ", " << getConstantPrefix() << Offset; | 455 Str << ", " << getConstantPrefix() << Offset; |
| 435 } | 456 } |
| 436 Str << "]"; | 457 Str << "]"; |
| 437 } | 458 } |
| 438 | 459 |
| 439 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { | 460 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { |
| 440 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 461 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
| 441 return false; | 462 return false; |
| 442 int32_t RegLo, RegHi; | 463 int32_t RegLo, RegHi; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 return; | 606 return; |
| 586 } | 607 } |
| 587 Type Ty = Arg->getType(); | 608 Type Ty = Arg->getType(); |
| 588 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); | 609 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); |
| 589 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); | 610 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); |
| 590 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 611 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 591 // If the argument variable has been assigned a register, we need to load the | 612 // If the argument variable has been assigned a register, we need to load the |
| 592 // value from the stack slot. | 613 // value from the stack slot. |
| 593 if (Arg->hasReg()) { | 614 if (Arg->hasReg()) { |
| 594 assert(Ty != IceType_i64); | 615 assert(Ty != IceType_i64); |
| 595 OperandARM32Mem *Mem = OperandARM32Mem::create( | 616 // This should be simple, just load the parameter off the stack using a nice |
| 617 // sp + imm addressing mode. Because ARM, we can't do that (e.g., VLDR, for |
| 618 // fp types, cannot have an index register), so we legalize the memory |
| 619 // operand instead. |
| 620 auto *Mem = OperandARM32Mem::create( |
| 596 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( | 621 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( |
| 597 Ctx->getConstantInt32(Arg->getStackOffset()))); | 622 Ctx->getConstantInt32(Arg->getStackOffset()))); |
| 598 if (isVectorType(Arg->getType())) { | 623 legalizeToReg(Mem, Arg->getRegNum()); |
| 599 // Use vld1.$elem or something? | |
| 600 UnimplementedError(Func->getContext()->getFlags()); | |
| 601 } else if (isFloatingType(Arg->getType())) { | |
| 602 _vldr(Arg, Mem); | |
| 603 } else { | |
| 604 _ldr(Arg, Mem); | |
| 605 } | |
| 606 // This argument-copying instruction uses an explicit OperandARM32Mem | 624 // This argument-copying instruction uses an explicit OperandARM32Mem |
| 607 // operand instead of a Variable, so its fill-from-stack operation has to | 625 // operand instead of a Variable, so its fill-from-stack operation has to |
| 608 // be tracked separately for statistics. | 626 // be tracked separately for statistics. |
| 609 Ctx->statsUpdateFills(); | 627 Ctx->statsUpdateFills(); |
| 610 } | 628 } |
| 611 } | 629 } |
| 612 | 630 |
| 613 Type TargetARM32::stackSlotType() { return IceType_i32; } | 631 Type TargetARM32::stackSlotType() { return IceType_i32; } |
| 614 | 632 |
| 615 void TargetARM32::addProlog(CfgNode *Node) { | 633 void TargetARM32::addProlog(CfgNode *Node) { |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 Variable *RetValue = nullptr; | 905 Variable *RetValue = nullptr; |
| 888 if (RI->getSrcSize()) | 906 if (RI->getSrcSize()) |
| 889 RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 907 RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
| 890 _bundle_lock(); | 908 _bundle_lock(); |
| 891 _bic(LR, LR, RetMask); | 909 _bic(LR, LR, RetMask); |
| 892 _ret(LR, RetValue); | 910 _ret(LR, RetValue); |
| 893 _bundle_unlock(); | 911 _bundle_unlock(); |
| 894 RI->setDeleted(); | 912 RI->setDeleted(); |
| 895 } | 913 } |
| 896 | 914 |
| 897 bool TargetARM32::isLegalVariableStackOffset(int32_t Offset) const { | 915 bool TargetARM32::isLegalVariableStackOffset(Type Ty, int32_t Offset) const { |
| 898 constexpr bool SignExt = false; | 916 constexpr bool SignExt = false; |
| 899 // TODO(jvoung): vldr of FP stack slots has a different limit from the plain | 917 return OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset); |
| 900 // stackSlotType(). | |
| 901 return OperandARM32Mem::canHoldOffset(stackSlotType(), SignExt, Offset); | |
| 902 } | 918 } |
| 903 | 919 |
| 904 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, | 920 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, |
| 921 int32_t StackAdjust, |
| 905 Variable *OrigBaseReg) { | 922 Variable *OrigBaseReg) { |
| 906 int32_t Offset = Var->getStackOffset(); | 923 int32_t Offset = Var->getStackOffset() + StackAdjust; |
| 907 // Legalize will likely need a movw/movt combination, but if the top bits are | 924 // Legalize will likely need a movw/movt combination, but if the top bits are |
| 908 // all 0 from negating the offset and subtracting, we could use that instead. | 925 // all 0 from negating the offset and subtracting, we could use that instead. |
| 909 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; | 926 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; |
| 910 if (ShouldSub) | 927 if (ShouldSub) |
| 911 Offset = -Offset; | 928 Offset = -Offset; |
| 912 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), | 929 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), |
| 913 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 930 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 914 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); | 931 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); |
| 915 if (ShouldSub) | 932 if (ShouldSub) |
| 916 _sub(ScratchReg, OrigBaseReg, OffsetVal); | 933 _sub(ScratchReg, OrigBaseReg, OffsetVal); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 930 // to: | 947 // to: |
| 931 // movw/movt TMP, OFF_PART | 948 // movw/movt TMP, OFF_PART |
| 932 // add TMP, TMP, SP | 949 // add TMP, TMP, SP |
| 933 // ldr X, OFF_MORE[TMP] | 950 // ldr X, OFF_MORE[TMP] |
| 934 // | 951 // |
| 935 // This is safe because we have reserved TMP, and add for ARM does not | 952 // This is safe because we have reserved TMP, and add for ARM does not |
| 936 // clobber the flags register. | 953 // clobber the flags register. |
| 937 Func->dump("Before legalizeStackSlots"); | 954 Func->dump("Before legalizeStackSlots"); |
| 938 assert(hasComputedFrame()); | 955 assert(hasComputedFrame()); |
| 939 // Early exit, if SpillAreaSizeBytes is really small. | 956 // Early exit, if SpillAreaSizeBytes is really small. |
| 940 if (isLegalVariableStackOffset(SpillAreaSizeBytes)) | 957 // TODO(jpp): this is not safe -- loads and stores of q registers can't have |
| 958 // offsets. |
| 959 if (isLegalVariableStackOffset(IceType_v4i32, SpillAreaSizeBytes)) |
| 941 return; | 960 return; |
| 942 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); | 961 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); |
| 943 int32_t StackAdjust = 0; | 962 int32_t StackAdjust = 0; |
| 944 // Do a fairly naive greedy clustering for now. Pick the first stack slot | 963 // Do a fairly naive greedy clustering for now. Pick the first stack slot |
| 945 // that's out of bounds and make a new base reg using the architecture's temp | 964 // that's out of bounds and make a new base reg using the architecture's temp |
| 946 // register. If that works for the next slot, then great. Otherwise, create a | 965 // register. If that works for the next slot, then great. Otherwise, create a |
| 947 // new base register, clobbering the previous base register. Never share a | 966 // new base register, clobbering the previous base register. Never share a |
| 948 // base reg across different basic blocks. This isn't ideal if local and | 967 // base reg across different basic blocks. This isn't ideal if local and |
| 949 // multi-block variables are far apart and their references are interspersed. | 968 // multi-block variables are far apart and their references are interspersed. |
| 950 // It may help to be more coordinated about assign stack slot numbers and may | 969 // It may help to be more coordinated about assign stack slot numbers and may |
| (...skipping 20 matching lines...) Expand all Loading... |
| 971 StackAdjust += AdjInst->getAmount(); | 990 StackAdjust += AdjInst->getAmount(); |
| 972 NewBaseOffset += AdjInst->getAmount(); | 991 NewBaseOffset += AdjInst->getAmount(); |
| 973 continue; | 992 continue; |
| 974 } | 993 } |
| 975 if (llvm::isa<InstARM32Call>(CurInstr)) { | 994 if (llvm::isa<InstARM32Call>(CurInstr)) { |
| 976 NewBaseOffset -= StackAdjust; | 995 NewBaseOffset -= StackAdjust; |
| 977 StackAdjust = 0; | 996 StackAdjust = 0; |
| 978 continue; | 997 continue; |
| 979 } | 998 } |
| 980 } | 999 } |
| 1000 |
| 981 // For now, only Mov instructions can have stack variables. We need to | 1001 // For now, only Mov instructions can have stack variables. We need to |
| 982 // know the type of instruction because we currently create a fresh one | 1002 // know the type of instruction because we currently create a fresh one |
| 983 // to replace Dest/Source, rather than mutate in place. | 1003 // to replace Dest/Source, rather than mutate in place. |
| 984 auto *MovInst = llvm::dyn_cast<InstARM32Mov>(CurInstr); | 1004 bool MayNeedOffsetRewrite = false; |
| 985 if (!MovInst) { | 1005 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { |
| 1006 MayNeedOffsetRewrite = |
| 1007 !MovInstr->isMultiDest() && !MovInstr->isMultiSource(); |
| 1008 } |
| 1009 |
| 1010 if (!MayNeedOffsetRewrite) { |
| 986 continue; | 1011 continue; |
| 987 } | 1012 } |
| 1013 |
| 1014 assert(Dest != nullptr); |
| 1015 Type DestTy = Dest->getType(); |
| 1016 assert(DestTy != IceType_i64); |
| 988 if (!Dest->hasReg()) { | 1017 if (!Dest->hasReg()) { |
| 989 int32_t Offset = Dest->getStackOffset(); | 1018 int32_t Offset = Dest->getStackOffset(); |
| 990 Offset += StackAdjust; | 1019 Offset += StackAdjust; |
| 991 if (!isLegalVariableStackOffset(Offset)) { | 1020 if (!isLegalVariableStackOffset(DestTy, Offset)) { |
| 992 if (NewBaseReg) { | 1021 if (NewBaseReg) { |
| 993 int32_t OffsetDiff = Offset - NewBaseOffset; | 1022 int32_t OffsetDiff = Offset - NewBaseOffset; |
| 994 if (isLegalVariableStackOffset(OffsetDiff)) { | 1023 if (isLegalVariableStackOffset(DestTy, OffsetDiff)) { |
| 995 StackVariable *NewDest = | 1024 StackVariable *NewDest = |
| 996 Func->makeVariable<StackVariable>(stackSlotType()); | 1025 Func->makeVariable<StackVariable>(stackSlotType()); |
| 997 NewDest->setMustNotHaveReg(); | 1026 NewDest->setMustNotHaveReg(); |
| 998 NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum()); | 1027 NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum()); |
| 999 NewDest->setStackOffset(OffsetDiff); | 1028 NewDest->setStackOffset(OffsetDiff); |
| 1000 Variable *NewDestVar = NewDest; | 1029 Variable *NewDestVar = NewDest; |
| 1001 _mov(NewDestVar, MovInst->getSrc(0)); | 1030 _mov(NewDestVar, CurInstr->getSrc(0)); |
| 1002 MovInst->setDeleted(); | 1031 CurInstr->setDeleted(); |
| 1003 continue; | 1032 continue; |
| 1004 } | 1033 } |
| 1005 } | 1034 } |
| 1006 StackVariable *LegalDest = legalizeVariableSlot(Dest, OrigBaseReg); | 1035 StackVariable *LegalDest = |
| 1036 legalizeVariableSlot(Dest, StackAdjust, OrigBaseReg); |
| 1007 assert(LegalDest != Dest); | 1037 assert(LegalDest != Dest); |
| 1008 Variable *LegalDestVar = LegalDest; | 1038 Variable *LegalDestVar = LegalDest; |
| 1009 _mov(LegalDestVar, MovInst->getSrc(0)); | 1039 _mov(LegalDestVar, CurInstr->getSrc(0)); |
| 1010 MovInst->setDeleted(); | 1040 CurInstr->setDeleted(); |
| 1011 NewBaseReg = LegalDest; | 1041 NewBaseReg = LegalDest; |
| 1012 NewBaseOffset = Offset; | 1042 NewBaseOffset = Offset; |
| 1013 continue; | 1043 continue; |
| 1014 } | 1044 } |
| 1015 } | 1045 } |
| 1016 assert(MovInst->getSrcSize() == 1); | 1046 assert(CurInstr->getSrcSize() == 1); |
| 1017 Variable *Var = llvm::dyn_cast<Variable>(MovInst->getSrc(0)); | 1047 Variable *Var = llvm::dyn_cast<Variable>(CurInstr->getSrc(0)); |
| 1018 if (Var && !Var->hasReg()) { | 1048 if (Var && !Var->hasReg()) { |
| 1049 Type VarTy = Var->getType(); |
| 1019 int32_t Offset = Var->getStackOffset(); | 1050 int32_t Offset = Var->getStackOffset(); |
| 1020 Offset += StackAdjust; | 1051 Offset += StackAdjust; |
| 1021 if (!isLegalVariableStackOffset(Offset)) { | 1052 if (!isLegalVariableStackOffset(VarTy, Offset)) { |
| 1022 if (NewBaseReg) { | 1053 if (NewBaseReg) { |
| 1023 int32_t OffsetDiff = Offset - NewBaseOffset; | 1054 int32_t OffsetDiff = Offset - NewBaseOffset; |
| 1024 if (isLegalVariableStackOffset(OffsetDiff)) { | 1055 if (isLegalVariableStackOffset(VarTy, OffsetDiff)) { |
| 1025 StackVariable *NewVar = | 1056 StackVariable *NewVar = |
| 1026 Func->makeVariable<StackVariable>(stackSlotType()); | 1057 Func->makeVariable<StackVariable>(stackSlotType()); |
| 1027 NewVar->setMustNotHaveReg(); | 1058 NewVar->setMustNotHaveReg(); |
| 1028 NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum()); | 1059 NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum()); |
| 1029 NewVar->setStackOffset(OffsetDiff); | 1060 NewVar->setStackOffset(OffsetDiff); |
| 1030 _mov(Dest, NewVar); | 1061 _mov(Dest, NewVar); |
| 1031 MovInst->setDeleted(); | 1062 CurInstr->setDeleted(); |
| 1032 continue; | 1063 continue; |
| 1033 } | 1064 } |
| 1034 } | 1065 } |
| 1035 StackVariable *LegalVar = legalizeVariableSlot(Var, OrigBaseReg); | 1066 StackVariable *LegalVar = |
| 1067 legalizeVariableSlot(Var, StackAdjust, OrigBaseReg); |
| 1036 assert(LegalVar != Var); | 1068 assert(LegalVar != Var); |
| 1037 _mov(Dest, LegalVar); | 1069 _mov(Dest, LegalVar); |
| 1038 MovInst->setDeleted(); | 1070 CurInstr->setDeleted(); |
| 1039 NewBaseReg = LegalVar; | 1071 NewBaseReg = LegalVar; |
| 1040 NewBaseOffset = Offset; | 1072 NewBaseOffset = Offset; |
| 1041 continue; | 1073 continue; |
| 1042 } | 1074 } |
| 1043 } | 1075 } |
| 1044 } | 1076 } |
| 1045 } | 1077 } |
| 1046 } | 1078 } |
| 1047 | 1079 |
| 1048 Operand *TargetARM32::loOperand(Operand *Operand) { | 1080 Operand *TargetARM32::loOperand(Operand *Operand) { |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1420 _mul(T_Acc, Src0RLo, Src1RHi); | 1452 _mul(T_Acc, Src0RLo, Src1RHi); |
| 1421 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); | 1453 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); |
| 1422 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); | 1454 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); |
| 1423 _add(T_Hi, T_Hi1, T_Acc1); | 1455 _add(T_Hi, T_Hi1, T_Acc1); |
| 1424 _mov(DestLo, T_Lo); | 1456 _mov(DestLo, T_Lo); |
| 1425 _mov(DestHi, T_Hi); | 1457 _mov(DestHi, T_Hi); |
| 1426 return; | 1458 return; |
| 1427 } | 1459 } |
| 1428 case InstArithmetic::Shl: { | 1460 case InstArithmetic::Shl: { |
| 1429 // a=b<<c ==> | 1461 // a=b<<c ==> |
| 1462 // pnacl-llc does: |
| 1463 // mov t_b.lo, b.lo |
| 1464 // mov t_b.hi, b.hi |
| 1465 // mov t_c.lo, c.lo |
| 1466 // rsb T0, t_c.lo, #32 |
| 1467 // lsr T1, t_b.lo, T0 |
| 1468 // orr t_a.hi, T1, t_b.hi, lsl t_c.lo |
| 1469 // sub T2, t_c.lo, #32 |
| 1470 // cmp T2, #0 |
| 1471 // lslge t_a.hi, t_b.lo, T2 |
| 1472 // lsl t_a.lo, t_b.lo, t_c.lo |
| 1473 // mov a.lo, t_a.lo |
| 1474 // mov a.hi, t_a.hi |
| 1475 // |
| 1430 // GCC 4.8 does: | 1476 // GCC 4.8 does: |
| 1431 // sub t_c1, c.lo, #32 | 1477 // sub t_c1, c.lo, #32 |
| 1432 // lsl t_hi, b.hi, c.lo | 1478 // lsl t_hi, b.hi, c.lo |
| 1433 // orr t_hi, t_hi, b.lo, lsl t_c1 | 1479 // orr t_hi, t_hi, b.lo, lsl t_c1 |
| 1434 // rsb t_c2, c.lo, #32 | 1480 // rsb t_c2, c.lo, #32 |
| 1435 // orr t_hi, t_hi, b.lo, lsr t_c2 | 1481 // orr t_hi, t_hi, b.lo, lsr t_c2 |
| 1436 // lsl t_lo, b.lo, c.lo | 1482 // lsl t_lo, b.lo, c.lo |
| 1437 // a.lo = t_lo | 1483 // a.lo = t_lo |
| 1438 // a.hi = t_hi | 1484 // a.hi = t_hi |
| 1485 // |
| 1486 // These are incompatible, therefore we mimic pnacl-llc. |
| 1439 // Can be strength-reduced for constant-shifts, but we don't do that for | 1487 // Can be strength-reduced for constant-shifts, but we don't do that for |
| 1440 // now. | 1488 // now. |
| 1441 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. On | 1489 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. On |
| 1442 // ARM, shifts only take the lower 8 bits of the shift register, and | 1490 // ARM, shifts only take the lower 8 bits of the shift register, and |
| 1443 // saturate to the range 0-32, so the negative value will saturate to 32. | 1491 // saturate to the range 0-32, so the negative value will saturate to 32. |
| 1444 Variable *T_Hi = makeReg(IceType_i32); | 1492 Constant *_32 = Ctx->getConstantInt32(32); |
| 1493 Constant *_0 = Ctx->getConstantZero(IceType_i32); |
| 1445 Variable *Src1RLo = legalizeToReg(Src1Lo); | 1494 Variable *Src1RLo = legalizeToReg(Src1Lo); |
| 1446 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | 1495 Variable *T0 = makeReg(IceType_i32); |
| 1447 Variable *T_C1 = makeReg(IceType_i32); | 1496 Variable *T1 = makeReg(IceType_i32); |
| 1448 Variable *T_C2 = makeReg(IceType_i32); | 1497 Variable *T2 = makeReg(IceType_i32); |
| 1449 _sub(T_C1, Src1RLo, ThirtyTwo); | 1498 Variable *TA_Hi = makeReg(IceType_i32); |
| 1450 _lsl(T_Hi, Src0RHi, Src1RLo); | 1499 Variable *TA_Lo = makeReg(IceType_i32); |
| 1451 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1500 _rsb(T0, Src1RLo, _32); |
| 1452 OperandARM32::LSL, T_C1)); | 1501 _lsr(T1, Src0RLo, T0); |
| 1453 _rsb(T_C2, Src1RLo, ThirtyTwo); | 1502 _orr(TA_Hi, T1, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, |
| 1454 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1503 OperandARM32::LSL, Src1RLo)); |
| 1455 OperandARM32::LSR, T_C2)); | 1504 _sub(T2, Src1RLo, _32); |
| 1456 _mov(DestHi, T_Hi); | 1505 _cmp(T2, _0); |
| 1457 Variable *T_Lo = makeReg(IceType_i32); | 1506 _lsl(TA_Hi, Src0RLo, T2, CondARM32::GE); |
| 1458 // _mov seems to sometimes have better register preferencing than lsl. | 1507 _set_dest_nonkillable(); |
| 1459 // Otherwise mov w/ lsl shifted register is a pseudo-instruction that | 1508 _lsl(TA_Lo, Src0RLo, Src1RLo); |
| 1460 // maps to lsl. | 1509 _mov(DestLo, TA_Lo); |
| 1461 _mov(T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1510 _mov(DestHi, TA_Hi); |
| 1462 OperandARM32::LSL, Src1RLo)); | |
| 1463 _mov(DestLo, T_Lo); | |
| 1464 return; | 1511 return; |
| 1465 } | 1512 } |
| 1466 case InstArithmetic::Lshr: | 1513 case InstArithmetic::Lshr: |
| 1467 // a=b>>c (unsigned) ==> | |
| 1468 // GCC 4.8 does: | |
| 1469 // rsb t_c1, c.lo, #32 | |
| 1470 // lsr t_lo, b.lo, c.lo | |
| 1471 // orr t_lo, t_lo, b.hi, lsl t_c1 | |
| 1472 // sub t_c2, c.lo, #32 | |
| 1473 // orr t_lo, t_lo, b.hi, lsr t_c2 | |
| 1474 // lsr t_hi, b.hi, c.lo | |
| 1475 // a.lo = t_lo | |
| 1476 // a.hi = t_hi | |
| 1477 case InstArithmetic::Ashr: { | 1514 case InstArithmetic::Ashr: { |
| 1478 // a=b>>c (signed) ==> ... | 1515 // a=b>>c |
| 1479 // Ashr is similar, but the sub t_c2, c.lo, #32 should set flags, and the | 1516 // pnacl-llc does: |
| 1480 // next orr should be conditioned on PLUS. The last two right shifts | 1517 // mov t_b.lo, b.lo |
| 1481 // should also be arithmetic. | 1518 // mov t_b.hi, b.hi |
| 1482 bool IsAshr = Inst->getOp() == InstArithmetic::Ashr; | 1519 // mov t_c.lo, c.lo |
| 1483 Variable *T_Lo = makeReg(IceType_i32); | 1520 // lsr T0, t_b.lo, t_c.lo |
| 1521 // rsb T1, t_c.lo, #32 |
| 1522 // orr t_a.lo, T0, t_b.hi, lsl T1 |
| 1523 // sub T2, t_c.lo, #32 |
| 1524 // cmp T2, #0 |
| 1525 // [al]srge t_a.lo, t_b.hi, T2 |
| 1526 // [al]sr t_a.hi, t_b.hi, t_c.lo |
| 1527 // mov a.lo, t_a.lo |
| 1528 // mov a.hi, t_a.hi |
| 1529 // |
| 1530 // GCC 4.8 does (lsr): |
| 1531 // rsb t_c1, c.lo, #32 |
| 1532 // lsr t_lo, b.lo, c.lo |
| 1533 // orr t_lo, t_lo, b.hi, lsl t_c1 |
| 1534 // sub t_c2, c.lo, #32 |
| 1535 // orr t_lo, t_lo, b.hi, lsr t_c2 |
| 1536 // lsr t_hi, b.hi, c.lo |
| 1537 // mov a.lo, t_lo |
| 1538 // mov a.hi, t_hi |
| 1539 // |
| 1540 // These are incompatible, therefore we mimic pnacl-llc. |
| 1541 const bool IsAshr = Inst->getOp() == InstArithmetic::Ashr; |
| 1542 Constant *_32 = Ctx->getConstantInt32(32); |
| 1543 Constant *_0 = Ctx->getConstantZero(IceType_i32); |
| 1484 Variable *Src1RLo = legalizeToReg(Src1Lo); | 1544 Variable *Src1RLo = legalizeToReg(Src1Lo); |
| 1485 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | 1545 Variable *T0 = makeReg(IceType_i32); |
| 1486 Variable *T_C1 = makeReg(IceType_i32); | 1546 Variable *T1 = makeReg(IceType_i32); |
| 1487 Variable *T_C2 = makeReg(IceType_i32); | 1547 Variable *T2 = makeReg(IceType_i32); |
| 1488 _rsb(T_C1, Src1RLo, ThirtyTwo); | 1548 Variable *TA_Lo = makeReg(IceType_i32); |
| 1489 _lsr(T_Lo, Src0RLo, Src1RLo); | 1549 Variable *TA_Hi = makeReg(IceType_i32); |
| 1490 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | 1550 _lsr(T0, Src0RLo, Src1RLo); |
| 1491 OperandARM32::LSL, T_C1)); | 1551 _rsb(T1, Src1RLo, _32); |
| 1492 OperandARM32::ShiftKind RShiftKind; | 1552 _orr(TA_Lo, T0, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, |
| 1493 CondARM32::Cond Pred; | 1553 OperandARM32::LSL, T1)); |
| 1554 _sub(T2, Src1RLo, _32); |
| 1555 _cmp(T2, _0); |
| 1494 if (IsAshr) { | 1556 if (IsAshr) { |
| 1495 _subs(T_C2, Src1RLo, ThirtyTwo); | 1557 _asr(TA_Lo, Src0RHi, T2, CondARM32::GE); |
| 1496 RShiftKind = OperandARM32::ASR; | 1558 _set_dest_nonkillable(); |
| 1497 Pred = CondARM32::PL; | 1559 _asr(TA_Hi, Src0RHi, Src1RLo); |
| 1498 } else { | 1560 } else { |
| 1499 _sub(T_C2, Src1RLo, ThirtyTwo); | 1561 _lsr(TA_Lo, Src0RHi, T2, CondARM32::GE); |
| 1500 RShiftKind = OperandARM32::LSR; | 1562 _set_dest_nonkillable(); |
| 1501 Pred = CondARM32::AL; | 1563 _lsr(TA_Hi, Src0RHi, Src1RLo); |
| 1502 } | 1564 } |
| 1503 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | 1565 _mov(DestLo, TA_Lo); |
| 1504 RShiftKind, T_C2), | 1566 _mov(DestHi, TA_Hi); |
| 1505 Pred); | |
| 1506 _mov(DestLo, T_Lo); | |
| 1507 Variable *T_Hi = makeReg(IceType_i32); | |
| 1508 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | |
| 1509 RShiftKind, Src1RLo)); | |
| 1510 _mov(DestHi, T_Hi); | |
| 1511 return; | 1567 return; |
| 1512 } | 1568 } |
| 1513 case InstArithmetic::Fadd: | 1569 case InstArithmetic::Fadd: |
| 1514 case InstArithmetic::Fsub: | 1570 case InstArithmetic::Fsub: |
| 1515 case InstArithmetic::Fmul: | 1571 case InstArithmetic::Fmul: |
| 1516 case InstArithmetic::Fdiv: | 1572 case InstArithmetic::Fdiv: |
| 1517 case InstArithmetic::Frem: | 1573 case InstArithmetic::Frem: |
| 1518 llvm_unreachable("FP instruction with i64 type"); | 1574 llvm_unreachable("FP instruction with i64 type"); |
| 1519 return; | 1575 return; |
| 1520 case InstArithmetic::Udiv: | 1576 case InstArithmetic::Udiv: |
| 1521 case InstArithmetic::Sdiv: | 1577 case InstArithmetic::Sdiv: |
| 1522 case InstArithmetic::Urem: | 1578 case InstArithmetic::Urem: |
| 1523 case InstArithmetic::Srem: | 1579 case InstArithmetic::Srem: |
| 1524 llvm_unreachable("Call-helper-involved instruction for i64 type " | 1580 llvm_unreachable("Call-helper-involved instruction for i64 type " |
| 1525 "should have already been handled before"); | 1581 "should have already been handled before"); |
| 1526 return; | 1582 return; |
| 1527 } | 1583 } |
| 1528 return; | 1584 return; |
| 1529 } else if (isVectorType(Dest->getType())) { | 1585 } else if (isVectorType(Dest->getType())) { |
| 1586 // Add a fake def to keep liveness consistent in the meantime. |
| 1587 Variable *T = makeReg(Dest->getType()); |
| 1588 Context.insert(InstFakeDef::create(Func, T)); |
| 1589 _mov(Dest, T); |
| 1530 UnimplementedError(Func->getContext()->getFlags()); | 1590 UnimplementedError(Func->getContext()->getFlags()); |
| 1531 // Add a fake def to keep liveness consistent in the meantime. | |
| 1532 Context.insert(InstFakeDef::create(Func, Dest)); | |
| 1533 return; | 1591 return; |
| 1534 } | 1592 } |
| 1535 // Dest->getType() is a non-i64 scalar. | 1593 // Dest->getType() is a non-i64 scalar. |
| 1536 Variable *Src0R = legalizeToReg(Src0); | 1594 Variable *Src0R = legalizeToReg(Src0); |
| 1537 Variable *T = makeReg(Dest->getType()); | 1595 Variable *T = makeReg(Dest->getType()); |
| 1538 // Handle div/rem separately. They require a non-legalized Src1 to inspect | 1596 // Handle div/rem separately. They require a non-legalized Src1 to inspect |
| 1539 // whether or not Src1 is a non-zero constant. Once legalized it is more | 1597 // whether or not Src1 is a non-zero constant. Once legalized it is more |
| 1540 // difficult to determine (constant may be moved to a register). | 1598 // difficult to determine (constant may be moved to a register). |
| 1541 switch (Inst->getOp()) { | 1599 switch (Inst->getOp()) { |
| 1542 default: | 1600 default: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1578 } | 1636 } |
| 1579 | 1637 |
| 1580 // Handle floating point arithmetic separately: they require Src1 to be | 1638 // Handle floating point arithmetic separately: they require Src1 to be |
| 1581 // legalized to a register. | 1639 // legalized to a register. |
| 1582 switch (Inst->getOp()) { | 1640 switch (Inst->getOp()) { |
| 1583 default: | 1641 default: |
| 1584 break; | 1642 break; |
| 1585 case InstArithmetic::Fadd: { | 1643 case InstArithmetic::Fadd: { |
| 1586 Variable *Src1R = legalizeToReg(Src1); | 1644 Variable *Src1R = legalizeToReg(Src1); |
| 1587 _vadd(T, Src0R, Src1R); | 1645 _vadd(T, Src0R, Src1R); |
| 1588 _vmov(Dest, T); | 1646 _mov(Dest, T); |
| 1589 return; | 1647 return; |
| 1590 } | 1648 } |
| 1591 case InstArithmetic::Fsub: { | 1649 case InstArithmetic::Fsub: { |
| 1592 Variable *Src1R = legalizeToReg(Src1); | 1650 Variable *Src1R = legalizeToReg(Src1); |
| 1593 _vsub(T, Src0R, Src1R); | 1651 _vsub(T, Src0R, Src1R); |
| 1594 _vmov(Dest, T); | 1652 _mov(Dest, T); |
| 1595 return; | 1653 return; |
| 1596 } | 1654 } |
| 1597 case InstArithmetic::Fmul: { | 1655 case InstArithmetic::Fmul: { |
| 1598 Variable *Src1R = legalizeToReg(Src1); | 1656 Variable *Src1R = legalizeToReg(Src1); |
| 1599 _vmul(T, Src0R, Src1R); | 1657 _vmul(T, Src0R, Src1R); |
| 1600 _vmov(Dest, T); | 1658 _mov(Dest, T); |
| 1601 return; | 1659 return; |
| 1602 } | 1660 } |
| 1603 case InstArithmetic::Fdiv: { | 1661 case InstArithmetic::Fdiv: { |
| 1604 Variable *Src1R = legalizeToReg(Src1); | 1662 Variable *Src1R = legalizeToReg(Src1); |
| 1605 _vdiv(T, Src0R, Src1R); | 1663 _vdiv(T, Src0R, Src1R); |
| 1606 _vmov(Dest, T); | 1664 _mov(Dest, T); |
| 1607 return; | 1665 return; |
| 1608 } | 1666 } |
| 1609 } | 1667 } |
| 1610 | 1668 |
| 1611 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); | 1669 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); |
| 1612 switch (Inst->getOp()) { | 1670 switch (Inst->getOp()) { |
| 1613 case InstArithmetic::_num: | 1671 case InstArithmetic::_num: |
| 1614 llvm_unreachable("Unknown arithmetic operator"); | 1672 llvm_unreachable("Unknown arithmetic operator"); |
| 1615 return; | 1673 return; |
| 1616 case InstArithmetic::Add: | 1674 case InstArithmetic::Add: |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1670 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 1728 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
| 1671 Variable *Dest = Inst->getDest(); | 1729 Variable *Dest = Inst->getDest(); |
| 1672 Operand *Src0 = Inst->getSrc(0); | 1730 Operand *Src0 = Inst->getSrc(0); |
| 1673 assert(Dest->getType() == Src0->getType()); | 1731 assert(Dest->getType() == Src0->getType()); |
| 1674 if (Dest->getType() == IceType_i64) { | 1732 if (Dest->getType() == IceType_i64) { |
| 1675 Src0 = legalizeUndef(Src0); | 1733 Src0 = legalizeUndef(Src0); |
| 1676 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); | 1734 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); |
| 1677 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex); | 1735 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex); |
| 1678 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1736 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1679 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1737 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1680 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 1738 Variable *T_Lo = makeReg(IceType_i32); |
| 1739 Variable *T_Hi = makeReg(IceType_i32); |
| 1681 _mov(T_Lo, Src0Lo); | 1740 _mov(T_Lo, Src0Lo); |
| 1682 _mov(DestLo, T_Lo); | 1741 _mov(DestLo, T_Lo); |
| 1683 _mov(T_Hi, Src0Hi); | 1742 _mov(T_Hi, Src0Hi); |
| 1684 _mov(DestHi, T_Hi); | 1743 _mov(DestHi, T_Hi); |
| 1685 } else { | 1744 } else { |
| 1686 Operand *NewSrc; | 1745 Operand *NewSrc; |
| 1687 if (Dest->hasReg()) { | 1746 if (Dest->hasReg()) { |
| 1688 // If Dest already has a physical register, then legalize the Src operand | 1747 // If Dest already has a physical register, then legalize the Src operand |
| 1689 // into a Variable with the same register assignment. This especially | 1748 // into a Variable with the same register assignment. This especially |
| 1690 // helps allow the use of Flex operands. | 1749 // helps allow the use of Flex operands. |
| 1691 NewSrc = legalize(Src0, Legal_Reg | Legal_Flex, Dest->getRegNum()); | 1750 NewSrc = legalize(Src0, Legal_Reg | Legal_Flex, Dest->getRegNum()); |
| 1692 } else { | 1751 } else { |
| 1693 // Dest could be a stack operand. Since we could potentially need to do a | 1752 // Dest could be a stack operand. Since we could potentially need to do a |
| 1694 // Store (and store can only have Register operands), legalize this to a | 1753 // Store (and store can only have Register operands), legalize this to a |
| 1695 // register. | 1754 // register. |
| 1696 NewSrc = legalize(Src0, Legal_Reg); | 1755 NewSrc = legalize(Src0, Legal_Reg); |
| 1697 } | 1756 } |
| 1698 if (isVectorType(Dest->getType())) { | 1757 if (isVectorType(Dest->getType())) { |
| 1699 UnimplementedError(Func->getContext()->getFlags()); | 1758 Variable *SrcR = legalizeToReg(NewSrc); |
| 1759 _mov(Dest, SrcR); |
| 1700 } else if (isFloatingType(Dest->getType())) { | 1760 } else if (isFloatingType(Dest->getType())) { |
| 1701 Variable *SrcR = legalizeToReg(NewSrc); | 1761 Variable *SrcR = legalizeToReg(NewSrc); |
| 1702 _vmov(Dest, SrcR); | 1762 _mov(Dest, SrcR); |
| 1703 } else { | 1763 } else { |
| 1704 _mov(Dest, NewSrc); | 1764 _mov(Dest, NewSrc); |
| 1705 } | 1765 } |
| 1706 } | 1766 } |
| 1707 } | 1767 } |
| 1708 | 1768 |
| 1709 void TargetARM32::lowerBr(const InstBr *Inst) { | 1769 void TargetARM32::lowerBr(const InstBr *Inst) { |
| 1710 if (Inst->isUnconditional()) { | 1770 if (Inst->isUnconditional()) { |
| 1711 _br(Inst->getTargetUnconditional()); | 1771 _br(Inst->getTargetUnconditional()); |
| 1712 return; | 1772 return; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1762 if (CC.I32InReg(&Reg)) { | 1822 if (CC.I32InReg(&Reg)) { |
| 1763 InRegs = true; | 1823 InRegs = true; |
| 1764 GPRArgs.push_back(std::make_pair(Arg, Reg)); | 1824 GPRArgs.push_back(std::make_pair(Arg, Reg)); |
| 1765 } | 1825 } |
| 1766 } | 1826 } |
| 1767 | 1827 |
| 1768 if (!InRegs) { | 1828 if (!InRegs) { |
| 1769 ParameterAreaSizeBytes = | 1829 ParameterAreaSizeBytes = |
| 1770 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | 1830 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); |
| 1771 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | 1831 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); |
| 1772 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); | 1832 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); |
| 1773 } | 1833 } |
| 1774 } | 1834 } |
| 1775 | 1835 |
| 1776 // Adjust the parameter area so that the stack is aligned. It is assumed that | 1836 // Adjust the parameter area so that the stack is aligned. It is assumed that |
| 1777 // the stack is already aligned at the start of the calling sequence. | 1837 // the stack is already aligned at the start of the calling sequence. |
| 1778 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | 1838 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); |
| 1779 | 1839 |
| 1780 // Subtract the appropriate amount for the argument area. This also takes | 1840 // Subtract the appropriate amount for the argument area. This also takes |
| 1781 // care of setting the stack adjustment during emission. | 1841 // care of setting the stack adjustment during emission. |
| 1782 // | 1842 // |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1802 Addr = OperandARM32Mem::create(Func, Ty, SP, Loc); | 1862 Addr = OperandARM32Mem::create(Func, Ty, SP, Loc); |
| 1803 } else { | 1863 } else { |
| 1804 Variable *NewBase = Func->makeVariable(SP->getType()); | 1864 Variable *NewBase = Func->makeVariable(SP->getType()); |
| 1805 lowerArithmetic( | 1865 lowerArithmetic( |
| 1806 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); | 1866 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); |
| 1807 Addr = formMemoryOperand(NewBase, Ty); | 1867 Addr = formMemoryOperand(NewBase, Ty); |
| 1808 } | 1868 } |
| 1809 lowerStore(InstStore::create(Func, StackArg.first, Addr)); | 1869 lowerStore(InstStore::create(Func, StackArg.first, Addr)); |
| 1810 } | 1870 } |
| 1811 | 1871 |
| 1812 // Copy arguments to be passed in registers to the appropriate registers. | |
| 1813 for (auto &GPRArg : GPRArgs) { | |
| 1814 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); | |
| 1815 // Generate a FakeUse of register arguments so that they do not get dead | |
| 1816 // code eliminated as a result of the FakeKill of scratch registers after | |
| 1817 // the call. | |
| 1818 Context.insert(InstFakeUse::create(Func, Reg)); | |
| 1819 } | |
| 1820 for (auto &FPArg : FPArgs) { | |
| 1821 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); | |
| 1822 Context.insert(InstFakeUse::create(Func, Reg)); | |
| 1823 } | |
| 1824 | |
| 1825 // Generate the call instruction. Assign its result to a temporary with high | 1872 // Generate the call instruction. Assign its result to a temporary with high |
| 1826 // register allocation weight. | 1873 // register allocation weight. |
| 1827 Variable *Dest = Instr->getDest(); | 1874 Variable *Dest = Instr->getDest(); |
| 1828 // ReturnReg doubles as ReturnRegLo as necessary. | 1875 // ReturnReg doubles as ReturnRegLo as necessary. |
| 1829 Variable *ReturnReg = nullptr; | 1876 Variable *ReturnReg = nullptr; |
| 1830 Variable *ReturnRegHi = nullptr; | 1877 Variable *ReturnRegHi = nullptr; |
| 1831 if (Dest) { | 1878 if (Dest) { |
| 1832 switch (Dest->getType()) { | 1879 switch (Dest->getType()) { |
| 1833 case IceType_NUM: | 1880 case IceType_NUM: |
| 1834 llvm_unreachable("Invalid Call dest type"); | 1881 llvm_unreachable("Invalid Call dest type"); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1865 Operand *CallTarget = Instr->getCallTarget(); | 1912 Operand *CallTarget = Instr->getCallTarget(); |
| 1866 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = | 1913 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = |
| 1867 // Ctx->getFlags().getUseSandboxing(); | 1914 // Ctx->getFlags().getUseSandboxing(); |
| 1868 | 1915 |
| 1869 // Allow ConstantRelocatable to be left alone as a direct call, but force | 1916 // Allow ConstantRelocatable to be left alone as a direct call, but force |
| 1870 // other constants like ConstantInteger32 to be in a register and make it an | 1917 // other constants like ConstantInteger32 to be in a register and make it an |
| 1871 // indirect call. | 1918 // indirect call. |
| 1872 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 1919 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| 1873 CallTarget = legalize(CallTarget, Legal_Reg); | 1920 CallTarget = legalize(CallTarget, Legal_Reg); |
| 1874 } | 1921 } |
| 1922 |
| 1923 // Copy arguments to be passed in registers to the appropriate registers. |
| 1924 for (auto &FPArg : FPArgs) { |
| 1925 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); |
| 1926 Context.insert(InstFakeUse::create(Func, Reg)); |
| 1927 } |
| 1928 for (auto &GPRArg : GPRArgs) { |
| 1929 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); |
| 1930 // Generate a FakeUse of register arguments so that they do not get dead |
| 1931 // code eliminated as a result of the FakeKill of scratch registers after |
| 1932 // the call. |
| 1933 Context.insert(InstFakeUse::create(Func, Reg)); |
| 1934 } |
| 1875 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); | 1935 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); |
| 1876 Context.insert(NewCall); | 1936 Context.insert(NewCall); |
| 1877 if (ReturnRegHi) | 1937 if (ReturnRegHi) |
| 1878 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 1938 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
| 1879 | 1939 |
| 1880 // Add the appropriate offset to SP. The call instruction takes care of | 1940 // Add the appropriate offset to SP. The call instruction takes care of |
| 1881 // resetting the stack offset during emission. | 1941 // resetting the stack offset during emission. |
| 1882 if (ParameterAreaSizeBytes) { | 1942 if (ParameterAreaSizeBytes) { |
| 1883 Operand *AddAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes), | 1943 Operand *AddAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes), |
| 1884 Legal_Reg | Legal_Flex); | 1944 Legal_Reg | Legal_Flex); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1901 // Assign the result of the call to Dest. | 1961 // Assign the result of the call to Dest. |
| 1902 if (ReturnReg) { | 1962 if (ReturnReg) { |
| 1903 if (ReturnRegHi) { | 1963 if (ReturnRegHi) { |
| 1904 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 1964 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 1905 Variable *DestLo = Dest64On32->getLo(); | 1965 Variable *DestLo = Dest64On32->getLo(); |
| 1906 Variable *DestHi = Dest64On32->getHi(); | 1966 Variable *DestHi = Dest64On32->getHi(); |
| 1907 _mov(DestLo, ReturnReg); | 1967 _mov(DestLo, ReturnReg); |
| 1908 _mov(DestHi, ReturnRegHi); | 1968 _mov(DestHi, ReturnRegHi); |
| 1909 } else { | 1969 } else { |
| 1910 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | 1970 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { |
| 1911 _vmov(Dest, ReturnReg); | 1971 _mov(Dest, ReturnReg); |
| 1912 } else { | 1972 } else { |
| 1913 assert(isIntegerType(Dest->getType()) && | 1973 assert(isIntegerType(Dest->getType()) && |
| 1914 typeWidthInBytes(Dest->getType()) <= 4); | 1974 typeWidthInBytes(Dest->getType()) <= 4); |
| 1915 _mov(Dest, ReturnReg); | 1975 _mov(Dest, ReturnReg); |
| 1916 } | 1976 } |
| 1917 } | 1977 } |
| 1918 } | 1978 } |
| 1919 } | 1979 } |
| 1920 | 1980 |
| 1981 namespace { |
| 1982 void forceHiLoInReg(Variable64On32 *Var) { |
| 1983 Var->getHi()->setMustHaveReg(); |
| 1984 Var->getLo()->setMustHaveReg(); |
| 1985 } |
| 1986 } // end of anonymous namespace |
| 1987 |
| 1921 void TargetARM32::lowerCast(const InstCast *Inst) { | 1988 void TargetARM32::lowerCast(const InstCast *Inst) { |
| 1922 InstCast::OpKind CastKind = Inst->getCastKind(); | 1989 InstCast::OpKind CastKind = Inst->getCastKind(); |
| 1923 Variable *Dest = Inst->getDest(); | 1990 Variable *Dest = Inst->getDest(); |
| 1924 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 1991 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 1925 switch (CastKind) { | 1992 switch (CastKind) { |
| 1926 default: | 1993 default: |
| 1927 Func->setError("Cast type not supported"); | 1994 Func->setError("Cast type not supported"); |
| 1928 return; | 1995 return; |
| 1929 case InstCast::Sext: { | 1996 case InstCast::Sext: { |
| 1930 if (isVectorType(Dest->getType())) { | 1997 if (isVectorType(Dest->getType())) { |
| 1998 Variable *T = makeReg(Dest->getType()); |
| 1999 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2000 _mov(Dest, T); |
| 1931 UnimplementedError(Func->getContext()->getFlags()); | 2001 UnimplementedError(Func->getContext()->getFlags()); |
| 1932 } else if (Dest->getType() == IceType_i64) { | 2002 } else if (Dest->getType() == IceType_i64) { |
| 1933 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 | 2003 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 |
| 1934 Constant *ShiftAmt = Ctx->getConstantInt32(31); | 2004 Constant *ShiftAmt = Ctx->getConstantInt32(31); |
| 1935 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2005 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1936 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2006 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1937 Variable *T_Lo = makeReg(DestLo->getType()); | 2007 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1938 if (Src0->getType() == IceType_i32) { | 2008 if (Src0->getType() == IceType_i32) { |
| 1939 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 2009 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 1940 _mov(T_Lo, Src0RF); | 2010 _mov(T_Lo, Src0RF); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1971 // t1 = sxt src; dst = t1 | 2041 // t1 = sxt src; dst = t1 |
| 1972 Variable *Src0R = legalizeToReg(Src0); | 2042 Variable *Src0R = legalizeToReg(Src0); |
| 1973 Variable *T = makeReg(Dest->getType()); | 2043 Variable *T = makeReg(Dest->getType()); |
| 1974 _sxt(T, Src0R); | 2044 _sxt(T, Src0R); |
| 1975 _mov(Dest, T); | 2045 _mov(Dest, T); |
| 1976 } | 2046 } |
| 1977 break; | 2047 break; |
| 1978 } | 2048 } |
| 1979 case InstCast::Zext: { | 2049 case InstCast::Zext: { |
| 1980 if (isVectorType(Dest->getType())) { | 2050 if (isVectorType(Dest->getType())) { |
| 2051 Variable *T = makeReg(Dest->getType()); |
| 2052 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2053 _mov(Dest, T); |
| 1981 UnimplementedError(Func->getContext()->getFlags()); | 2054 UnimplementedError(Func->getContext()->getFlags()); |
| 1982 } else if (Dest->getType() == IceType_i64) { | 2055 } else if (Dest->getType() == IceType_i64) { |
| 1983 // t1=uxtb src; dst.lo=t1; dst.hi=0 | 2056 // t1=uxtb src; dst.lo=t1; dst.hi=0 |
| 1984 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 2057 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 1985 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2058 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1986 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2059 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1987 Variable *T_Lo = makeReg(DestLo->getType()); | 2060 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1988 // i32 and i1 can just take up the whole register. i32 doesn't need uxt, | 2061 // i32 and i1 can just take up the whole register. i32 doesn't need uxt, |
| 1989 // while i1 will have an and mask later anyway. | 2062 // while i1 will have an and mask later anyway. |
| 1990 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) { | 2063 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2017 // t1 = uxt src; dst = t1 | 2090 // t1 = uxt src; dst = t1 |
| 2018 Variable *Src0R = legalizeToReg(Src0); | 2091 Variable *Src0R = legalizeToReg(Src0); |
| 2019 Variable *T = makeReg(Dest->getType()); | 2092 Variable *T = makeReg(Dest->getType()); |
| 2020 _uxt(T, Src0R); | 2093 _uxt(T, Src0R); |
| 2021 _mov(Dest, T); | 2094 _mov(Dest, T); |
| 2022 } | 2095 } |
| 2023 break; | 2096 break; |
| 2024 } | 2097 } |
| 2025 case InstCast::Trunc: { | 2098 case InstCast::Trunc: { |
| 2026 if (isVectorType(Dest->getType())) { | 2099 if (isVectorType(Dest->getType())) { |
| 2100 Variable *T = makeReg(Dest->getType()); |
| 2101 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2102 _mov(Dest, T); |
| 2027 UnimplementedError(Func->getContext()->getFlags()); | 2103 UnimplementedError(Func->getContext()->getFlags()); |
| 2028 } else { | 2104 } else { |
| 2029 if (Src0->getType() == IceType_i64) | 2105 if (Src0->getType() == IceType_i64) |
| 2030 Src0 = loOperand(Src0); | 2106 Src0 = loOperand(Src0); |
| 2031 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 2107 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 2032 // t1 = trunc Src0RF; Dest = t1 | 2108 // t1 = trunc Src0RF; Dest = t1 |
| 2033 Variable *T = makeReg(Dest->getType()); | 2109 Variable *T = makeReg(Dest->getType()); |
| 2034 _mov(T, Src0RF); | 2110 _mov(T, Src0RF); |
| 2035 if (Dest->getType() == IceType_i1) | 2111 if (Dest->getType() == IceType_i1) |
| 2036 _and(T, T, Ctx->getConstantInt1(1)); | 2112 _and(T, T, Ctx->getConstantInt1(1)); |
| 2037 _mov(Dest, T); | 2113 _mov(Dest, T); |
| 2038 } | 2114 } |
| 2039 break; | 2115 break; |
| 2040 } | 2116 } |
| 2041 case InstCast::Fptrunc: | 2117 case InstCast::Fptrunc: |
| 2042 case InstCast::Fpext: { | 2118 case InstCast::Fpext: { |
| 2043 // fptrunc: dest.f32 = fptrunc src0.fp64 | 2119 // fptrunc: dest.f32 = fptrunc src0.fp64 |
| 2044 // fpext: dest.f64 = fptrunc src0.fp32 | 2120 // fpext: dest.f64 = fptrunc src0.fp32 |
| 2045 const bool IsTrunc = CastKind == InstCast::Fptrunc; | 2121 const bool IsTrunc = CastKind == InstCast::Fptrunc; |
| 2046 if (isVectorType(Dest->getType())) { | 2122 if (isVectorType(Dest->getType())) { |
| 2123 Variable *T = makeReg(Dest->getType()); |
| 2124 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2125 _mov(Dest, T); |
| 2047 UnimplementedError(Func->getContext()->getFlags()); | 2126 UnimplementedError(Func->getContext()->getFlags()); |
| 2048 break; | 2127 break; |
| 2049 } | 2128 } |
| 2050 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); | 2129 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); |
| 2051 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); | 2130 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); |
| 2052 Variable *Src0R = legalizeToReg(Src0); | 2131 Variable *Src0R = legalizeToReg(Src0); |
| 2053 Variable *T = makeReg(Dest->getType()); | 2132 Variable *T = makeReg(Dest->getType()); |
| 2054 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); | 2133 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); |
| 2055 _mov(Dest, T); | 2134 _mov(Dest, T); |
| 2056 break; | 2135 break; |
| 2057 } | 2136 } |
| 2058 case InstCast::Fptosi: | 2137 case InstCast::Fptosi: |
| 2059 case InstCast::Fptoui: { | 2138 case InstCast::Fptoui: { |
| 2139 if (isVectorType(Dest->getType())) { |
| 2140 Variable *T = makeReg(Dest->getType()); |
| 2141 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2142 _mov(Dest, T); |
| 2143 UnimplementedError(Func->getContext()->getFlags()); |
| 2144 break; |
| 2145 } |
| 2146 |
| 2147 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
| 2148 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); |
| 2149 if (llvm::isa<Variable64On32>(Dest)) { |
| 2150 const char *HelperName = |
| 2151 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) |
| 2152 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64); |
| 2153 static constexpr SizeT MaxSrcs = 1; |
| 2154 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); |
| 2155 Call->addArg(Src0); |
| 2156 lowerCall(Call); |
| 2157 break; |
| 2158 } |
| 2060 // fptosi: | 2159 // fptosi: |
| 2061 // t1.fp = vcvt src0.fp | 2160 // t1.fp = vcvt src0.fp |
| 2062 // t2.i32 = vmov t1.fp | 2161 // t2.i32 = vmov t1.fp |
| 2063 // dest.int = conv t2.i32 @ Truncates the result if needed. | 2162 // dest.int = conv t2.i32 @ Truncates the result if needed. |
| 2064 // fptoui: | 2163 // fptoui: |
| 2065 // t1.fp = vcvt src0.fp | 2164 // t1.fp = vcvt src0.fp |
| 2066 // t2.u32 = vmov t1.fp | 2165 // t2.u32 = vmov t1.fp |
| 2067 // dest.uint = conv t2.u32 @ Truncates the result if needed. | 2166 // dest.uint = conv t2.u32 @ Truncates the result if needed. |
| 2068 if (isVectorType(Dest->getType())) { | |
| 2069 UnimplementedError(Func->getContext()->getFlags()); | |
| 2070 break; | |
| 2071 } | |
| 2072 if (auto *Dest64On32 = llvm::dyn_cast<Variable64On32>(Dest)) { | |
| 2073 Context.insert(InstFakeDef::create(Func, Dest64On32->getLo())); | |
| 2074 Context.insert(InstFakeDef::create(Func, Dest64On32->getHi())); | |
| 2075 UnimplementedError(Func->getContext()->getFlags()); | |
| 2076 break; | |
| 2077 } | |
| 2078 const bool DestIsSigned = CastKind == InstCast::Fptosi; | |
| 2079 Variable *Src0R = legalizeToReg(Src0); | 2167 Variable *Src0R = legalizeToReg(Src0); |
| 2080 Variable *T_fp = makeReg(IceType_f32); | 2168 Variable *T_fp = makeReg(IceType_f32); |
| 2081 if (isFloat32Asserting32Or64(Src0->getType())) { | 2169 const InstARM32Vcvt::VcvtVariant Conversion = |
| 2082 _vcvt(T_fp, Src0R, | 2170 Src0IsF32 ? (DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui) |
| 2083 DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui); | 2171 : (DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui); |
| 2084 } else { | 2172 _vcvt(T_fp, Src0R, Conversion); |
| 2085 _vcvt(T_fp, Src0R, | |
| 2086 DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui); | |
| 2087 } | |
| 2088 Variable *T = makeReg(IceType_i32); | 2173 Variable *T = makeReg(IceType_i32); |
| 2089 _vmov(T, T_fp); | 2174 _mov(T, T_fp); |
| 2090 if (Dest->getType() != IceType_i32) { | 2175 if (Dest->getType() != IceType_i32) { |
| 2091 Variable *T_1 = makeReg(Dest->getType()); | 2176 Variable *T_1 = makeReg(Dest->getType()); |
| 2092 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); | 2177 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); |
| 2093 T = T_1; | 2178 T = T_1; |
| 2094 } | 2179 } |
| 2095 _mov(Dest, T); | 2180 _mov(Dest, T); |
| 2096 break; | 2181 break; |
| 2097 } | 2182 } |
| 2098 case InstCast::Sitofp: | 2183 case InstCast::Sitofp: |
| 2099 case InstCast::Uitofp: { | 2184 case InstCast::Uitofp: { |
| 2185 if (isVectorType(Dest->getType())) { |
| 2186 Variable *T = makeReg(Dest->getType()); |
| 2187 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2188 _mov(Dest, T); |
| 2189 UnimplementedError(Func->getContext()->getFlags()); |
| 2190 break; |
| 2191 } |
| 2192 const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
| 2193 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
| 2194 if (Src0->getType() == IceType_i64) { |
| 2195 const char *HelperName = |
| 2196 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) |
| 2197 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64); |
| 2198 static constexpr SizeT MaxSrcs = 1; |
| 2199 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); |
| 2200 Call->addArg(Src0); |
| 2201 lowerCall(Call); |
| 2202 break; |
| 2203 } |
| 2100 // sitofp: | 2204 // sitofp: |
| 2101 // t1.i32 = sext src.int @ sign-extends src0 if needed. | 2205 // t1.i32 = sext src.int @ sign-extends src0 if needed. |
| 2102 // t2.fp32 = vmov t1.i32 | 2206 // t2.fp32 = vmov t1.i32 |
| 2103 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 | 2207 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 |
| 2104 // uitofp: | 2208 // uitofp: |
| 2105 // t1.i32 = zext src.int @ zero-extends src0 if needed. | 2209 // t1.i32 = zext src.int @ zero-extends src0 if needed. |
| 2106 // t2.fp32 = vmov t1.i32 | 2210 // t2.fp32 = vmov t1.i32 |
| 2107 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 | 2211 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 |
| 2108 if (isVectorType(Dest->getType())) { | |
| 2109 UnimplementedError(Func->getContext()->getFlags()); | |
| 2110 break; | |
| 2111 } | |
| 2112 if (Src0->getType() == IceType_i64) { | |
| 2113 // avoid cryptic liveness errors | |
| 2114 Context.insert(InstFakeDef::create(Func, Dest)); | |
| 2115 UnimplementedError(Func->getContext()->getFlags()); | |
| 2116 break; | |
| 2117 } | |
| 2118 const bool SourceIsSigned = CastKind == InstCast::Sitofp; | |
| 2119 if (Src0->getType() != IceType_i32) { | 2212 if (Src0->getType() != IceType_i32) { |
| 2120 Variable *Src0R_32 = makeReg(IceType_i32); | 2213 Variable *Src0R_32 = makeReg(IceType_i32); |
| 2121 lowerCast(InstCast::create(Func, SourceIsSigned ? InstCast::Sext | 2214 lowerCast(InstCast::create(Func, SourceIsSigned ? InstCast::Sext |
| 2122 : InstCast::Zext, | 2215 : InstCast::Zext, |
| 2123 Src0R_32, Src0)); | 2216 Src0R_32, Src0)); |
| 2124 Src0 = Src0R_32; | 2217 Src0 = Src0R_32; |
| 2125 } | 2218 } |
| 2126 Variable *Src0R = legalizeToReg(Src0); | 2219 Variable *Src0R = legalizeToReg(Src0); |
| 2127 Variable *Src0R_f32 = makeReg(IceType_f32); | 2220 Variable *Src0R_f32 = makeReg(IceType_f32); |
| 2128 _vmov(Src0R_f32, Src0R); | 2221 _mov(Src0R_f32, Src0R); |
| 2129 Src0R = Src0R_f32; | 2222 Src0R = Src0R_f32; |
| 2130 Variable *T = makeReg(Dest->getType()); | 2223 Variable *T = makeReg(Dest->getType()); |
| 2131 if (isFloat32Asserting32Or64(Dest->getType())) { | 2224 const InstARM32Vcvt::VcvtVariant Conversion = |
| 2132 _vcvt(T, Src0R, | 2225 DestIsF32 |
| 2133 SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s); | 2226 ? (SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s) |
| 2134 } else { | 2227 : (SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d); |
| 2135 _vcvt(T, Src0R, | 2228 _vcvt(T, Src0R, Conversion); |
| 2136 SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d); | |
| 2137 } | |
| 2138 _mov(Dest, T); | 2229 _mov(Dest, T); |
| 2139 break; | 2230 break; |
| 2140 } | 2231 } |
| 2141 case InstCast::Bitcast: { | 2232 case InstCast::Bitcast: { |
| 2142 Operand *Src0 = Inst->getSrc(0); | 2233 Operand *Src0 = Inst->getSrc(0); |
| 2143 if (Dest->getType() == Src0->getType()) { | 2234 if (Dest->getType() == Src0->getType()) { |
| 2144 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); | 2235 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); |
| 2145 lowerAssign(Assign); | 2236 lowerAssign(Assign); |
| 2146 return; | 2237 return; |
| 2147 } | 2238 } |
| 2148 Type DestType = Dest->getType(); | 2239 Type DestType = Dest->getType(); |
| 2149 switch (DestType) { | 2240 switch (DestType) { |
| 2150 case IceType_NUM: | 2241 case IceType_NUM: |
| 2151 case IceType_void: | 2242 case IceType_void: |
| 2152 llvm::report_fatal_error("Unexpected bitcast."); | 2243 llvm::report_fatal_error("Unexpected bitcast."); |
| 2153 case IceType_i1: | 2244 case IceType_i1: |
| 2154 UnimplementedError(Func->getContext()->getFlags()); | 2245 UnimplementedError(Func->getContext()->getFlags()); |
| 2155 break; | 2246 break; |
| 2156 case IceType_v4i1: | |
| 2157 UnimplementedError(Func->getContext()->getFlags()); | |
| 2158 break; | |
| 2159 case IceType_i8: | 2247 case IceType_i8: |
| 2160 UnimplementedError(Func->getContext()->getFlags()); | 2248 UnimplementedError(Func->getContext()->getFlags()); |
| 2161 break; | 2249 break; |
| 2162 case IceType_i16: | 2250 case IceType_i16: |
| 2163 UnimplementedError(Func->getContext()->getFlags()); | 2251 UnimplementedError(Func->getContext()->getFlags()); |
| 2164 break; | 2252 break; |
| 2165 case IceType_i32: | 2253 case IceType_i32: |
| 2166 case IceType_f32: { | 2254 case IceType_f32: { |
| 2167 Variable *Src0R = legalizeToReg(Src0); | 2255 Variable *Src0R = legalizeToReg(Src0); |
| 2168 Variable *T = makeReg(DestType); | 2256 Variable *T = makeReg(DestType); |
| 2169 _vmov(T, Src0R); | 2257 _mov(T, Src0R); |
| 2170 lowerAssign(InstAssign::create(Func, Dest, T)); | 2258 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 2171 break; | 2259 break; |
| 2172 } | 2260 } |
| 2173 case IceType_i64: { | 2261 case IceType_i64: { |
| 2174 // t0, t1 <- src0 | 2262 // t0, t1 <- src0 |
| 2175 // dest[31..0] = t0 | 2263 // dest[31..0] = t0 |
| 2176 // dest[63..32] = t1 | 2264 // dest[63..32] = t1 |
| 2177 assert(Src0->getType() == IceType_f64); | 2265 assert(Src0->getType() == IceType_f64); |
| 2178 Variable *T0 = makeReg(IceType_i32); | 2266 auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 2179 Variable *T1 = makeReg(IceType_i32); | 2267 T->initHiLo(Func); |
| 2268 forceHiLoInReg(T); |
| 2180 Variable *Src0R = legalizeToReg(Src0); | 2269 Variable *Src0R = legalizeToReg(Src0); |
| 2181 _vmov(InstARM32Vmov::RegisterPair(T0, T1), Src0R); | 2270 _mov(T, Src0R); |
| 2271 Context.insert(InstFakeDef::create(Func, T->getLo())); |
| 2272 Context.insert(InstFakeDef::create(Func, T->getHi())); |
| 2182 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 2273 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 2183 lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T0)); | 2274 lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T->getLo())); |
| 2184 lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T1)); | 2275 lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T->getHi())); |
| 2276 Context.insert(InstFakeUse::create(Func, T)); |
| 2185 break; | 2277 break; |
| 2186 } | 2278 } |
| 2187 case IceType_f64: { | 2279 case IceType_f64: { |
| 2188 // T0 <- lo(src) | 2280 // T0 <- lo(src) |
| 2189 // T1 <- hi(src) | 2281 // T1 <- hi(src) |
| 2190 // vmov T2, T0, T1 | 2282 // vmov T2, T0, T1 |
| 2191 // Dest <- T2 | 2283 // Dest <- T2 |
| 2192 assert(Src0->getType() == IceType_i64); | 2284 assert(Src0->getType() == IceType_i64); |
| 2193 Variable *SrcLo = legalizeToReg(loOperand(Src0)); | 2285 auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 2194 Variable *SrcHi = legalizeToReg(hiOperand(Src0)); | 2286 Src64->initHiLo(Func); |
| 2195 Variable *T = makeReg(IceType_f64); | 2287 forceHiLoInReg(Src64); |
| 2196 _vmov(T, InstARM32Vmov::RegisterPair(SrcLo, SrcHi)); | 2288 Variable *T = Src64->getLo(); |
| 2289 _mov(T, legalizeToReg(loOperand(Src0))); |
| 2290 T = Src64->getHi(); |
| 2291 _mov(T, legalizeToReg(hiOperand(Src0))); |
| 2292 T = makeReg(IceType_f64); |
| 2293 Context.insert(InstFakeDef::create(Func, Src64)); |
| 2294 _mov(T, Src64); |
| 2295 Context.insert(InstFakeUse::create(Func, Src64->getLo())); |
| 2296 Context.insert(InstFakeUse::create(Func, Src64->getHi())); |
| 2197 lowerAssign(InstAssign::create(Func, Dest, T)); | 2297 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 2198 break; | 2298 break; |
| 2199 } | 2299 } |
| 2300 case IceType_v4i1: |
| 2200 case IceType_v8i1: | 2301 case IceType_v8i1: |
| 2302 case IceType_v16i1: |
| 2303 case IceType_v8i16: |
| 2304 case IceType_v16i8: |
| 2305 case IceType_v4f32: |
| 2306 case IceType_v4i32: { |
| 2307 // avoid cryptic liveness errors |
| 2308 Variable *T = makeReg(DestType); |
| 2309 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2310 _mov(Dest, T); |
| 2201 UnimplementedError(Func->getContext()->getFlags()); | 2311 UnimplementedError(Func->getContext()->getFlags()); |
| 2202 break; | 2312 break; |
| 2203 case IceType_v16i1: | 2313 } |
| 2204 UnimplementedError(Func->getContext()->getFlags()); | |
| 2205 break; | |
| 2206 case IceType_v8i16: | |
| 2207 UnimplementedError(Func->getContext()->getFlags()); | |
| 2208 break; | |
| 2209 case IceType_v16i8: | |
| 2210 UnimplementedError(Func->getContext()->getFlags()); | |
| 2211 break; | |
| 2212 case IceType_v4i32: | |
| 2213 // avoid cryptic liveness errors | |
| 2214 Context.insert(InstFakeDef::create(Func, Dest)); | |
| 2215 UnimplementedError(Func->getContext()->getFlags()); | |
| 2216 break; | |
| 2217 case IceType_v4f32: | |
| 2218 UnimplementedError(Func->getContext()->getFlags()); | |
| 2219 break; | |
| 2220 } | 2314 } |
| 2221 break; | 2315 break; |
| 2222 } | 2316 } |
| 2223 } | 2317 } |
| 2224 } | 2318 } |
| 2225 | 2319 |
| 2226 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { | 2320 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { |
| 2227 (void)Inst; | 2321 Variable *Dest = Inst->getDest(); |
| 2322 Type DestType = Dest->getType(); |
| 2323 Variable *T = makeReg(DestType); |
| 2324 Context.insert(InstFakeDef::create(Func, T)); |
| 2325 _mov(Dest, T); |
| 2228 UnimplementedError(Func->getContext()->getFlags()); | 2326 UnimplementedError(Func->getContext()->getFlags()); |
| 2229 } | 2327 } |
| 2230 | 2328 |
| 2231 namespace { | 2329 namespace { |
| 2232 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering | 2330 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering |
| 2233 // (and naming). | 2331 // (and naming). |
| 2234 enum { | 2332 enum { |
| 2235 #define X(val, CC0, CC1) _fcmp_ll_##val, | 2333 #define X(val, CC0, CC1) _fcmp_ll_##val, |
| 2236 FCMPARM32_TABLE | 2334 FCMPARM32_TABLE |
| 2237 #undef X | 2335 #undef X |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2262 { CondARM32::CC0, CondARM32::CC1 } \ | 2360 { CondARM32::CC0, CondARM32::CC1 } \ |
| 2263 , | 2361 , |
| 2264 FCMPARM32_TABLE | 2362 FCMPARM32_TABLE |
| 2265 #undef X | 2363 #undef X |
| 2266 }; | 2364 }; |
| 2267 } // end of anonymous namespace | 2365 } // end of anonymous namespace |
| 2268 | 2366 |
| 2269 void TargetARM32::lowerFcmp(const InstFcmp *Inst) { | 2367 void TargetARM32::lowerFcmp(const InstFcmp *Inst) { |
| 2270 Variable *Dest = Inst->getDest(); | 2368 Variable *Dest = Inst->getDest(); |
| 2271 if (isVectorType(Dest->getType())) { | 2369 if (isVectorType(Dest->getType())) { |
| 2370 Variable *T = makeReg(Dest->getType()); |
| 2371 Context.insert(InstFakeDef::create(Func, T)); |
| 2372 _mov(Dest, T); |
| 2272 UnimplementedError(Func->getContext()->getFlags()); | 2373 UnimplementedError(Func->getContext()->getFlags()); |
| 2273 return; | 2374 return; |
| 2274 } | 2375 } |
| 2275 | 2376 |
| 2276 Variable *Src0R = legalizeToReg(Inst->getSrc(0)); | 2377 Variable *Src0R = legalizeToReg(Inst->getSrc(0)); |
| 2277 Variable *Src1R = legalizeToReg(Inst->getSrc(1)); | 2378 Variable *Src1R = legalizeToReg(Inst->getSrc(1)); |
| 2278 Variable *T = makeReg(IceType_i32); | 2379 Variable *T = makeReg(IceType_i32); |
| 2279 _vcmp(Src0R, Src1R); | 2380 _vcmp(Src0R, Src1R); |
| 2280 _mov(T, Ctx->getConstantZero(IceType_i32)); | 2381 _mov(T, Ctx->getConstantZero(IceType_i32)); |
| 2281 _vmrs(); | 2382 _vmrs(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2299 } | 2400 } |
| 2300 _mov(Dest, T); | 2401 _mov(Dest, T); |
| 2301 } | 2402 } |
| 2302 | 2403 |
| 2303 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { | 2404 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
| 2304 Variable *Dest = Inst->getDest(); | 2405 Variable *Dest = Inst->getDest(); |
| 2305 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 2406 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 2306 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | 2407 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| 2307 | 2408 |
| 2308 if (isVectorType(Dest->getType())) { | 2409 if (isVectorType(Dest->getType())) { |
| 2410 Variable *T = makeReg(Dest->getType()); |
| 2411 Context.insert(InstFakeDef::create(Func, T)); |
| 2412 _mov(Dest, T); |
| 2309 UnimplementedError(Func->getContext()->getFlags()); | 2413 UnimplementedError(Func->getContext()->getFlags()); |
| 2310 return; | 2414 return; |
| 2311 } | 2415 } |
| 2312 | 2416 |
| 2313 // a=icmp cond, b, c ==> | 2417 // a=icmp cond, b, c ==> |
| 2314 // GCC does: | 2418 // GCC does: |
| 2315 // cmp b.hi, c.hi or cmp b.lo, c.lo | 2419 // cmp b.hi, c.hi or cmp b.lo, c.lo |
| 2316 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi | 2420 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi |
| 2317 // mov.<C1> t, #1 mov.<C1> t, #1 | 2421 // mov.<C1> t, #1 mov.<C1> t, #1 |
| 2318 // mov.<C2> t, #0 mov.<C2> t, #0 | 2422 // mov.<C2> t, #0 mov.<C2> t, #0 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2507 Call->addArg(Val); | 2611 Call->addArg(Val); |
| 2508 lowerCall(Call); | 2612 lowerCall(Call); |
| 2509 // The popcount helpers always return 32-bit values, while the intrinsic's | 2613 // The popcount helpers always return 32-bit values, while the intrinsic's |
| 2510 // signature matches some 64-bit platform's native instructions and expect | 2614 // signature matches some 64-bit platform's native instructions and expect |
| 2511 // to fill a 64-bit reg. Thus, clear the upper bits of the dest just in | 2615 // to fill a 64-bit reg. Thus, clear the upper bits of the dest just in |
| 2512 // case the user doesn't do that in the IR or doesn't toss the bits via | 2616 // case the user doesn't do that in the IR or doesn't toss the bits via |
| 2513 // truncate. | 2617 // truncate. |
| 2514 if (Val->getType() == IceType_i64) { | 2618 if (Val->getType() == IceType_i64) { |
| 2515 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2619 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2516 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 2620 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 2517 Variable *T = nullptr; | 2621 Variable *T = makeReg(Zero->getType()); |
| 2518 _mov(T, Zero); | 2622 _mov(T, Zero); |
| 2519 _mov(DestHi, T); | 2623 _mov(DestHi, T); |
| 2520 } | 2624 } |
| 2521 return; | 2625 return; |
| 2522 } | 2626 } |
| 2523 case Intrinsics::Ctlz: { | 2627 case Intrinsics::Ctlz: { |
| 2524 // The "is zero undef" parameter is ignored and we always return a | 2628 // The "is zero undef" parameter is ignored and we always return a |
| 2525 // well-defined value. | 2629 // well-defined value. |
| 2526 Operand *Val = Instr->getArg(0); | 2630 Operand *Val = Instr->getArg(0); |
| 2527 Variable *ValLoR; | 2631 Variable *ValLoR; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2554 } else { | 2658 } else { |
| 2555 ValLoR = legalizeToReg(Val); | 2659 ValLoR = legalizeToReg(Val); |
| 2556 Variable *T = makeReg(IceType_i32); | 2660 Variable *T = makeReg(IceType_i32); |
| 2557 _rbit(T, ValLoR); | 2661 _rbit(T, ValLoR); |
| 2558 ValLoR = T; | 2662 ValLoR = T; |
| 2559 } | 2663 } |
| 2560 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); | 2664 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); |
| 2561 return; | 2665 return; |
| 2562 } | 2666 } |
| 2563 case Intrinsics::Fabs: { | 2667 case Intrinsics::Fabs: { |
| 2564 // Add a fake def to keep liveness consistent in the meantime. | 2668 Variable *Dest = Instr->getDest(); |
| 2565 Context.insert(InstFakeDef::create(Func, Instr->getDest())); | 2669 Type DestTy = Dest->getType(); |
| 2566 UnimplementedError(Func->getContext()->getFlags()); | 2670 Variable *T = makeReg(DestTy); |
| 2671 if (isVectorType(DestTy)) { |
| 2672 // Add a fake def to keep liveness consistent in the meantime. |
| 2673 Context.insert(InstFakeDef::create(Func, T)); |
| 2674 _mov(Instr->getDest(), T); |
| 2675 UnimplementedError(Func->getContext()->getFlags()); |
| 2676 return; |
| 2677 } |
| 2678 _vabs(T, legalizeToReg(Instr->getArg(0))); |
| 2679 _mov(Dest, T); |
| 2567 return; | 2680 return; |
| 2568 } | 2681 } |
| 2569 case Intrinsics::Longjmp: { | 2682 case Intrinsics::Longjmp: { |
| 2570 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); | 2683 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); |
| 2571 Call->addArg(Instr->getArg(0)); | 2684 Call->addArg(Instr->getArg(0)); |
| 2572 Call->addArg(Instr->getArg(1)); | 2685 Call->addArg(Instr->getArg(1)); |
| 2573 lowerCall(Call); | 2686 lowerCall(Call); |
| 2574 return; | 2687 return; |
| 2575 } | 2688 } |
| 2576 case Intrinsics::Memcpy: { | 2689 case Intrinsics::Memcpy: { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2621 InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1); | 2734 InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1); |
| 2622 Call->addArg(Instr->getArg(0)); | 2735 Call->addArg(Instr->getArg(0)); |
| 2623 lowerCall(Call); | 2736 lowerCall(Call); |
| 2624 return; | 2737 return; |
| 2625 } | 2738 } |
| 2626 case Intrinsics::Sqrt: { | 2739 case Intrinsics::Sqrt: { |
| 2627 Variable *Src = legalizeToReg(Instr->getArg(0)); | 2740 Variable *Src = legalizeToReg(Instr->getArg(0)); |
| 2628 Variable *Dest = Instr->getDest(); | 2741 Variable *Dest = Instr->getDest(); |
| 2629 Variable *T = makeReg(Dest->getType()); | 2742 Variable *T = makeReg(Dest->getType()); |
| 2630 _vsqrt(T, Src); | 2743 _vsqrt(T, Src); |
| 2631 _vmov(Dest, T); | 2744 _mov(Dest, T); |
| 2632 return; | 2745 return; |
| 2633 } | 2746 } |
| 2634 case Intrinsics::Stacksave: { | 2747 case Intrinsics::Stacksave: { |
| 2635 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2748 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 2636 Variable *Dest = Instr->getDest(); | 2749 Variable *Dest = Instr->getDest(); |
| 2637 _mov(Dest, SP); | 2750 _mov(Dest, SP); |
| 2638 return; | 2751 return; |
| 2639 } | 2752 } |
| 2640 case Intrinsics::Stackrestore: { | 2753 case Intrinsics::Stackrestore: { |
| 2641 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2754 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2667 legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); | 2780 legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); |
| 2668 _cmp(ValHiR, Zero); | 2781 _cmp(ValHiR, Zero); |
| 2669 Variable *T2 = makeReg(IceType_i32); | 2782 Variable *T2 = makeReg(IceType_i32); |
| 2670 _add(T2, T, ThirtyTwo); | 2783 _add(T2, T, ThirtyTwo); |
| 2671 _clz(T2, ValHiR, CondARM32::NE); | 2784 _clz(T2, ValHiR, CondARM32::NE); |
| 2672 // T2 is actually a source as well when the predicate is not AL (since it | 2785 // T2 is actually a source as well when the predicate is not AL (since it |
| 2673 // may leave T2 alone). We use set_dest_nonkillable to prolong the liveness | 2786 // may leave T2 alone). We use set_dest_nonkillable to prolong the liveness |
| 2674 // of T2 as if it was used as a source. | 2787 // of T2 as if it was used as a source. |
| 2675 _set_dest_nonkillable(); | 2788 _set_dest_nonkillable(); |
| 2676 _mov(DestLo, T2); | 2789 _mov(DestLo, T2); |
| 2677 Variable *T3 = nullptr; | 2790 Variable *T3 = makeReg(Zero->getType()); |
| 2678 _mov(T3, Zero); | 2791 _mov(T3, Zero); |
| 2679 _mov(DestHi, T3); | 2792 _mov(DestHi, T3); |
| 2680 return; | 2793 return; |
| 2681 } | 2794 } |
| 2682 _mov(Dest, T); | 2795 _mov(Dest, T); |
| 2683 return; | 2796 return; |
| 2684 } | 2797 } |
| 2685 | 2798 |
| 2686 void TargetARM32::lowerLoad(const InstLoad *Load) { | 2799 void TargetARM32::lowerLoad(const InstLoad *Load) { |
| 2687 // A Load instruction can be treated the same as an Assign instruction, after | 2800 // A Load instruction can be treated the same as an Assign instruction, after |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2727 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); | 2840 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); |
| 2728 Reg = S0; | 2841 Reg = S0; |
| 2729 } else if (Ty == IceType_f64) { | 2842 } else if (Ty == IceType_f64) { |
| 2730 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); | 2843 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); |
| 2731 Reg = D0; | 2844 Reg = D0; |
| 2732 } else if (isVectorType(Src0->getType())) { | 2845 } else if (isVectorType(Src0->getType())) { |
| 2733 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); | 2846 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); |
| 2734 Reg = Q0; | 2847 Reg = Q0; |
| 2735 } else { | 2848 } else { |
| 2736 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 2849 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| 2737 _mov(Reg, Src0F, CondARM32::AL, RegARM32::Reg_r0); | 2850 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); |
| 2851 _mov(Reg, Src0F, CondARM32::AL); |
| 2738 } | 2852 } |
| 2739 } | 2853 } |
| 2740 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 2854 // Add a ret instruction even if sandboxing is enabled, because addEpilog |
| 2741 // explicitly looks for a ret instruction as a marker for where to insert the | 2855 // explicitly looks for a ret instruction as a marker for where to insert the |
| 2742 // frame removal instructions. addEpilog is responsible for restoring the | 2856 // frame removal instructions. addEpilog is responsible for restoring the |
| 2743 // "lr" register as needed prior to this ret instruction. | 2857 // "lr" register as needed prior to this ret instruction. |
| 2744 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 2858 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
| 2745 // Add a fake use of sp to make sure sp stays alive for the entire function. | 2859 // Add a fake use of sp to make sure sp stays alive for the entire function. |
| 2746 // Otherwise post-call sp adjustments get dead-code eliminated. | 2860 // Otherwise post-call sp adjustments get dead-code eliminated. |
| 2747 // TODO: Are there more places where the fake use should be inserted? E.g. | 2861 // TODO: Are there more places where the fake use should be inserted? E.g. |
| 2748 // "void f(int n){while(1) g(n);}" may not have a ret instruction. | 2862 // "void f(int n){while(1) g(n);}" may not have a ret instruction. |
| 2749 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2863 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 2750 Context.insert(InstFakeUse::create(Func, SP)); | 2864 Context.insert(InstFakeUse::create(Func, SP)); |
| 2751 } | 2865 } |
| 2752 | 2866 |
| 2753 void TargetARM32::lowerSelect(const InstSelect *Inst) { | 2867 void TargetARM32::lowerSelect(const InstSelect *Inst) { |
| 2754 Variable *Dest = Inst->getDest(); | 2868 Variable *Dest = Inst->getDest(); |
| 2755 Type DestTy = Dest->getType(); | 2869 Type DestTy = Dest->getType(); |
| 2756 Operand *SrcT = Inst->getTrueOperand(); | 2870 Operand *SrcT = Inst->getTrueOperand(); |
| 2757 Operand *SrcF = Inst->getFalseOperand(); | 2871 Operand *SrcF = Inst->getFalseOperand(); |
| 2758 Operand *Condition = Inst->getCondition(); | 2872 Operand *Condition = Inst->getCondition(); |
| 2759 | 2873 |
| 2760 if (isVectorType(DestTy)) { | 2874 if (isVectorType(DestTy)) { |
| 2875 Variable *T = makeReg(DestTy); |
| 2876 Context.insert(InstFakeDef::create(Func, T)); |
| 2877 _mov(Dest, T); |
| 2761 UnimplementedError(Func->getContext()->getFlags()); | 2878 UnimplementedError(Func->getContext()->getFlags()); |
| 2762 return; | 2879 return; |
| 2763 } | 2880 } |
| 2764 // TODO(jvoung): handle folding opportunities. | 2881 // TODO(jvoung): handle folding opportunities. |
| 2765 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t | 2882 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t |
| 2766 Variable *CmpOpnd0 = legalizeToReg(Condition); | 2883 Variable *CmpOpnd0 = legalizeToReg(Condition); |
| 2767 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); | 2884 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); |
| 2768 _cmp(CmpOpnd0, CmpOpnd1); | 2885 _cmp(CmpOpnd0, CmpOpnd1); |
| 2769 static constexpr CondARM32::Cond Cond = CondARM32::NE; | 2886 static constexpr CondARM32::Cond Cond = CondARM32::NE; |
| 2770 if (DestTy == IceType_i64) { | 2887 if (DestTy == IceType_i64) { |
| 2771 SrcT = legalizeUndef(SrcT); | 2888 SrcT = legalizeUndef(SrcT); |
| 2772 SrcF = legalizeUndef(SrcF); | 2889 SrcF = legalizeUndef(SrcF); |
| 2773 // Set the low portion. | 2890 // Set the low portion. |
| 2774 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2891 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2775 Variable *TLo = nullptr; | |
| 2776 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); | 2892 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); |
| 2893 Variable *TLo = makeReg(SrcFLo->getType()); |
| 2777 _mov(TLo, SrcFLo); | 2894 _mov(TLo, SrcFLo); |
| 2778 Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex); | 2895 Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex); |
| 2779 _mov_nonkillable(TLo, SrcTLo, Cond); | 2896 _mov_nonkillable(TLo, SrcTLo, Cond); |
| 2780 _mov(DestLo, TLo); | 2897 _mov(DestLo, TLo); |
| 2781 // Set the high portion. | 2898 // Set the high portion. |
| 2782 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2899 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2783 Variable *THi = nullptr; | |
| 2784 Operand *SrcFHi = legalize(hiOperand(SrcF), Legal_Reg | Legal_Flex); | 2900 Operand *SrcFHi = legalize(hiOperand(SrcF), Legal_Reg | Legal_Flex); |
| 2901 Variable *THi = makeReg(SrcFHi->getType()); |
| 2785 _mov(THi, SrcFHi); | 2902 _mov(THi, SrcFHi); |
| 2786 Operand *SrcTHi = legalize(hiOperand(SrcT), Legal_Reg | Legal_Flex); | 2903 Operand *SrcTHi = legalize(hiOperand(SrcT), Legal_Reg | Legal_Flex); |
| 2787 _mov_nonkillable(THi, SrcTHi, Cond); | 2904 _mov_nonkillable(THi, SrcTHi, Cond); |
| 2788 _mov(DestHi, THi); | 2905 _mov(DestHi, THi); |
| 2789 return; | 2906 return; |
| 2790 } | 2907 } |
| 2791 | 2908 |
| 2792 if (isFloatingType(DestTy)) { | 2909 if (isFloatingType(DestTy)) { |
| 2793 Variable *T = makeReg(DestTy); | 2910 Variable *T = makeReg(DestTy); |
| 2794 SrcF = legalizeToReg(SrcF); | 2911 SrcF = legalizeToReg(SrcF); |
| 2795 assert(DestTy == SrcF->getType()); | 2912 assert(DestTy == SrcF->getType()); |
| 2796 _vmov(T, SrcF); | 2913 _mov(T, SrcF); |
| 2797 SrcT = legalizeToReg(SrcT); | 2914 SrcT = legalizeToReg(SrcT); |
| 2798 assert(DestTy == SrcT->getType()); | 2915 assert(DestTy == SrcT->getType()); |
| 2799 _vmov(T, SrcT, Cond); | 2916 _mov(T, SrcT, Cond); |
| 2800 _set_dest_nonkillable(); | 2917 _set_dest_nonkillable(); |
| 2801 _vmov(Dest, T); | 2918 _mov(Dest, T); |
| 2802 return; | 2919 return; |
| 2803 } | 2920 } |
| 2804 | 2921 |
| 2805 Variable *T = nullptr; | |
| 2806 SrcF = legalize(SrcF, Legal_Reg | Legal_Flex); | 2922 SrcF = legalize(SrcF, Legal_Reg | Legal_Flex); |
| 2923 Variable *T = makeReg(SrcF->getType()); |
| 2807 _mov(T, SrcF); | 2924 _mov(T, SrcF); |
| 2808 SrcT = legalize(SrcT, Legal_Reg | Legal_Flex); | 2925 SrcT = legalize(SrcT, Legal_Reg | Legal_Flex); |
| 2809 _mov_nonkillable(T, SrcT, Cond); | 2926 _mov_nonkillable(T, SrcT, Cond); |
| 2810 _mov(Dest, T); | 2927 _mov(Dest, T); |
| 2811 } | 2928 } |
| 2812 | 2929 |
| 2813 void TargetARM32::lowerStore(const InstStore *Inst) { | 2930 void TargetARM32::lowerStore(const InstStore *Inst) { |
| 2814 Operand *Value = Inst->getData(); | 2931 Operand *Value = Inst->getData(); |
| 2815 Operand *Addr = Inst->getAddr(); | 2932 Operand *Addr = Inst->getAddr(); |
| 2816 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); | 2933 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
| 2817 Type Ty = NewAddr->getType(); | 2934 Type Ty = NewAddr->getType(); |
| 2818 | 2935 |
| 2819 if (Ty == IceType_i64) { | 2936 if (Ty == IceType_i64) { |
| 2820 Value = legalizeUndef(Value); | 2937 Value = legalizeUndef(Value); |
| 2821 Variable *ValueHi = legalizeToReg(hiOperand(Value)); | 2938 Variable *ValueHi = legalizeToReg(hiOperand(Value)); |
| 2822 Variable *ValueLo = legalizeToReg(loOperand(Value)); | 2939 Variable *ValueLo = legalizeToReg(loOperand(Value)); |
| 2823 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); | 2940 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); |
| 2824 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); | 2941 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); |
| 2825 } else { | 2942 } else { |
| 2826 if (isVectorType(Ty)) { | |
| 2827 UnimplementedError(Func->getContext()->getFlags()); | |
| 2828 } | |
| 2829 Variable *ValueR = legalizeToReg(Value); | 2943 Variable *ValueR = legalizeToReg(Value); |
| 2830 _str(ValueR, NewAddr); | 2944 _str(ValueR, NewAddr); |
| 2831 } | 2945 } |
| 2832 } | 2946 } |
| 2833 | 2947 |
| 2834 void TargetARM32::doAddressOptStore() { | 2948 void TargetARM32::doAddressOptStore() { |
| 2835 UnimplementedError(Func->getContext()->getFlags()); | 2949 UnimplementedError(Func->getContext()->getFlags()); |
| 2836 } | 2950 } |
| 2837 | 2951 |
| 2838 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 2952 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2871 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 2985 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
| 2872 _trap(); | 2986 _trap(); |
| 2873 } | 2987 } |
| 2874 | 2988 |
| 2875 void TargetARM32::prelowerPhis() { | 2989 void TargetARM32::prelowerPhis() { |
| 2876 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); | 2990 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); |
| 2877 } | 2991 } |
| 2878 | 2992 |
| 2879 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | 2993 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { |
| 2880 Variable *Reg = makeReg(Ty, RegNum); | 2994 Variable *Reg = makeReg(Ty, RegNum); |
| 2995 Context.insert(InstFakeDef::create(Func, Reg)); |
| 2881 UnimplementedError(Func->getContext()->getFlags()); | 2996 UnimplementedError(Func->getContext()->getFlags()); |
| 2882 return Reg; | 2997 return Reg; |
| 2883 } | 2998 } |
| 2884 | 2999 |
| 2885 // Helper for legalize() to emit the right code to lower an operand to a | 3000 // Helper for legalize() to emit the right code to lower an operand to a |
| 2886 // register of the appropriate type. | 3001 // register of the appropriate type. |
| 2887 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 3002 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
| 2888 Type Ty = Src->getType(); | 3003 Type Ty = Src->getType(); |
| 2889 Variable *Reg = makeReg(Ty, RegNum); | 3004 Variable *Reg = makeReg(Ty, RegNum); |
| 2890 if (isVectorType(Ty)) { | 3005 _mov(Reg, Src); |
| 2891 // TODO(jpp): Src must be a register, or an address with base register. | |
| 2892 _vmov(Reg, Src); | |
| 2893 } else if (isFloatingType(Ty)) { | |
| 2894 _vmov(Reg, Src); | |
| 2895 } else { | |
| 2896 // Mov's Src operand can really only be the flexible second operand type or | |
| 2897 // a register. Users should guarantee that. | |
| 2898 _mov(Reg, Src); | |
| 2899 } | |
| 2900 return Reg; | 3006 return Reg; |
| 2901 } | 3007 } |
| 2902 | 3008 |
| 2903 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 3009 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
| 2904 int32_t RegNum) { | 3010 int32_t RegNum) { |
| 2905 Type Ty = From->getType(); | 3011 Type Ty = From->getType(); |
| 2906 // Assert that a physical register is allowed. To date, all calls to | 3012 // Assert that a physical register is allowed. To date, all calls to |
| 2907 // legalize() allow a physical register. Legal_Flex converts registers to the | 3013 // legalize() allow a physical register. Legal_Flex converts registers to the |
| 2908 // right type OperandARM32FlexReg as needed. | 3014 // right type OperandARM32FlexReg as needed. |
| 2909 assert(Allowed & Legal_Reg); | 3015 assert(Allowed & Legal_Reg); |
| 2910 // Go through the various types of operands: OperandARM32Mem, | 3016 // Go through the various types of operands: OperandARM32Mem, |
| 2911 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if | 3017 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if |
| 2912 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we | 3018 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we |
| 2913 // can always copy to a register. | 3019 // can always copy to a register. |
| 2914 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { | 3020 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { |
| 3021 static const struct { |
| 3022 bool CanHaveOffset; |
| 3023 bool CanHaveIndex; |
| 3024 } MemTraits[] = { |
| 3025 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr) \ |
| 3026 { (ubits) > 0, rraddr } \ |
| 3027 , |
| 3028 ICETYPEARM32_TABLE |
| 3029 #undef X |
| 3030 }; |
| 2915 // Before doing anything with a Mem operand, we need to ensure that the | 3031 // Before doing anything with a Mem operand, we need to ensure that the |
| 2916 // Base and Index components are in physical registers. | 3032 // Base and Index components are in physical registers. |
| 2917 Variable *Base = Mem->getBase(); | 3033 Variable *Base = Mem->getBase(); |
| 2918 Variable *Index = Mem->getIndex(); | 3034 Variable *Index = Mem->getIndex(); |
| 3035 ConstantInteger32 *Offset = Mem->getOffset(); |
| 3036 assert(Index == nullptr || Offset == nullptr); |
| 2919 Variable *RegBase = nullptr; | 3037 Variable *RegBase = nullptr; |
| 2920 Variable *RegIndex = nullptr; | 3038 Variable *RegIndex = nullptr; |
| 2921 if (Base) { | 3039 if (Base) { |
| 2922 RegBase = legalizeToReg(Base); | 3040 RegBase = legalizeToReg(Base); |
| 2923 } | 3041 } |
| 2924 if (Index) { | 3042 if (Index) { |
| 2925 RegIndex = legalizeToReg(Index); | 3043 RegIndex = legalizeToReg(Index); |
| 3044 if (!MemTraits[Ty].CanHaveIndex) { |
| 3045 Variable *T = makeReg(IceType_i32, getReservedTmpReg()); |
| 3046 _add(T, RegBase, RegIndex); |
| 3047 RegBase = T; |
| 3048 RegIndex = nullptr; |
| 3049 } |
| 2926 } | 3050 } |
| 3051 if (Offset && Offset->getValue() != 0) { |
| 3052 static constexpr bool SignExt = false; |
| 3053 if (!MemTraits[Ty].CanHaveOffset || |
| 3054 !OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset->getValue())) { |
| 3055 Variable *T = legalizeToReg(Offset, getReservedTmpReg()); |
| 3056 _add(T, T, RegBase); |
| 3057 RegBase = T; |
| 3058 Offset = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)); |
| 3059 } |
| 3060 } |
| 3061 |
| 2927 // Create a new operand if there was a change. | 3062 // Create a new operand if there was a change. |
| 2928 if (Base != RegBase || Index != RegIndex) { | 3063 if (Base != RegBase || Index != RegIndex) { |
| 2929 // There is only a reg +/- reg or reg + imm form. | 3064 // There is only a reg +/- reg or reg + imm form. |
| 2930 // Figure out which to re-create. | 3065 // Figure out which to re-create. |
| 2931 if (Mem->isRegReg()) { | 3066 if (RegBase && RegIndex) { |
| 2932 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, | 3067 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, |
| 2933 Mem->getShiftOp(), Mem->getShiftAmt(), | 3068 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 2934 Mem->getAddrMode()); | 3069 Mem->getAddrMode()); |
| 2935 } else { | 3070 } else { |
| 2936 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Mem->getOffset(), | 3071 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset, |
| 2937 Mem->getAddrMode()); | 3072 Mem->getAddrMode()); |
| 2938 } | 3073 } |
| 2939 } | 3074 } |
| 2940 if (!(Allowed & Legal_Mem)) { | 3075 if (Allowed & Legal_Mem) { |
| 3076 From = Mem; |
| 3077 } else { |
| 2941 Variable *Reg = makeReg(Ty, RegNum); | 3078 Variable *Reg = makeReg(Ty, RegNum); |
| 2942 if (isVectorType(Ty)) { | 3079 _ldr(Reg, Mem); |
| 2943 UnimplementedError(Func->getContext()->getFlags()); | |
| 2944 } else if (isFloatingType(Ty)) { | |
| 2945 _vldr(Reg, Mem); | |
| 2946 } else { | |
| 2947 _ldr(Reg, Mem); | |
| 2948 } | |
| 2949 From = Reg; | 3080 From = Reg; |
| 2950 } else { | |
| 2951 From = Mem; | |
| 2952 } | 3081 } |
| 2953 return From; | 3082 return From; |
| 2954 } | 3083 } |
| 2955 | 3084 |
| 2956 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { | 3085 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { |
| 2957 if (!(Allowed & Legal_Flex)) { | 3086 if (!(Allowed & Legal_Flex)) { |
| 2958 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { | 3087 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { |
| 2959 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { | 3088 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { |
| 2960 From = FlexReg->getReg(); | 3089 From = FlexReg->getReg(); |
| 2961 // Fall through and let From be checked as a Variable below, where it | 3090 // Fall through and let From be checked as a Variable below, where it |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3354 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; | 3483 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
| 3355 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 3484 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
| 3356 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 3485 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
| 3357 } | 3486 } |
| 3358 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 3487 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 3359 // However, for compatibility with current NaCl LLVM, don't claim that. | 3488 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 3360 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 3489 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 3361 } | 3490 } |
| 3362 | 3491 |
| 3363 } // end of namespace Ice | 3492 } // end of namespace Ice |
| OLD | NEW |