Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(409)

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1359193003: Subzero. Enables (most) crosstests for ARM32. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698