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

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1422753010: Subzero. ARM32. Address mode formation. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comment. Created 5 years, 1 month 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') | no next file » | 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
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 "Infinite-weight Variable has no register assigned"); 458 "Infinite-weight Variable has no register assigned");
459 } 459 }
460 int32_t Offset = Var->getStackOffset(); 460 int32_t Offset = Var->getStackOffset();
461 int32_t BaseRegNum = Var->getBaseRegNum(); 461 int32_t BaseRegNum = Var->getBaseRegNum();
462 if (BaseRegNum == Variable::NoRegister) { 462 if (BaseRegNum == Variable::NoRegister) {
463 BaseRegNum = getFrameOrStackReg(); 463 BaseRegNum = getFrameOrStackReg();
464 if (!hasFramePointer()) 464 if (!hasFramePointer())
465 Offset += getStackAdjustment(); 465 Offset += getStackAdjustment();
466 } 466 }
467 const Type VarTy = Var->getType(); 467 const Type VarTy = Var->getType();
468 if (!isLegalVariableStackOffset(VarTy, Offset)) { 468 if (!isLegalMemOffset(VarTy, Offset)) {
469 llvm::report_fatal_error("Illegal stack offset"); 469 llvm::report_fatal_error("Illegal stack offset");
470 } 470 }
471 Str << "[" << getRegName(BaseRegNum, VarTy); 471 Str << "[" << getRegName(BaseRegNum, VarTy);
472 if (Offset != 0) { 472 if (Offset != 0) {
473 Str << ", " << getConstantPrefix() << Offset; 473 Str << ", " << getConstantPrefix() << Offset;
474 } 474 }
475 Str << "]"; 475 Str << "]";
476 } 476 }
477 477
478 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { 478 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) {
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); 830 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes);
831 } 831 }
832 832
833 // Fill in stack offsets for locals. 833 // Fill in stack offsets for locals.
834 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, 834 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes,
835 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, 835 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize,
836 UsesFramePointer); 836 UsesFramePointer);
837 this->HasComputedFrame = true; 837 this->HasComputedFrame = true;
838 838
839 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { 839 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) {
840 OstreamLocker L(Func->getContext()); 840 OstreamLocker _(Func->getContext());
841 Ostream &Str = Func->getContext()->getStrDump(); 841 Ostream &Str = Func->getContext()->getStrDump();
842 842
843 Str << "Stack layout:\n"; 843 Str << "Stack layout:\n";
844 uint32_t SPAdjustmentPaddingSize = 844 uint32_t SPAdjustmentPaddingSize =
845 SpillAreaSizeBytes - LocalsSpillAreaSize - 845 SpillAreaSizeBytes - LocalsSpillAreaSize -
846 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; 846 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes;
847 Str << " in-args = " << InArgsSizeBytes << " bytes\n" 847 Str << " in-args = " << InArgsSizeBytes << " bytes\n"
848 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" 848 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n"
849 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n" 849 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n"
850 << " globals spill area = " << GlobalsSize << " bytes\n" 850 << " globals spill area = " << GlobalsSize << " bytes\n"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 Variable *RetValue = nullptr; 940 Variable *RetValue = nullptr;
941 if (RI->getSrcSize()) 941 if (RI->getSrcSize())
942 RetValue = llvm::cast<Variable>(RI->getSrc(0)); 942 RetValue = llvm::cast<Variable>(RI->getSrc(0));
943 _bundle_lock(); 943 _bundle_lock();
944 _bic(LR, LR, RetMask); 944 _bic(LR, LR, RetMask);
945 _ret(LR, RetValue); 945 _ret(LR, RetValue);
946 _bundle_unlock(); 946 _bundle_unlock();
947 RI->setDeleted(); 947 RI->setDeleted();
948 } 948 }
949 949
950 bool TargetARM32::isLegalVariableStackOffset(Type Ty, int32_t Offset) const { 950 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const {
951 constexpr bool SignExt = false; 951 constexpr bool ZeroExt = false;
952 return OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset); 952 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset);
953 } 953 }
954 954
955 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, 955 Variable *TargetARM32::newBaseRegister(int32_t OriginalOffset,
956 int32_t StackAdjust, 956 int32_t StackAdjust,
957 Variable *OrigBaseReg) { 957 Variable *OrigBaseReg) {
958 int32_t Offset = Var->getStackOffset() + StackAdjust; 958 int32_t Offset = OriginalOffset + StackAdjust;
959 // Legalize will likely need a movw/movt combination, but if the top bits are 959 // Legalize will likely need a movw/movt combination, but if the top bits are
960 // all 0 from negating the offset and subtracting, we could use that instead. 960 // all 0 from negating the offset and subtracting, we could use that instead.
961 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; 961 bool ShouldSub = (-Offset & 0xFFFF0000) == 0;
962 if (ShouldSub) 962 if (ShouldSub)
963 Offset = -Offset; 963 Offset = -Offset;
964 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), 964 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset),
965 Legal_Reg | Legal_Flex, getReservedTmpReg()); 965 Legal_Reg | Legal_Flex, getReservedTmpReg());
966 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); 966 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg());
967 if (ShouldSub) 967 if (ShouldSub)
968 _sub(ScratchReg, OrigBaseReg, OffsetVal); 968 _sub(ScratchReg, OrigBaseReg, OffsetVal);
969 else 969 else
970 _add(ScratchReg, OrigBaseReg, OffsetVal); 970 _add(ScratchReg, OrigBaseReg, OffsetVal);
971 StackVariable *NewVar = Func->makeVariable<StackVariable>(stackSlotType()); 971 return ScratchReg;
972 NewVar->setMustNotHaveReg(); 972 }
973 NewVar->setBaseRegNum(ScratchReg->getRegNum()); 973
974 constexpr int32_t NewOffset = 0; 974 StackVariable *TargetARM32::legalizeStackSlot(Type Ty, int32_t Offset,
975 NewVar->setStackOffset(NewOffset); 975 int32_t StackAdjust,
976 return NewVar; 976 Variable *OrigBaseReg,
977 Variable **NewBaseReg,
978 int32_t *NewBaseOffset) {
979 if (*NewBaseReg == nullptr) {
980 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg);
981 *NewBaseOffset = Offset + StackAdjust;
982 }
983
984 int32_t OffsetDiff = Offset + StackAdjust - *NewBaseOffset;
985 if (!isLegalMemOffset(Ty, OffsetDiff)) {
986 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg);
987 *NewBaseOffset = Offset + StackAdjust;
988 OffsetDiff = 0;
989 }
990
991 StackVariable *NewDest = Func->makeVariable<StackVariable>(Ty);
992 NewDest->setMustNotHaveReg();
993 NewDest->setBaseRegNum((*NewBaseReg)->getRegNum());
994 NewDest->setStackOffset(OffsetDiff);
995 return NewDest;
996 }
997
998 void TargetARM32::legalizeMovStackAddrImm(InstARM32Mov *MovInstr,
999 int32_t StackAdjust,
1000 Variable *OrigBaseReg,
1001 Variable **NewBaseReg,
1002 int32_t *NewBaseOffset) {
1003 Variable *Dest = MovInstr->getDest();
1004 assert(Dest != nullptr);
1005 Type DestTy = Dest->getType();
1006 assert(DestTy != IceType_i64);
1007
1008 Operand *Src = MovInstr->getSrc(0);
1009 Type SrcTy = Src->getType();
1010 assert(SrcTy != IceType_i64);
1011
1012 if (MovInstr->isMultiDest() || MovInstr->isMultiSource())
1013 return;
1014
1015 bool Legalized = false;
1016 if (!Dest->hasReg()) {
1017 assert(llvm::cast<Variable>(Src)->hasReg());
1018 const int32_t Offset = Dest->getStackOffset();
1019 if (!isLegalMemOffset(DestTy, Offset + StackAdjust)) {
1020 Legalized = true;
1021 Dest = legalizeStackSlot(DestTy, Offset, StackAdjust, OrigBaseReg,
1022 NewBaseReg, NewBaseOffset);
1023 }
1024 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) {
1025 if (!Var->hasReg()) {
1026 const int32_t Offset = Var->getStackOffset();
1027 if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) {
1028 Legalized = true;
1029 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg,
1030 NewBaseReg, NewBaseOffset);
1031 }
1032 }
1033 } else if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) {
1034 if (ConstantInteger32 *OffsetOp = Mem->getOffset()) {
1035 const int32_t Offset = OffsetOp->getValue();
1036 if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) {
1037 assert(Mem->getBase()->hasReg());
1038 assert(Mem->getBase()->getRegNum() == (int32_t)getFrameOrStackReg());
1039 Legalized = true;
1040 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg,
1041 NewBaseReg, NewBaseOffset);
1042 }
1043 }
1044 }
1045
1046 if (Legalized) {
1047 _mov(Dest, Src);
1048 MovInstr->setDeleted();
1049 }
977 } 1050 }
978 1051
979 void TargetARM32::legalizeStackSlots() { 1052 void TargetARM32::legalizeStackSlots() {
980 // If a stack variable's frame offset doesn't fit, convert from: 1053 // If a stack variable's frame offset doesn't fit, convert from:
981 // ldr X, OFF[SP] 1054 // ldr X, OFF[SP]
982 // to: 1055 // to:
983 // movw/movt TMP, OFF_PART 1056 // movw/movt TMP, OFF_PART
984 // add TMP, TMP, SP 1057 // add TMP, TMP, SP
985 // ldr X, OFF_MORE[TMP] 1058 // ldr X, OFF_MORE[TMP]
986 // 1059 //
987 // This is safe because we have reserved TMP, and add for ARM does not 1060 // This is safe because we have reserved TMP, and add for ARM does not
988 // clobber the flags register. 1061 // clobber the flags register.
989 Func->dump("Before legalizeStackSlots"); 1062 Func->dump("Before legalizeStackSlots");
990 assert(hasComputedFrame()); 1063 assert(hasComputedFrame());
991 // Early exit, if SpillAreaSizeBytes is really small. 1064 // Early exit, if SpillAreaSizeBytes is really small.
992 // TODO(jpp): this is not safe -- loads and stores of q registers can't have 1065 // TODO(jpp): this is not safe -- loads and stores of q registers can't have
993 // offsets. 1066 // offsets.
994 if (isLegalVariableStackOffset(IceType_v4i32, SpillAreaSizeBytes)) 1067 if (isLegalMemOffset(IceType_v4i32, SpillAreaSizeBytes))
995 return; 1068 return;
996 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); 1069 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg());
997 int32_t StackAdjust = 0; 1070 int32_t StackAdjust = 0;
998 // Do a fairly naive greedy clustering for now. Pick the first stack slot 1071 // Do a fairly naive greedy clustering for now. Pick the first stack slot
999 // that's out of bounds and make a new base reg using the architecture's temp 1072 // that's out of bounds and make a new base reg using the architecture's temp
1000 // register. If that works for the next slot, then great. Otherwise, create a 1073 // register. If that works for the next slot, then great. Otherwise, create a
1001 // new base register, clobbering the previous base register. Never share a 1074 // new base register, clobbering the previous base register. Never share a
1002 // base reg across different basic blocks. This isn't ideal if local and 1075 // base reg across different basic blocks. This isn't ideal if local and
1003 // multi-block variables are far apart and their references are interspersed. 1076 // multi-block variables are far apart and their references are interspersed.
1004 // It may help to be more coordinated about assign stack slot numbers and may 1077 // It may help to be more coordinated about assign stack slot numbers and may
1005 // help to assign smaller offsets to higher-weight variables so that they 1078 // help to assign smaller offsets to higher-weight variables so that they
1006 // don't depend on this legalization. 1079 // don't depend on this legalization.
1007 for (CfgNode *Node : Func->getNodes()) { 1080 for (CfgNode *Node : Func->getNodes()) {
1008 Context.init(Node); 1081 Context.init(Node);
1009 StackVariable *NewBaseReg = nullptr; 1082 Variable *NewBaseReg = nullptr;
1010 int32_t NewBaseOffset = 0; 1083 int32_t NewBaseOffset = 0;
1011 while (!Context.atEnd()) { 1084 while (!Context.atEnd()) {
1012 PostIncrLoweringContext PostIncrement(Context); 1085 PostIncrLoweringContext PostIncrement(Context);
1013 Inst *CurInstr = Context.getCur(); 1086 Inst *CurInstr = Context.getCur();
1014 Variable *Dest = CurInstr->getDest(); 1087 Variable *Dest = CurInstr->getDest();
1088
1015 // Check if the previous NewBaseReg is clobbered, and reset if needed. 1089 // Check if the previous NewBaseReg is clobbered, and reset if needed.
1016 if ((Dest && NewBaseReg && Dest->hasReg() && 1090 if ((Dest && NewBaseReg && Dest->hasReg() &&
1017 Dest->getRegNum() == NewBaseReg->getBaseRegNum()) || 1091 Dest->getRegNum() == NewBaseReg->getBaseRegNum()) ||
1018 llvm::isa<InstFakeKill>(CurInstr)) { 1092 llvm::isa<InstFakeKill>(CurInstr)) {
1019 NewBaseReg = nullptr; 1093 NewBaseReg = nullptr;
1020 NewBaseOffset = 0; 1094 NewBaseOffset = 0;
1021 } 1095 }
1096
1022 // The stack adjustment only matters if we are using SP instead of FP. 1097 // The stack adjustment only matters if we are using SP instead of FP.
1023 if (!hasFramePointer()) { 1098 if (!hasFramePointer()) {
1024 if (auto *AdjInst = llvm::dyn_cast<InstARM32AdjustStack>(CurInstr)) { 1099 if (auto *AdjInst = llvm::dyn_cast<InstARM32AdjustStack>(CurInstr)) {
1025 StackAdjust += AdjInst->getAmount(); 1100 StackAdjust += AdjInst->getAmount();
1026 NewBaseOffset += AdjInst->getAmount(); 1101 NewBaseOffset += AdjInst->getAmount();
1027 continue; 1102 continue;
1028 } 1103 }
1029 if (llvm::isa<InstARM32Call>(CurInstr)) { 1104 if (llvm::isa<InstARM32Call>(CurInstr)) {
1030 NewBaseOffset -= StackAdjust; 1105 NewBaseOffset -= StackAdjust;
1031 StackAdjust = 0; 1106 StackAdjust = 0;
1032 continue; 1107 continue;
1033 } 1108 }
1034 } 1109 }
1035 1110
1036 // For now, only Mov instructions can have stack variables. We need to 1111 // The Lowering ensures that ldr and str always have legal Mem operands.
1037 // know the type of instruction because we currently create a fresh one 1112 // The only other instruction that may access memory is mov.
1038 // to replace Dest/Source, rather than mutate in place.
1039 bool MayNeedOffsetRewrite = false;
1040 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { 1113 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) {
1041 MayNeedOffsetRewrite = 1114 legalizeMovStackAddrImm(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg,
1042 !MovInstr->isMultiDest() && !MovInstr->isMultiSource(); 1115 &NewBaseOffset);
1043 }
1044
1045 if (!MayNeedOffsetRewrite) {
1046 continue;
1047 }
1048
1049 assert(Dest != nullptr);
1050 Type DestTy = Dest->getType();
1051 assert(DestTy != IceType_i64);
1052 if (!Dest->hasReg()) {
1053 int32_t Offset = Dest->getStackOffset();
1054 Offset += StackAdjust;
1055 if (!isLegalVariableStackOffset(DestTy, Offset)) {
1056 if (NewBaseReg) {
1057 int32_t OffsetDiff = Offset - NewBaseOffset;
1058 if (isLegalVariableStackOffset(DestTy, OffsetDiff)) {
1059 StackVariable *NewDest =
1060 Func->makeVariable<StackVariable>(stackSlotType());
1061 NewDest->setMustNotHaveReg();
1062 NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum());
1063 NewDest->setStackOffset(OffsetDiff);
1064 Variable *NewDestVar = NewDest;
1065 _mov(NewDestVar, CurInstr->getSrc(0));
1066 CurInstr->setDeleted();
1067 continue;
1068 }
1069 }
1070 StackVariable *LegalDest =
1071 legalizeVariableSlot(Dest, StackAdjust, OrigBaseReg);
1072 assert(LegalDest != Dest);
1073 Variable *LegalDestVar = LegalDest;
1074 _mov(LegalDestVar, CurInstr->getSrc(0));
1075 CurInstr->setDeleted();
1076 NewBaseReg = LegalDest;
1077 NewBaseOffset = Offset;
1078 continue;
1079 }
1080 }
1081 assert(CurInstr->getSrcSize() == 1);
1082 Variable *Var = llvm::dyn_cast<Variable>(CurInstr->getSrc(0));
1083 if (Var && !Var->hasReg()) {
1084 Type VarTy = Var->getType();
1085 int32_t Offset = Var->getStackOffset();
1086 Offset += StackAdjust;
1087 if (!isLegalVariableStackOffset(VarTy, Offset)) {
1088 if (NewBaseReg) {
1089 int32_t OffsetDiff = Offset - NewBaseOffset;
1090 if (isLegalVariableStackOffset(VarTy, OffsetDiff)) {
1091 StackVariable *NewVar =
1092 Func->makeVariable<StackVariable>(stackSlotType());
1093 NewVar->setMustNotHaveReg();
1094 NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum());
1095 NewVar->setStackOffset(OffsetDiff);
1096 _mov(Dest, NewVar);
1097 CurInstr->setDeleted();
1098 continue;
1099 }
1100 }
1101 StackVariable *LegalVar =
1102 legalizeVariableSlot(Var, StackAdjust, OrigBaseReg);
1103 assert(LegalVar != Var);
1104 _mov(Dest, LegalVar);
1105 CurInstr->setDeleted();
1106 NewBaseReg = LegalVar;
1107 NewBaseOffset = Offset;
1108 continue;
1109 }
1110 } 1116 }
1111 } 1117 }
1112 } 1118 }
1113 } 1119 }
1114 1120
1115 Operand *TargetARM32::loOperand(Operand *Operand) { 1121 Operand *TargetARM32::loOperand(Operand *Operand) {
1116 assert(Operand->getType() == IceType_i64); 1122 assert(Operand->getType() == IceType_i64);
1117 if (Operand->getType() != IceType_i64) 1123 if (Operand->getType() != IceType_i64)
1118 return Operand; 1124 return Operand;
1119 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) 1125 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, 1170 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase,
1165 Base, Four)); 1171 Base, Four));
1166 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(), 1172 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(),
1167 Mem->getShiftOp(), Mem->getShiftAmt(), 1173 Mem->getShiftOp(), Mem->getShiftAmt(),
1168 Mem->getAddrMode()); 1174 Mem->getAddrMode());
1169 } else { 1175 } else {
1170 Variable *Base = Mem->getBase(); 1176 Variable *Base = Mem->getBase();
1171 ConstantInteger32 *Offset = Mem->getOffset(); 1177 ConstantInteger32 *Offset = Mem->getOffset();
1172 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); 1178 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4));
1173 int32_t NextOffsetVal = Offset->getValue() + 4; 1179 int32_t NextOffsetVal = Offset->getValue() + 4;
1174 const bool SignExt = false; 1180 constexpr bool ZeroExt = false;
1175 if (!OperandARM32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) { 1181 if (!OperandARM32Mem::canHoldOffset(SplitType, ZeroExt, NextOffsetVal)) {
1176 // We have to make a temp variable and add 4 to either Base or Offset. 1182 // We have to make a temp variable and add 4 to either Base or Offset.
1177 // If we add 4 to Offset, this will convert a non-RegReg addressing 1183 // If we add 4 to Offset, this will convert a non-RegReg addressing
1178 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows 1184 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows
1179 // RegReg addressing modes, prefer adding to base and replacing 1185 // RegReg addressing modes, prefer adding to base and replacing
1180 // instead. Thus we leave the old offset alone. 1186 // instead. Thus we leave the old offset alone.
1181 Constant *Four = Ctx->getConstantInt32(4); 1187 Constant *Four = Ctx->getConstantInt32(4);
1182 Variable *NewBase = Func->makeVariable(Base->getType()); 1188 Variable *NewBase = Func->makeVariable(Base->getType());
1183 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, 1189 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add,
1184 NewBase, Base, Four)); 1190 NewBase, Base, Four));
1185 Base = NewBase; 1191 Base = NewBase;
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
1812 if (Instr->isUnconditional()) { 1818 if (Instr->isUnconditional()) {
1813 _br(Instr->getTargetUnconditional()); 1819 _br(Instr->getTargetUnconditional());
1814 return; 1820 return;
1815 } 1821 }
1816 Operand *Cond = Instr->getCondition(); 1822 Operand *Cond = Instr->getCondition();
1817 1823
1818 CondARM32::Cond BrCondTrue0 = CondARM32::NE; 1824 CondARM32::Cond BrCondTrue0 = CondARM32::NE;
1819 CondARM32::Cond BrCondTrue1 = CondARM32::kNone; 1825 CondARM32::Cond BrCondTrue1 = CondARM32::kNone;
1820 CondARM32::Cond BrCondFalse = CondARM32::kNone; 1826 CondARM32::Cond BrCondFalse = CondARM32::kNone;
1821 if (!_mov_i1_to_flags(Cond, &BrCondTrue0, &BrCondTrue1, &BrCondFalse)) { 1827 if (!_mov_i1_to_flags(Cond, &BrCondTrue0, &BrCondTrue1, &BrCondFalse)) {
1822 // "Cond" was not fold. 1828 // "Cond" was not folded.
1823 Type Ty = Cond->getType(); 1829 Type Ty = Cond->getType();
1824 Variable *Src0R = legalizeToReg(Cond); 1830 Variable *Src0R = legalizeToReg(Cond);
1825 assert(Ty == IceType_i1); 1831 assert(Ty == IceType_i1);
1826 if (Ty != IceType_i32) 1832 if (Ty != IceType_i32)
1827 _uxt(Src0R, Src0R); 1833 _uxt(Src0R, Src0R);
1828 Constant *_0 = Ctx->getConstantZero(IceType_i32); 1834 Constant *_0 = Ctx->getConstantZero(IceType_i32);
1829 _cmp(Src0R, _0); 1835 _cmp(Src0R, _0);
1830 BrCondTrue0 = CondARM32::NE; 1836 BrCondTrue0 = CondARM32::NE;
1831 } 1837 }
1832 1838
(...skipping 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after
3368 Type Ty = Load->getDest()->getType(); 3374 Type Ty = Load->getDest()->getType();
3369 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); 3375 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty);
3370 Variable *DestLoad = Load->getDest(); 3376 Variable *DestLoad = Load->getDest();
3371 3377
3372 // TODO(jvoung): handled folding opportunities. Sign and zero extension can 3378 // TODO(jvoung): handled folding opportunities. Sign and zero extension can
3373 // be folded into a load. 3379 // be folded into a load.
3374 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0); 3380 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0);
3375 lowerAssign(Assign); 3381 lowerAssign(Assign);
3376 } 3382 }
3377 3383
3378 void TargetARM32::doAddressOptLoad() {} 3384 namespace {
3385 void dumpAddressOpt(const Cfg *Func, const Variable *Base, int32_t Offset,
3386 const Variable *OffsetReg, int16_t OffsetRegShAmt,
3387 const Inst *Reason) {
3388 if (!BuildDefs::dump())
3389 return;
3390 if (!Func->isVerbose(IceV_AddrOpt))
3391 return;
3392 OstreamLocker _(Func->getContext());
3393 Ostream &Str = Func->getContext()->getStrDump();
3394 Str << "Instruction: ";
3395 Reason->dumpDecorated(Func);
3396 Str << " results in Base=";
3397 if (Base)
3398 Base->dump(Func);
3399 else
3400 Str << "<null>";
3401 Str << ", OffsetReg=";
3402 if (OffsetReg)
3403 OffsetReg->dump(Func);
3404 else
3405 Str << "<null>";
3406 Str << ", Shift=" << OffsetRegShAmt << ", Offset=" << Offset << "\n";
3407 }
3408
3409 bool matchAssign(const VariablesMetadata *VMetadata, Variable **Var,
3410 int32_t *Offset, const Inst **Reason) {
3411 // Var originates from Var=SrcVar ==> set Var:=SrcVar
3412 if (*Var == nullptr)
3413 return false;
3414 const Inst *VarAssign = VMetadata->getSingleDefinition(*Var);
3415 if (!VarAssign)
3416 return false;
3417 assert(!VMetadata->isMultiDef(*Var));
3418 if (!llvm::isa<InstAssign>(VarAssign))
3419 return false;
3420
3421 Operand *SrcOp = VarAssign->getSrc(0);
3422 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
3423 if (!VMetadata->isMultiDef(SrcVar) ||
3424 // TODO: ensure SrcVar stays single-BB
3425 false) {
3426 *Var = SrcVar;
3427 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
3428 int32_t MoreOffset = Const->getValue();
3429 int32_t NewOffset = MoreOffset + *Offset;
3430 if (Utils::WouldOverflowAdd(*Offset, MoreOffset))
3431 return false;
3432 *Var = nullptr;
3433 *Offset += NewOffset;
3434 }
3435
3436 *Reason = VarAssign;
3437 return true;
3438 }
3439
3440 return false;
3441 }
3442
3443 bool isAddOrSub(const Inst *Inst, InstArithmetic::OpKind *Kind) {
3444 if (const auto *Arith = llvm::dyn_cast<InstArithmetic>(Inst)) {
3445 switch (Arith->getOp()) {
3446 default:
3447 return false;
3448 case InstArithmetic::Add:
3449 case InstArithmetic::Sub:
3450 *Kind = Arith->getOp();
3451 return true;
3452 }
3453 }
3454 return false;
3455 }
3456
3457 bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, Variable **Base,
3458 Variable **OffsetReg, int32_t OffsetRegShamt,
3459 const Inst **Reason) {
3460 // OffsetReg==nullptr && Base is Base=Var1+Var2 ==>
3461 // set Base=Var1, OffsetReg=Var2, Shift=0
3462 if (*Base == nullptr)
3463 return false;
3464 if (*OffsetReg != nullptr)
3465 return false;
3466 (void)OffsetRegShamt;
3467 assert(OffsetRegShamt == 0);
3468 const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
3469 if (BaseInst == nullptr)
3470 return false;
3471 assert(!VMetadata->isMultiDef(*Base));
3472 if (BaseInst->getSrcSize() < 2)
3473 return false;
3474 auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0));
3475 if (!Var1)
3476 return false;
3477 if (VMetadata->isMultiDef(Var1))
3478 return false;
3479 auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1));
3480 if (!Var2)
3481 return false;
3482 if (VMetadata->isMultiDef(Var2))
3483 return false;
3484 InstArithmetic::OpKind _;
3485 if (!isAddOrSub(BaseInst, &_) ||
3486 // TODO: ensure Var1 and Var2 stay single-BB
3487 false)
3488 return false;
3489 *Base = Var1;
3490 *OffsetReg = Var2;
3491 // OffsetRegShamt is already 0.
3492 *Reason = BaseInst;
3493 return true;
3494 }
3495
3496 bool matchShiftedOffsetReg(const VariablesMetadata *VMetadata,
3497 Variable **OffsetReg, OperandARM32::ShiftKind *Kind,
3498 int32_t *OffsetRegShamt, const Inst **Reason) {
3499 // OffsetReg is OffsetReg=Var*Const && log2(Const)+Shift<=32 ==>
3500 // OffsetReg=Var, Shift+=log2(Const)
3501 // OffsetReg is OffsetReg=Var<<Const && Const+Shift<=32 ==>
3502 // OffsetReg=Var, Shift+=Const
3503 // OffsetReg is OffsetReg=Var>>Const && Const-Shift>=-32 ==>
3504 // OffsetReg=Var, Shift-=Const
3505 OperandARM32::ShiftKind NewShiftKind = OperandARM32::kNoShift;
3506 if (*OffsetReg == nullptr)
3507 return false;
3508 auto *IndexInst = VMetadata->getSingleDefinition(*OffsetReg);
3509 if (IndexInst == nullptr)
3510 return false;
3511 assert(!VMetadata->isMultiDef(*OffsetReg));
3512 if (IndexInst->getSrcSize() < 2)
3513 return false;
3514 auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst);
3515 if (ArithInst == nullptr)
3516 return false;
3517 auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0));
3518 if (Var == nullptr)
3519 return false;
3520 auto *Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1));
3521 if (Const == nullptr) {
3522 assert(!llvm::isa<ConstantInteger32>(ArithInst->getSrc(0)));
3523 return false;
3524 }
3525 if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32)
3526 return false;
3527
3528 uint32_t NewShamt = -1;
3529 switch (ArithInst->getOp()) {
3530 default:
3531 return false;
3532 case InstArithmetic::Shl: {
3533 NewShiftKind = OperandARM32::LSL;
3534 NewShamt = Const->getValue();
3535 if (NewShamt > 31)
3536 return false;
3537 } break;
3538 case InstArithmetic::Lshr: {
3539 NewShiftKind = OperandARM32::LSR;
3540 NewShamt = Const->getValue();
3541 if (NewShamt > 31)
3542 return false;
3543 } break;
3544 case InstArithmetic::Ashr: {
3545 NewShiftKind = OperandARM32::ASR;
3546 NewShamt = Const->getValue();
3547 if (NewShamt > 31)
3548 return false;
3549 } break;
3550 case InstArithmetic::Udiv:
3551 case InstArithmetic::Mul: {
3552 const uint32_t UnsignedConst = Const->getValue();
3553 NewShamt = llvm::findFirstSet(UnsignedConst);
3554 if (NewShamt != llvm::findLastSet(UnsignedConst)) {
3555 // First bit set is not the same as the last bit set, so Const is not
3556 // a power of 2.
3557 return false;
3558 }
3559 NewShiftKind = ArithInst->getOp() == InstArithmetic::Udiv
3560 ? OperandARM32::LSR
3561 : OperandARM32::LSL;
3562 } break;
3563 }
3564 // Allowed "transitions":
3565 // kNoShift -> * iff NewShamt < 31
3566 // LSL -> LSL iff NewShamt + OffsetRegShamt < 31
3567 // LSR -> LSR iff NewShamt + OffsetRegShamt < 31
3568 // ASR -> ASR iff NewShamt + OffsetRegShamt < 31
3569 if (*Kind != OperandARM32::kNoShift && *Kind != NewShiftKind) {
3570 return false;
3571 }
3572 const int32_t NewOffsetRegShamt = *OffsetRegShamt + NewShamt;
3573 if (NewOffsetRegShamt > 31)
3574 return false;
3575 *OffsetReg = Var;
3576 *OffsetRegShamt = NewOffsetRegShamt;
3577 *Kind = NewShiftKind;
3578 *Reason = IndexInst;
3579 return true;
3580 }
3581
3582 bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable **Base,
3583 int32_t *Offset, const Inst **Reason) {
3584 // Base is Base=Var+Const || Base is Base=Const+Var ==>
3585 // set Base=Var, Offset+=Const
3586 // Base is Base=Var-Const ==>
3587 // set Base=Var, Offset-=Const
3588 if (*Base == nullptr)
3589 return false;
3590 const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
3591 if (BaseInst == nullptr) {
3592 return false;
3593 }
3594 assert(!VMetadata->isMultiDef(*Base));
3595
3596 auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst);
3597 if (ArithInst == nullptr)
3598 return false;
3599 InstArithmetic::OpKind Kind;
3600 if (!isAddOrSub(ArithInst, &Kind))
3601 return false;
3602 bool IsAdd = Kind == InstArithmetic::Add;
3603 Operand *Src0 = ArithInst->getSrc(0);
3604 Operand *Src1 = ArithInst->getSrc(1);
3605 auto *Var0 = llvm::dyn_cast<Variable>(Src0);
3606 auto *Var1 = llvm::dyn_cast<Variable>(Src1);
3607 auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0);
3608 auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1);
3609 Variable *NewBase = nullptr;
3610 int32_t NewOffset = *Offset;
3611
3612 if (Var0 == nullptr && Const0 == nullptr) {
3613 assert(llvm::isa<ConstantRelocatable>(Src0));
3614 return false;
3615 }
3616
3617 if (Var1 == nullptr && Const1 == nullptr) {
3618 assert(llvm::isa<ConstantRelocatable>(Src1));
3619 return false;
3620 }
3621
3622 if (Var0 && Var1)
3623 // TODO(jpp): merge base/index splitting into here.
3624 return false;
3625 if (!IsAdd && Var1)
3626 return false;
3627 if (Var0)
3628 NewBase = Var0;
3629 else if (Var1)
3630 NewBase = Var1;
3631 // Compute the updated constant offset.
3632 if (Const0) {
3633 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue();
3634 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
3635 return false;
3636 NewOffset += MoreOffset;
3637 }
3638 if (Const1) {
3639 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue();
3640 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
3641 return false;
3642 NewOffset += MoreOffset;
3643 }
3644
3645 // Update the computed address parameters once we are sure optimization
3646 // is valid.
3647 *Base = NewBase;
3648 *Offset = NewOffset;
3649 *Reason = BaseInst;
3650 return true;
3651 }
3652 } // end of anonymous namespace
3653
3654 // ARM32 address modes:
3655 // ld/st i[8|16|32]: [reg], [reg +/- imm12], [pc +/- imm12],
3656 // [reg +/- reg << shamt5]
3657 // ld/st f[32|64] : [reg], [reg +/- imm8] , [pc +/- imm8]
3658 // ld/st vectors : [reg]
3659 //
3660 // For now, we don't handle address modes with Relocatables.
3661 namespace {
3662 // MemTraits contains per-type valid address mode information.
3663 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
3664 static_assert(!(shaddr) || rraddr, "Check ICETYPEARM32_TABLE::" #tag);
3665 ICETYPEARM32_TABLE
3666 #undef X
3667
3668 static const struct {
3669 int32_t ValidImmMask;
3670 bool CanHaveImm;
3671 bool CanHaveIndex;
3672 bool CanHaveShiftedIndex;
3673 } MemTraits[] = {
3674 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
3675 { (1 << ubits) - 1, (ubits) > 0, rraddr, shaddr, } \
3676 ,
3677 ICETYPEARM32_TABLE
3678 #undef X
3679 };
3680 static constexpr SizeT MemTraitsSize = llvm::array_lengthof(MemTraits);
3681 } // end of anonymous namespace
3682
3683 OperandARM32Mem *TargetARM32::formAddressingMode(Type Ty, Cfg *Func,
3684 const Inst *LdSt,
3685 Operand *Base) {
3686 assert(Base != nullptr);
3687 int32_t OffsetImm = 0;
3688 Variable *OffsetReg = nullptr;
3689 int32_t OffsetRegShamt = 0;
3690 OperandARM32::ShiftKind ShiftKind = OperandARM32::kNoShift;
3691
3692 Func->resetCurrentNode();
3693 if (Func->isVerbose(IceV_AddrOpt)) {
3694 OstreamLocker _(Func->getContext());
3695 Ostream &Str = Func->getContext()->getStrDump();
3696 Str << "\nAddress mode formation:\t";
3697 LdSt->dumpDecorated(Func);
3698 }
3699
3700 if (isVectorType(Ty))
3701 // vector loads and stores do not allow offsets, and only support the
3702 // "[reg]" addressing mode (the other supported modes are write back.)
3703 return nullptr;
3704
3705 auto *BaseVar = llvm::dyn_cast<Variable>(Base);
3706 if (BaseVar == nullptr)
3707 return nullptr;
3708
3709 (void)MemTraitsSize;
3710 assert(Ty < MemTraitsSize);
3711 auto *TypeTraits = &MemTraits[Ty];
3712 const bool CanHaveIndex = TypeTraits->CanHaveIndex;
3713 const bool CanHaveShiftedIndex = TypeTraits->CanHaveShiftedIndex;
3714 const bool CanHaveImm = TypeTraits->CanHaveImm;
3715 const int32_t ValidImmMask = TypeTraits->ValidImmMask;
3716 (void)ValidImmMask;
3717 assert(!CanHaveImm || ValidImmMask >= 0);
3718
3719 const VariablesMetadata *VMetadata = Func->getVMetadata();
3720 const Inst *Reason = nullptr;
3721
3722 do {
3723 if (Reason != nullptr) {
3724 dumpAddressOpt(Func, BaseVar, OffsetImm, OffsetReg, OffsetRegShamt,
3725 Reason);
3726 Reason = nullptr;
3727 }
3728
3729 if (matchAssign(VMetadata, &BaseVar, &OffsetImm, &Reason)) {
3730 continue;
3731 }
3732
3733 if (CanHaveIndex &&
3734 matchAssign(VMetadata, &OffsetReg, &OffsetImm, &Reason)) {
3735 continue;
3736 }
3737
3738 if (CanHaveIndex && matchCombinedBaseIndex(VMetadata, &BaseVar, &OffsetReg,
3739 OffsetRegShamt, &Reason)) {
3740 continue;
3741 }
3742
3743 if (CanHaveShiftedIndex) {
3744 if (matchShiftedOffsetReg(VMetadata, &OffsetReg, &ShiftKind,
3745 &OffsetRegShamt, &Reason)) {
3746 continue;
3747 }
3748
3749 if ((OffsetRegShamt == 0) &&
3750 matchShiftedOffsetReg(VMetadata, &BaseVar, &ShiftKind,
3751 &OffsetRegShamt, &Reason)) {
3752 std::swap(BaseVar, OffsetReg);
3753 continue;
3754 }
3755 }
3756
3757 if (matchOffsetBase(VMetadata, &BaseVar, &OffsetImm, &Reason)) {
3758 continue;
3759 }
3760 } while (Reason);
3761
3762 if (BaseVar == nullptr) {
3763 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] is not legal in ARM, so we have to
3764 // legalize the addressing mode to [BaseReg, OffsetReg{, LSL Shamt}].
3765 // Instead of a zeroed BaseReg, we initialize it with OffsetImm:
3766 //
3767 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] ->
3768 // mov BaseReg, #OffsetImm
3769 // use of [BaseReg, OffsetReg{, LSL Shamt}]
3770 //
3771 const Type PointerType = getPointerType();
3772 BaseVar = makeReg(PointerType);
3773 Context.insert(
3774 InstAssign::create(Func, BaseVar, Ctx->getConstantInt32(OffsetImm)));
3775 OffsetImm = 0;
3776 } else if (OffsetImm != 0) {
3777 // ARM Ldr/Str instructions have limited range immediates. The formation
3778 // loop above materialized an Immediate carelessly, so we ensure the
3779 // generated offset is sane.
3780 const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm;
3781 const InstArithmetic::OpKind Op =
3782 OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub;
3783
3784 if (!CanHaveImm || !isLegalMemOffset(Ty, OffsetImm) ||
3785 OffsetReg != nullptr) {
3786 if (OffsetReg == nullptr) {
3787 // We formed a [Base, #const] addressing mode which is not encodable in
3788 // ARM. There is little point in forming an address mode now if we don't
3789 // have an offset. Effectively, we would end up with something like
3790 //
3791 // [Base, #const] -> add T, Base, #const
3792 // use of [T]
3793 //
3794 // Which is exactly what we already have. So we just bite the bullet
3795 // here and don't form any address mode.
3796 return nullptr;
3797 }
3798 // We formed [Base, Offset {, LSL Amnt}, #const]. Oops. Legalize it to
3799 //
3800 // [Base, Offset, {LSL amount}, #const] ->
3801 // add T, Base, #const
3802 // use of [T, Offset {, LSL amount}]
3803 const Type PointerType = getPointerType();
3804 Variable *T = makeReg(PointerType);
3805 Context.insert(InstArithmetic::create(
3806 Func, Op, T, BaseVar, Ctx->getConstantInt32(PositiveOffset)));
3807 BaseVar = T;
3808 OffsetImm = 0;
3809 }
3810 }
3811
3812 assert(BaseVar != nullptr);
3813 assert(OffsetImm == 0 || OffsetReg == nullptr);
3814 assert(OffsetReg == nullptr || CanHaveIndex);
3815 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm
3816 : (ValidImmMask & OffsetImm) == OffsetImm);
3817
3818 if (OffsetReg != nullptr) {
3819 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetReg, ShiftKind,
3820 OffsetRegShamt);
3821 }
3822
3823 return OperandARM32Mem::create(
3824 Func, Ty, BaseVar,
3825 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm)));
3826 }
3827
3828 void TargetARM32::doAddressOptLoad() {
3829 Inst *Instr = Context.getCur();
3830 assert(llvm::isa<InstLoad>(Instr));
3831 Variable *Dest = Instr->getDest();
3832 Operand *Addr = Instr->getSrc(0);
3833 if (OperandARM32Mem *Mem =
3834 formAddressingMode(Dest->getType(), Func, Instr, Addr)) {
3835 Instr->setDeleted();
3836 Context.insert(InstLoad::create(Func, Dest, Mem));
3837 }
3838 }
3379 3839
3380 void TargetARM32::randomlyInsertNop(float Probability, 3840 void TargetARM32::randomlyInsertNop(float Probability,
3381 RandomNumberGenerator &RNG) { 3841 RandomNumberGenerator &RNG) {
3382 RandomNumberGeneratorWrapper RNGW(RNG); 3842 RandomNumberGeneratorWrapper RNGW(RNG);
3383 if (RNGW.getTrueWithProbability(Probability)) { 3843 if (RNGW.getTrueWithProbability(Probability)) {
3384 UnimplementedError(Func->getContext()->getFlags()); 3844 UnimplementedError(Func->getContext()->getFlags());
3385 } 3845 }
3386 } 3846 }
3387 3847
3388 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { 3848 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
3569 Variable *ValueHi = legalizeToReg(hiOperand(Value)); 4029 Variable *ValueHi = legalizeToReg(hiOperand(Value));
3570 Variable *ValueLo = legalizeToReg(loOperand(Value)); 4030 Variable *ValueLo = legalizeToReg(loOperand(Value));
3571 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); 4031 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr)));
3572 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); 4032 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr)));
3573 } else { 4033 } else {
3574 Variable *ValueR = legalizeToReg(Value); 4034 Variable *ValueR = legalizeToReg(Value);
3575 _str(ValueR, NewAddr); 4035 _str(ValueR, NewAddr);
3576 } 4036 }
3577 } 4037 }
3578 4038
3579 void TargetARM32::doAddressOptStore() {} 4039 void TargetARM32::doAddressOptStore() {
4040 Inst *Instr = Context.getCur();
4041 assert(llvm::isa<InstStore>(Instr));
4042 Operand *Src = Instr->getSrc(0);
4043 Operand *Addr = Instr->getSrc(1);
4044 if (OperandARM32Mem *Mem =
4045 formAddressingMode(Src->getType(), Func, Instr, Addr)) {
4046 Instr->setDeleted();
4047 Context.insert(InstStore::create(Func, Src, Mem));
4048 }
4049 }
3580 4050
3581 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { 4051 void TargetARM32::lowerSwitch(const InstSwitch *Inst) {
3582 // This implements the most naive possible lowering. 4052 // This implements the most naive possible lowering.
3583 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default 4053 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default
3584 Operand *Src0 = Inst->getComparison(); 4054 Operand *Src0 = Inst->getComparison();
3585 SizeT NumCases = Inst->getNumCases(); 4055 SizeT NumCases = Inst->getNumCases();
3586 if (Src0->getType() == IceType_i64) { 4056 if (Src0->getType() == IceType_i64) {
3587 Src0 = legalizeUndef(Src0); 4057 Src0 = legalizeUndef(Src0);
3588 Variable *Src0Lo = legalizeToReg(loOperand(Src0)); 4058 Variable *Src0Lo = legalizeToReg(loOperand(Src0));
3589 Variable *Src0Hi = legalizeToReg(hiOperand(Src0)); 4059 Variable *Src0Hi = legalizeToReg(hiOperand(Src0));
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3666 } 4136 }
3667 } 4137 }
3668 } 4138 }
3669 } 4139 }
3670 4140
3671 // Go through the various types of operands: OperandARM32Mem, 4141 // Go through the various types of operands: OperandARM32Mem,
3672 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if 4142 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if
3673 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we 4143 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we
3674 // can always copy to a register. 4144 // can always copy to a register.
3675 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { 4145 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(From)) {
3676 static const struct {
3677 bool CanHaveOffset;
3678 bool CanHaveIndex;
3679 } MemTraits[] = {
3680 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr) \
3681 { (ubits) > 0, rraddr } \
3682 ,
3683 ICETYPEARM32_TABLE
3684 #undef X
3685 };
3686 // Before doing anything with a Mem operand, we need to ensure that the 4146 // Before doing anything with a Mem operand, we need to ensure that the
3687 // Base and Index components are in physical registers. 4147 // Base and Index components are in physical registers.
3688 Variable *Base = Mem->getBase(); 4148 Variable *Base = Mem->getBase();
3689 Variable *Index = Mem->getIndex(); 4149 Variable *Index = Mem->getIndex();
3690 ConstantInteger32 *Offset = Mem->getOffset(); 4150 ConstantInteger32 *Offset = Mem->getOffset();
3691 assert(Index == nullptr || Offset == nullptr); 4151 assert(Index == nullptr || Offset == nullptr);
3692 Variable *RegBase = nullptr; 4152 Variable *RegBase = nullptr;
3693 Variable *RegIndex = nullptr; 4153 Variable *RegIndex = nullptr;
3694 if (Base) { 4154 assert(Base);
3695 RegBase = legalizeToReg(Base); 4155 RegBase = legalizeToReg(Base);
3696 } 4156 bool InvalidImm = false;
4157 assert(Ty < MemTraitsSize);
3697 if (Index) { 4158 if (Index) {
4159 assert(Offset == nullptr);
4160 assert(MemTraits[Ty].CanHaveIndex);
3698 RegIndex = legalizeToReg(Index); 4161 RegIndex = legalizeToReg(Index);
3699 if (!MemTraits[Ty].CanHaveIndex) {
3700 Variable *T = makeReg(IceType_i32, getReservedTmpReg());
3701 _add(T, RegBase, RegIndex);
3702 RegBase = T;
3703 RegIndex = nullptr;
3704 }
3705 } 4162 }
3706 if (Offset && Offset->getValue() != 0) { 4163 if (Offset && Offset->getValue() != 0) {
3707 static constexpr bool SignExt = false; 4164 assert(Index == nullptr);
3708 if (!MemTraits[Ty].CanHaveOffset || 4165 static constexpr bool ZeroExt = false;
3709 !OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset->getValue())) { 4166 assert(MemTraits[Ty].CanHaveImm);
3710 Variable *T = legalizeToReg(Offset, getReservedTmpReg()); 4167 if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) {
3711 _add(T, T, RegBase); 4168 assert(RegBase->hasReg());
3712 RegBase = T; 4169 assert(RegBase->getRegNum() == (int32_t)getFrameOrStackReg());
3713 Offset = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)); 4170 // We are a bit more lenient with invalid immediate when accessing the
4171 // stack here, and then rely on legalizeStackSlots() to fix things as
4172 // appropriate.
4173 InvalidImm = true;
3714 } 4174 }
3715 } 4175 }
3716 4176
3717 // Create a new operand if there was a change. 4177 // Create a new operand if there was a change.
3718 if (Base != RegBase || Index != RegIndex) { 4178 if (Base != RegBase || Index != RegIndex) {
3719 // There is only a reg +/- reg or reg + imm form. 4179 // There is only a reg +/- reg or reg + imm form.
3720 // Figure out which to re-create. 4180 // Figure out which to re-create.
3721 if (RegBase && RegIndex) { 4181 if (RegIndex) {
3722 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, 4182 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex,
3723 Mem->getShiftOp(), Mem->getShiftAmt(), 4183 Mem->getShiftOp(), Mem->getShiftAmt(),
3724 Mem->getAddrMode()); 4184 Mem->getAddrMode());
3725 } else { 4185 } else {
3726 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset, 4186 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset,
3727 Mem->getAddrMode()); 4187 Mem->getAddrMode());
3728 } 4188 }
3729 } 4189 }
3730 if (Allowed & Legal_Mem) { 4190 if (Allowed & Legal_Mem) {
3731 From = Mem; 4191 From = Mem;
3732 } else { 4192 } else {
3733 Variable *Reg = makeReg(Ty, RegNum); 4193 Variable *Reg = makeReg(Ty, RegNum);
3734 _ldr(Reg, Mem); 4194 if (InvalidImm) {
4195 // If Mem has an invalid immediate, we legalize it to a Reg using mov
4196 // instead of ldr because legalizeStackSlots() will later kick in and
4197 // fix the immediate for us.
4198 _mov(Reg, Mem);
4199 } else {
4200 _ldr(Reg, Mem);
4201 }
4202
3735 From = Reg; 4203 From = Reg;
3736 } 4204 }
3737 return From; 4205 return From;
3738 } 4206 }
3739 4207
3740 if (auto *Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { 4208 if (auto *Flex = llvm::dyn_cast<OperandARM32Flex>(From)) {
3741 if (!(Allowed & Legal_Flex)) { 4209 if (!(Allowed & Legal_Flex)) {
3742 if (auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { 4210 if (auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) {
3743 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { 4211 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) {
3744 From = FlexReg->getReg(); 4212 From = FlexReg->getReg();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3797 Variable *Reg = makeReg(Ty, RegNum); 4265 Variable *Reg = makeReg(Ty, RegNum);
3798 _movw(Reg, C); 4266 _movw(Reg, C);
3799 _movt(Reg, C); 4267 _movt(Reg, C);
3800 return Reg; 4268 return Reg;
3801 } else { 4269 } else {
3802 assert(isScalarFloatingType(Ty)); 4270 assert(isScalarFloatingType(Ty));
3803 // Load floats/doubles from literal pool. 4271 // Load floats/doubles from literal pool.
3804 // TODO(jvoung): Allow certain immediates to be encoded directly in an 4272 // TODO(jvoung): Allow certain immediates to be encoded directly in an
3805 // operand. See Table A7-18 of the ARM manual: "Floating-point modified 4273 // operand. See Table A7-18 of the ARM manual: "Floating-point modified
3806 // immediate constants". Or, for 32-bit floating point numbers, just 4274 // immediate constants". Or, for 32-bit floating point numbers, just
3807 // encode the raw bits into a movw/movt pair to GPR, and vmov to an SREG, 4275 // encode the raw bits into a movw/movt pair to GPR, and vmov to an SREG
3808 // instead of using a movw/movt pair to get the const-pool address then 4276 // instead of using a movw/movt pair to get the const-pool address then
3809 // loading to SREG. 4277 // loading to SREG.
3810 std::string Buffer; 4278 std::string Buffer;
3811 llvm::raw_string_ostream StrBuf(Buffer); 4279 llvm::raw_string_ostream StrBuf(Buffer);
3812 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); 4280 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx);
3813 llvm::cast<Constant>(From)->setShouldBePooled(true); 4281 llvm::cast<Constant>(From)->setShouldBePooled(true);
3814 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); 4282 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
3815 Variable *BaseReg = makeReg(getPointerType()); 4283 Variable *BaseReg = makeReg(getPointerType());
3816 _movw(BaseReg, Offset); 4284 _movw(BaseReg, Offset);
3817 _movt(BaseReg, Offset); 4285 _movt(BaseReg, Offset);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3867 } 4335 }
3868 4336
3869 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) { 4337 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) {
3870 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); 4338 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand);
3871 // It may be the case that address mode optimization already creates an 4339 // It may be the case that address mode optimization already creates an
3872 // OperandARM32Mem, so in that case it wouldn't need another level of 4340 // OperandARM32Mem, so in that case it wouldn't need another level of
3873 // transformation. 4341 // transformation.
3874 if (Mem) { 4342 if (Mem) {
3875 return llvm::cast<OperandARM32Mem>(legalize(Mem)); 4343 return llvm::cast<OperandARM32Mem>(legalize(Mem));
3876 } 4344 }
3877 // If we didn't do address mode optimization, then we only have a base/offset 4345 // If we didn't do address mode optimization, then we only have a
3878 // to work with. ARM always requires a base register, so just use that to 4346 // base/offset to work with. ARM always requires a base register, so
3879 // hold the operand. 4347 // just use that to hold the operand.
3880 Variable *Base = legalizeToReg(Operand); 4348 Variable *Base = legalizeToReg(Operand);
3881 return OperandARM32Mem::create( 4349 return OperandARM32Mem::create(
3882 Func, Ty, Base, 4350 Func, Ty, Base,
3883 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); 4351 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)));
3884 } 4352 }
3885 4353
3886 Variable64On32 *TargetARM32::makeI64RegPair() { 4354 Variable64On32 *TargetARM32::makeI64RegPair() {
3887 Variable64On32 *Reg = 4355 Variable64On32 *Reg =
3888 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); 4356 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
3889 Reg->setMustHaveReg(); 4357 Reg->setMustHaveReg();
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
4088 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars, 4556 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars,
4089 const IceString &SectionSuffix) { 4557 const IceString &SectionSuffix) {
4090 switch (Ctx->getFlags().getOutFileType()) { 4558 switch (Ctx->getFlags().getOutFileType()) {
4091 case FT_Elf: { 4559 case FT_Elf: {
4092 ELFObjectWriter *Writer = Ctx->getObjectWriter(); 4560 ELFObjectWriter *Writer = Ctx->getObjectWriter();
4093 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix); 4561 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix);
4094 } break; 4562 } break;
4095 case FT_Asm: 4563 case FT_Asm:
4096 case FT_Iasm: { 4564 case FT_Iasm: {
4097 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); 4565 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
4098 OstreamLocker L(Ctx); 4566 OstreamLocker _(Ctx);
4099 for (const VariableDeclaration *Var : Vars) { 4567 for (const VariableDeclaration *Var : Vars) {
4100 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { 4568 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
4101 emitGlobal(*Var, SectionSuffix); 4569 emitGlobal(*Var, SectionSuffix);
4102 } 4570 }
4103 } 4571 }
4104 } break; 4572 } break;
4105 } 4573 }
4106 } 4574 }
4107 4575
4108 namespace { 4576 namespace {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
4191 4659
4192 void TargetDataARM32::lowerConstants() { 4660 void TargetDataARM32::lowerConstants() {
4193 if (Ctx->getFlags().getDisableTranslation()) 4661 if (Ctx->getFlags().getDisableTranslation())
4194 return; 4662 return;
4195 switch (Ctx->getFlags().getOutFileType()) { 4663 switch (Ctx->getFlags().getOutFileType()) {
4196 case FT_Elf: 4664 case FT_Elf:
4197 UnimplementedError(Ctx->getFlags()); 4665 UnimplementedError(Ctx->getFlags());
4198 break; 4666 break;
4199 case FT_Asm: 4667 case FT_Asm:
4200 case FT_Iasm: { 4668 case FT_Iasm: {
4201 OstreamLocker L(Ctx); 4669 OstreamLocker _(Ctx);
4202 emitConstantPool<float>(Ctx); 4670 emitConstantPool<float>(Ctx);
4203 emitConstantPool<double>(Ctx); 4671 emitConstantPool<double>(Ctx);
4204 break; 4672 break;
4205 } 4673 }
4206 } 4674 }
4207 } 4675 }
4208 4676
4209 void TargetDataARM32::lowerJumpTables() { 4677 void TargetDataARM32::lowerJumpTables() {
4210 if (Ctx->getFlags().getDisableTranslation()) 4678 if (Ctx->getFlags().getDisableTranslation())
4211 return; 4679 return;
4212 switch (Ctx->getFlags().getOutFileType()) { 4680 switch (Ctx->getFlags().getOutFileType()) {
4213 case FT_Elf: 4681 case FT_Elf:
4214 UnimplementedError(Ctx->getFlags()); 4682 UnimplementedError(Ctx->getFlags());
4215 break; 4683 break;
4216 case FT_Asm: 4684 case FT_Asm:
4217 // Already emitted from Cfg 4685 // Already emitted from Cfg
4218 break; 4686 break;
4219 case FT_Iasm: { 4687 case FT_Iasm: {
4220 // TODO(kschimpf): Fill this in when we get more information. 4688 // TODO(kschimpf): Fill this in when we get more information.
4221 break; 4689 break;
4222 } 4690 }
4223 } 4691 }
4224 } 4692 }
4225 4693
4226 TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx) 4694 TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx)
4227 : TargetHeaderLowering(Ctx), CPUFeatures(Ctx->getFlags()) {} 4695 : TargetHeaderLowering(Ctx), CPUFeatures(Ctx->getFlags()) {}
4228 4696
4229 void TargetHeaderARM32::lower() { 4697 void TargetHeaderARM32::lower() {
4230 OstreamLocker L(Ctx); 4698 OstreamLocker _(Ctx);
4231 Ostream &Str = Ctx->getStrEmit(); 4699 Ostream &Str = Ctx->getStrEmit();
4232 Str << ".syntax unified\n"; 4700 Str << ".syntax unified\n";
4233 // Emit build attributes in format: .eabi_attribute TAG, VALUE. See Sec. 2 of 4701 // Emit build attributes in format: .eabi_attribute TAG, VALUE. See Sec. 2 of
4234 // "Addenda to, and Errata in the ABI for the ARM architecture" 4702 // "Addenda to, and Errata in the ABI for the ARM architecture"
4235 // http://infocenter.arm.com 4703 // http://infocenter.arm.com
4236 // /help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf 4704 // /help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf
4237 // 4705 //
4238 // Tag_conformance should be be emitted first in a file-scope sub-subsection 4706 // Tag_conformance should be be emitted first in a file-scope sub-subsection
4239 // of the first public subsection of the attributes. 4707 // of the first public subsection of the attributes.
4240 Str << ".eabi_attribute 67, \"2.09\" @ Tag_conformance\n"; 4708 Str << ".eabi_attribute 67, \"2.09\" @ Tag_conformance\n";
(...skipping 29 matching lines...) Expand all
4270 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 4738 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
4271 // However, for compatibility with current NaCl LLVM, don't claim that. 4739 // However, for compatibility with current NaCl LLVM, don't claim that.
4272 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 4740 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
4273 } 4741 }
4274 4742
4275 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; 4743 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM];
4276 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; 4744 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
4277 llvm::SmallBitVector TargetARM32::ScratchRegs; 4745 llvm::SmallBitVector TargetARM32::ScratchRegs;
4278 4746
4279 } // end of namespace Ice 4747 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698