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