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

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: Renames isLevalVariableStackOffset to isLegalMemOffset. 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 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 "Infinite-weight Variable has no register assigned"); 454 "Infinite-weight Variable has no register assigned");
455 } 455 }
456 int32_t Offset = Var->getStackOffset(); 456 int32_t Offset = Var->getStackOffset();
457 int32_t BaseRegNum = Var->getBaseRegNum(); 457 int32_t BaseRegNum = Var->getBaseRegNum();
458 if (BaseRegNum == Variable::NoRegister) { 458 if (BaseRegNum == Variable::NoRegister) {
459 BaseRegNum = getFrameOrStackReg(); 459 BaseRegNum = getFrameOrStackReg();
460 if (!hasFramePointer()) 460 if (!hasFramePointer())
461 Offset += getStackAdjustment(); 461 Offset += getStackAdjustment();
462 } 462 }
463 const Type VarTy = Var->getType(); 463 const Type VarTy = Var->getType();
464 if (!isLegalVariableStackOffset(VarTy, Offset)) { 464 if (!isLegalMemOffset(VarTy, Offset)) {
465 llvm::report_fatal_error("Illegal stack offset"); 465 llvm::report_fatal_error("Illegal stack offset");
466 } 466 }
467 Str << "[" << getRegName(BaseRegNum, VarTy); 467 Str << "[" << getRegName(BaseRegNum, VarTy);
468 if (Offset != 0) { 468 if (Offset != 0) {
469 Str << ", " << getConstantPrefix() << Offset; 469 Str << ", " << getConstantPrefix() << Offset;
470 } 470 }
471 Str << "]"; 471 Str << "]";
472 } 472 }
473 473
474 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { 474 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) {
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 Variable *RetValue = nullptr; 936 Variable *RetValue = nullptr;
937 if (RI->getSrcSize()) 937 if (RI->getSrcSize())
938 RetValue = llvm::cast<Variable>(RI->getSrc(0)); 938 RetValue = llvm::cast<Variable>(RI->getSrc(0));
939 _bundle_lock(); 939 _bundle_lock();
940 _bic(LR, LR, RetMask); 940 _bic(LR, LR, RetMask);
941 _ret(LR, RetValue); 941 _ret(LR, RetValue);
942 _bundle_unlock(); 942 _bundle_unlock();
943 RI->setDeleted(); 943 RI->setDeleted();
944 } 944 }
945 945
946 bool TargetARM32::isLegalVariableStackOffset(Type Ty, int32_t Offset) const { 946 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const {
947 constexpr bool SignExt = false; 947 constexpr bool ZeroExt = false;
948 return OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset); 948 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset);
949 } 949 }
950 950
951 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, 951 Variable *TargetARM32::newBaseRegister(int32_t OriginalOffset,
952 int32_t StackAdjust, 952 int32_t StackAdjust,
953 Variable *OrigBaseReg) { 953 Variable *OrigBaseReg) {
954 int32_t Offset = Var->getStackOffset() + StackAdjust; 954 int32_t Offset = OriginalOffset + StackAdjust;
955 // Legalize will likely need a movw/movt combination, but if the top bits are 955 // Legalize will likely need a movw/movt combination, but if the top bits are
956 // all 0 from negating the offset and subtracting, we could use that instead. 956 // all 0 from negating the offset and subtracting, we could use that instead.
957 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; 957 bool ShouldSub = (-Offset & 0xFFFF0000) == 0;
958 if (ShouldSub) 958 if (ShouldSub)
959 Offset = -Offset; 959 Offset = -Offset;
960 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), 960 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset),
961 Legal_Reg | Legal_Flex, getReservedTmpReg()); 961 Legal_Reg | Legal_Flex, getReservedTmpReg());
962 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); 962 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg());
963 if (ShouldSub) 963 if (ShouldSub)
964 _sub(ScratchReg, OrigBaseReg, OffsetVal); 964 _sub(ScratchReg, OrigBaseReg, OffsetVal);
965 else 965 else
966 _add(ScratchReg, OrigBaseReg, OffsetVal); 966 _add(ScratchReg, OrigBaseReg, OffsetVal);
967 StackVariable *NewVar = Func->makeVariable<StackVariable>(stackSlotType()); 967 return ScratchReg;
968 NewVar->setMustNotHaveReg(); 968 }
969 NewVar->setBaseRegNum(ScratchReg->getRegNum()); 969
970 constexpr int32_t NewOffset = 0; 970 StackVariable *TargetARM32::legalizeStackSlot(Type Ty, int32_t Offset,
971 NewVar->setStackOffset(NewOffset); 971 int32_t StackAdjust,
972 return NewVar; 972 Variable *OrigBaseReg,
973 Variable **NewBaseReg,
974 int32_t *NewBaseOffset) {
Karl 2015/11/06 21:11:01 Why not int32_t &NewBaseOffset?
John 2015/11/09 22:42:25 Because the method changes NewBaseOffset inside.
975 if (*NewBaseReg == nullptr) {
976 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg);
977 *NewBaseOffset = Offset + StackAdjust;
978 }
979
980 int32_t OffsetDiff = Offset + StackAdjust - *NewBaseOffset;
981 if (!isLegalMemOffset(Ty, OffsetDiff)) {
982 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg);
983 *NewBaseOffset = Offset + StackAdjust;
984 OffsetDiff = 0;
985 }
986
987 StackVariable *NewDest = Func->makeVariable<StackVariable>(Ty);
988 NewDest->setMustNotHaveReg();
989 NewDest->setBaseRegNum((*NewBaseReg)->getRegNum());
990 NewDest->setStackOffset(OffsetDiff);
991 return NewDest;
992 }
993
994 void TargetARM32::legalizeMovStackAddrImm(InstARM32Mov *MovInstr,
995 int32_t StackAdjust,
996 Variable *OrigBaseReg,
997 Variable **NewBaseReg,
998 int32_t *NewBaseOffset) {
999 Variable *Dest = MovInstr->getDest();
1000 assert(Dest != nullptr);
1001 Type DestTy = Dest->getType();
1002 assert(DestTy != IceType_i64);
1003
1004 Operand *Src = MovInstr->getSrc(0);
1005 Type SrcTy = Src->getType();
1006 assert(SrcTy != IceType_i64);
1007
1008 if (MovInstr->isMultiDest() || MovInstr->isMultiSource())
1009 return;
1010
1011 bool Legalized = false;
1012 if (!Dest->hasReg()) {
1013 assert(llvm::cast<Variable>(Src)->hasReg());
1014 const int32_t Offset = Dest->getStackOffset();
1015 if (!isLegalMemOffset(DestTy, Offset + StackAdjust)) {
1016 Legalized = true;
1017 Dest = legalizeStackSlot(DestTy, Offset, StackAdjust, OrigBaseReg,
1018 NewBaseReg, NewBaseOffset);
1019 }
1020 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) {
1021 if (!Var->hasReg()) {
1022 const int32_t Offset = Var->getStackOffset();
1023 if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) {
1024 Legalized = true;
1025 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg,
1026 NewBaseReg, NewBaseOffset);
1027 }
1028 }
1029 } else if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) {
1030 if (ConstantInteger32 *OffsetOp = Mem->getOffset()) {
1031 const int32_t Offset = OffsetOp->getValue();
1032 if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) {
1033 assert(Mem->getBase()->hasReg());
1034 assert(Mem->getBase()->getRegNum() == (int)getFrameOrStackReg());
Jim Stichnoth 2015/11/08 20:05:51 int32_t for consistency
John 2015/11/09 22:42:24 Done.
1035 Legalized = true;
1036 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg,
1037 NewBaseReg, NewBaseOffset);
1038 }
1039 }
1040 }
1041
1042 if (Legalized) {
1043 _mov(Dest, Src);
1044 MovInstr->setDeleted();
1045 }
973 } 1046 }
974 1047
975 void TargetARM32::legalizeStackSlots() { 1048 void TargetARM32::legalizeStackSlots() {
976 // If a stack variable's frame offset doesn't fit, convert from: 1049 // If a stack variable's frame offset doesn't fit, convert from:
977 // ldr X, OFF[SP] 1050 // ldr X, OFF[SP]
978 // to: 1051 // to:
979 // movw/movt TMP, OFF_PART 1052 // movw/movt TMP, OFF_PART
980 // add TMP, TMP, SP 1053 // add TMP, TMP, SP
981 // ldr X, OFF_MORE[TMP] 1054 // ldr X, OFF_MORE[TMP]
982 // 1055 //
983 // This is safe because we have reserved TMP, and add for ARM does not 1056 // This is safe because we have reserved TMP, and add for ARM does not
984 // clobber the flags register. 1057 // clobber the flags register.
985 Func->dump("Before legalizeStackSlots"); 1058 Func->dump("Before legalizeStackSlots");
986 assert(hasComputedFrame()); 1059 assert(hasComputedFrame());
987 // Early exit, if SpillAreaSizeBytes is really small. 1060 // Early exit, if SpillAreaSizeBytes is really small.
988 // TODO(jpp): this is not safe -- loads and stores of q registers can't have 1061 // TODO(jpp): this is not safe -- loads and stores of q registers can't have
989 // offsets. 1062 // offsets.
990 if (isLegalVariableStackOffset(IceType_v4i32, SpillAreaSizeBytes)) 1063 if (isLegalMemOffset(IceType_v4i32, SpillAreaSizeBytes))
991 return; 1064 return;
992 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); 1065 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg());
993 int32_t StackAdjust = 0; 1066 int32_t StackAdjust = 0;
994 // Do a fairly naive greedy clustering for now. Pick the first stack slot 1067 // Do a fairly naive greedy clustering for now. Pick the first stack slot
995 // that's out of bounds and make a new base reg using the architecture's temp 1068 // that's out of bounds and make a new base reg using the architecture's temp
996 // register. If that works for the next slot, then great. Otherwise, create a 1069 // register. If that works for the next slot, then great. Otherwise, create a
997 // new base register, clobbering the previous base register. Never share a 1070 // new base register, clobbering the previous base register. Never share a
998 // base reg across different basic blocks. This isn't ideal if local and 1071 // base reg across different basic blocks. This isn't ideal if local and
999 // multi-block variables are far apart and their references are interspersed. 1072 // multi-block variables are far apart and their references are interspersed.
1000 // It may help to be more coordinated about assign stack slot numbers and may 1073 // It may help to be more coordinated about assign stack slot numbers and may
1001 // help to assign smaller offsets to higher-weight variables so that they 1074 // help to assign smaller offsets to higher-weight variables so that they
1002 // don't depend on this legalization. 1075 // don't depend on this legalization.
1003 for (CfgNode *Node : Func->getNodes()) { 1076 for (CfgNode *Node : Func->getNodes()) {
1004 Context.init(Node); 1077 Context.init(Node);
1005 StackVariable *NewBaseReg = nullptr; 1078 Variable *NewBaseReg = nullptr;
1006 int32_t NewBaseOffset = 0; 1079 int32_t NewBaseOffset = 0;
1007 while (!Context.atEnd()) { 1080 while (!Context.atEnd()) {
1008 PostIncrLoweringContext PostIncrement(Context); 1081 PostIncrLoweringContext PostIncrement(Context);
1009 Inst *CurInstr = Context.getCur(); 1082 Inst *CurInstr = Context.getCur();
1010 Variable *Dest = CurInstr->getDest(); 1083 Variable *Dest = CurInstr->getDest();
1084
1011 // Check if the previous NewBaseReg is clobbered, and reset if needed. 1085 // Check if the previous NewBaseReg is clobbered, and reset if needed.
1012 if ((Dest && NewBaseReg && Dest->hasReg() && 1086 if ((Dest && NewBaseReg && Dest->hasReg() &&
1013 Dest->getRegNum() == NewBaseReg->getBaseRegNum()) || 1087 Dest->getRegNum() == NewBaseReg->getBaseRegNum()) ||
1014 llvm::isa<InstFakeKill>(CurInstr)) { 1088 llvm::isa<InstFakeKill>(CurInstr)) {
1015 NewBaseReg = nullptr; 1089 NewBaseReg = nullptr;
1016 NewBaseOffset = 0; 1090 NewBaseOffset = 0;
1017 } 1091 }
1092
1018 // The stack adjustment only matters if we are using SP instead of FP. 1093 // The stack adjustment only matters if we are using SP instead of FP.
1019 if (!hasFramePointer()) { 1094 if (!hasFramePointer()) {
1020 if (auto *AdjInst = llvm::dyn_cast<InstARM32AdjustStack>(CurInstr)) { 1095 if (auto *AdjInst = llvm::dyn_cast<InstARM32AdjustStack>(CurInstr)) {
1021 StackAdjust += AdjInst->getAmount(); 1096 StackAdjust += AdjInst->getAmount();
1022 NewBaseOffset += AdjInst->getAmount(); 1097 NewBaseOffset += AdjInst->getAmount();
1023 continue; 1098 continue;
1024 } 1099 }
1025 if (llvm::isa<InstARM32Call>(CurInstr)) { 1100 if (llvm::isa<InstARM32Call>(CurInstr)) {
1026 NewBaseOffset -= StackAdjust; 1101 NewBaseOffset -= StackAdjust;
1027 StackAdjust = 0; 1102 StackAdjust = 0;
1028 continue; 1103 continue;
1029 } 1104 }
1030 } 1105 }
1031 1106
1032 // For now, only Mov instructions can have stack variables. We need to 1107 // The Lowering ensures that ldr and str always have legal Mem operands.
1033 // know the type of instruction because we currently create a fresh one 1108 // The only other instruction that may access memory is mov.
1034 // to replace Dest/Source, rather than mutate in place.
1035 bool MayNeedOffsetRewrite = false;
1036 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { 1109 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) {
1037 MayNeedOffsetRewrite = 1110 legalizeMovStackAddrImm(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg,
1038 !MovInstr->isMultiDest() && !MovInstr->isMultiSource(); 1111 &NewBaseOffset);
1039 }
1040
1041 if (!MayNeedOffsetRewrite) {
1042 continue;
1043 }
1044
1045 assert(Dest != nullptr);
1046 Type DestTy = Dest->getType();
1047 assert(DestTy != IceType_i64);
1048 if (!Dest->hasReg()) {
1049 int32_t Offset = Dest->getStackOffset();
1050 Offset += StackAdjust;
1051 if (!isLegalVariableStackOffset(DestTy, Offset)) {
1052 if (NewBaseReg) {
1053 int32_t OffsetDiff = Offset - NewBaseOffset;
1054 if (isLegalVariableStackOffset(DestTy, OffsetDiff)) {
1055 StackVariable *NewDest =
1056 Func->makeVariable<StackVariable>(stackSlotType());
1057 NewDest->setMustNotHaveReg();
1058 NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum());
1059 NewDest->setStackOffset(OffsetDiff);
1060 Variable *NewDestVar = NewDest;
1061 _mov(NewDestVar, CurInstr->getSrc(0));
1062 CurInstr->setDeleted();
1063 continue;
1064 }
1065 }
1066 StackVariable *LegalDest =
1067 legalizeVariableSlot(Dest, StackAdjust, OrigBaseReg);
1068 assert(LegalDest != Dest);
1069 Variable *LegalDestVar = LegalDest;
1070 _mov(LegalDestVar, CurInstr->getSrc(0));
1071 CurInstr->setDeleted();
1072 NewBaseReg = LegalDest;
1073 NewBaseOffset = Offset;
1074 continue;
1075 }
1076 }
1077 assert(CurInstr->getSrcSize() == 1);
1078 Variable *Var = llvm::dyn_cast<Variable>(CurInstr->getSrc(0));
1079 if (Var && !Var->hasReg()) {
1080 Type VarTy = Var->getType();
1081 int32_t Offset = Var->getStackOffset();
1082 Offset += StackAdjust;
1083 if (!isLegalVariableStackOffset(VarTy, Offset)) {
1084 if (NewBaseReg) {
1085 int32_t OffsetDiff = Offset - NewBaseOffset;
1086 if (isLegalVariableStackOffset(VarTy, OffsetDiff)) {
1087 StackVariable *NewVar =
1088 Func->makeVariable<StackVariable>(stackSlotType());
1089 NewVar->setMustNotHaveReg();
1090 NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum());
1091 NewVar->setStackOffset(OffsetDiff);
1092 _mov(Dest, NewVar);
1093 CurInstr->setDeleted();
1094 continue;
1095 }
1096 }
1097 StackVariable *LegalVar =
1098 legalizeVariableSlot(Var, StackAdjust, OrigBaseReg);
1099 assert(LegalVar != Var);
1100 _mov(Dest, LegalVar);
1101 CurInstr->setDeleted();
1102 NewBaseReg = LegalVar;
1103 NewBaseOffset = Offset;
1104 continue;
1105 }
1106 } 1112 }
1107 } 1113 }
1108 } 1114 }
1109 } 1115 }
1110 1116
1111 Operand *TargetARM32::loOperand(Operand *Operand) { 1117 Operand *TargetARM32::loOperand(Operand *Operand) {
1112 assert(Operand->getType() == IceType_i64); 1118 assert(Operand->getType() == IceType_i64);
1113 if (Operand->getType() != IceType_i64) 1119 if (Operand->getType() != IceType_i64)
1114 return Operand; 1120 return Operand;
1115 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) 1121 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, 1166 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase,
1161 Base, Four)); 1167 Base, Four));
1162 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(), 1168 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(),
1163 Mem->getShiftOp(), Mem->getShiftAmt(), 1169 Mem->getShiftOp(), Mem->getShiftAmt(),
1164 Mem->getAddrMode()); 1170 Mem->getAddrMode());
1165 } else { 1171 } else {
1166 Variable *Base = Mem->getBase(); 1172 Variable *Base = Mem->getBase();
1167 ConstantInteger32 *Offset = Mem->getOffset(); 1173 ConstantInteger32 *Offset = Mem->getOffset();
1168 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); 1174 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4));
1169 int32_t NextOffsetVal = Offset->getValue() + 4; 1175 int32_t NextOffsetVal = Offset->getValue() + 4;
1170 const bool SignExt = false; 1176 const bool ZeroExt = false;
Karl 2015/11/06 21:11:01 constexpr?
John 2015/11/09 22:42:25 Done.
1171 if (!OperandARM32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) { 1177 if (!OperandARM32Mem::canHoldOffset(SplitType, ZeroExt, NextOffsetVal)) {
1172 // We have to make a temp variable and add 4 to either Base or Offset. 1178 // We have to make a temp variable and add 4 to either Base or Offset.
1173 // If we add 4 to Offset, this will convert a non-RegReg addressing 1179 // If we add 4 to Offset, this will convert a non-RegReg addressing
1174 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows 1180 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows
1175 // RegReg addressing modes, prefer adding to base and replacing 1181 // RegReg addressing modes, prefer adding to base and replacing
1176 // instead. Thus we leave the old offset alone. 1182 // instead. Thus we leave the old offset alone.
1177 Constant *Four = Ctx->getConstantInt32(4); 1183 Constant *Four = Ctx->getConstantInt32(4);
1178 Variable *NewBase = Func->makeVariable(Base->getType()); 1184 Variable *NewBase = Func->makeVariable(Base->getType());
1179 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, 1185 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add,
1180 NewBase, Base, Four)); 1186 NewBase, Base, Four));
1181 Base = NewBase; 1187 Base = NewBase;
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 if (Instr->isUnconditional()) { 1814 if (Instr->isUnconditional()) {
1809 _br(Instr->getTargetUnconditional()); 1815 _br(Instr->getTargetUnconditional());
1810 return; 1816 return;
1811 } 1817 }
1812 Operand *Cond = Instr->getCondition(); 1818 Operand *Cond = Instr->getCondition();
1813 1819
1814 CondARM32::Cond BrCondTrue0 = CondARM32::NE; 1820 CondARM32::Cond BrCondTrue0 = CondARM32::NE;
1815 CondARM32::Cond BrCondTrue1 = CondARM32::kNone; 1821 CondARM32::Cond BrCondTrue1 = CondARM32::kNone;
1816 CondARM32::Cond BrCondFalse = CondARM32::kNone; 1822 CondARM32::Cond BrCondFalse = CondARM32::kNone;
1817 if (!_mov_i1_to_flags(Cond, &BrCondTrue0, &BrCondTrue1, &BrCondFalse)) { 1823 if (!_mov_i1_to_flags(Cond, &BrCondTrue0, &BrCondTrue1, &BrCondFalse)) {
1818 // "Cond" was not fold. 1824 // "Cond" was not folded.
1819 Type Ty = Cond->getType(); 1825 Type Ty = Cond->getType();
1820 Variable *Src0R = legalizeToReg(Cond); 1826 Variable *Src0R = legalizeToReg(Cond);
1821 assert(Ty == IceType_i1); 1827 assert(Ty == IceType_i1);
1822 if (Ty != IceType_i32) 1828 if (Ty != IceType_i32)
1823 _uxt(Src0R, Src0R); 1829 _uxt(Src0R, Src0R);
1824 Constant *_0 = Ctx->getConstantZero(IceType_i32); 1830 Constant *_0 = Ctx->getConstantZero(IceType_i32);
1825 _cmp(Src0R, _0); 1831 _cmp(Src0R, _0);
1826 BrCondTrue0 = CondARM32::NE; 1832 BrCondTrue0 = CondARM32::NE;
1827 } 1833 }
1828 1834
(...skipping 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after
3364 Type Ty = Load->getDest()->getType(); 3370 Type Ty = Load->getDest()->getType();
3365 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); 3371 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty);
3366 Variable *DestLoad = Load->getDest(); 3372 Variable *DestLoad = Load->getDest();
3367 3373
3368 // TODO(jvoung): handled folding opportunities. Sign and zero extension can 3374 // TODO(jvoung): handled folding opportunities. Sign and zero extension can
3369 // be folded into a load. 3375 // be folded into a load.
3370 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0); 3376 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0);
3371 lowerAssign(Assign); 3377 lowerAssign(Assign);
3372 } 3378 }
3373 3379
3374 void TargetARM32::doAddressOptLoad() {} 3380 namespace {
3381 void dumpAddressOpt(const Cfg *Func, const Variable *Base, int32_t Offset,
3382 const Variable *OffsetReg, int16_t OffsetRegShamt,
Jim Stichnoth 2015/11/08 20:05:51 tiny nit - OffsetRegShAmt ? (here and below)
John 2015/11/09 22:42:24 Done.
3383 const Inst *Reason) {
3384 if (!BuildDefs::dump())
3385 return;
3386 if (!Func->isVerbose(IceV_AddrOpt))
3387 return;
3388 OstreamLocker _(Func->getContext());
3389 Ostream &Str = Func->getContext()->getStrDump();
3390 Str << "Instruction: ";
3391 Reason->dumpDecorated(Func);
3392 Str << " results in Base=";
3393 if (Base)
3394 Base->dump(Func);
3395 else
3396 Str << "<null>";
3397 Str << ", OffsetReg=";
3398 if (OffsetReg)
3399 OffsetReg->dump(Func);
3400 else
3401 Str << "<null>";
3402 Str << ", Shift=" << OffsetRegShamt << ", Offset=" << Offset << "\n";
3403 }
3404
3405 bool matchAssign(const VariablesMetadata *VMetadata, Variable **Var,
3406 int32_t *Offset, const Inst **Reason) {
3407 // Var originates from Var=SrcVar ==> set Var:=SrcVar
3408 if (*Var == nullptr)
3409 return false;
3410 const Inst *VarAssign = VMetadata->getSingleDefinition(*Var);
3411 if (!VarAssign)
3412 return false;
3413 assert(!VMetadata->isMultiDef(*Var));
3414 if (!llvm::isa<InstAssign>(VarAssign))
3415 return false;
3416
3417 Operand *SrcOp = VarAssign->getSrc(0);
3418 assert(SrcOp);
Jim Stichnoth 2015/11/08 20:05:50 This assert is a relic of the early days when mayb
John 2015/11/09 22:42:25 Done.
3419 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
3420 if (!VMetadata->isMultiDef(SrcVar) ||
3421 // TODO: ensure SrcVar stays single-BB
3422 false) {
3423 return false;
3424 *Var = SrcVar;
Jim Stichnoth 2015/11/08 20:05:51 this statement is unreachable
John 2015/11/09 22:42:24 Done.
3425 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
Jim Stichnoth 2015/11/08 20:05:51 Don't use "else if" if the previous branch is real
John 2015/11/09 22:42:24 N/A.
3426 if (false)
3427 return false;
Jim Stichnoth 2015/11/08 20:05:51 Why not return true? :)
John 2015/11/09 22:42:24 I really don't know how high I was here.
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 (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
Jim Stichnoth 2015/11/08 20:05:51 Can you just use dyn_cast? It looks like Inst can
John 2015/11/09 22:42:24 Done.
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 assert(OffsetRegShamt == 0);
3467 const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
3468 if (BaseInst == nullptr)
3469 return false;
3470 assert(!VMetadata->isMultiDef(*Base));
3471 if (BaseInst->getSrcSize() < 2)
3472 return false;
3473 auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0));
3474 if (!Var1)
3475 return false;
3476 if (VMetadata->isMultiDef(Var1))
3477 return false;
3478 auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1));
3479 if (!Var2)
3480 return false;
3481 if (VMetadata->isMultiDef(Var2))
3482 return false;
3483 InstArithmetic::OpKind _;
3484 if (!isAddOrSub(BaseInst, &_) ||
3485 // TODO: ensure Var1 and Var2 stay single-BB
3486 false)
3487 return false;
3488 *Base = Var1;
3489 *OffsetReg = Var2;
3490 // OffsetRegShamt is already 0.
3491 *Reason = BaseInst;
3492 return true;
3493 }
3494
3495 bool matchShiftedOffsetReg(const VariablesMetadata *VMetadata,
3496 Variable **OffsetReg, OperandARM32::ShiftKind *Kind,
3497 int32_t *OffsetRegShamt, const Inst **Reason) {
3498 // OffsetReg is OffsetReg=Var*Const && log2(Const)+Shift<=32 ==>
3499 // OffsetReg=Var, Shift+=log2(Const)
3500 // OffsetReg is OffsetReg=Var<<Const && Const+Shift<=32 ==>
3501 // OffsetReg=Var, Shift+=Const
3502 // OffsetReg is OffsetReg=Var>>Const && Const-Shift>=-32 ==>
3503 // OffsetReg=Var, Shift-=Const
3504 OperandARM32::ShiftKind NewShiftKind = OperandARM32::kNoShift;
3505 if (*OffsetReg == nullptr)
3506 return false;
3507 auto *IndexInst = VMetadata->getSingleDefinition(*OffsetReg);
3508 if (IndexInst == nullptr)
3509 return false;
3510 assert(!VMetadata->isMultiDef(*OffsetReg));
3511 if (IndexInst->getSrcSize() < 2)
3512 return false;
3513 auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst);
3514 if (ArithInst == nullptr)
3515 return false;
3516 auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0));
3517 if (Var == nullptr)
3518 return false;
3519 auto *Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1));
3520 if (Const == nullptr) {
3521 assert(!llvm::isa<ConstantInteger32>(ArithInst->getSrc(0)));
3522 return false;
3523 }
3524 if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32)
3525 return false;
3526
3527 uint32_t NewShamt = -1;
3528 switch (ArithInst->getOp()) {
3529 default:
3530 return false;
3531 case InstArithmetic::Shl: {
3532 NewShiftKind = OperandARM32::LSL;
3533 NewShamt = Const->getValue();
3534 if (NewShamt > 31)
3535 return false;
3536 } break;
3537 case InstArithmetic::Lshr: {
3538 NewShiftKind = OperandARM32::LSR;
3539 NewShamt = Const->getValue();
3540 if (NewShamt > 31)
3541 return false;
3542 } break;
3543 case InstArithmetic::Ashr: {
3544 NewShiftKind = OperandARM32::ASR;
3545 NewShamt = Const->getValue();
3546 if (NewShamt > 31)
3547 return false;
3548 } break;
3549 case InstArithmetic::Udiv:
3550 case InstArithmetic::Mul: {
3551 const uint32_t UnsignedConst = Const->getValue();
3552 NewShamt = llvm::findFirstSet(UnsignedConst);
3553 if (NewShamt != llvm::findLastSet(UnsignedConst)) {
3554 // First bit set is not the same as the last bit set, so Const is not
3555 // a power of 2.
3556 return false;
3557 }
3558 NewShiftKind = ArithInst->getOp() == InstArithmetic::Udiv
3559 ? OperandARM32::LSR
3560 : OperandARM32::LSL;
3561 } break;
3562 }
3563 // Allowed "transitions":
3564 // kNoShift -> * iff NewShamt < 31
3565 // LSL -> LSL iff NewShamt + OffsetRegShamt < 31
3566 // LSR -> LSR iff NewShamt + OffsetRegShamt < 31
3567 // ASR -> ASR iff NewShamt + OffsetRegShamt < 31
3568 if (*Kind != OperandARM32::kNoShift && *Kind != NewShiftKind) {
3569 return false;
3570 }
3571 const int32_t NewOffsetRegShamt = *OffsetRegShamt + NewShamt;
3572 if (NewOffsetRegShamt > 31)
3573 return false;
3574 *OffsetReg = Var;
3575 *OffsetRegShamt = NewOffsetRegShamt;
3576 *Kind = NewShiftKind;
3577 *Reason = IndexInst;
3578 return true;
3579 }
3580
3581 bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable **Base,
3582 int32_t *Offset, const Inst **Reason) {
3583 // Base is Base=Var+Const || Base is Base=Const+Var ==>
3584 // set Base=Var, Offset+=Const
3585 // Base is Base=Var-Const ==>
3586 // set Base=Var, Offset-=Const
3587 if (*Base == nullptr)
3588 return false;
3589 const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
3590 if (BaseInst == nullptr) {
3591 return false;
3592 }
3593 assert(!VMetadata->isMultiDef(*Base));
3594
3595 auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst);
3596 if (ArithInst == nullptr)
3597 return false;
3598 InstArithmetic::OpKind Kind;
3599 if (!isAddOrSub(ArithInst, &Kind))
3600 return false;
3601 bool IsAdd = Kind == InstArithmetic::Add;
3602 Operand *Src0 = ArithInst->getSrc(0);
3603 Operand *Src1 = ArithInst->getSrc(1);
3604 auto *Var0 = llvm::dyn_cast<Variable>(Src0);
3605 auto *Var1 = llvm::dyn_cast<Variable>(Src1);
3606 auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0);
3607 auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1);
3608 Variable *NewBase = nullptr;
3609 int32_t NewOffset = *Offset;
3610
3611 if (Var0 == nullptr && Const0 == nullptr) {
3612 assert(llvm::isa<ConstantRelocatable>(Src0));
3613 return false;
3614 }
3615
3616 if (Var1 == nullptr && Const1 == nullptr) {
3617 assert(llvm::isa<ConstantRelocatable>(Src1));
3618 return false;
3619 }
3620
3621 if (Var0 && Var1)
3622 // TODO(jpp): merge base/index splitting into here.
3623 return false;
3624 if (!IsAdd && Var1)
3625 return false;
3626 if (Var0)
3627 NewBase = Var0;
3628 else if (Var1)
3629 NewBase = Var1;
3630 // Compute the updated constant offset.
3631 if (Const0) {
3632 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue();
3633 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
3634 return false;
3635 NewOffset += MoreOffset;
3636 }
3637 if (Const1) {
3638 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue();
3639 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
3640 return false;
3641 NewOffset += MoreOffset;
3642 }
3643
3644 // Update the computed address parameters once we are sure optimization
3645 // is valid.
3646 *Base = NewBase;
3647 *Offset = NewOffset;
3648 *Reason = BaseInst;
3649 return true;
3650 }
3651 } // end of anonymous namespace
3652
3653 // ARM32 address modes:
3654 // ld/st i[8|16|32]: [reg], [reg +/- imm12], [pc +/- imm12],
3655 // [reg +/- reg << shamt5]
3656 // ld/st f[32|64] : [reg], [reg +/- imm8] , [pc +/- imm8]
3657 // ld/st vectors : [reg]
3658 //
3659 // For now, we don't handle address modes with Relocatables.
3660 namespace {
3661 // MemTraits contains per-type valid address mode information.
3662 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
3663 static_assert(!(shaddr) || rraddr, "Check ICETYPEARM32_TABLE::" #tag);
3664 ICETYPEARM32_TABLE
3665 #undef X
3666
3667 static const struct {
3668 int32_t ValidImmMask;
3669 bool CanHaveImm;
3670 bool CanHaveIndex;
3671 bool CanHaveShiftedIndex;
3672 } MemTraits[] = {
3673 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
3674 { (1 << ubits) - 1, (ubits) > 0, rraddr, shaddr, } \
3675 ,
3676 ICETYPEARM32_TABLE
3677 #undef X
3678 };
3679 static constexpr SizeT MemTraitsSize = llvm::array_lengthof(MemTraits);
3680 } // end of anonymous namespace
3681
3682 OperandARM32Mem *TargetARM32::formAddressingMode(Type Ty, Cfg *Func,
3683 const Inst *LdSt,
3684 Operand *Base) {
3685 assert(Base != nullptr);
3686 int32_t OffsetImm = 0;
3687 Variable *OffsetReg = nullptr;
3688 int32_t OffsetRegShamt = 0;
3689 OperandARM32::ShiftKind ShiftKind = OperandARM32::kNoShift;
3690
3691 Func->resetCurrentNode();
3692 if (Func->isVerbose(IceV_AddrOpt)) {
3693 OstreamLocker L(Func->getContext());
Jim Stichnoth 2015/11/08 20:05:51 Earlier you used "OstreamLocker _(...);"
John 2015/11/09 22:42:24 Changes everywhere.
3694 Ostream &Str = Func->getContext()->getStrDump();
3695 Str << "\nAddress mode formation:\t";
3696 LdSt->dumpDecorated(Func);
3697 }
3698
3699 if (isVectorType(Ty))
3700 // vector loads and stores do not allow offsets, and only support the
3701 // "[reg]" addressing mode (the other supported modes are write back.)
3702 return nullptr;
3703
3704 auto *BaseVar = llvm::dyn_cast<Variable>(Base);
3705 if (BaseVar == nullptr)
3706 return nullptr;
3707
3708 assert(Ty < MemTraitsSize);
3709 auto *TypeTraits = &MemTraits[Ty];
3710 const bool CanHaveIndex = TypeTraits->CanHaveIndex;
3711 const bool CanHaveShiftedIndex = TypeTraits->CanHaveShiftedIndex;
3712 const bool CanHaveImm = TypeTraits->CanHaveImm;
3713 const int32_t ValidImmMask = TypeTraits->ValidImmMask;
3714 assert(!CanHaveImm || ValidImmMask >= 0);
3715
3716 const VariablesMetadata *VMetadata = Func->getVMetadata();
3717 const Inst *Reason = nullptr;
3718
3719 do {
3720 if (Reason != nullptr) {
3721 dumpAddressOpt(Func, BaseVar, OffsetImm, OffsetReg, OffsetRegShamt,
3722 Reason);
3723 Reason = nullptr;
3724 }
3725
3726 if (matchAssign(VMetadata, &BaseVar, &OffsetImm, &Reason)) {
3727 continue;
3728 }
3729
3730 if (CanHaveIndex &&
3731 matchAssign(VMetadata, &OffsetReg, &OffsetImm, &Reason)) {
3732 continue;
3733 }
3734
3735 if (CanHaveIndex && matchCombinedBaseIndex(VMetadata, &BaseVar, &OffsetReg,
3736 OffsetRegShamt, &Reason)) {
3737 continue;
3738 }
3739
3740 if (CanHaveShiftedIndex) {
3741 if (matchShiftedOffsetReg(VMetadata, &OffsetReg, &ShiftKind,
3742 &OffsetRegShamt, &Reason)) {
3743 continue;
3744 }
3745
3746 if ((OffsetRegShamt == 0) &&
3747 matchShiftedOffsetReg(VMetadata, &BaseVar, &ShiftKind,
3748 &OffsetRegShamt, &Reason)) {
3749 std::swap(BaseVar, OffsetReg);
3750 continue;
3751 }
3752 }
3753
3754 if (matchOffsetBase(VMetadata, &BaseVar, &OffsetImm, &Reason)) {
3755 continue;
3756 }
3757 } while (Reason);
3758
3759 if (BaseVar == nullptr) {
3760 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] is not legal in ARM, so we have to
3761 // legalize the addressing mode to [BaseReg, OffsetReg{, LSL Shamt}].
3762 // Instead of a zeroed BaseReg, we initialize it with OffsetImm:
3763 //
3764 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] ->
3765 // mov BaseReg, #OffsetImm
3766 // use of [BaseReg, OffsetReg{, LSL Shamt}]
3767 //
3768 static constexpr Type PointerType = IceType_i32;
3769 BaseVar = makeReg(PointerType);
3770 Context.insert(
3771 InstAssign::create(Func, BaseVar, Ctx->getConstantInt32(OffsetImm)));
3772 OffsetImm = 0;
3773 } else if (OffsetImm != 0) {
3774 // ARM Ldr/Str instructions have limited range immediates. The formation
3775 // loop above materialized an Immediate carelessly, so we ensure the
3776 // generated offset is sane.
3777 const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm;
3778 const InstArithmetic::OpKind Op =
3779 OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub;
3780
3781 if (!CanHaveImm || !isLegalMemOffset(Ty, OffsetImm) ||
3782 OffsetReg != nullptr) {
3783 if (OffsetReg == nullptr) {
3784 // We formed a [Base, #const] addressing mode which is not encodable in
3785 // ARM. There is little point in forming an address mode now if we don't
3786 // have an offset. Effectively, we would end up with something like
3787 //
3788 // [Base, #const] -> add T, Base, #const
3789 // use of [T]
3790 //
3791 // Which is exactly what we already have. So we just bite the bullet
3792 // here and don't form any address mode.
3793 return nullptr;
3794 }
3795 // We formed [Base, Offset {, LSL Amnt}, #const]. Oops. Legalize it to
3796 //
3797 // [Base, Offset, {LSL amount}, #const] ->
3798 // add T, Base, #const
3799 // use of [T, Offset {, LSL amount}]
3800 static constexpr Type PointerType = IceType_i32;
Jim Stichnoth 2015/11/08 20:05:51 Can you use the existing getPointerType() instead?
John 2015/11/09 22:42:24 Then it is no longer a constexpr. :(
Jim Stichnoth 2015/11/09 22:47:49 Then why did you subsequently change it to "const"
John 2015/11/09 22:52:30 Done.
3801 Variable *T = makeReg(PointerType);
3802 Context.insert(InstArithmetic::create(
3803 Func, Op, T, BaseVar, Ctx->getConstantInt32(PositiveOffset)));
3804 BaseVar = T;
3805 OffsetImm = 0;
3806 }
3807 }
3808
3809 assert(BaseVar != nullptr);
3810 assert(OffsetImm == 0 || OffsetReg == nullptr);
3811 assert(OffsetReg == nullptr || CanHaveIndex);
3812 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm
3813 : (ValidImmMask & OffsetImm) == OffsetImm);
3814
3815 if (OffsetReg != nullptr) {
3816 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetReg, ShiftKind,
3817 OffsetRegShamt);
3818 }
3819
3820 return OperandARM32Mem::create(
3821 Func, Ty, BaseVar,
3822 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm)));
3823 }
3824
3825 void TargetARM32::doAddressOptLoad() {
3826 Inst *Instr = Context.getCur();
3827 assert(llvm::isa<InstLoad>(Instr));
3828 Variable *Dest = Instr->getDest();
3829 Operand *Addr = Instr->getSrc(0);
3830 if (OperandARM32Mem *Mem =
3831 formAddressingMode(Dest->getType(), Func, Instr, Addr)) {
3832 Instr->setDeleted();
3833 Context.insert(InstLoad::create(Func, Dest, Mem));
3834 }
3835 }
3375 3836
3376 void TargetARM32::randomlyInsertNop(float Probability, 3837 void TargetARM32::randomlyInsertNop(float Probability,
3377 RandomNumberGenerator &RNG) { 3838 RandomNumberGenerator &RNG) {
3378 RandomNumberGeneratorWrapper RNGW(RNG); 3839 RandomNumberGeneratorWrapper RNGW(RNG);
3379 if (RNGW.getTrueWithProbability(Probability)) { 3840 if (RNGW.getTrueWithProbability(Probability)) {
3380 UnimplementedError(Func->getContext()->getFlags()); 3841 UnimplementedError(Func->getContext()->getFlags());
3381 } 3842 }
3382 } 3843 }
3383 3844
3384 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { 3845 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
3565 Variable *ValueHi = legalizeToReg(hiOperand(Value)); 4026 Variable *ValueHi = legalizeToReg(hiOperand(Value));
3566 Variable *ValueLo = legalizeToReg(loOperand(Value)); 4027 Variable *ValueLo = legalizeToReg(loOperand(Value));
3567 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); 4028 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr)));
3568 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); 4029 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr)));
3569 } else { 4030 } else {
3570 Variable *ValueR = legalizeToReg(Value); 4031 Variable *ValueR = legalizeToReg(Value);
3571 _str(ValueR, NewAddr); 4032 _str(ValueR, NewAddr);
3572 } 4033 }
3573 } 4034 }
3574 4035
3575 void TargetARM32::doAddressOptStore() {} 4036 void TargetARM32::doAddressOptStore() {
4037 Inst *Instr = Context.getCur();
4038 assert(llvm::isa<InstStore>(Instr));
4039 Operand *Src = Instr->getSrc(0);
4040 Operand *Addr = Instr->getSrc(1);
4041 if (OperandARM32Mem *Mem =
4042 formAddressingMode(Src->getType(), Func, Instr, Addr)) {
4043 Instr->setDeleted();
4044 Context.insert(InstStore::create(Func, Src, Mem));
4045 }
4046 }
3576 4047
3577 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { 4048 void TargetARM32::lowerSwitch(const InstSwitch *Inst) {
3578 // This implements the most naive possible lowering. 4049 // This implements the most naive possible lowering.
3579 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default 4050 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default
3580 Operand *Src0 = Inst->getComparison(); 4051 Operand *Src0 = Inst->getComparison();
3581 SizeT NumCases = Inst->getNumCases(); 4052 SizeT NumCases = Inst->getNumCases();
3582 if (Src0->getType() == IceType_i64) { 4053 if (Src0->getType() == IceType_i64) {
3583 Src0 = legalizeUndef(Src0); 4054 Src0 = legalizeUndef(Src0);
3584 Variable *Src0Lo = legalizeToReg(loOperand(Src0)); 4055 Variable *Src0Lo = legalizeToReg(loOperand(Src0));
3585 Variable *Src0Hi = legalizeToReg(hiOperand(Src0)); 4056 Variable *Src0Hi = legalizeToReg(hiOperand(Src0));
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3662 } 4133 }
3663 } 4134 }
3664 } 4135 }
3665 } 4136 }
3666 4137
3667 // Go through the various types of operands: OperandARM32Mem, 4138 // Go through the various types of operands: OperandARM32Mem,
3668 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if 4139 // OperandARM32Flex, Constant, and Variable. Given the above assertion, if
3669 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we 4140 // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we
3670 // can always copy to a register. 4141 // can always copy to a register.
3671 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { 4142 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(From)) {
3672 static const struct {
3673 bool CanHaveOffset;
3674 bool CanHaveIndex;
3675 } MemTraits[] = {
3676 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr) \
3677 { (ubits) > 0, rraddr } \
3678 ,
3679 ICETYPEARM32_TABLE
3680 #undef X
3681 };
3682 // Before doing anything with a Mem operand, we need to ensure that the 4143 // Before doing anything with a Mem operand, we need to ensure that the
3683 // Base and Index components are in physical registers. 4144 // Base and Index components are in physical registers.
3684 Variable *Base = Mem->getBase(); 4145 Variable *Base = Mem->getBase();
3685 Variable *Index = Mem->getIndex(); 4146 Variable *Index = Mem->getIndex();
3686 ConstantInteger32 *Offset = Mem->getOffset(); 4147 ConstantInteger32 *Offset = Mem->getOffset();
3687 assert(Index == nullptr || Offset == nullptr); 4148 assert(Index == nullptr || Offset == nullptr);
3688 Variable *RegBase = nullptr; 4149 Variable *RegBase = nullptr;
3689 Variable *RegIndex = nullptr; 4150 Variable *RegIndex = nullptr;
3690 if (Base) { 4151 assert(Base);
3691 RegBase = legalizeToReg(Base); 4152 RegBase = legalizeToReg(Base);
3692 } 4153 bool InvalidImm = false;
4154 assert(Ty < MemTraitsSize);
3693 if (Index) { 4155 if (Index) {
4156 assert(Offset == nullptr);
4157 assert(MemTraits[Ty].CanHaveIndex);
3694 RegIndex = legalizeToReg(Index); 4158 RegIndex = legalizeToReg(Index);
3695 if (!MemTraits[Ty].CanHaveIndex) {
3696 Variable *T = makeReg(IceType_i32, getReservedTmpReg());
3697 _add(T, RegBase, RegIndex);
3698 RegBase = T;
3699 RegIndex = nullptr;
3700 }
3701 } 4159 }
3702 if (Offset && Offset->getValue() != 0) { 4160 if (Offset && Offset->getValue() != 0) {
3703 static constexpr bool SignExt = false; 4161 assert(Index == nullptr);
3704 if (!MemTraits[Ty].CanHaveOffset || 4162 static constexpr bool ZeroExt = false;
3705 !OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset->getValue())) { 4163 assert(MemTraits[Ty].CanHaveImm);
3706 Variable *T = legalizeToReg(Offset, getReservedTmpReg()); 4164 if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) {
3707 _add(T, T, RegBase); 4165 assert(RegBase->hasReg() &&
Jim Stichnoth 2015/11/08 20:05:51 Two separate asserts for better precision when it
John 2015/11/09 22:42:24 Done.
3708 RegBase = T; 4166 RegBase->getRegNum() == (int)getFrameOrStackReg());
3709 Offset = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)); 4167 // We are a bit more lenient with invalid immediate when accessing the
4168 // stack here, and then rely on legalizeStackSlots() to fix things as
4169 // appropriate.
4170 InvalidImm = true;
3710 } 4171 }
3711 } 4172 }
3712 4173
3713 // Create a new operand if there was a change. 4174 // Create a new operand if there was a change.
3714 if (Base != RegBase || Index != RegIndex) { 4175 if (Base != RegBase || Index != RegIndex) {
3715 // There is only a reg +/- reg or reg + imm form. 4176 // There is only a reg +/- reg or reg + imm form.
3716 // Figure out which to re-create. 4177 // Figure out which to re-create.
3717 if (RegBase && RegIndex) { 4178 if (RegIndex) {
3718 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, 4179 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex,
3719 Mem->getShiftOp(), Mem->getShiftAmt(), 4180 Mem->getShiftOp(), Mem->getShiftAmt(),
3720 Mem->getAddrMode()); 4181 Mem->getAddrMode());
3721 } else { 4182 } else {
3722 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset, 4183 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset,
3723 Mem->getAddrMode()); 4184 Mem->getAddrMode());
3724 } 4185 }
3725 } 4186 }
3726 if (Allowed & Legal_Mem) { 4187 if (Allowed & Legal_Mem) {
3727 From = Mem; 4188 From = Mem;
3728 } else { 4189 } else {
3729 Variable *Reg = makeReg(Ty, RegNum); 4190 Variable *Reg = makeReg(Ty, RegNum);
3730 _ldr(Reg, Mem); 4191 if (InvalidImm) {
4192 // If Mem has an invalid immediate, we legalize it to a Reg using mov
4193 // instead of ldr because legalizeStackSlots() will later kick in and
4194 // fix the immediate for us.
4195 _mov(Reg, Mem);
4196 } else {
4197 _ldr(Reg, Mem);
4198 }
4199
3731 From = Reg; 4200 From = Reg;
3732 } 4201 }
3733 return From; 4202 return From;
3734 } 4203 }
3735 4204
3736 if (auto *Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { 4205 if (auto *Flex = llvm::dyn_cast<OperandARM32Flex>(From)) {
3737 if (!(Allowed & Legal_Flex)) { 4206 if (!(Allowed & Legal_Flex)) {
3738 if (auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { 4207 if (auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) {
3739 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { 4208 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) {
3740 From = FlexReg->getReg(); 4209 From = FlexReg->getReg();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3793 Variable *Reg = makeReg(Ty, RegNum); 4262 Variable *Reg = makeReg(Ty, RegNum);
3794 _movw(Reg, C); 4263 _movw(Reg, C);
3795 _movt(Reg, C); 4264 _movt(Reg, C);
3796 return Reg; 4265 return Reg;
3797 } else { 4266 } else {
3798 assert(isScalarFloatingType(Ty)); 4267 assert(isScalarFloatingType(Ty));
3799 // Load floats/doubles from literal pool. 4268 // Load floats/doubles from literal pool.
3800 // TODO(jvoung): Allow certain immediates to be encoded directly in an 4269 // TODO(jvoung): Allow certain immediates to be encoded directly in an
3801 // operand. See Table A7-18 of the ARM manual: "Floating-point modified 4270 // operand. See Table A7-18 of the ARM manual: "Floating-point modified
3802 // immediate constants". Or, for 32-bit floating point numbers, just 4271 // immediate constants". Or, for 32-bit floating point numbers, just
3803 // encode the raw bits into a movw/movt pair to GPR, and vmov to an SREG, 4272 // encode the raw bits into a movw/movt pair to GPR, and vmov to an SREG
3804 // instead of using a movw/movt pair to get the const-pool address then 4273 // instead of using a movw/movt pair to get the const-pool address then
3805 // loading to SREG. 4274 // loading to SREG.
3806 std::string Buffer; 4275 std::string Buffer;
3807 llvm::raw_string_ostream StrBuf(Buffer); 4276 llvm::raw_string_ostream StrBuf(Buffer);
3808 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); 4277 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx);
3809 llvm::cast<Constant>(From)->setShouldBePooled(true); 4278 llvm::cast<Constant>(From)->setShouldBePooled(true);
3810 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); 4279 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
3811 Variable *BaseReg = makeReg(getPointerType()); 4280 Variable *BaseReg = makeReg(getPointerType());
3812 _movw(BaseReg, Offset); 4281 _movw(BaseReg, Offset);
3813 _movt(BaseReg, Offset); 4282 _movt(BaseReg, Offset);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3863 } 4332 }
3864 4333
3865 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) { 4334 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) {
3866 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); 4335 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand);
3867 // It may be the case that address mode optimization already creates an 4336 // It may be the case that address mode optimization already creates an
3868 // OperandARM32Mem, so in that case it wouldn't need another level of 4337 // OperandARM32Mem, so in that case it wouldn't need another level of
3869 // transformation. 4338 // transformation.
3870 if (Mem) { 4339 if (Mem) {
3871 return llvm::cast<OperandARM32Mem>(legalize(Mem)); 4340 return llvm::cast<OperandARM32Mem>(legalize(Mem));
3872 } 4341 }
3873 // If we didn't do address mode optimization, then we only have a base/offset 4342 // If we didn't do address mode optimization, then we only have a
3874 // to work with. ARM always requires a base register, so just use that to 4343 // base/offset to work with. ARM always requires a base register, so
3875 // hold the operand. 4344 // just use that to hold the operand.
3876 Variable *Base = legalizeToReg(Operand); 4345 Variable *Base = legalizeToReg(Operand);
3877 return OperandARM32Mem::create( 4346 return OperandARM32Mem::create(
3878 Func, Ty, Base, 4347 Func, Ty, Base,
3879 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); 4348 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)));
3880 } 4349 }
3881 4350
3882 Variable64On32 *TargetARM32::makeI64RegPair() { 4351 Variable64On32 *TargetARM32::makeI64RegPair() {
3883 Variable64On32 *Reg = 4352 Variable64On32 *Reg =
3884 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); 4353 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
3885 Reg->setMustHaveReg(); 4354 Reg->setMustHaveReg();
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
4266 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 4735 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
4267 // However, for compatibility with current NaCl LLVM, don't claim that. 4736 // However, for compatibility with current NaCl LLVM, don't claim that.
4268 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 4737 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
4269 } 4738 }
4270 4739
4271 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; 4740 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM];
4272 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; 4741 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
4273 llvm::SmallBitVector TargetARM32::ScratchRegs; 4742 llvm::SmallBitVector TargetARM32::ScratchRegs;
4274 4743
4275 } // end of namespace Ice 4744 } // 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