Chromium Code Reviews| 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 if (!isLegalVariableStackOffset(VarTy, Offset)) { | |
| 429 llvm::report_fatal_error("Illegal stack offset"); | 445 llvm::report_fatal_error("Illegal stack offset"); |
| 430 } | 446 } |
| 431 const Type FrameSPTy = stackSlotType(); | 447 Str << "[" << getRegName(BaseRegNum, VarTy); |
| 432 Str << "[" << getRegName(BaseRegNum, FrameSPTy); | |
| 433 if (Offset != 0) { | 448 if (Offset != 0) { |
| 434 Str << ", " << getConstantPrefix() << Offset; | 449 Str << ", " << getConstantPrefix() << Offset; |
| 435 } | 450 } |
| 436 Str << "]"; | 451 Str << "]"; |
| 437 } | 452 } |
| 438 | 453 |
| 439 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { | 454 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { |
| 440 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 455 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
| 441 return false; | 456 return false; |
| 442 int32_t RegLo, RegHi; | 457 int32_t RegLo, RegHi; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 585 return; | 600 return; |
| 586 } | 601 } |
| 587 Type Ty = Arg->getType(); | 602 Type Ty = Arg->getType(); |
| 588 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); | 603 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); |
| 589 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); | 604 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); |
| 590 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 605 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 591 // If the argument variable has been assigned a register, we need to load the | 606 // If the argument variable has been assigned a register, we need to load the |
| 592 // value from the stack slot. | 607 // value from the stack slot. |
| 593 if (Arg->hasReg()) { | 608 if (Arg->hasReg()) { |
| 594 assert(Ty != IceType_i64); | 609 assert(Ty != IceType_i64); |
| 595 OperandARM32Mem *Mem = OperandARM32Mem::create( | 610 // This should be simple, just load the parameter off the stack using a nice |
| 611 // sp + imm addressing mode. Because ARM, we can't do that (e.g., VLDR, for | |
| 612 // fp types, cannot have an index register.) This ARM nonsense makes one | |
|
Jim Stichnoth
2015/09/24 05:57:13
I don't think that sort of editorial comment shoul
John
2015/09/24 21:28:40
That's because you are not working with ARM32.. :P
| |
| 613 // miss x86. | |
| 614 auto *Mem = OperandARM32Mem::create( | |
| 596 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( | 615 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( |
| 597 Ctx->getConstantInt32(Arg->getStackOffset()))); | 616 Ctx->getConstantInt32(Arg->getStackOffset()))); |
| 598 if (isVectorType(Arg->getType())) { | 617 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 | 618 // This argument-copying instruction uses an explicit OperandARM32Mem |
| 607 // operand instead of a Variable, so its fill-from-stack operation has to | 619 // operand instead of a Variable, so its fill-from-stack operation has to |
| 608 // be tracked separately for statistics. | 620 // be tracked separately for statistics. |
| 609 Ctx->statsUpdateFills(); | 621 Ctx->statsUpdateFills(); |
| 610 } | 622 } |
| 611 } | 623 } |
| 612 | 624 |
| 613 Type TargetARM32::stackSlotType() { return IceType_i32; } | 625 Type TargetARM32::stackSlotType() { return IceType_i32; } |
| 614 | 626 |
| 615 void TargetARM32::addProlog(CfgNode *Node) { | 627 void TargetARM32::addProlog(CfgNode *Node) { |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 887 Variable *RetValue = nullptr; | 899 Variable *RetValue = nullptr; |
| 888 if (RI->getSrcSize()) | 900 if (RI->getSrcSize()) |
| 889 RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 901 RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
| 890 _bundle_lock(); | 902 _bundle_lock(); |
| 891 _bic(LR, LR, RetMask); | 903 _bic(LR, LR, RetMask); |
| 892 _ret(LR, RetValue); | 904 _ret(LR, RetValue); |
| 893 _bundle_unlock(); | 905 _bundle_unlock(); |
| 894 RI->setDeleted(); | 906 RI->setDeleted(); |
| 895 } | 907 } |
| 896 | 908 |
| 897 bool TargetARM32::isLegalVariableStackOffset(int32_t Offset) const { | 909 bool TargetARM32::isLegalVariableStackOffset(Type Ty, int32_t Offset) const { |
| 898 constexpr bool SignExt = false; | 910 constexpr bool SignExt = false; |
| 899 // TODO(jvoung): vldr of FP stack slots has a different limit from the plain | 911 return OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset); |
| 900 // stackSlotType(). | |
| 901 return OperandARM32Mem::canHoldOffset(stackSlotType(), SignExt, Offset); | |
| 902 } | 912 } |
| 903 | 913 |
| 904 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, | 914 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, |
| 905 Variable *OrigBaseReg) { | 915 Variable *OrigBaseReg) { |
| 906 int32_t Offset = Var->getStackOffset(); | 916 int32_t Offset = Var->getStackOffset(); |
| 907 // Legalize will likely need a movw/movt combination, but if the top bits are | 917 // 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. | 918 // all 0 from negating the offset and subtracting, we could use that instead. |
| 909 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; | 919 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; |
| 910 if (ShouldSub) | 920 if (ShouldSub) |
| 911 Offset = -Offset; | 921 Offset = -Offset; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 930 // to: | 940 // to: |
| 931 // movw/movt TMP, OFF_PART | 941 // movw/movt TMP, OFF_PART |
| 932 // add TMP, TMP, SP | 942 // add TMP, TMP, SP |
| 933 // ldr X, OFF_MORE[TMP] | 943 // ldr X, OFF_MORE[TMP] |
| 934 // | 944 // |
| 935 // This is safe because we have reserved TMP, and add for ARM does not | 945 // This is safe because we have reserved TMP, and add for ARM does not |
| 936 // clobber the flags register. | 946 // clobber the flags register. |
| 937 Func->dump("Before legalizeStackSlots"); | 947 Func->dump("Before legalizeStackSlots"); |
| 938 assert(hasComputedFrame()); | 948 assert(hasComputedFrame()); |
| 939 // Early exit, if SpillAreaSizeBytes is really small. | 949 // Early exit, if SpillAreaSizeBytes is really small. |
| 940 if (isLegalVariableStackOffset(SpillAreaSizeBytes)) | 950 // TODO(jpp): this is not safe -- loads and stores of q registers can't have |
| 951 // offsets. | |
| 952 if (isLegalVariableStackOffset(IceType_v4i32, SpillAreaSizeBytes)) | |
| 941 return; | 953 return; |
| 942 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); | 954 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); |
| 943 int32_t StackAdjust = 0; | 955 int32_t StackAdjust = 0; |
| 944 // Do a fairly naive greedy clustering for now. Pick the first stack slot | 956 // 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 | 957 // 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 | 958 // 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 | 959 // 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 | 960 // 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. | 961 // 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 | 962 // 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(); | 983 StackAdjust += AdjInst->getAmount(); |
| 972 NewBaseOffset += AdjInst->getAmount(); | 984 NewBaseOffset += AdjInst->getAmount(); |
| 973 continue; | 985 continue; |
| 974 } | 986 } |
| 975 if (llvm::isa<InstARM32Call>(CurInstr)) { | 987 if (llvm::isa<InstARM32Call>(CurInstr)) { |
| 976 NewBaseOffset -= StackAdjust; | 988 NewBaseOffset -= StackAdjust; |
| 977 StackAdjust = 0; | 989 StackAdjust = 0; |
| 978 continue; | 990 continue; |
| 979 } | 991 } |
| 980 } | 992 } |
| 993 | |
| 981 // For now, only Mov instructions can have stack variables. We need to | 994 // 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 | 995 // know the type of instruction because we currently create a fresh one |
| 983 // to replace Dest/Source, rather than mutate in place. | 996 // to replace Dest/Source, rather than mutate in place. |
| 984 auto *MovInst = llvm::dyn_cast<InstARM32Mov>(CurInstr); | 997 bool MayNeedOffsetRewrite = false; |
| 985 if (!MovInst) { | 998 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { |
| 999 MayNeedOffsetRewrite = | |
| 1000 !MovInstr->isMultiDest() && !MovInstr->isMultiSource(); | |
| 1001 } | |
| 1002 | |
| 1003 if (!MayNeedOffsetRewrite) { | |
| 986 continue; | 1004 continue; |
| 987 } | 1005 } |
| 1006 | |
| 1007 assert(Dest != nullptr); | |
| 1008 Type DestTy = Dest->getType(); | |
| 1009 assert(DestTy != IceType_i64); | |
| 988 if (!Dest->hasReg()) { | 1010 if (!Dest->hasReg()) { |
| 989 int32_t Offset = Dest->getStackOffset(); | 1011 int32_t Offset = Dest->getStackOffset(); |
| 990 Offset += StackAdjust; | 1012 Offset += StackAdjust; |
| 991 if (!isLegalVariableStackOffset(Offset)) { | 1013 if (!isLegalVariableStackOffset(DestTy, Offset)) { |
| 992 if (NewBaseReg) { | 1014 if (NewBaseReg) { |
| 993 int32_t OffsetDiff = Offset - NewBaseOffset; | 1015 int32_t OffsetDiff = Offset - NewBaseOffset; |
| 994 if (isLegalVariableStackOffset(OffsetDiff)) { | 1016 if (isLegalVariableStackOffset(DestTy, OffsetDiff)) { |
| 995 StackVariable *NewDest = | 1017 StackVariable *NewDest = |
| 996 Func->makeVariable<StackVariable>(stackSlotType()); | 1018 Func->makeVariable<StackVariable>(stackSlotType()); |
| 997 NewDest->setMustNotHaveReg(); | 1019 NewDest->setMustNotHaveReg(); |
| 998 NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum()); | 1020 NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum()); |
| 999 NewDest->setStackOffset(OffsetDiff); | 1021 NewDest->setStackOffset(OffsetDiff); |
| 1000 Variable *NewDestVar = NewDest; | 1022 Variable *NewDestVar = NewDest; |
| 1001 _mov(NewDestVar, MovInst->getSrc(0)); | 1023 _mov(NewDestVar, CurInstr->getSrc(0)); |
| 1002 MovInst->setDeleted(); | 1024 CurInstr->setDeleted(); |
| 1003 continue; | 1025 continue; |
| 1004 } | 1026 } |
| 1005 } | 1027 } |
| 1006 StackVariable *LegalDest = legalizeVariableSlot(Dest, OrigBaseReg); | 1028 StackVariable *LegalDest = legalizeVariableSlot(Dest, OrigBaseReg); |
| 1007 assert(LegalDest != Dest); | 1029 assert(LegalDest != Dest); |
| 1008 Variable *LegalDestVar = LegalDest; | 1030 Variable *LegalDestVar = LegalDest; |
| 1009 _mov(LegalDestVar, MovInst->getSrc(0)); | 1031 _mov(LegalDestVar, CurInstr->getSrc(0)); |
| 1010 MovInst->setDeleted(); | 1032 CurInstr->setDeleted(); |
| 1011 NewBaseReg = LegalDest; | 1033 NewBaseReg = LegalDest; |
| 1012 NewBaseOffset = Offset; | 1034 NewBaseOffset = Offset; |
| 1013 continue; | 1035 continue; |
| 1014 } | 1036 } |
| 1015 } | 1037 } |
| 1016 assert(MovInst->getSrcSize() == 1); | 1038 assert(CurInstr->getSrcSize() == 1); |
| 1017 Variable *Var = llvm::dyn_cast<Variable>(MovInst->getSrc(0)); | 1039 Variable *Var = llvm::dyn_cast<Variable>(CurInstr->getSrc(0)); |
| 1018 if (Var && !Var->hasReg()) { | 1040 if (Var && !Var->hasReg()) { |
| 1041 Type VarTy = Var->getType(); | |
| 1019 int32_t Offset = Var->getStackOffset(); | 1042 int32_t Offset = Var->getStackOffset(); |
| 1020 Offset += StackAdjust; | 1043 Offset += StackAdjust; |
| 1021 if (!isLegalVariableStackOffset(Offset)) { | 1044 if (!isLegalVariableStackOffset(VarTy, Offset)) { |
| 1022 if (NewBaseReg) { | 1045 if (NewBaseReg) { |
| 1023 int32_t OffsetDiff = Offset - NewBaseOffset; | 1046 int32_t OffsetDiff = Offset - NewBaseOffset; |
| 1024 if (isLegalVariableStackOffset(OffsetDiff)) { | 1047 if (isLegalVariableStackOffset(VarTy, OffsetDiff)) { |
| 1025 StackVariable *NewVar = | 1048 StackVariable *NewVar = |
| 1026 Func->makeVariable<StackVariable>(stackSlotType()); | 1049 Func->makeVariable<StackVariable>(stackSlotType()); |
| 1027 NewVar->setMustNotHaveReg(); | 1050 NewVar->setMustNotHaveReg(); |
| 1028 NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum()); | 1051 NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum()); |
| 1029 NewVar->setStackOffset(OffsetDiff); | 1052 NewVar->setStackOffset(OffsetDiff); |
| 1030 _mov(Dest, NewVar); | 1053 _mov(Dest, NewVar); |
| 1031 MovInst->setDeleted(); | 1054 CurInstr->setDeleted(); |
| 1032 continue; | 1055 continue; |
| 1033 } | 1056 } |
| 1034 } | 1057 } |
| 1035 StackVariable *LegalVar = legalizeVariableSlot(Var, OrigBaseReg); | 1058 StackVariable *LegalVar = legalizeVariableSlot(Var, OrigBaseReg); |
| 1036 assert(LegalVar != Var); | 1059 assert(LegalVar != Var); |
| 1037 _mov(Dest, LegalVar); | 1060 _mov(Dest, LegalVar); |
| 1038 MovInst->setDeleted(); | 1061 CurInstr->setDeleted(); |
| 1039 NewBaseReg = LegalVar; | 1062 NewBaseReg = LegalVar; |
| 1040 NewBaseOffset = Offset; | 1063 NewBaseOffset = Offset; |
| 1041 continue; | 1064 continue; |
| 1042 } | 1065 } |
| 1043 } | 1066 } |
| 1044 } | 1067 } |
| 1045 } | 1068 } |
| 1046 } | 1069 } |
| 1047 | 1070 |
| 1048 Operand *TargetARM32::loOperand(Operand *Operand) { | 1071 Operand *TargetARM32::loOperand(Operand *Operand) { |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1420 _mul(T_Acc, Src0RLo, Src1RHi); | 1443 _mul(T_Acc, Src0RLo, Src1RHi); |
| 1421 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); | 1444 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); |
| 1422 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); | 1445 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); |
| 1423 _add(T_Hi, T_Hi1, T_Acc1); | 1446 _add(T_Hi, T_Hi1, T_Acc1); |
| 1424 _mov(DestLo, T_Lo); | 1447 _mov(DestLo, T_Lo); |
| 1425 _mov(DestHi, T_Hi); | 1448 _mov(DestHi, T_Hi); |
| 1426 return; | 1449 return; |
| 1427 } | 1450 } |
| 1428 case InstArithmetic::Shl: { | 1451 case InstArithmetic::Shl: { |
| 1429 // a=b<<c ==> | 1452 // a=b<<c ==> |
| 1453 // pnacl-llc does: | |
| 1454 // rsb T, Src1RLo, #32 | |
| 1455 // lsr T, Src0RLo, T | |
| 1456 // orr Src0RHi, T, Src0RHi, lsl Src1RLo | |
|
Jim Stichnoth
2015/09/24 05:57:13
I don't think this is a correct abstraction of wha
John
2015/09/24 21:28:40
Done.
| |
| 1457 // sub T, Src1RLo, #32 | |
| 1458 // cmp T, #0 | |
| 1459 // lslge Src0RHi, Src0RLo, T | |
| 1460 // lsl Src0RLo, Src0RLo, Src1RLo | |
| 1461 // | |
| 1430 // GCC 4.8 does: | 1462 // GCC 4.8 does: |
| 1431 // sub t_c1, c.lo, #32 | 1463 // sub t_c1, c.lo, #32 |
| 1432 // lsl t_hi, b.hi, c.lo | 1464 // lsl t_hi, b.hi, c.lo |
| 1433 // orr t_hi, t_hi, b.lo, lsl t_c1 | 1465 // orr t_hi, t_hi, b.lo, lsl t_c1 |
| 1434 // rsb t_c2, c.lo, #32 | 1466 // rsb t_c2, c.lo, #32 |
| 1435 // orr t_hi, t_hi, b.lo, lsr t_c2 | 1467 // orr t_hi, t_hi, b.lo, lsr t_c2 |
| 1436 // lsl t_lo, b.lo, c.lo | 1468 // lsl t_lo, b.lo, c.lo |
| 1437 // a.lo = t_lo | 1469 // a.lo = t_lo |
| 1438 // a.hi = t_hi | 1470 // a.hi = t_hi |
| 1471 // | |
| 1472 // These are incompatible, therefore we mimic pnacl-llc. | |
| 1439 // Can be strength-reduced for constant-shifts, but we don't do that for | 1473 // Can be strength-reduced for constant-shifts, but we don't do that for |
| 1440 // now. | 1474 // now. |
| 1441 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. On | 1475 // 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 | 1476 // 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. | 1477 // saturate to the range 0-32, so the negative value will saturate to 32. |
| 1444 Variable *T_Hi = makeReg(IceType_i32); | |
| 1445 Variable *Src1RLo = legalizeToReg(Src1Lo); | 1478 Variable *Src1RLo = legalizeToReg(Src1Lo); |
| 1446 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | 1479 Variable *T = makeReg(IceType_i32); |
| 1447 Variable *T_C1 = makeReg(IceType_i32); | 1480 Constant *_32 = Ctx->getConstantInt32(32); |
| 1448 Variable *T_C2 = makeReg(IceType_i32); | 1481 Constant *_0 = Ctx->getConstantZero(IceType_i32); |
| 1449 _sub(T_C1, Src1RLo, ThirtyTwo); | 1482 _rsb(T, Src1RLo, _32); |
| 1450 _lsl(T_Hi, Src0RHi, Src1RLo); | 1483 Variable *T1 = makeReg(IceType_i32); |
|
Jim Stichnoth
2015/09/24 05:57:13
Suggestion: I think the pseudo-assembly reads easi
John
2015/09/24 21:28:40
Done.
| |
| 1451 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1484 _lsr(T1, Src0RLo, T); |
| 1452 OperandARM32::LSL, T_C1)); | 1485 Variable *T3 = makeReg(IceType_i32); |
| 1453 _rsb(T_C2, Src1RLo, ThirtyTwo); | 1486 _orr(T3, T1, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, |
| 1454 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1487 OperandARM32::LSL, Src1RLo)); |
| 1455 OperandARM32::LSR, T_C2)); | 1488 Variable *T2 = makeReg(IceType_i32); |
| 1456 _mov(DestHi, T_Hi); | 1489 _sub(T2, Src1RLo, _32); |
| 1457 Variable *T_Lo = makeReg(IceType_i32); | 1490 _cmp(T2, _0); |
| 1458 // _mov seems to sometimes have better register preferencing than lsl. | 1491 _lsl(T3, Src0RLo, T2, CondARM32::GE); |
| 1459 // Otherwise mov w/ lsl shifted register is a pseudo-instruction that | 1492 _set_dest_nonkillable(); |
| 1460 // maps to lsl. | 1493 Variable *T5 = makeReg(IceType_i32); |
| 1461 _mov(T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1494 _lsl(T5, Src0RLo, Src1RLo); |
| 1462 OperandARM32::LSL, Src1RLo)); | 1495 _mov(DestLo, T5); |
| 1463 _mov(DestLo, T_Lo); | 1496 _mov(DestHi, T3); |
| 1464 return; | 1497 return; |
| 1465 } | 1498 } |
| 1466 case InstArithmetic::Lshr: | 1499 case InstArithmetic::Lshr: |
| 1467 // a=b>>c (unsigned) ==> | 1500 // a=b>>c (unsigned) ==> |
| 1501 // pnacl-llc does: | |
| 1502 // lsr Src0RLo, Src0RLo, Src1RLo | |
| 1503 // rsb T, Src1RLo, #32 | |
| 1504 // orr Src0RLo, Src0RLo, Src0RHi, lsl T | |
| 1505 // sub T, Src1RLo, #32 | |
| 1506 // cmp T, #0 | |
| 1507 // lsrge Src0RLo, Src0RHi, T | |
| 1508 // lsr Src0RHi, Src0RHi, Src1RLo | |
| 1509 // | |
| 1468 // GCC 4.8 does: | 1510 // GCC 4.8 does: |
| 1469 // rsb t_c1, c.lo, #32 | 1511 // rsb t_c1, c.lo, #32 |
| 1470 // lsr t_lo, b.lo, c.lo | 1512 // lsr t_lo, b.lo, c.lo |
| 1471 // orr t_lo, t_lo, b.hi, lsl t_c1 | 1513 // orr t_lo, t_lo, b.hi, lsl t_c1 |
| 1472 // sub t_c2, c.lo, #32 | 1514 // sub t_c2, c.lo, #32 |
| 1473 // orr t_lo, t_lo, b.hi, lsr t_c2 | 1515 // orr t_lo, t_lo, b.hi, lsr t_c2 |
| 1474 // lsr t_hi, b.hi, c.lo | 1516 // lsr t_hi, b.hi, c.lo |
| 1475 // a.lo = t_lo | 1517 // a.lo = t_lo |
| 1476 // a.hi = t_hi | 1518 // a.hi = t_hi |
| 1519 // | |
| 1520 // These are incompatible, therefore we mimic pnacl-llc. | |
| 1477 case InstArithmetic::Ashr: { | 1521 case InstArithmetic::Ashr: { |
| 1478 // a=b>>c (signed) ==> ... | 1522 // a=b>>c (signed) ==> ... |
| 1479 // Ashr is similar, but the sub t_c2, c.lo, #32 should set flags, and the | 1523 // |
| 1480 // next orr should be conditioned on PLUS. The last two right shifts | 1524 // Ashr is similar, with _asr instead of _lsr. |
| 1481 // should also be arithmetic. | 1525 const bool IsAshr = Inst->getOp() == InstArithmetic::Ashr; |
| 1482 bool IsAshr = Inst->getOp() == InstArithmetic::Ashr; | 1526 Variable *T = makeReg(IceType_i32); |
| 1483 Variable *T_Lo = makeReg(IceType_i32); | |
| 1484 Variable *Src1RLo = legalizeToReg(Src1Lo); | 1527 Variable *Src1RLo = legalizeToReg(Src1Lo); |
| 1485 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | 1528 Constant *_32 = Ctx->getConstantInt32(32); |
| 1486 Variable *T_C1 = makeReg(IceType_i32); | 1529 Constant *_0 = Ctx->getConstantZero(IceType_i32); |
| 1487 Variable *T_C2 = makeReg(IceType_i32); | 1530 Variable *T1 = makeReg(IceType_i32); |
| 1488 _rsb(T_C1, Src1RLo, ThirtyTwo); | 1531 _lsr(T1, Src0RLo, Src1RLo); |
| 1489 _lsr(T_Lo, Src0RLo, Src1RLo); | 1532 _rsb(T, Src1RLo, _32); |
| 1490 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | 1533 Variable *T2 = makeReg(IceType_i32); |
| 1491 OperandARM32::LSL, T_C1)); | 1534 _orr(T2, T1, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, |
| 1492 OperandARM32::ShiftKind RShiftKind; | 1535 OperandARM32::LSL, T)); |
| 1493 CondARM32::Cond Pred; | 1536 Variable *T3 = makeReg(IceType_i32); |
| 1537 _sub(T3, Src1RLo, _32); | |
| 1538 _cmp(T3, _0); | |
| 1539 Variable *T4 = makeReg(IceType_i32); | |
| 1494 if (IsAshr) { | 1540 if (IsAshr) { |
| 1495 _subs(T_C2, Src1RLo, ThirtyTwo); | 1541 _asr(T2, Src0RHi, T3, CondARM32::GE); |
| 1496 RShiftKind = OperandARM32::ASR; | 1542 _set_dest_nonkillable(); |
| 1497 Pred = CondARM32::PL; | 1543 _asr(T4, Src0RHi, Src1RLo); |
| 1498 } else { | 1544 } else { |
| 1499 _sub(T_C2, Src1RLo, ThirtyTwo); | 1545 _lsr(T2, Src0RHi, T3, CondARM32::GE); |
| 1500 RShiftKind = OperandARM32::LSR; | 1546 _set_dest_nonkillable(); |
| 1501 Pred = CondARM32::AL; | 1547 _lsr(T4, Src0RHi, Src1RLo); |
| 1502 } | 1548 } |
| 1503 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | 1549 _mov(DestLo, T2); |
| 1504 RShiftKind, T_C2), | 1550 _mov(DestHi, T4); |
| 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; | 1551 return; |
| 1512 } | 1552 } |
| 1513 case InstArithmetic::Fadd: | 1553 case InstArithmetic::Fadd: |
| 1514 case InstArithmetic::Fsub: | 1554 case InstArithmetic::Fsub: |
| 1515 case InstArithmetic::Fmul: | 1555 case InstArithmetic::Fmul: |
| 1516 case InstArithmetic::Fdiv: | 1556 case InstArithmetic::Fdiv: |
| 1517 case InstArithmetic::Frem: | 1557 case InstArithmetic::Frem: |
| 1518 llvm_unreachable("FP instruction with i64 type"); | 1558 llvm_unreachable("FP instruction with i64 type"); |
| 1519 return; | 1559 return; |
| 1520 case InstArithmetic::Udiv: | 1560 case InstArithmetic::Udiv: |
| 1521 case InstArithmetic::Sdiv: | 1561 case InstArithmetic::Sdiv: |
| 1522 case InstArithmetic::Urem: | 1562 case InstArithmetic::Urem: |
| 1523 case InstArithmetic::Srem: | 1563 case InstArithmetic::Srem: |
| 1524 llvm_unreachable("Call-helper-involved instruction for i64 type " | 1564 llvm_unreachable("Call-helper-involved instruction for i64 type " |
| 1525 "should have already been handled before"); | 1565 "should have already been handled before"); |
| 1526 return; | 1566 return; |
| 1527 } | 1567 } |
| 1528 return; | 1568 return; |
| 1529 } else if (isVectorType(Dest->getType())) { | 1569 } else if (isVectorType(Dest->getType())) { |
| 1570 // Add a fake def to keep liveness consistent in the meantime. | |
| 1571 Variable *T = makeReg(Dest->getType()); | |
|
Jim Stichnoth
2015/09/24 05:57:13
What do you think about bundling these 4 statement
John
2015/09/24 21:28:40
I thought about that, but these are not going to b
| |
| 1572 Context.insert(InstFakeDef::create(Func, T)); | |
| 1573 _mov(Dest, T); | |
| 1530 UnimplementedError(Func->getContext()->getFlags()); | 1574 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; | 1575 return; |
| 1534 } | 1576 } |
| 1535 // Dest->getType() is a non-i64 scalar. | 1577 // Dest->getType() is a non-i64 scalar. |
| 1536 Variable *Src0R = legalizeToReg(Src0); | 1578 Variable *Src0R = legalizeToReg(Src0); |
| 1537 Variable *T = makeReg(Dest->getType()); | 1579 Variable *T = makeReg(Dest->getType()); |
| 1538 // Handle div/rem separately. They require a non-legalized Src1 to inspect | 1580 // 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 | 1581 // 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). | 1582 // difficult to determine (constant may be moved to a register). |
| 1541 switch (Inst->getOp()) { | 1583 switch (Inst->getOp()) { |
| 1542 default: | 1584 default: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1578 } | 1620 } |
| 1579 | 1621 |
| 1580 // Handle floating point arithmetic separately: they require Src1 to be | 1622 // Handle floating point arithmetic separately: they require Src1 to be |
| 1581 // legalized to a register. | 1623 // legalized to a register. |
| 1582 switch (Inst->getOp()) { | 1624 switch (Inst->getOp()) { |
| 1583 default: | 1625 default: |
| 1584 break; | 1626 break; |
| 1585 case InstArithmetic::Fadd: { | 1627 case InstArithmetic::Fadd: { |
| 1586 Variable *Src1R = legalizeToReg(Src1); | 1628 Variable *Src1R = legalizeToReg(Src1); |
| 1587 _vadd(T, Src0R, Src1R); | 1629 _vadd(T, Src0R, Src1R); |
| 1588 _vmov(Dest, T); | 1630 _mov(Dest, T); |
| 1589 return; | 1631 return; |
| 1590 } | 1632 } |
| 1591 case InstArithmetic::Fsub: { | 1633 case InstArithmetic::Fsub: { |
| 1592 Variable *Src1R = legalizeToReg(Src1); | 1634 Variable *Src1R = legalizeToReg(Src1); |
| 1593 _vsub(T, Src0R, Src1R); | 1635 _vsub(T, Src0R, Src1R); |
| 1594 _vmov(Dest, T); | 1636 _mov(Dest, T); |
| 1595 return; | 1637 return; |
| 1596 } | 1638 } |
| 1597 case InstArithmetic::Fmul: { | 1639 case InstArithmetic::Fmul: { |
| 1598 Variable *Src1R = legalizeToReg(Src1); | 1640 Variable *Src1R = legalizeToReg(Src1); |
| 1599 _vmul(T, Src0R, Src1R); | 1641 _vmul(T, Src0R, Src1R); |
| 1600 _vmov(Dest, T); | 1642 _mov(Dest, T); |
| 1601 return; | 1643 return; |
| 1602 } | 1644 } |
| 1603 case InstArithmetic::Fdiv: { | 1645 case InstArithmetic::Fdiv: { |
| 1604 Variable *Src1R = legalizeToReg(Src1); | 1646 Variable *Src1R = legalizeToReg(Src1); |
| 1605 _vdiv(T, Src0R, Src1R); | 1647 _vdiv(T, Src0R, Src1R); |
| 1606 _vmov(Dest, T); | 1648 _mov(Dest, T); |
| 1607 return; | 1649 return; |
| 1608 } | 1650 } |
| 1609 } | 1651 } |
| 1610 | 1652 |
| 1611 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); | 1653 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); |
| 1612 switch (Inst->getOp()) { | 1654 switch (Inst->getOp()) { |
| 1613 case InstArithmetic::_num: | 1655 case InstArithmetic::_num: |
| 1614 llvm_unreachable("Unknown arithmetic operator"); | 1656 llvm_unreachable("Unknown arithmetic operator"); |
| 1615 return; | 1657 return; |
| 1616 case InstArithmetic::Add: | 1658 case InstArithmetic::Add: |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1670 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 1712 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
| 1671 Variable *Dest = Inst->getDest(); | 1713 Variable *Dest = Inst->getDest(); |
| 1672 Operand *Src0 = Inst->getSrc(0); | 1714 Operand *Src0 = Inst->getSrc(0); |
| 1673 assert(Dest->getType() == Src0->getType()); | 1715 assert(Dest->getType() == Src0->getType()); |
| 1674 if (Dest->getType() == IceType_i64) { | 1716 if (Dest->getType() == IceType_i64) { |
| 1675 Src0 = legalizeUndef(Src0); | 1717 Src0 = legalizeUndef(Src0); |
| 1676 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); | 1718 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); |
| 1677 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex); | 1719 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex); |
| 1678 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1720 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1679 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1721 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1680 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 1722 Variable *T_Lo = makeReg(IceType_i32); |
| 1723 Variable *T_Hi = makeReg(IceType_i32); | |
| 1681 _mov(T_Lo, Src0Lo); | 1724 _mov(T_Lo, Src0Lo); |
| 1682 _mov(DestLo, T_Lo); | 1725 _mov(DestLo, T_Lo); |
| 1683 _mov(T_Hi, Src0Hi); | 1726 _mov(T_Hi, Src0Hi); |
| 1684 _mov(DestHi, T_Hi); | 1727 _mov(DestHi, T_Hi); |
| 1685 } else { | 1728 } else { |
| 1686 Operand *NewSrc; | 1729 Operand *NewSrc; |
| 1687 if (Dest->hasReg()) { | 1730 if (Dest->hasReg()) { |
| 1688 // If Dest already has a physical register, then legalize the Src operand | 1731 // If Dest already has a physical register, then legalize the Src operand |
| 1689 // into a Variable with the same register assignment. This especially | 1732 // into a Variable with the same register assignment. This especially |
| 1690 // helps allow the use of Flex operands. | 1733 // helps allow the use of Flex operands. |
| 1691 NewSrc = legalize(Src0, Legal_Reg | Legal_Flex, Dest->getRegNum()); | 1734 NewSrc = legalize(Src0, Legal_Reg | Legal_Flex, Dest->getRegNum()); |
| 1692 } else { | 1735 } else { |
| 1693 // Dest could be a stack operand. Since we could potentially need to do a | 1736 // 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 | 1737 // Store (and store can only have Register operands), legalize this to a |
| 1695 // register. | 1738 // register. |
| 1696 NewSrc = legalize(Src0, Legal_Reg); | 1739 NewSrc = legalize(Src0, Legal_Reg); |
| 1697 } | 1740 } |
| 1698 if (isVectorType(Dest->getType())) { | 1741 if (isVectorType(Dest->getType())) { |
| 1699 UnimplementedError(Func->getContext()->getFlags()); | 1742 Variable *SrcR = legalizeToReg(NewSrc); |
| 1743 _mov(Dest, SrcR); | |
| 1700 } else if (isFloatingType(Dest->getType())) { | 1744 } else if (isFloatingType(Dest->getType())) { |
| 1701 Variable *SrcR = legalizeToReg(NewSrc); | 1745 Variable *SrcR = legalizeToReg(NewSrc); |
| 1702 _vmov(Dest, SrcR); | 1746 _mov(Dest, SrcR); |
| 1703 } else { | 1747 } else { |
| 1704 _mov(Dest, NewSrc); | 1748 _mov(Dest, NewSrc); |
| 1705 } | 1749 } |
| 1706 } | 1750 } |
| 1707 } | 1751 } |
| 1708 | 1752 |
| 1709 void TargetARM32::lowerBr(const InstBr *Inst) { | 1753 void TargetARM32::lowerBr(const InstBr *Inst) { |
| 1710 if (Inst->isUnconditional()) { | 1754 if (Inst->isUnconditional()) { |
| 1711 _br(Inst->getTargetUnconditional()); | 1755 _br(Inst->getTargetUnconditional()); |
| 1712 return; | 1756 return; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1762 if (CC.I32InReg(&Reg)) { | 1806 if (CC.I32InReg(&Reg)) { |
| 1763 InRegs = true; | 1807 InRegs = true; |
| 1764 GPRArgs.push_back(std::make_pair(Arg, Reg)); | 1808 GPRArgs.push_back(std::make_pair(Arg, Reg)); |
| 1765 } | 1809 } |
| 1766 } | 1810 } |
| 1767 | 1811 |
| 1768 if (!InRegs) { | 1812 if (!InRegs) { |
| 1769 ParameterAreaSizeBytes = | 1813 ParameterAreaSizeBytes = |
| 1770 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | 1814 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); |
| 1771 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | 1815 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); |
| 1772 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); | 1816 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); |
| 1773 } | 1817 } |
| 1774 } | 1818 } |
| 1775 | 1819 |
| 1776 // Adjust the parameter area so that the stack is aligned. It is assumed that | 1820 // 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. | 1821 // the stack is already aligned at the start of the calling sequence. |
| 1778 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | 1822 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); |
| 1779 | 1823 |
| 1780 // Subtract the appropriate amount for the argument area. This also takes | 1824 // Subtract the appropriate amount for the argument area. This also takes |
| 1781 // care of setting the stack adjustment during emission. | 1825 // care of setting the stack adjustment during emission. |
| 1782 // | 1826 // |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1802 Addr = OperandARM32Mem::create(Func, Ty, SP, Loc); | 1846 Addr = OperandARM32Mem::create(Func, Ty, SP, Loc); |
| 1803 } else { | 1847 } else { |
| 1804 Variable *NewBase = Func->makeVariable(SP->getType()); | 1848 Variable *NewBase = Func->makeVariable(SP->getType()); |
| 1805 lowerArithmetic( | 1849 lowerArithmetic( |
| 1806 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); | 1850 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); |
| 1807 Addr = formMemoryOperand(NewBase, Ty); | 1851 Addr = formMemoryOperand(NewBase, Ty); |
| 1808 } | 1852 } |
| 1809 lowerStore(InstStore::create(Func, StackArg.first, Addr)); | 1853 lowerStore(InstStore::create(Func, StackArg.first, Addr)); |
| 1810 } | 1854 } |
| 1811 | 1855 |
| 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 | 1856 // Generate the call instruction. Assign its result to a temporary with high |
| 1826 // register allocation weight. | 1857 // register allocation weight. |
| 1827 Variable *Dest = Instr->getDest(); | 1858 Variable *Dest = Instr->getDest(); |
| 1828 // ReturnReg doubles as ReturnRegLo as necessary. | 1859 // ReturnReg doubles as ReturnRegLo as necessary. |
| 1829 Variable *ReturnReg = nullptr; | 1860 Variable *ReturnReg = nullptr; |
| 1830 Variable *ReturnRegHi = nullptr; | 1861 Variable *ReturnRegHi = nullptr; |
| 1831 if (Dest) { | 1862 if (Dest) { |
| 1832 switch (Dest->getType()) { | 1863 switch (Dest->getType()) { |
| 1833 case IceType_NUM: | 1864 case IceType_NUM: |
| 1834 llvm_unreachable("Invalid Call dest type"); | 1865 llvm_unreachable("Invalid Call dest type"); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1865 Operand *CallTarget = Instr->getCallTarget(); | 1896 Operand *CallTarget = Instr->getCallTarget(); |
| 1866 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = | 1897 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = |
| 1867 // Ctx->getFlags().getUseSandboxing(); | 1898 // Ctx->getFlags().getUseSandboxing(); |
| 1868 | 1899 |
| 1869 // Allow ConstantRelocatable to be left alone as a direct call, but force | 1900 // 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 | 1901 // other constants like ConstantInteger32 to be in a register and make it an |
| 1871 // indirect call. | 1902 // indirect call. |
| 1872 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 1903 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| 1873 CallTarget = legalize(CallTarget, Legal_Reg); | 1904 CallTarget = legalize(CallTarget, Legal_Reg); |
| 1874 } | 1905 } |
| 1906 | |
| 1907 // Copy arguments to be passed in registers to the appropriate registers. | |
| 1908 for (auto &FPArg : FPArgs) { | |
| 1909 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); | |
| 1910 Context.insert(InstFakeUse::create(Func, Reg)); | |
| 1911 } | |
| 1912 for (auto &GPRArg : GPRArgs) { | |
| 1913 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); | |
| 1914 // Generate a FakeUse of register arguments so that they do not get dead | |
| 1915 // code eliminated as a result of the FakeKill of scratch registers after | |
| 1916 // the call. | |
| 1917 Context.insert(InstFakeUse::create(Func, Reg)); | |
| 1918 } | |
| 1875 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); | 1919 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); |
| 1876 Context.insert(NewCall); | 1920 Context.insert(NewCall); |
| 1877 if (ReturnRegHi) | 1921 if (ReturnRegHi) |
| 1878 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 1922 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
| 1879 | 1923 |
| 1880 // Add the appropriate offset to SP. The call instruction takes care of | 1924 // Add the appropriate offset to SP. The call instruction takes care of |
| 1881 // resetting the stack offset during emission. | 1925 // resetting the stack offset during emission. |
| 1882 if (ParameterAreaSizeBytes) { | 1926 if (ParameterAreaSizeBytes) { |
| 1883 Operand *AddAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes), | 1927 Operand *AddAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes), |
| 1884 Legal_Reg | Legal_Flex); | 1928 Legal_Reg | Legal_Flex); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1901 // Assign the result of the call to Dest. | 1945 // Assign the result of the call to Dest. |
| 1902 if (ReturnReg) { | 1946 if (ReturnReg) { |
| 1903 if (ReturnRegHi) { | 1947 if (ReturnRegHi) { |
| 1904 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 1948 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 1905 Variable *DestLo = Dest64On32->getLo(); | 1949 Variable *DestLo = Dest64On32->getLo(); |
| 1906 Variable *DestHi = Dest64On32->getHi(); | 1950 Variable *DestHi = Dest64On32->getHi(); |
| 1907 _mov(DestLo, ReturnReg); | 1951 _mov(DestLo, ReturnReg); |
| 1908 _mov(DestHi, ReturnRegHi); | 1952 _mov(DestHi, ReturnRegHi); |
| 1909 } else { | 1953 } else { |
| 1910 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | 1954 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { |
| 1911 _vmov(Dest, ReturnReg); | 1955 _mov(Dest, ReturnReg); |
| 1912 } else { | 1956 } else { |
| 1913 assert(isIntegerType(Dest->getType()) && | 1957 assert(isIntegerType(Dest->getType()) && |
| 1914 typeWidthInBytes(Dest->getType()) <= 4); | 1958 typeWidthInBytes(Dest->getType()) <= 4); |
| 1915 _mov(Dest, ReturnReg); | 1959 _mov(Dest, ReturnReg); |
| 1916 } | 1960 } |
| 1917 } | 1961 } |
| 1918 } | 1962 } |
| 1919 } | 1963 } |
| 1920 | 1964 |
| 1965 namespace { | |
| 1966 void forceHiLoInReg(Variable64On32 *Var) { | |
| 1967 Var->getHi()->setMustHaveReg(); | |
| 1968 Var->getLo()->setMustHaveReg(); | |
| 1969 } | |
| 1970 } // end of anonymous namespace | |
| 1971 | |
| 1921 void TargetARM32::lowerCast(const InstCast *Inst) { | 1972 void TargetARM32::lowerCast(const InstCast *Inst) { |
| 1922 InstCast::OpKind CastKind = Inst->getCastKind(); | 1973 InstCast::OpKind CastKind = Inst->getCastKind(); |
| 1923 Variable *Dest = Inst->getDest(); | 1974 Variable *Dest = Inst->getDest(); |
| 1924 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 1975 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 1925 switch (CastKind) { | 1976 switch (CastKind) { |
| 1926 default: | 1977 default: |
| 1927 Func->setError("Cast type not supported"); | 1978 Func->setError("Cast type not supported"); |
| 1928 return; | 1979 return; |
| 1929 case InstCast::Sext: { | 1980 case InstCast::Sext: { |
| 1930 if (isVectorType(Dest->getType())) { | 1981 if (isVectorType(Dest->getType())) { |
| 1982 Variable *T = makeReg(Dest->getType()); | |
| 1983 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | |
| 1984 _mov(Dest, T); | |
| 1931 UnimplementedError(Func->getContext()->getFlags()); | 1985 UnimplementedError(Func->getContext()->getFlags()); |
| 1932 } else if (Dest->getType() == IceType_i64) { | 1986 } else if (Dest->getType() == IceType_i64) { |
| 1933 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 | 1987 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 |
| 1934 Constant *ShiftAmt = Ctx->getConstantInt32(31); | 1988 Constant *ShiftAmt = Ctx->getConstantInt32(31); |
| 1935 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1989 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1936 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1990 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1937 Variable *T_Lo = makeReg(DestLo->getType()); | 1991 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1938 if (Src0->getType() == IceType_i32) { | 1992 if (Src0->getType() == IceType_i32) { |
| 1939 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 1993 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 1940 _mov(T_Lo, Src0RF); | 1994 _mov(T_Lo, Src0RF); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1971 // t1 = sxt src; dst = t1 | 2025 // t1 = sxt src; dst = t1 |
| 1972 Variable *Src0R = legalizeToReg(Src0); | 2026 Variable *Src0R = legalizeToReg(Src0); |
| 1973 Variable *T = makeReg(Dest->getType()); | 2027 Variable *T = makeReg(Dest->getType()); |
| 1974 _sxt(T, Src0R); | 2028 _sxt(T, Src0R); |
| 1975 _mov(Dest, T); | 2029 _mov(Dest, T); |
| 1976 } | 2030 } |
| 1977 break; | 2031 break; |
| 1978 } | 2032 } |
| 1979 case InstCast::Zext: { | 2033 case InstCast::Zext: { |
| 1980 if (isVectorType(Dest->getType())) { | 2034 if (isVectorType(Dest->getType())) { |
| 2035 Variable *T = makeReg(Dest->getType()); | |
| 2036 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | |
| 2037 _mov(Dest, T); | |
| 1981 UnimplementedError(Func->getContext()->getFlags()); | 2038 UnimplementedError(Func->getContext()->getFlags()); |
| 1982 } else if (Dest->getType() == IceType_i64) { | 2039 } else if (Dest->getType() == IceType_i64) { |
| 1983 // t1=uxtb src; dst.lo=t1; dst.hi=0 | 2040 // t1=uxtb src; dst.lo=t1; dst.hi=0 |
| 1984 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 2041 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 1985 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2042 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1986 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2043 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1987 Variable *T_Lo = makeReg(DestLo->getType()); | 2044 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1988 // i32 and i1 can just take up the whole register. i32 doesn't need uxt, | 2045 // 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. | 2046 // while i1 will have an and mask later anyway. |
| 1990 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) { | 2047 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2017 // t1 = uxt src; dst = t1 | 2074 // t1 = uxt src; dst = t1 |
| 2018 Variable *Src0R = legalizeToReg(Src0); | 2075 Variable *Src0R = legalizeToReg(Src0); |
| 2019 Variable *T = makeReg(Dest->getType()); | 2076 Variable *T = makeReg(Dest->getType()); |
| 2020 _uxt(T, Src0R); | 2077 _uxt(T, Src0R); |
| 2021 _mov(Dest, T); | 2078 _mov(Dest, T); |
| 2022 } | 2079 } |
| 2023 break; | 2080 break; |
| 2024 } | 2081 } |
| 2025 case InstCast::Trunc: { | 2082 case InstCast::Trunc: { |
| 2026 if (isVectorType(Dest->getType())) { | 2083 if (isVectorType(Dest->getType())) { |
| 2084 Variable *T = makeReg(Dest->getType()); | |
| 2085 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | |
| 2086 _mov(Dest, T); | |
| 2027 UnimplementedError(Func->getContext()->getFlags()); | 2087 UnimplementedError(Func->getContext()->getFlags()); |
| 2028 } else { | 2088 } else { |
| 2029 if (Src0->getType() == IceType_i64) | 2089 if (Src0->getType() == IceType_i64) |
| 2030 Src0 = loOperand(Src0); | 2090 Src0 = loOperand(Src0); |
| 2031 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 2091 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 2032 // t1 = trunc Src0RF; Dest = t1 | 2092 // t1 = trunc Src0RF; Dest = t1 |
| 2033 Variable *T = makeReg(Dest->getType()); | 2093 Variable *T = makeReg(Dest->getType()); |
| 2034 _mov(T, Src0RF); | 2094 _mov(T, Src0RF); |
| 2035 if (Dest->getType() == IceType_i1) | 2095 if (Dest->getType() == IceType_i1) |
| 2036 _and(T, T, Ctx->getConstantInt1(1)); | 2096 _and(T, T, Ctx->getConstantInt1(1)); |
| 2037 _mov(Dest, T); | 2097 _mov(Dest, T); |
| 2038 } | 2098 } |
| 2039 break; | 2099 break; |
| 2040 } | 2100 } |
| 2041 case InstCast::Fptrunc: | 2101 case InstCast::Fptrunc: |
| 2042 case InstCast::Fpext: { | 2102 case InstCast::Fpext: { |
| 2043 // fptrunc: dest.f32 = fptrunc src0.fp64 | 2103 // fptrunc: dest.f32 = fptrunc src0.fp64 |
| 2044 // fpext: dest.f64 = fptrunc src0.fp32 | 2104 // fpext: dest.f64 = fptrunc src0.fp32 |
| 2045 const bool IsTrunc = CastKind == InstCast::Fptrunc; | 2105 const bool IsTrunc = CastKind == InstCast::Fptrunc; |
| 2046 if (isVectorType(Dest->getType())) { | 2106 if (isVectorType(Dest->getType())) { |
| 2107 Variable *T = makeReg(Dest->getType()); | |
| 2108 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | |
| 2109 _mov(Dest, T); | |
| 2047 UnimplementedError(Func->getContext()->getFlags()); | 2110 UnimplementedError(Func->getContext()->getFlags()); |
| 2048 break; | 2111 break; |
| 2049 } | 2112 } |
| 2050 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); | 2113 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); |
| 2051 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); | 2114 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); |
| 2052 Variable *Src0R = legalizeToReg(Src0); | 2115 Variable *Src0R = legalizeToReg(Src0); |
| 2053 Variable *T = makeReg(Dest->getType()); | 2116 Variable *T = makeReg(Dest->getType()); |
| 2054 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); | 2117 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); |
| 2055 _mov(Dest, T); | 2118 _mov(Dest, T); |
| 2056 break; | 2119 break; |
| 2057 } | 2120 } |
| 2058 case InstCast::Fptosi: | 2121 case InstCast::Fptosi: |
| 2059 case InstCast::Fptoui: { | 2122 case InstCast::Fptoui: { |
| 2123 if (isVectorType(Dest->getType())) { | |
| 2124 Variable *T = makeReg(Dest->getType()); | |
| 2125 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | |
| 2126 _mov(Dest, T); | |
| 2127 UnimplementedError(Func->getContext()->getFlags()); | |
| 2128 break; | |
| 2129 } | |
| 2130 | |
| 2131 const bool DestIsSigned = CastKind == InstCast::Fptosi; | |
| 2132 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); | |
| 2133 if (llvm::isa<Variable64On32>(Dest)) { | |
| 2134 const char *HelperName = | |
| 2135 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) | |
| 2136 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64); | |
| 2137 static constexpr SizeT MaxSrcs = 1; | |
| 2138 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); | |
| 2139 Call->addArg(Src0); | |
| 2140 lowerCall(Call); | |
| 2141 break; | |
| 2142 } | |
| 2060 // fptosi: | 2143 // fptosi: |
| 2061 // t1.fp = vcvt src0.fp | 2144 // t1.fp = vcvt src0.fp |
| 2062 // t2.i32 = vmov t1.fp | 2145 // t2.i32 = vmov t1.fp |
| 2063 // dest.int = conv t2.i32 @ Truncates the result if needed. | 2146 // dest.int = conv t2.i32 @ Truncates the result if needed. |
| 2064 // fptoui: | 2147 // fptoui: |
| 2065 // t1.fp = vcvt src0.fp | 2148 // t1.fp = vcvt src0.fp |
| 2066 // t2.u32 = vmov t1.fp | 2149 // t2.u32 = vmov t1.fp |
| 2067 // dest.uint = conv t2.u32 @ Truncates the result if needed. | 2150 // 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); | 2151 Variable *Src0R = legalizeToReg(Src0); |
| 2080 Variable *T_fp = makeReg(IceType_f32); | 2152 Variable *T_fp = makeReg(IceType_f32); |
| 2081 if (isFloat32Asserting32Or64(Src0->getType())) { | 2153 const InstARM32Vcvt::VcvtVariant Conversion = |
| 2082 _vcvt(T_fp, Src0R, | 2154 Src0IsF32 ? (DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui) |
| 2083 DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui); | 2155 : (DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui); |
| 2084 } else { | 2156 _vcvt(T_fp, Src0R, Conversion); |
| 2085 _vcvt(T_fp, Src0R, | |
| 2086 DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui); | |
| 2087 } | |
| 2088 Variable *T = makeReg(IceType_i32); | 2157 Variable *T = makeReg(IceType_i32); |
| 2089 _vmov(T, T_fp); | 2158 _mov(T, T_fp); |
| 2090 if (Dest->getType() != IceType_i32) { | 2159 if (Dest->getType() != IceType_i32) { |
| 2091 Variable *T_1 = makeReg(Dest->getType()); | 2160 Variable *T_1 = makeReg(Dest->getType()); |
| 2092 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); | 2161 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); |
| 2093 T = T_1; | 2162 T = T_1; |
| 2094 } | 2163 } |
| 2095 _mov(Dest, T); | 2164 _mov(Dest, T); |
| 2096 break; | 2165 break; |
| 2097 } | 2166 } |
| 2098 case InstCast::Sitofp: | 2167 case InstCast::Sitofp: |
| 2099 case InstCast::Uitofp: { | 2168 case InstCast::Uitofp: { |
| 2169 if (isVectorType(Dest->getType())) { | |
| 2170 Variable *T = makeReg(Dest->getType()); | |
| 2171 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | |
| 2172 _mov(Dest, T); | |
| 2173 UnimplementedError(Func->getContext()->getFlags()); | |
| 2174 break; | |
| 2175 } | |
| 2176 const bool SourceIsSigned = CastKind == InstCast::Sitofp; | |
| 2177 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); | |
| 2178 if (Src0->getType() == IceType_i64) { | |
| 2179 const char *HelperName = | |
| 2180 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) | |
| 2181 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64); | |
| 2182 static constexpr SizeT MaxSrcs = 1; | |
| 2183 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); | |
| 2184 Call->addArg(Src0); | |
| 2185 lowerCall(Call); | |
| 2186 break; | |
| 2187 } | |
| 2100 // sitofp: | 2188 // sitofp: |
| 2101 // t1.i32 = sext src.int @ sign-extends src0 if needed. | 2189 // t1.i32 = sext src.int @ sign-extends src0 if needed. |
| 2102 // t2.fp32 = vmov t1.i32 | 2190 // t2.fp32 = vmov t1.i32 |
| 2103 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 | 2191 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 |
| 2104 // uitofp: | 2192 // uitofp: |
| 2105 // t1.i32 = zext src.int @ zero-extends src0 if needed. | 2193 // t1.i32 = zext src.int @ zero-extends src0 if needed. |
| 2106 // t2.fp32 = vmov t1.i32 | 2194 // t2.fp32 = vmov t1.i32 |
| 2107 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 | 2195 // 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) { | 2196 if (Src0->getType() != IceType_i32) { |
| 2120 Variable *Src0R_32 = makeReg(IceType_i32); | 2197 Variable *Src0R_32 = makeReg(IceType_i32); |
| 2121 lowerCast(InstCast::create(Func, SourceIsSigned ? InstCast::Sext | 2198 lowerCast(InstCast::create(Func, SourceIsSigned ? InstCast::Sext |
| 2122 : InstCast::Zext, | 2199 : InstCast::Zext, |
| 2123 Src0R_32, Src0)); | 2200 Src0R_32, Src0)); |
| 2124 Src0 = Src0R_32; | 2201 Src0 = Src0R_32; |
| 2125 } | 2202 } |
| 2126 Variable *Src0R = legalizeToReg(Src0); | 2203 Variable *Src0R = legalizeToReg(Src0); |
| 2127 Variable *Src0R_f32 = makeReg(IceType_f32); | 2204 Variable *Src0R_f32 = makeReg(IceType_f32); |
| 2128 _vmov(Src0R_f32, Src0R); | 2205 _mov(Src0R_f32, Src0R); |
| 2129 Src0R = Src0R_f32; | 2206 Src0R = Src0R_f32; |
| 2130 Variable *T = makeReg(Dest->getType()); | 2207 Variable *T = makeReg(Dest->getType()); |
| 2131 if (isFloat32Asserting32Or64(Dest->getType())) { | 2208 const InstARM32Vcvt::VcvtVariant Conversion = |
| 2132 _vcvt(T, Src0R, | 2209 DestIsF32 |
| 2133 SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s); | 2210 ? (SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s) |
| 2134 } else { | 2211 : (SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d); |
| 2135 _vcvt(T, Src0R, | 2212 _vcvt(T, Src0R, Conversion); |
| 2136 SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d); | |
| 2137 } | |
| 2138 _mov(Dest, T); | 2213 _mov(Dest, T); |
| 2139 break; | 2214 break; |
| 2140 } | 2215 } |
| 2141 case InstCast::Bitcast: { | 2216 case InstCast::Bitcast: { |
| 2142 Operand *Src0 = Inst->getSrc(0); | 2217 Operand *Src0 = Inst->getSrc(0); |
| 2143 if (Dest->getType() == Src0->getType()) { | 2218 if (Dest->getType() == Src0->getType()) { |
| 2144 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); | 2219 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); |
| 2145 lowerAssign(Assign); | 2220 lowerAssign(Assign); |
| 2146 return; | 2221 return; |
| 2147 } | 2222 } |
| 2148 Type DestType = Dest->getType(); | 2223 Type DestType = Dest->getType(); |
| 2149 switch (DestType) { | 2224 switch (DestType) { |
| 2150 case IceType_NUM: | 2225 case IceType_NUM: |
| 2151 case IceType_void: | 2226 case IceType_void: |
| 2152 llvm::report_fatal_error("Unexpected bitcast."); | 2227 llvm::report_fatal_error("Unexpected bitcast."); |
| 2153 case IceType_i1: | 2228 case IceType_i1: |
| 2154 UnimplementedError(Func->getContext()->getFlags()); | 2229 UnimplementedError(Func->getContext()->getFlags()); |
| 2155 break; | 2230 break; |
| 2156 case IceType_v4i1: | |
| 2157 UnimplementedError(Func->getContext()->getFlags()); | |
| 2158 break; | |
| 2159 case IceType_i8: | 2231 case IceType_i8: |
| 2160 UnimplementedError(Func->getContext()->getFlags()); | 2232 UnimplementedError(Func->getContext()->getFlags()); |
| 2161 break; | 2233 break; |
| 2162 case IceType_i16: | 2234 case IceType_i16: |
| 2163 UnimplementedError(Func->getContext()->getFlags()); | 2235 UnimplementedError(Func->getContext()->getFlags()); |
| 2164 break; | 2236 break; |
| 2165 case IceType_i32: | 2237 case IceType_i32: |
| 2166 case IceType_f32: { | 2238 case IceType_f32: { |
| 2167 Variable *Src0R = legalizeToReg(Src0); | 2239 Variable *Src0R = legalizeToReg(Src0); |
| 2168 Variable *T = makeReg(DestType); | 2240 Variable *T = makeReg(DestType); |
| 2169 _vmov(T, Src0R); | 2241 _mov(T, Src0R); |
| 2170 lowerAssign(InstAssign::create(Func, Dest, T)); | 2242 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 2171 break; | 2243 break; |
| 2172 } | 2244 } |
| 2173 case IceType_i64: { | 2245 case IceType_i64: { |
| 2174 // t0, t1 <- src0 | 2246 // t0, t1 <- src0 |
| 2175 // dest[31..0] = t0 | 2247 // dest[31..0] = t0 |
| 2176 // dest[63..32] = t1 | 2248 // dest[63..32] = t1 |
| 2177 assert(Src0->getType() == IceType_f64); | 2249 assert(Src0->getType() == IceType_f64); |
| 2178 Variable *T0 = makeReg(IceType_i32); | 2250 auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 2179 Variable *T1 = makeReg(IceType_i32); | 2251 T->initHiLo(Func); |
| 2252 forceHiLoInReg(T); | |
| 2180 Variable *Src0R = legalizeToReg(Src0); | 2253 Variable *Src0R = legalizeToReg(Src0); |
| 2181 _vmov(InstARM32Vmov::RegisterPair(T0, T1), Src0R); | 2254 _mov(T, Src0R); |
| 2255 Context.insert(InstFakeDef::create(Func, T->getLo())); | |
| 2256 Context.insert(InstFakeDef::create(Func, T->getHi())); | |
| 2182 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 2257 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 2183 lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T0)); | 2258 lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T->getLo())); |
| 2184 lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T1)); | 2259 lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T->getHi())); |
| 2260 Context.insert(InstFakeUse::create(Func, T)); | |
| 2185 break; | 2261 break; |
| 2186 } | 2262 } |
| 2187 case IceType_f64: { | 2263 case IceType_f64: { |
| 2188 // T0 <- lo(src) | 2264 // T0 <- lo(src) |
| 2189 // T1 <- hi(src) | 2265 // T1 <- hi(src) |
| 2190 // vmov T2, T0, T1 | 2266 // vmov T2, T0, T1 |
| 2191 // Dest <- T2 | 2267 // Dest <- T2 |
| 2192 assert(Src0->getType() == IceType_i64); | 2268 assert(Src0->getType() == IceType_i64); |
| 2193 Variable *SrcLo = legalizeToReg(loOperand(Src0)); | 2269 auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 2194 Variable *SrcHi = legalizeToReg(hiOperand(Src0)); | 2270 Src64->initHiLo(Func); |
| 2195 Variable *T = makeReg(IceType_f64); | 2271 forceHiLoInReg(Src64); |
| 2196 _vmov(T, InstARM32Vmov::RegisterPair(SrcLo, SrcHi)); | 2272 Variable *T = Src64->getLo(); |
| 2273 _mov(T, legalizeToReg(loOperand(Src0))); | |
| 2274 T = Src64->getHi(); | |
| 2275 _mov(T, legalizeToReg(hiOperand(Src0))); | |
| 2276 T = makeReg(IceType_f64); | |
| 2277 Context.insert(InstFakeDef::create(Func, Src64)); | |
| 2278 _mov(T, Src64); | |
| 2279 Context.insert(InstFakeUse::create(Func, Src64->getLo())); | |
| 2280 Context.insert(InstFakeUse::create(Func, Src64->getHi())); | |
| 2197 lowerAssign(InstAssign::create(Func, Dest, T)); | 2281 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 2198 break; | 2282 break; |
| 2199 } | 2283 } |
| 2284 case IceType_v4i1: | |
| 2200 case IceType_v8i1: | 2285 case IceType_v8i1: |
| 2286 case IceType_v16i1: | |
| 2287 case IceType_v8i16: | |
| 2288 case IceType_v16i8: | |
| 2289 case IceType_v4f32: | |
| 2290 case IceType_v4i32: { | |
| 2291 // avoid cryptic liveness errors | |
| 2292 Variable *T = makeReg(DestType); | |
| 2293 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | |
| 2294 _mov(Dest, T); | |
| 2201 UnimplementedError(Func->getContext()->getFlags()); | 2295 UnimplementedError(Func->getContext()->getFlags()); |
| 2202 break; | 2296 break; |
| 2203 case IceType_v16i1: | 2297 } |
| 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 } | 2298 } |
| 2221 break; | 2299 break; |
| 2222 } | 2300 } |
| 2223 } | 2301 } |
| 2224 } | 2302 } |
| 2225 | 2303 |
| 2226 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { | 2304 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { |
| 2227 (void)Inst; | 2305 Variable *Dest = Inst->getDest(); |
| 2306 Type DestType = Dest->getType(); | |
| 2307 Variable *T = makeReg(DestType); | |
| 2308 Context.insert(InstFakeDef::create(Func, T)); | |
| 2309 _mov(Dest, T); | |
| 2228 UnimplementedError(Func->getContext()->getFlags()); | 2310 UnimplementedError(Func->getContext()->getFlags()); |
| 2229 } | 2311 } |
| 2230 | 2312 |
| 2231 namespace { | 2313 namespace { |
| 2232 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering | 2314 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering |
| 2233 // (and naming). | 2315 // (and naming). |
| 2234 enum { | 2316 enum { |
| 2235 #define X(val, CC0, CC1) _fcmp_ll_##val, | 2317 #define X(val, CC0, CC1) _fcmp_ll_##val, |
| 2236 FCMPARM32_TABLE | 2318 FCMPARM32_TABLE |
| 2237 #undef X | 2319 #undef X |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2262 { CondARM32::CC0, CondARM32::CC1 } \ | 2344 { CondARM32::CC0, CondARM32::CC1 } \ |
| 2263 , | 2345 , |
| 2264 FCMPARM32_TABLE | 2346 FCMPARM32_TABLE |
| 2265 #undef X | 2347 #undef X |
| 2266 }; | 2348 }; |
| 2267 } // end of anonymous namespace | 2349 } // end of anonymous namespace |
| 2268 | 2350 |
| 2269 void TargetARM32::lowerFcmp(const InstFcmp *Inst) { | 2351 void TargetARM32::lowerFcmp(const InstFcmp *Inst) { |
| 2270 Variable *Dest = Inst->getDest(); | 2352 Variable *Dest = Inst->getDest(); |
| 2271 if (isVectorType(Dest->getType())) { | 2353 if (isVectorType(Dest->getType())) { |
| 2272 UnimplementedError(Func->getContext()->getFlags()); | 2354 UnimplementedError(Func->getContext()->getFlags()); |
|
Jim Stichnoth
2015/09/24 05:57:13
Usually the UnimplementedError() comes after the p
John
2015/09/24 21:28:40
Done.
| |
| 2355 Variable *T = makeReg(Dest->getType()); | |
| 2356 Context.insert(InstFakeDef::create(Func, T)); | |
| 2357 _mov(Dest, T); | |
| 2273 return; | 2358 return; |
| 2274 } | 2359 } |
| 2275 | 2360 |
| 2276 Variable *Src0R = legalizeToReg(Inst->getSrc(0)); | 2361 Variable *Src0R = legalizeToReg(Inst->getSrc(0)); |
| 2277 Variable *Src1R = legalizeToReg(Inst->getSrc(1)); | 2362 Variable *Src1R = legalizeToReg(Inst->getSrc(1)); |
| 2278 Variable *T = makeReg(IceType_i32); | 2363 Variable *T = makeReg(IceType_i32); |
| 2279 _vcmp(Src0R, Src1R); | 2364 _vcmp(Src0R, Src1R); |
| 2280 _mov(T, Ctx->getConstantZero(IceType_i32)); | 2365 _mov(T, Ctx->getConstantZero(IceType_i32)); |
| 2281 _vmrs(); | 2366 _vmrs(); |
| 2282 Operand *One = Ctx->getConstantInt32(1); | 2367 Operand *One = Ctx->getConstantInt32(1); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2299 } | 2384 } |
| 2300 _mov(Dest, T); | 2385 _mov(Dest, T); |
| 2301 } | 2386 } |
| 2302 | 2387 |
| 2303 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { | 2388 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
| 2304 Variable *Dest = Inst->getDest(); | 2389 Variable *Dest = Inst->getDest(); |
| 2305 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 2390 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 2306 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | 2391 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| 2307 | 2392 |
| 2308 if (isVectorType(Dest->getType())) { | 2393 if (isVectorType(Dest->getType())) { |
| 2394 Variable *T = makeReg(Dest->getType()); | |
| 2395 Context.insert(InstFakeDef::create(Func, T)); | |
| 2396 _mov(Dest, T); | |
| 2309 UnimplementedError(Func->getContext()->getFlags()); | 2397 UnimplementedError(Func->getContext()->getFlags()); |
| 2310 return; | 2398 return; |
| 2311 } | 2399 } |
| 2312 | 2400 |
| 2313 // a=icmp cond, b, c ==> | 2401 // a=icmp cond, b, c ==> |
| 2314 // GCC does: | 2402 // GCC does: |
| 2315 // cmp b.hi, c.hi or cmp b.lo, c.lo | 2403 // cmp b.hi, c.hi or cmp b.lo, c.lo |
| 2316 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi | 2404 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi |
| 2317 // mov.<C1> t, #1 mov.<C1> t, #1 | 2405 // mov.<C1> t, #1 mov.<C1> t, #1 |
| 2318 // mov.<C2> t, #0 mov.<C2> t, #0 | 2406 // 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); | 2595 Call->addArg(Val); |
| 2508 lowerCall(Call); | 2596 lowerCall(Call); |
| 2509 // The popcount helpers always return 32-bit values, while the intrinsic's | 2597 // The popcount helpers always return 32-bit values, while the intrinsic's |
| 2510 // signature matches some 64-bit platform's native instructions and expect | 2598 // 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 | 2599 // 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 | 2600 // case the user doesn't do that in the IR or doesn't toss the bits via |
| 2513 // truncate. | 2601 // truncate. |
| 2514 if (Val->getType() == IceType_i64) { | 2602 if (Val->getType() == IceType_i64) { |
| 2515 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2603 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2516 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 2604 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 2517 Variable *T = nullptr; | 2605 Variable *T = makeReg(Zero->getType()); |
| 2518 _mov(T, Zero); | 2606 _mov(T, Zero); |
| 2519 _mov(DestHi, T); | 2607 _mov(DestHi, T); |
| 2520 } | 2608 } |
| 2521 return; | 2609 return; |
| 2522 } | 2610 } |
| 2523 case Intrinsics::Ctlz: { | 2611 case Intrinsics::Ctlz: { |
| 2524 // The "is zero undef" parameter is ignored and we always return a | 2612 // The "is zero undef" parameter is ignored and we always return a |
| 2525 // well-defined value. | 2613 // well-defined value. |
| 2526 Operand *Val = Instr->getArg(0); | 2614 Operand *Val = Instr->getArg(0); |
| 2527 Variable *ValLoR; | 2615 Variable *ValLoR; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2554 } else { | 2642 } else { |
| 2555 ValLoR = legalizeToReg(Val); | 2643 ValLoR = legalizeToReg(Val); |
| 2556 Variable *T = makeReg(IceType_i32); | 2644 Variable *T = makeReg(IceType_i32); |
| 2557 _rbit(T, ValLoR); | 2645 _rbit(T, ValLoR); |
| 2558 ValLoR = T; | 2646 ValLoR = T; |
| 2559 } | 2647 } |
| 2560 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); | 2648 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); |
| 2561 return; | 2649 return; |
| 2562 } | 2650 } |
| 2563 case Intrinsics::Fabs: { | 2651 case Intrinsics::Fabs: { |
| 2564 // Add a fake def to keep liveness consistent in the meantime. | 2652 Variable *Dest = Instr->getDest(); |
| 2565 Context.insert(InstFakeDef::create(Func, Instr->getDest())); | 2653 Type DestTy = Dest->getType(); |
| 2566 UnimplementedError(Func->getContext()->getFlags()); | 2654 Variable *T = makeReg(DestTy); |
| 2655 if (isVectorType(DestTy)) { | |
| 2656 // Add a fake def to keep liveness consistent in the meantime. | |
| 2657 Context.insert(InstFakeDef::create(Func, T)); | |
| 2658 _mov(Instr->getDest(), T); | |
| 2659 UnimplementedError(Func->getContext()->getFlags()); | |
| 2660 return; | |
| 2661 } | |
| 2662 _vabs(T, legalizeToReg(Instr->getArg(0))); | |
| 2663 _mov(Dest, T); | |
| 2567 return; | 2664 return; |
| 2568 } | 2665 } |
| 2569 case Intrinsics::Longjmp: { | 2666 case Intrinsics::Longjmp: { |
| 2570 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); | 2667 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); |
| 2571 Call->addArg(Instr->getArg(0)); | 2668 Call->addArg(Instr->getArg(0)); |
| 2572 Call->addArg(Instr->getArg(1)); | 2669 Call->addArg(Instr->getArg(1)); |
| 2573 lowerCall(Call); | 2670 lowerCall(Call); |
| 2574 return; | 2671 return; |
| 2575 } | 2672 } |
| 2576 case Intrinsics::Memcpy: { | 2673 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); | 2718 InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1); |
| 2622 Call->addArg(Instr->getArg(0)); | 2719 Call->addArg(Instr->getArg(0)); |
| 2623 lowerCall(Call); | 2720 lowerCall(Call); |
| 2624 return; | 2721 return; |
| 2625 } | 2722 } |
| 2626 case Intrinsics::Sqrt: { | 2723 case Intrinsics::Sqrt: { |
| 2627 Variable *Src = legalizeToReg(Instr->getArg(0)); | 2724 Variable *Src = legalizeToReg(Instr->getArg(0)); |
| 2628 Variable *Dest = Instr->getDest(); | 2725 Variable *Dest = Instr->getDest(); |
| 2629 Variable *T = makeReg(Dest->getType()); | 2726 Variable *T = makeReg(Dest->getType()); |
| 2630 _vsqrt(T, Src); | 2727 _vsqrt(T, Src); |
| 2631 _vmov(Dest, T); | 2728 _mov(Dest, T); |
| 2632 return; | 2729 return; |
| 2633 } | 2730 } |
| 2634 case Intrinsics::Stacksave: { | 2731 case Intrinsics::Stacksave: { |
| 2635 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2732 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 2636 Variable *Dest = Instr->getDest(); | 2733 Variable *Dest = Instr->getDest(); |
| 2637 _mov(Dest, SP); | 2734 _mov(Dest, SP); |
| 2638 return; | 2735 return; |
| 2639 } | 2736 } |
| 2640 case Intrinsics::Stackrestore: { | 2737 case Intrinsics::Stackrestore: { |
| 2641 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2738 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2667 legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); | 2764 legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); |
| 2668 _cmp(ValHiR, Zero); | 2765 _cmp(ValHiR, Zero); |
| 2669 Variable *T2 = makeReg(IceType_i32); | 2766 Variable *T2 = makeReg(IceType_i32); |
| 2670 _add(T2, T, ThirtyTwo); | 2767 _add(T2, T, ThirtyTwo); |
| 2671 _clz(T2, ValHiR, CondARM32::NE); | 2768 _clz(T2, ValHiR, CondARM32::NE); |
| 2672 // T2 is actually a source as well when the predicate is not AL (since it | 2769 // 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 | 2770 // may leave T2 alone). We use set_dest_nonkillable to prolong the liveness |
| 2674 // of T2 as if it was used as a source. | 2771 // of T2 as if it was used as a source. |
| 2675 _set_dest_nonkillable(); | 2772 _set_dest_nonkillable(); |
| 2676 _mov(DestLo, T2); | 2773 _mov(DestLo, T2); |
| 2677 Variable *T3 = nullptr; | 2774 Variable *T3 = makeReg(Zero->getType()); |
| 2678 _mov(T3, Zero); | 2775 _mov(T3, Zero); |
| 2679 _mov(DestHi, T3); | 2776 _mov(DestHi, T3); |
| 2680 return; | 2777 return; |
| 2681 } | 2778 } |
| 2682 _mov(Dest, T); | 2779 _mov(Dest, T); |
| 2683 return; | 2780 return; |
| 2684 } | 2781 } |
| 2685 | 2782 |
| 2686 void TargetARM32::lowerLoad(const InstLoad *Load) { | 2783 void TargetARM32::lowerLoad(const InstLoad *Load) { |
| 2687 // A Load instruction can be treated the same as an Assign instruction, after | 2784 // 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); | 2824 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); |
| 2728 Reg = S0; | 2825 Reg = S0; |
| 2729 } else if (Ty == IceType_f64) { | 2826 } else if (Ty == IceType_f64) { |
| 2730 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); | 2827 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); |
| 2731 Reg = D0; | 2828 Reg = D0; |
| 2732 } else if (isVectorType(Src0->getType())) { | 2829 } else if (isVectorType(Src0->getType())) { |
| 2733 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); | 2830 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); |
| 2734 Reg = Q0; | 2831 Reg = Q0; |
| 2735 } else { | 2832 } else { |
| 2736 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 2833 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| 2737 _mov(Reg, Src0F, CondARM32::AL, RegARM32::Reg_r0); | 2834 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); |
| 2835 _mov(Reg, Src0F, CondARM32::AL); | |
| 2738 } | 2836 } |
| 2739 } | 2837 } |
| 2740 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 2838 // 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 | 2839 // explicitly looks for a ret instruction as a marker for where to insert the |
| 2742 // frame removal instructions. addEpilog is responsible for restoring the | 2840 // frame removal instructions. addEpilog is responsible for restoring the |
| 2743 // "lr" register as needed prior to this ret instruction. | 2841 // "lr" register as needed prior to this ret instruction. |
| 2744 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 2842 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
| 2745 // Add a fake use of sp to make sure sp stays alive for the entire function. | 2843 // 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. | 2844 // Otherwise post-call sp adjustments get dead-code eliminated. |
| 2747 // TODO: Are there more places where the fake use should be inserted? E.g. | 2845 // 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. | 2846 // "void f(int n){while(1) g(n);}" may not have a ret instruction. |
| 2749 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2847 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 2750 Context.insert(InstFakeUse::create(Func, SP)); | 2848 Context.insert(InstFakeUse::create(Func, SP)); |
| 2751 } | 2849 } |
| 2752 | 2850 |
| 2753 void TargetARM32::lowerSelect(const InstSelect *Inst) { | 2851 void TargetARM32::lowerSelect(const InstSelect *Inst) { |
| 2754 Variable *Dest = Inst->getDest(); | 2852 Variable *Dest = Inst->getDest(); |
| 2755 Type DestTy = Dest->getType(); | 2853 Type DestTy = Dest->getType(); |
| 2756 Operand *SrcT = Inst->getTrueOperand(); | 2854 Operand *SrcT = Inst->getTrueOperand(); |
| 2757 Operand *SrcF = Inst->getFalseOperand(); | 2855 Operand *SrcF = Inst->getFalseOperand(); |
| 2758 Operand *Condition = Inst->getCondition(); | 2856 Operand *Condition = Inst->getCondition(); |
| 2759 | 2857 |
| 2760 if (isVectorType(DestTy)) { | 2858 if (isVectorType(DestTy)) { |
| 2859 Variable *T = makeReg(DestTy); | |
| 2860 Context.insert(InstFakeDef::create(Func, T)); | |
| 2861 _mov(Dest, T); | |
| 2761 UnimplementedError(Func->getContext()->getFlags()); | 2862 UnimplementedError(Func->getContext()->getFlags()); |
| 2762 return; | 2863 return; |
| 2763 } | 2864 } |
| 2764 // TODO(jvoung): handle folding opportunities. | 2865 // TODO(jvoung): handle folding opportunities. |
| 2765 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t | 2866 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t |
| 2766 Variable *CmpOpnd0 = legalizeToReg(Condition); | 2867 Variable *CmpOpnd0 = legalizeToReg(Condition); |
| 2767 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); | 2868 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); |
| 2768 _cmp(CmpOpnd0, CmpOpnd1); | 2869 _cmp(CmpOpnd0, CmpOpnd1); |
| 2769 static constexpr CondARM32::Cond Cond = CondARM32::NE; | 2870 static constexpr CondARM32::Cond Cond = CondARM32::NE; |
| 2770 if (DestTy == IceType_i64) { | 2871 if (DestTy == IceType_i64) { |
| 2771 SrcT = legalizeUndef(SrcT); | 2872 SrcT = legalizeUndef(SrcT); |
| 2772 SrcF = legalizeUndef(SrcF); | 2873 SrcF = legalizeUndef(SrcF); |
| 2773 // Set the low portion. | 2874 // Set the low portion. |
| 2774 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2875 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2775 Variable *TLo = nullptr; | |
| 2776 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); | 2876 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); |
| 2877 Variable *TLo = makeReg(SrcFLo->getType()); | |
| 2777 _mov(TLo, SrcFLo); | 2878 _mov(TLo, SrcFLo); |
| 2778 Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex); | 2879 Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex); |
| 2779 _mov_nonkillable(TLo, SrcTLo, Cond); | 2880 _mov_nonkillable(TLo, SrcTLo, Cond); |
| 2780 _mov(DestLo, TLo); | 2881 _mov(DestLo, TLo); |
| 2781 // Set the high portion. | 2882 // Set the high portion. |
| 2782 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2883 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2783 Variable *THi = nullptr; | |
| 2784 Operand *SrcFHi = legalize(hiOperand(SrcF), Legal_Reg | Legal_Flex); | 2884 Operand *SrcFHi = legalize(hiOperand(SrcF), Legal_Reg | Legal_Flex); |
| 2885 Variable *THi = makeReg(SrcFHi->getType()); | |
| 2785 _mov(THi, SrcFHi); | 2886 _mov(THi, SrcFHi); |
| 2786 Operand *SrcTHi = legalize(hiOperand(SrcT), Legal_Reg | Legal_Flex); | 2887 Operand *SrcTHi = legalize(hiOperand(SrcT), Legal_Reg | Legal_Flex); |
| 2787 _mov_nonkillable(THi, SrcTHi, Cond); | 2888 _mov_nonkillable(THi, SrcTHi, Cond); |
| 2788 _mov(DestHi, THi); | 2889 _mov(DestHi, THi); |
| 2789 return; | 2890 return; |
| 2790 } | 2891 } |
| 2791 | 2892 |
| 2792 if (isFloatingType(DestTy)) { | 2893 if (isFloatingType(DestTy)) { |
| 2793 Variable *T = makeReg(DestTy); | 2894 Variable *T = makeReg(DestTy); |
| 2794 SrcF = legalizeToReg(SrcF); | 2895 SrcF = legalizeToReg(SrcF); |
| 2795 assert(DestTy == SrcF->getType()); | 2896 assert(DestTy == SrcF->getType()); |
| 2796 _vmov(T, SrcF); | 2897 _mov(T, SrcF); |
| 2797 SrcT = legalizeToReg(SrcT); | 2898 SrcT = legalizeToReg(SrcT); |
| 2798 assert(DestTy == SrcT->getType()); | 2899 assert(DestTy == SrcT->getType()); |
| 2799 _vmov(T, SrcT, Cond); | 2900 _mov(T, SrcT, Cond); |
| 2800 _set_dest_nonkillable(); | 2901 _set_dest_nonkillable(); |
| 2801 _vmov(Dest, T); | 2902 _mov(Dest, T); |
| 2802 return; | 2903 return; |
| 2803 } | 2904 } |
| 2804 | 2905 |
| 2805 Variable *T = nullptr; | |
| 2806 SrcF = legalize(SrcF, Legal_Reg | Legal_Flex); | 2906 SrcF = legalize(SrcF, Legal_Reg | Legal_Flex); |
| 2907 Variable *T = makeReg(SrcF->getType()); | |
| 2807 _mov(T, SrcF); | 2908 _mov(T, SrcF); |
| 2808 SrcT = legalize(SrcT, Legal_Reg | Legal_Flex); | 2909 SrcT = legalize(SrcT, Legal_Reg | Legal_Flex); |
| 2809 _mov_nonkillable(T, SrcT, Cond); | 2910 _mov_nonkillable(T, SrcT, Cond); |
| 2810 _mov(Dest, T); | 2911 _mov(Dest, T); |
| 2811 } | 2912 } |
| 2812 | 2913 |
| 2813 void TargetARM32::lowerStore(const InstStore *Inst) { | 2914 void TargetARM32::lowerStore(const InstStore *Inst) { |
| 2814 Operand *Value = Inst->getData(); | 2915 Operand *Value = Inst->getData(); |
| 2815 Operand *Addr = Inst->getAddr(); | 2916 Operand *Addr = Inst->getAddr(); |
| 2816 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); | 2917 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
| 2817 Type Ty = NewAddr->getType(); | 2918 Type Ty = NewAddr->getType(); |
| 2818 | 2919 |
| 2819 if (Ty == IceType_i64) { | 2920 if (Ty == IceType_i64) { |
| 2820 Value = legalizeUndef(Value); | 2921 Value = legalizeUndef(Value); |
| 2821 Variable *ValueHi = legalizeToReg(hiOperand(Value)); | 2922 Variable *ValueHi = legalizeToReg(hiOperand(Value)); |
| 2822 Variable *ValueLo = legalizeToReg(loOperand(Value)); | 2923 Variable *ValueLo = legalizeToReg(loOperand(Value)); |
| 2823 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); | 2924 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); |
| 2824 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); | 2925 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); |
| 2825 } else { | 2926 } else { |
| 2826 if (isVectorType(Ty)) { | |
| 2827 UnimplementedError(Func->getContext()->getFlags()); | |
| 2828 } | |
| 2829 Variable *ValueR = legalizeToReg(Value); | 2927 Variable *ValueR = legalizeToReg(Value); |
| 2830 _str(ValueR, NewAddr); | 2928 _str(ValueR, NewAddr); |
| 2831 } | 2929 } |
| 2832 } | 2930 } |
| 2833 | 2931 |
| 2834 void TargetARM32::doAddressOptStore() { | 2932 void TargetARM32::doAddressOptStore() { |
| 2835 UnimplementedError(Func->getContext()->getFlags()); | 2933 UnimplementedError(Func->getContext()->getFlags()); |
| 2836 } | 2934 } |
| 2837 | 2935 |
| 2838 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 2936 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*/) { | 2969 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
| 2872 _trap(); | 2970 _trap(); |
| 2873 } | 2971 } |
| 2874 | 2972 |
| 2875 void TargetARM32::prelowerPhis() { | 2973 void TargetARM32::prelowerPhis() { |
| 2876 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); | 2974 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); |
| 2877 } | 2975 } |
| 2878 | 2976 |
| 2879 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | 2977 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { |
| 2880 Variable *Reg = makeReg(Ty, RegNum); | 2978 Variable *Reg = makeReg(Ty, RegNum); |
| 2979 Context.insert(InstFakeDef::create(Func, Reg)); | |
| 2881 UnimplementedError(Func->getContext()->getFlags()); | 2980 UnimplementedError(Func->getContext()->getFlags()); |
| 2882 return Reg; | 2981 return Reg; |
| 2883 } | 2982 } |
| 2884 | 2983 |
| 2885 // Helper for legalize() to emit the right code to lower an operand to a | 2984 // Helper for legalize() to emit the right code to lower an operand to a |
| 2886 // register of the appropriate type. | 2985 // register of the appropriate type. |
| 2887 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 2986 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
| 2888 Type Ty = Src->getType(); | 2987 Type Ty = Src->getType(); |
| 2889 Variable *Reg = makeReg(Ty, RegNum); | 2988 Variable *Reg = makeReg(Ty, RegNum); |
| 2890 if (isVectorType(Ty)) { | 2989 _mov(Reg, Src); |
| 2891 // TODO(jpp): Src must be a register, or an address with base register. | 2990 _mov(Reg, Src); |
|
Jim Stichnoth
2015/09/24 05:57:13
Should there be just one _mov() ?
John
2015/09/24 21:28:40
Done.
| |
| 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; | 2991 return Reg; |
| 2901 } | 2992 } |
| 2902 | 2993 |
| 2903 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 2994 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
| 2904 int32_t RegNum) { | 2995 int32_t RegNum) { |
| 2905 Type Ty = From->getType(); | 2996 Type Ty = From->getType(); |
| 2906 // Assert that a physical register is allowed. To date, all calls to | 2997 // Assert that a physical register is allowed. To date, all calls to |
| 2907 // legalize() allow a physical register. Legal_Flex converts registers to the | 2998 // legalize() allow a physical register. Legal_Flex converts registers to the |
| 2908 // right type OperandARM32FlexReg as needed. | 2999 // right type OperandARM32FlexReg as needed. |
| 2909 assert(Allowed & Legal_Reg); | 3000 assert(Allowed & Legal_Reg); |
| 2910 // Go through the various types of operands: OperandARM32Mem, | 3001 // Go through the various types of operands: OperandARM32Mem, |
| 2911 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if | 3002 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if |
| 2912 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we | 3003 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we |
| 2913 // can always copy to a register. | 3004 // can always copy to a register. |
| 2914 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { | 3005 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { |
| 3006 static const struct { | |
| 3007 bool CanHaveOffset; | |
| 3008 bool CanHaveIndex; | |
| 3009 } MemTraits[] = { | |
| 3010 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr) \ | |
| 3011 { (ubits) > 0, rraddr } \ | |
| 3012 , | |
| 3013 ICETYPEARM32_TABLE | |
| 3014 #undef X | |
| 3015 }; | |
| 2915 // Before doing anything with a Mem operand, we need to ensure that the | 3016 // Before doing anything with a Mem operand, we need to ensure that the |
| 2916 // Base and Index components are in physical registers. | 3017 // Base and Index components are in physical registers. |
| 2917 Variable *Base = Mem->getBase(); | 3018 Variable *Base = Mem->getBase(); |
| 2918 Variable *Index = Mem->getIndex(); | 3019 Variable *Index = Mem->getIndex(); |
| 3020 ConstantInteger32 *Offset = Mem->getOffset(); | |
| 3021 assert(Index == nullptr || Offset == nullptr); | |
| 2919 Variable *RegBase = nullptr; | 3022 Variable *RegBase = nullptr; |
| 2920 Variable *RegIndex = nullptr; | 3023 Variable *RegIndex = nullptr; |
| 2921 if (Base) { | 3024 if (Base) { |
| 2922 RegBase = legalizeToReg(Base); | 3025 RegBase = legalizeToReg(Base); |
| 2923 } | 3026 } |
| 2924 if (Index) { | 3027 if (Index) { |
| 2925 RegIndex = legalizeToReg(Index); | 3028 RegIndex = legalizeToReg(Index); |
| 3029 if (!MemTraits[Ty].CanHaveIndex) { | |
| 3030 Variable *T = makeReg(IceType_i32, getReservedTmpReg()); | |
| 3031 _add(T, RegBase, RegIndex); | |
| 3032 RegBase = T; | |
| 3033 RegIndex = nullptr; | |
| 3034 } | |
| 2926 } | 3035 } |
| 3036 if (Offset && Offset->getValue() != 0) { | |
| 3037 static constexpr bool SignExt = false; | |
| 3038 if (!MemTraits[Ty].CanHaveOffset || | |
| 3039 !OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset->getValue())) { | |
| 3040 Variable *T = legalizeToReg(Offset, getReservedTmpReg()); | |
| 3041 _add(T, T, RegBase); | |
| 3042 RegBase = T; | |
| 3043 Offset = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)); | |
| 3044 } | |
| 3045 } | |
| 3046 | |
| 2927 // Create a new operand if there was a change. | 3047 // Create a new operand if there was a change. |
| 2928 if (Base != RegBase || Index != RegIndex) { | 3048 if (Base != RegBase || Index != RegIndex) { |
| 2929 // There is only a reg +/- reg or reg + imm form. | 3049 // There is only a reg +/- reg or reg + imm form. |
| 2930 // Figure out which to re-create. | 3050 // Figure out which to re-create. |
| 2931 if (Mem->isRegReg()) { | 3051 if (RegBase && RegIndex) { |
| 2932 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, | 3052 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, |
| 2933 Mem->getShiftOp(), Mem->getShiftAmt(), | 3053 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 2934 Mem->getAddrMode()); | 3054 Mem->getAddrMode()); |
| 2935 } else { | 3055 } else { |
| 2936 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Mem->getOffset(), | 3056 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset, |
| 2937 Mem->getAddrMode()); | 3057 Mem->getAddrMode()); |
| 2938 } | 3058 } |
| 2939 } | 3059 } |
| 2940 if (!(Allowed & Legal_Mem)) { | 3060 if (Allowed & Legal_Mem) { |
| 3061 From = Mem; | |
| 3062 } else { | |
| 2941 Variable *Reg = makeReg(Ty, RegNum); | 3063 Variable *Reg = makeReg(Ty, RegNum); |
| 2942 if (isVectorType(Ty)) { | 3064 _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; | 3065 From = Reg; |
| 2950 } else { | |
| 2951 From = Mem; | |
| 2952 } | 3066 } |
| 2953 return From; | 3067 return From; |
| 2954 } | 3068 } |
| 2955 | 3069 |
| 2956 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { | 3070 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { |
| 2957 if (!(Allowed & Legal_Flex)) { | 3071 if (!(Allowed & Legal_Flex)) { |
| 2958 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { | 3072 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { |
| 2959 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { | 3073 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { |
| 2960 From = FlexReg->getReg(); | 3074 From = FlexReg->getReg(); |
| 2961 // Fall through and let From be checked as a Variable below, where it | 3075 // 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"; | 3468 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
| 3355 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 3469 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
| 3356 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 3470 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
| 3357 } | 3471 } |
| 3358 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 3472 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 3359 // However, for compatibility with current NaCl LLVM, don't claim that. | 3473 // 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"; | 3474 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 3361 } | 3475 } |
| 3362 | 3476 |
| 3363 } // end of namespace Ice | 3477 } // end of namespace Ice |
| OLD | NEW |