| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 } | 258 } |
| 259 | 259 |
| 260 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); | 260 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); |
| 261 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 261 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 262 } | 262 } |
| 263 | 263 |
| 264 return applyStackAlignment(OutArgsSizeBytes); | 264 return applyStackAlignment(OutArgsSizeBytes); |
| 265 } | 265 } |
| 266 | 266 |
| 267 void TargetARM32::findMaxStackOutArgsSize() { | 267 void TargetARM32::findMaxStackOutArgsSize() { |
| 268 // MinNeededOutArgsBytes should be updated if the Target ever creates an | 268 // MinNeededOutArgsBytes should be updated if the Target ever creates a |
| 269 // high-level InstCall that requires more stack bytes. | 269 // high-level InstCall that requires more stack bytes. |
| 270 constexpr size_t MinNeededOutArgsBytes = 0; | 270 constexpr size_t MinNeededOutArgsBytes = 0; |
| 271 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; | 271 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; |
| 272 for (CfgNode *Node : Func->getNodes()) { | 272 for (CfgNode *Node : Func->getNodes()) { |
| 273 Context.init(Node); | 273 Context.init(Node); |
| 274 while (!Context.atEnd()) { | 274 while (!Context.atEnd()) { |
| 275 PostIncrLoweringContext PostIncrement(Context); | 275 PostIncrLoweringContext PostIncrement(Context); |
| 276 Inst *CurInstr = Context.getCur(); | 276 Inst *CurInstr = Context.getCur(); |
| 277 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) { | 277 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) { |
| 278 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call); | 278 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call); |
| 279 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes); | 279 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes); |
| 280 } | 280 } |
| 281 } | 281 } |
| 282 } | 282 } |
| 283 } | 283 } |
| 284 | 284 |
| 285 void TargetARM32::translateO2() { | 285 void TargetARM32::translateO2() { |
| 286 TimerMarker T(TimerStack::TT_O2, Func); | 286 TimerMarker T(TimerStack::TT_O2, Func); |
| 287 | 287 |
| 288 // TODO(stichnot): share passes with X86? | 288 // TODO(stichnot): share passes with X86? |
| 289 // https://code.google.com/p/nativeclient/issues/detail?id=4094 | 289 // https://code.google.com/p/nativeclient/issues/detail?id=4094 |
| 290 genTargetHelperCalls(); | 290 genTargetHelperCalls(); |
| 291 findMaxStackOutArgsSize(); | 291 findMaxStackOutArgsSize(); |
| 292 | 292 |
| 293 // Do not merge Alloca instructions, and lay out the stack. | 293 // Do not merge Alloca instructions, and lay out the stack. |
| 294 static constexpr bool SortAndCombineAllocas = false; | 294 static constexpr bool SortAndCombineAllocas = true; |
| 295 Func->processAllocas(SortAndCombineAllocas); | 295 Func->processAllocas(SortAndCombineAllocas); |
| 296 Func->dump("After Alloca processing"); | 296 Func->dump("After Alloca processing"); |
| 297 | 297 |
| 298 if (!Ctx->getFlags().getPhiEdgeSplit()) { | 298 if (!Ctx->getFlags().getPhiEdgeSplit()) { |
| 299 // Lower Phi instructions. | 299 // Lower Phi instructions. |
| 300 Func->placePhiLoads(); | 300 Func->placePhiLoads(); |
| 301 if (Func->hasError()) | 301 if (Func->hasError()) |
| 302 return; | 302 return; |
| 303 Func->placePhiStores(); | 303 Func->placePhiStores(); |
| 304 if (Func->hasError()) | 304 if (Func->hasError()) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 // Validate the live range computations. The expensive validation call is | 349 // Validate the live range computations. The expensive validation call is |
| 350 // deliberately only made when assertions are enabled. | 350 // deliberately only made when assertions are enabled. |
| 351 assert(Func->validateLiveness()); | 351 assert(Func->validateLiveness()); |
| 352 // The post-codegen dump is done here, after liveness analysis and associated | 352 // The post-codegen dump is done here, after liveness analysis and associated |
| 353 // cleanup, to make the dump cleaner and more useful. | 353 // cleanup, to make the dump cleaner and more useful. |
| 354 Func->dump("After initial ARM32 codegen"); | 354 Func->dump("After initial ARM32 codegen"); |
| 355 Func->getVMetadata()->init(VMK_All); | 355 Func->getVMetadata()->init(VMK_All); |
| 356 regAlloc(RAK_Global); | 356 regAlloc(RAK_Global); |
| 357 if (Func->hasError()) | 357 if (Func->hasError()) |
| 358 return; | 358 return; |
| 359 |
| 359 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); | 360 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); |
| 360 Func->dump("After linear scan regalloc"); | 361 Func->dump("After linear scan regalloc"); |
| 361 | 362 |
| 362 if (Ctx->getFlags().getPhiEdgeSplit()) { | 363 if (Ctx->getFlags().getPhiEdgeSplit()) { |
| 363 Func->advancedPhiLowering(); | 364 Func->advancedPhiLowering(); |
| 364 Func->dump("After advanced Phi lowering"); | 365 Func->dump("After advanced Phi lowering"); |
| 365 } | 366 } |
| 366 | 367 |
| 368 ForbidTemporaryWithoutReg _(this); |
| 369 |
| 367 // Stack frame mapping. | 370 // Stack frame mapping. |
| 368 Func->genFrame(); | 371 Func->genFrame(); |
| 369 if (Func->hasError()) | 372 if (Func->hasError()) |
| 370 return; | 373 return; |
| 371 Func->dump("After stack frame mapping"); | 374 Func->dump("After stack frame mapping"); |
| 372 | 375 |
| 373 legalizeStackSlots(); | 376 legalizeStackSlots(); |
| 374 if (Func->hasError()) | 377 if (Func->hasError()) |
| 375 return; | 378 return; |
| 376 Func->dump("After legalizeStackSlots"); | 379 Func->dump("After legalizeStackSlots"); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 392 } | 395 } |
| 393 | 396 |
| 394 void TargetARM32::translateOm1() { | 397 void TargetARM32::translateOm1() { |
| 395 TimerMarker T(TimerStack::TT_Om1, Func); | 398 TimerMarker T(TimerStack::TT_Om1, Func); |
| 396 | 399 |
| 397 // TODO: share passes with X86? | 400 // TODO: share passes with X86? |
| 398 genTargetHelperCalls(); | 401 genTargetHelperCalls(); |
| 399 findMaxStackOutArgsSize(); | 402 findMaxStackOutArgsSize(); |
| 400 | 403 |
| 401 // Do not merge Alloca instructions, and lay out the stack. | 404 // Do not merge Alloca instructions, and lay out the stack. |
| 402 static constexpr bool SortAndCombineAllocas = false; | 405 static constexpr bool DontSortAndCombineAllocas = false; |
| 403 Func->processAllocas(SortAndCombineAllocas); | 406 Func->processAllocas(DontSortAndCombineAllocas); |
| 404 Func->dump("After Alloca processing"); | 407 Func->dump("After Alloca processing"); |
| 405 | 408 |
| 406 Func->placePhiLoads(); | 409 Func->placePhiLoads(); |
| 407 if (Func->hasError()) | 410 if (Func->hasError()) |
| 408 return; | 411 return; |
| 409 Func->placePhiStores(); | 412 Func->placePhiStores(); |
| 410 if (Func->hasError()) | 413 if (Func->hasError()) |
| 411 return; | 414 return; |
| 412 Func->deletePhis(); | 415 Func->deletePhis(); |
| 413 if (Func->hasError()) | 416 if (Func->hasError()) |
| 414 return; | 417 return; |
| 415 Func->dump("After Phi lowering"); | 418 Func->dump("After Phi lowering"); |
| 416 | 419 |
| 417 Func->doArgLowering(); | 420 Func->doArgLowering(); |
| 418 | 421 |
| 419 Func->genCode(); | 422 Func->genCode(); |
| 420 if (Func->hasError()) | 423 if (Func->hasError()) |
| 421 return; | 424 return; |
| 422 Func->dump("After initial ARM32 codegen"); | 425 Func->dump("After initial ARM32 codegen"); |
| 423 | 426 |
| 424 regAlloc(RAK_InfOnly); | 427 regAlloc(RAK_InfOnly); |
| 425 if (Func->hasError()) | 428 if (Func->hasError()) |
| 426 return; | 429 return; |
| 430 |
| 427 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); | 431 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); |
| 428 Func->dump("After regalloc of infinite-weight variables"); | 432 Func->dump("After regalloc of infinite-weight variables"); |
| 429 | 433 |
| 434 ForbidTemporaryWithoutReg _(this); |
| 435 |
| 430 Func->genFrame(); | 436 Func->genFrame(); |
| 431 if (Func->hasError()) | 437 if (Func->hasError()) |
| 432 return; | 438 return; |
| 433 Func->dump("After stack frame mapping"); | 439 Func->dump("After stack frame mapping"); |
| 434 | 440 |
| 435 legalizeStackSlots(); | 441 legalizeStackSlots(); |
| 436 if (Func->hasError()) | 442 if (Func->hasError()) |
| 437 return; | 443 return; |
| 438 Func->dump("After legalizeStackSlots"); | 444 Func->dump("After legalizeStackSlots"); |
| 439 | 445 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 return; | 519 return; |
| 514 Ostream &Str = Ctx->getStrEmit(); | 520 Ostream &Str = Ctx->getStrEmit(); |
| 515 if (Var->hasReg()) { | 521 if (Var->hasReg()) { |
| 516 Str << getRegName(Var->getRegNum(), Var->getType()); | 522 Str << getRegName(Var->getRegNum(), Var->getType()); |
| 517 return; | 523 return; |
| 518 } | 524 } |
| 519 if (Var->mustHaveReg()) { | 525 if (Var->mustHaveReg()) { |
| 520 llvm::report_fatal_error( | 526 llvm::report_fatal_error( |
| 521 "Infinite-weight Variable has no register assigned"); | 527 "Infinite-weight Variable has no register assigned"); |
| 522 } | 528 } |
| 529 assert(!Var->isRematerializable()); |
| 523 int32_t Offset = Var->getStackOffset(); | 530 int32_t Offset = Var->getStackOffset(); |
| 524 int32_t BaseRegNum = Var->getBaseRegNum(); | 531 int32_t BaseRegNum = Var->getBaseRegNum(); |
| 525 if (BaseRegNum == Variable::NoRegister) { | 532 if (BaseRegNum == Variable::NoRegister) { |
| 526 BaseRegNum = getFrameOrStackReg(); | 533 BaseRegNum = getFrameOrStackReg(); |
| 527 } | 534 } |
| 528 const Type VarTy = Var->getType(); | 535 const Type VarTy = Var->getType(); |
| 529 Str << "[" << getRegName(BaseRegNum, VarTy); | 536 Str << "[" << getRegName(BaseRegNum, VarTy); |
| 530 if (Offset != 0) { | 537 if (Offset != 0) { |
| 531 Str << ", " << getConstantPrefix() << Offset; | 538 Str << ", " << getConstantPrefix() << Offset; |
| 532 } | 539 } |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 // Adds the out args space to the stack, and align SP if necessary. | 850 // Adds the out args space to the stack, and align SP if necessary. |
| 844 if (!NeedsStackAlignment) { | 851 if (!NeedsStackAlignment) { |
| 845 SpillAreaSizeBytes += MaxOutArgsSizeBytes; | 852 SpillAreaSizeBytes += MaxOutArgsSizeBytes; |
| 846 } else { | 853 } else { |
| 847 uint32_t StackOffset = PreservedRegsSizeBytes; | 854 uint32_t StackOffset = PreservedRegsSizeBytes; |
| 848 uint32_t StackSize = applyStackAlignment(StackOffset + SpillAreaSizeBytes); | 855 uint32_t StackSize = applyStackAlignment(StackOffset + SpillAreaSizeBytes); |
| 849 StackSize = applyStackAlignment(StackSize + MaxOutArgsSizeBytes); | 856 StackSize = applyStackAlignment(StackSize + MaxOutArgsSizeBytes); |
| 850 SpillAreaSizeBytes = StackSize - StackOffset; | 857 SpillAreaSizeBytes = StackSize - StackOffset; |
| 851 } | 858 } |
| 852 | 859 |
| 860 // Combine fixed alloca with SpillAreaSize. |
| 861 SpillAreaSizeBytes += FixedAllocaSizeBytes; |
| 862 |
| 853 // Generate "sub sp, SpillAreaSizeBytes" | 863 // Generate "sub sp, SpillAreaSizeBytes" |
| 854 if (SpillAreaSizeBytes) { | 864 if (SpillAreaSizeBytes) { |
| 855 // Use the scratch register if needed to legalize the immediate. | 865 // Use the scratch register if needed to legalize the immediate. |
| 856 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 866 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
| 857 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 867 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 858 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 868 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 859 _sub(SP, SP, SubAmount); | 869 _sub(SP, SP, SubAmount); |
| 870 if (FixedAllocaAlignBytes > ARM32_STACK_ALIGNMENT_BYTES) { |
| 871 alignRegisterPow2(SP, FixedAllocaAlignBytes); |
| 872 } |
| 860 } | 873 } |
| 874 |
| 861 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | 875 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); |
| 862 | 876 |
| 863 // Fill in stack offsets for stack args, and copy args into registers for | 877 // Fill in stack offsets for stack args, and copy args into registers for |
| 864 // those that were register-allocated. Args are pushed right to left, so | 878 // those that were register-allocated. Args are pushed right to left, so |
| 865 // Arg[0] is closest to the stack/frame pointer. | 879 // Arg[0] is closest to the stack/frame pointer. |
| 866 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 880 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 867 size_t BasicFrameOffset = PreservedRegsSizeBytes; | 881 size_t BasicFrameOffset = PreservedRegsSizeBytes; |
| 868 if (!UsesFramePointer) | 882 if (!UsesFramePointer) |
| 869 BasicFrameOffset += SpillAreaSizeBytes; | 883 BasicFrameOffset += SpillAreaSizeBytes; |
| 870 | 884 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 _sub(ScratchReg, OrigBaseReg, OffsetVal); | 1041 _sub(ScratchReg, OrigBaseReg, OffsetVal); |
| 1028 else | 1042 else |
| 1029 _add(ScratchReg, OrigBaseReg, OffsetVal); | 1043 _add(ScratchReg, OrigBaseReg, OffsetVal); |
| 1030 return ScratchReg; | 1044 return ScratchReg; |
| 1031 } | 1045 } |
| 1032 | 1046 |
| 1033 OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset, | 1047 OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset, |
| 1034 Variable *OrigBaseReg, | 1048 Variable *OrigBaseReg, |
| 1035 Variable **NewBaseReg, | 1049 Variable **NewBaseReg, |
| 1036 int32_t *NewBaseOffset) { | 1050 int32_t *NewBaseOffset) { |
| 1051 assert(!OrigBaseReg->isRematerializable()); |
| 1037 if (isLegalMemOffset(Ty, Offset)) { | 1052 if (isLegalMemOffset(Ty, Offset)) { |
| 1038 return OperandARM32Mem::create( | 1053 return OperandARM32Mem::create( |
| 1039 Func, Ty, OrigBaseReg, | 1054 Func, Ty, OrigBaseReg, |
| 1040 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(Offset)), | 1055 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(Offset)), |
| 1041 OperandARM32Mem::Offset); | 1056 OperandARM32Mem::Offset); |
| 1042 } | 1057 } |
| 1043 | 1058 |
| 1044 if (*NewBaseReg == nullptr) { | 1059 if (*NewBaseReg == nullptr) { |
| 1045 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); | 1060 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); |
| 1046 *NewBaseOffset = Offset; | 1061 *NewBaseOffset = Offset; |
| 1047 } | 1062 } |
| 1048 | 1063 |
| 1049 int32_t OffsetDiff = Offset - *NewBaseOffset; | 1064 int32_t OffsetDiff = Offset - *NewBaseOffset; |
| 1050 if (!isLegalMemOffset(Ty, OffsetDiff)) { | 1065 if (!isLegalMemOffset(Ty, OffsetDiff)) { |
| 1051 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); | 1066 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); |
| 1052 *NewBaseOffset = Offset; | 1067 *NewBaseOffset = Offset; |
| 1053 OffsetDiff = 0; | 1068 OffsetDiff = 0; |
| 1054 } | 1069 } |
| 1055 | 1070 |
| 1071 assert(!(*NewBaseReg)->isRematerializable()); |
| 1056 return OperandARM32Mem::create( | 1072 return OperandARM32Mem::create( |
| 1057 Func, Ty, *NewBaseReg, | 1073 Func, Ty, *NewBaseReg, |
| 1058 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)), | 1074 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)), |
| 1059 OperandARM32Mem::Offset); | 1075 OperandARM32Mem::Offset); |
| 1060 } | 1076 } |
| 1061 | 1077 |
| 1062 void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, Variable *OrigBaseReg, | 1078 void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, Variable *OrigBaseReg, |
| 1063 Variable **NewBaseReg, int32_t *NewBaseOffset) { | 1079 Variable **NewBaseReg, int32_t *NewBaseOffset) { |
| 1064 Variable *Dest = MovInstr->getDest(); | 1080 Variable *Dest = MovInstr->getDest(); |
| 1065 assert(Dest != nullptr); | 1081 assert(Dest != nullptr); |
| 1066 Type DestTy = Dest->getType(); | 1082 Type DestTy = Dest->getType(); |
| 1067 assert(DestTy != IceType_i64); | 1083 assert(DestTy != IceType_i64); |
| 1068 | 1084 |
| 1069 Operand *Src = MovInstr->getSrc(0); | 1085 Operand *Src = MovInstr->getSrc(0); |
| 1070 Type SrcTy = Src->getType(); | 1086 Type SrcTy = Src->getType(); |
| 1071 (void)SrcTy; | 1087 (void)SrcTy; |
| 1072 assert(SrcTy != IceType_i64); | 1088 assert(SrcTy != IceType_i64); |
| 1073 | 1089 |
| 1074 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1090 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
| 1075 return; | 1091 return; |
| 1076 | 1092 |
| 1077 bool Legalized = false; | 1093 bool Legalized = false; |
| 1078 if (!Dest->hasReg()) { | 1094 if (!Dest->hasReg()) { |
| 1079 auto *const SrcR = llvm::cast<Variable>(Src); | 1095 auto *SrcR = llvm::cast<Variable>(Src); |
| 1080 assert(SrcR->hasReg()); | 1096 assert(SrcR->hasReg()); |
| 1097 assert(!SrcR->isRematerializable()); |
| 1081 const int32_t Offset = Dest->getStackOffset(); | 1098 const int32_t Offset = Dest->getStackOffset(); |
| 1082 // This is a _mov(Mem(), Variable), i.e., a store. | 1099 // This is a _mov(Mem(), Variable), i.e., a store. |
| 1083 _str(SrcR, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, | 1100 _str(SrcR, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, |
| 1084 NewBaseOffset), | 1101 NewBaseOffset), |
| 1085 MovInstr->getPredicate()); | 1102 MovInstr->getPredicate()); |
| 1086 // _str() does not have a Dest, so we add a fake-def(Dest). | 1103 // _str() does not have a Dest, so we add a fake-def(Dest). |
| 1087 Context.insert(InstFakeDef::create(Func, Dest)); | 1104 Context.insert(InstFakeDef::create(Func, Dest)); |
| 1088 Legalized = true; | 1105 Legalized = true; |
| 1089 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1106 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1090 if (!Var->hasReg()) { | 1107 if (Var->isRematerializable()) { |
| 1091 const int32_t Offset = Var->getStackOffset(); | 1108 // Rematerialization arithmetic. |
| 1092 _ldr(Dest, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, | 1109 const int32_t ExtraOffset = |
| 1093 NewBaseOffset), | 1110 (static_cast<SizeT>(Var->getRegNum()) == getFrameReg()) |
| 1094 MovInstr->getPredicate()); | 1111 ? getFrameFixedAllocaOffset() |
| 1112 : 0; |
| 1113 |
| 1114 const int32_t Offset = Var->getStackOffset() + ExtraOffset; |
| 1115 Operand *OffsetRF = legalize(Ctx->getConstantInt32(Offset), |
| 1116 Legal_Reg | Legal_Flex, Dest->getRegNum()); |
| 1117 _add(Dest, Var, OffsetRF); |
| 1095 Legalized = true; | 1118 Legalized = true; |
| 1119 } else { |
| 1120 if (!Var->hasReg()) { |
| 1121 const int32_t Offset = Var->getStackOffset(); |
| 1122 _ldr(Dest, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, |
| 1123 NewBaseOffset), |
| 1124 MovInstr->getPredicate()); |
| 1125 Legalized = true; |
| 1126 } |
| 1096 } | 1127 } |
| 1097 } | 1128 } |
| 1098 | 1129 |
| 1099 if (Legalized) { | 1130 if (Legalized) { |
| 1100 if (MovInstr->isDestRedefined()) { | 1131 if (MovInstr->isDestRedefined()) { |
| 1101 _set_dest_redefined(); | 1132 _set_dest_redefined(); |
| 1102 } | 1133 } |
| 1103 MovInstr->setDeleted(); | 1134 MovInstr->setDeleted(); |
| 1104 } | 1135 } |
| 1105 } | 1136 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 return Operand; | 1187 return Operand; |
| 1157 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | 1188 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
| 1158 return Var64On32->getLo(); | 1189 return Var64On32->getLo(); |
| 1159 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) | 1190 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) |
| 1160 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | 1191 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
| 1161 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | 1192 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
| 1162 // Conservatively disallow memory operands with side-effects (pre/post | 1193 // Conservatively disallow memory operands with side-effects (pre/post |
| 1163 // increment) in case of duplication. | 1194 // increment) in case of duplication. |
| 1164 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | 1195 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
| 1165 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | 1196 Mem->getAddrMode() == OperandARM32Mem::NegOffset); |
| 1197 Variable *BaseR = legalizeToReg(Mem->getBase()); |
| 1166 if (Mem->isRegReg()) { | 1198 if (Mem->isRegReg()) { |
| 1167 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | 1199 Variable *IndexR = legalizeToReg(Mem->getIndex()); |
| 1168 Mem->getIndex(), Mem->getShiftOp(), | 1200 return OperandARM32Mem::create(Func, IceType_i32, BaseR, IndexR, |
| 1169 Mem->getShiftAmt(), Mem->getAddrMode()); | 1201 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 1202 Mem->getAddrMode()); |
| 1170 } else { | 1203 } else { |
| 1171 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | 1204 return OperandARM32Mem::create(Func, IceType_i32, BaseR, Mem->getOffset(), |
| 1172 Mem->getOffset(), Mem->getAddrMode()); | 1205 Mem->getAddrMode()); |
| 1173 } | 1206 } |
| 1174 } | 1207 } |
| 1175 llvm_unreachable("Unsupported operand type"); | 1208 llvm_unreachable("Unsupported operand type"); |
| 1176 return nullptr; | 1209 return nullptr; |
| 1177 } | 1210 } |
| 1178 | 1211 |
| 1179 Operand *TargetARM32::hiOperand(Operand *Operand) { | 1212 Operand *TargetARM32::hiOperand(Operand *Operand) { |
| 1180 assert(Operand->getType() == IceType_i64); | 1213 assert(Operand->getType() == IceType_i64); |
| 1181 if (Operand->getType() != IceType_i64) | 1214 if (Operand->getType() != IceType_i64) |
| 1182 return Operand; | 1215 return Operand; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1194 const Type SplitType = IceType_i32; | 1227 const Type SplitType = IceType_i32; |
| 1195 if (Mem->isRegReg()) { | 1228 if (Mem->isRegReg()) { |
| 1196 // We have to make a temp variable T, and add 4 to either Base or Index. | 1229 // We have to make a temp variable T, and add 4 to either Base or Index. |
| 1197 // The Index may be shifted, so adding 4 can mean something else. Thus, | 1230 // The Index may be shifted, so adding 4 can mean something else. Thus, |
| 1198 // prefer T := Base + 4, and use T as the new Base. | 1231 // prefer T := Base + 4, and use T as the new Base. |
| 1199 Variable *Base = Mem->getBase(); | 1232 Variable *Base = Mem->getBase(); |
| 1200 Constant *Four = Ctx->getConstantInt32(4); | 1233 Constant *Four = Ctx->getConstantInt32(4); |
| 1201 Variable *NewBase = Func->makeVariable(Base->getType()); | 1234 Variable *NewBase = Func->makeVariable(Base->getType()); |
| 1202 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, | 1235 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, |
| 1203 Base, Four)); | 1236 Base, Four)); |
| 1204 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(), | 1237 Variable *BaseR = legalizeToReg(NewBase); |
| 1238 Variable *IndexR = legalizeToReg(Mem->getIndex()); |
| 1239 return OperandARM32Mem::create(Func, SplitType, BaseR, IndexR, |
| 1205 Mem->getShiftOp(), Mem->getShiftAmt(), | 1240 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 1206 Mem->getAddrMode()); | 1241 Mem->getAddrMode()); |
| 1207 } else { | 1242 } else { |
| 1208 Variable *Base = Mem->getBase(); | 1243 Variable *Base = Mem->getBase(); |
| 1209 ConstantInteger32 *Offset = Mem->getOffset(); | 1244 ConstantInteger32 *Offset = Mem->getOffset(); |
| 1210 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); | 1245 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); |
| 1211 int32_t NextOffsetVal = Offset->getValue() + 4; | 1246 int32_t NextOffsetVal = Offset->getValue() + 4; |
| 1212 constexpr bool ZeroExt = false; | 1247 constexpr bool ZeroExt = false; |
| 1213 if (!OperandARM32Mem::canHoldOffset(SplitType, ZeroExt, NextOffsetVal)) { | 1248 if (!OperandARM32Mem::canHoldOffset(SplitType, ZeroExt, NextOffsetVal)) { |
| 1214 // We have to make a temp variable and add 4 to either Base or Offset. | 1249 // We have to make a temp variable and add 4 to either Base or Offset. |
| 1215 // If we add 4 to Offset, this will convert a non-RegReg addressing | 1250 // If we add 4 to Offset, this will convert a non-RegReg addressing |
| 1216 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows | 1251 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows |
| 1217 // RegReg addressing modes, prefer adding to base and replacing | 1252 // RegReg addressing modes, prefer adding to base and replacing |
| 1218 // instead. Thus we leave the old offset alone. | 1253 // instead. Thus we leave the old offset alone. |
| 1219 Constant *Four = Ctx->getConstantInt32(4); | 1254 Constant *_4 = Ctx->getConstantInt32(4); |
| 1220 Variable *NewBase = Func->makeVariable(Base->getType()); | 1255 Variable *NewBase = Func->makeVariable(Base->getType()); |
| 1221 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, | 1256 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, |
| 1222 NewBase, Base, Four)); | 1257 NewBase, Base, _4)); |
| 1223 Base = NewBase; | 1258 Base = NewBase; |
| 1224 } else { | 1259 } else { |
| 1225 Offset = | 1260 Offset = |
| 1226 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); | 1261 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); |
| 1227 } | 1262 } |
| 1228 return OperandARM32Mem::create(Func, SplitType, Base, Offset, | 1263 Variable *BaseR = legalizeToReg(Base); |
| 1264 return OperandARM32Mem::create(Func, SplitType, BaseR, Offset, |
| 1229 Mem->getAddrMode()); | 1265 Mem->getAddrMode()); |
| 1230 } | 1266 } |
| 1231 } | 1267 } |
| 1232 llvm_unreachable("Unsupported operand type"); | 1268 llvm_unreachable("Unsupported operand type"); |
| 1233 return nullptr; | 1269 return nullptr; |
| 1234 } | 1270 } |
| 1235 | 1271 |
| 1236 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 1272 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
| 1237 RegSetMask Exclude) const { | 1273 RegSetMask Exclude) const { |
| 1238 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 1274 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1257 Registers[RegARM32::val] = false; | 1293 Registers[RegARM32::val] = false; |
| 1258 | 1294 |
| 1259 REGARM32_TABLE | 1295 REGARM32_TABLE |
| 1260 | 1296 |
| 1261 #undef X | 1297 #undef X |
| 1262 | 1298 |
| 1263 return Registers; | 1299 return Registers; |
| 1264 } | 1300 } |
| 1265 | 1301 |
| 1266 void TargetARM32::lowerAlloca(const InstAlloca *Inst) { | 1302 void TargetARM32::lowerAlloca(const InstAlloca *Inst) { |
| 1267 UsesFramePointer = true; | |
| 1268 // Conservatively require the stack to be aligned. Some stack adjustment | 1303 // Conservatively require the stack to be aligned. Some stack adjustment |
| 1269 // operations implemented below assume that the stack is aligned before the | 1304 // operations implemented below assume that the stack is aligned before the |
| 1270 // alloca. All the alloca code ensures that the stack alignment is preserved | 1305 // alloca. All the alloca code ensures that the stack alignment is preserved |
| 1271 // after the alloca. The stack alignment restriction can be relaxed in some | 1306 // after the alloca. The stack alignment restriction can be relaxed in some |
| 1272 // cases. | 1307 // cases. |
| 1273 NeedsStackAlignment = true; | 1308 NeedsStackAlignment = true; |
| 1274 | 1309 |
| 1275 // TODO(stichnot): minimize the number of adjustments of SP, etc. | |
| 1276 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | |
| 1277 Variable *Dest = Inst->getDest(); | |
| 1278 uint32_t AlignmentParam = Inst->getAlignInBytes(); | |
| 1279 // For default align=0, set it to the real value 1, to avoid any | 1310 // For default align=0, set it to the real value 1, to avoid any |
| 1280 // bit-manipulation problems below. | 1311 // bit-manipulation problems below. |
| 1281 AlignmentParam = std::max(AlignmentParam, 1u); | 1312 const uint32_t AlignmentParam = std::max(1u, Inst->getAlignInBytes()); |
| 1282 | 1313 |
| 1283 // LLVM enforces power of 2 alignment. | 1314 // LLVM enforces power of 2 alignment. |
| 1284 assert(llvm::isPowerOf2_32(AlignmentParam)); | 1315 assert(llvm::isPowerOf2_32(AlignmentParam)); |
| 1285 assert(llvm::isPowerOf2_32(ARM32_STACK_ALIGNMENT_BYTES)); | 1316 assert(llvm::isPowerOf2_32(ARM32_STACK_ALIGNMENT_BYTES)); |
| 1286 | 1317 |
| 1287 uint32_t Alignment = std::max(AlignmentParam, ARM32_STACK_ALIGNMENT_BYTES); | 1318 const uint32_t Alignment = |
| 1288 if (Alignment > ARM32_STACK_ALIGNMENT_BYTES) { | 1319 std::max(AlignmentParam, ARM32_STACK_ALIGNMENT_BYTES); |
| 1320 const bool OverAligned = Alignment > ARM32_STACK_ALIGNMENT_BYTES; |
| 1321 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; |
| 1322 const bool AllocaWithKnownOffset = Inst->getKnownFrameOffset(); |
| 1323 const bool UseFramePointer = |
| 1324 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; |
| 1325 |
| 1326 if (UseFramePointer) |
| 1327 setHasFramePointer(); |
| 1328 |
| 1329 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1330 if (OverAligned) { |
| 1289 alignRegisterPow2(SP, Alignment); | 1331 alignRegisterPow2(SP, Alignment); |
| 1290 } | 1332 } |
| 1333 |
| 1334 Variable *Dest = Inst->getDest(); |
| 1291 Operand *TotalSize = Inst->getSizeInBytes(); | 1335 Operand *TotalSize = Inst->getSizeInBytes(); |
| 1336 |
| 1292 if (const auto *ConstantTotalSize = | 1337 if (const auto *ConstantTotalSize = |
| 1293 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { | 1338 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
| 1294 uint32_t Value = ConstantTotalSize->getValue(); | 1339 const uint32_t Value = |
| 1295 Value = Utils::applyAlignment(Value, Alignment); | 1340 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); |
| 1296 Operand *SubAmount = legalize(Ctx->getConstantInt32(Value)); | 1341 // Constant size alloca. |
| 1297 _sub(SP, SP, SubAmount); | 1342 if (!UseFramePointer) { |
| 1343 // If we don't need a Frame Pointer, this alloca has a known offset to the |
| 1344 // stack pointer. We don't need adjust the stack pointer, nor assign any |
| 1345 // value to Dest, as Dest is rematerializable. |
| 1346 assert(Dest->isRematerializable()); |
| 1347 FixedAllocaSizeBytes += Value; |
| 1348 Context.insert(InstFakeDef::create(Func, Dest)); |
| 1349 return; |
| 1350 } |
| 1351 |
| 1352 // If a frame pointer is required, then we need to store the alloca'd result |
| 1353 // in Dest. |
| 1354 Operand *SubAmountRF = |
| 1355 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); |
| 1356 _sub(SP, SP, SubAmountRF); |
| 1298 } else { | 1357 } else { |
| 1299 // Non-constant sizes need to be adjusted to the next highest multiple of | 1358 // Non-constant sizes need to be adjusted to the next highest multiple of |
| 1300 // the required alignment at runtime. | 1359 // the required alignment at runtime. |
| 1301 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); | 1360 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); |
| 1302 Variable *T = makeReg(IceType_i32); | 1361 Variable *T = makeReg(IceType_i32); |
| 1303 _mov(T, TotalSize); | 1362 _mov(T, TotalSize); |
| 1304 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); | 1363 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); |
| 1305 _add(T, T, AddAmount); | 1364 _add(T, T, AddAmount); |
| 1306 alignRegisterPow2(T, Alignment); | 1365 alignRegisterPow2(T, Alignment); |
| 1307 _sub(SP, SP, T); | 1366 _sub(SP, SP, T); |
| 1308 } | 1367 } |
| 1368 |
| 1369 // Adds back a few bytes to SP to account for the out args area. |
| 1309 Variable *T = SP; | 1370 Variable *T = SP; |
| 1310 if (MaxOutArgsSizeBytes != 0) { | 1371 if (MaxOutArgsSizeBytes != 0) { |
| 1311 T = makeReg(getPointerType()); | 1372 T = makeReg(getPointerType()); |
| 1312 Operand *OutArgsSizeRF = legalize( | 1373 Operand *OutArgsSizeRF = legalize( |
| 1313 Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex); | 1374 Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex); |
| 1314 _add(T, SP, OutArgsSizeRF); | 1375 _add(T, SP, OutArgsSizeRF); |
| 1315 } | 1376 } |
| 1377 |
| 1316 _mov(Dest, T); | 1378 _mov(Dest, T); |
| 1317 } | 1379 } |
| 1318 | 1380 |
| 1319 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { | 1381 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { |
| 1320 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) | 1382 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) |
| 1321 return; | 1383 return; |
| 1322 Variable *SrcLoReg = legalizeToReg(SrcLo); | 1384 Variable *SrcLoReg = legalizeToReg(SrcLo); |
| 1323 switch (Ty) { | 1385 switch (Ty) { |
| 1324 default: | 1386 default: |
| 1325 llvm::report_fatal_error("Unexpected type"); | 1387 llvm::report_fatal_error("Unexpected type"); |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1969 case InstArithmetic::Urem: | 2031 case InstArithmetic::Urem: |
| 1970 case InstArithmetic::Srem: | 2032 case InstArithmetic::Srem: |
| 1971 llvm::report_fatal_error("Call-helper-involved instruction for i64 type " | 2033 llvm::report_fatal_error("Call-helper-involved instruction for i64 type " |
| 1972 "should have already been handled before"); | 2034 "should have already been handled before"); |
| 1973 return; | 2035 return; |
| 1974 } | 2036 } |
| 1975 } | 2037 } |
| 1976 | 2038 |
| 1977 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { | 2039 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
| 1978 Variable *Dest = Inst->getDest(); | 2040 Variable *Dest = Inst->getDest(); |
| 2041 |
| 2042 if (Dest->isRematerializable()) { |
| 2043 Context.insert(InstFakeDef::create(Func, Dest)); |
| 2044 return; |
| 2045 } |
| 2046 |
| 1979 if (Dest->getType() == IceType_i1) { | 2047 if (Dest->getType() == IceType_i1) { |
| 1980 lowerInt1Arithmetic(Inst); | 2048 lowerInt1Arithmetic(Inst); |
| 1981 return; | 2049 return; |
| 1982 } | 2050 } |
| 1983 | 2051 |
| 1984 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 2052 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 1985 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | 2053 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| 1986 if (Dest->getType() == IceType_i64) { | 2054 if (Dest->getType() == IceType_i64) { |
| 1987 lowerInt64Arithmetic(Inst->getOp(), Inst->getDest(), Src0, Src1); | 2055 lowerInt64Arithmetic(Inst->getOp(), Inst->getDest(), Src0, Src1); |
| 1988 return; | 2056 return; |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2132 Variable *Src0R = Srcs.src0R(this); | 2200 Variable *Src0R = Srcs.src0R(this); |
| 2133 Operand *Src1RF = Srcs.src1RF(this); | 2201 Operand *Src1RF = Srcs.src1RF(this); |
| 2134 _eor(T, Src0R, Src1RF); | 2202 _eor(T, Src0R, Src1RF); |
| 2135 _mov(Dest, T); | 2203 _mov(Dest, T); |
| 2136 return; | 2204 return; |
| 2137 } | 2205 } |
| 2138 case InstArithmetic::Sub: { | 2206 case InstArithmetic::Sub: { |
| 2139 if (Srcs.hasConstOperand()) { | 2207 if (Srcs.hasConstOperand()) { |
| 2140 // TODO(jpp): lowering Src0R here is wrong -- Src0R it is not guaranteed | 2208 // TODO(jpp): lowering Src0R here is wrong -- Src0R it is not guaranteed |
| 2141 // to be used. | 2209 // to be used. |
| 2142 Variable *Src0R = Srcs.src0R(this); | |
| 2143 if (Srcs.immediateIsFlexEncodable()) { | 2210 if (Srcs.immediateIsFlexEncodable()) { |
| 2211 Variable *Src0R = Srcs.src0R(this); |
| 2144 Operand *Src1RF = Srcs.src1RF(this); | 2212 Operand *Src1RF = Srcs.src1RF(this); |
| 2145 if (Srcs.swappedOperands()) { | 2213 if (Srcs.swappedOperands()) { |
| 2146 _rsb(T, Src0R, Src1RF); | 2214 _rsb(T, Src0R, Src1RF); |
| 2147 } else { | 2215 } else { |
| 2148 _sub(T, Src0R, Src1RF); | 2216 _sub(T, Src0R, Src1RF); |
| 2149 } | 2217 } |
| 2150 _mov(Dest, T); | 2218 _mov(Dest, T); |
| 2151 return; | 2219 return; |
| 2152 } | 2220 } |
| 2153 if (!Srcs.swappedOperands() && Srcs.negatedImmediateIsFlexEncodable()) { | 2221 if (!Srcs.swappedOperands() && Srcs.negatedImmediateIsFlexEncodable()) { |
| 2222 Variable *Src0R = Srcs.src0R(this); |
| 2154 Operand *Src1F = Srcs.negatedSrc1F(this); | 2223 Operand *Src1F = Srcs.negatedSrc1F(this); |
| 2155 _add(T, Src0R, Src1F); | 2224 _add(T, Src0R, Src1F); |
| 2156 _mov(Dest, T); | 2225 _mov(Dest, T); |
| 2157 return; | 2226 return; |
| 2158 } | 2227 } |
| 2159 } | 2228 } |
| 2160 Variable *Src0R = Srcs.unswappedSrc0R(this); | 2229 Variable *Src0R = Srcs.unswappedSrc0R(this); |
| 2161 Variable *Src1R = Srcs.unswappedSrc1R(this); | 2230 Variable *Src1R = Srcs.unswappedSrc1R(this); |
| 2162 _sub(T, Src0R, Src1R); | 2231 _sub(T, Src0R, Src1R); |
| 2163 _mov(Dest, T); | 2232 _mov(Dest, T); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2208 case InstArithmetic::Fdiv: | 2277 case InstArithmetic::Fdiv: |
| 2209 case InstArithmetic::Frem: | 2278 case InstArithmetic::Frem: |
| 2210 llvm::report_fatal_error( | 2279 llvm::report_fatal_error( |
| 2211 "Floating point arith should have been handled earlier."); | 2280 "Floating point arith should have been handled earlier."); |
| 2212 return; | 2281 return; |
| 2213 } | 2282 } |
| 2214 } | 2283 } |
| 2215 | 2284 |
| 2216 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 2285 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
| 2217 Variable *Dest = Inst->getDest(); | 2286 Variable *Dest = Inst->getDest(); |
| 2287 |
| 2288 if (Dest->isRematerializable()) { |
| 2289 Context.insert(InstFakeDef::create(Func, Dest)); |
| 2290 return; |
| 2291 } |
| 2292 |
| 2218 Operand *Src0 = Inst->getSrc(0); | 2293 Operand *Src0 = Inst->getSrc(0); |
| 2219 assert(Dest->getType() == Src0->getType()); | 2294 assert(Dest->getType() == Src0->getType()); |
| 2220 if (Dest->getType() == IceType_i64) { | 2295 if (Dest->getType() == IceType_i64) { |
| 2221 Src0 = legalizeUndef(Src0); | 2296 Src0 = legalizeUndef(Src0); |
| 2222 | 2297 |
| 2223 Variable *T_Lo = makeReg(IceType_i32); | 2298 Variable *T_Lo = makeReg(IceType_i32); |
| 2224 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2299 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2225 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); | 2300 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); |
| 2226 _mov(T_Lo, Src0Lo); | 2301 _mov(T_Lo, Src0Lo); |
| 2227 _mov(DestLo, T_Lo); | 2302 _mov(DestLo, T_Lo); |
| (...skipping 2190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4418 OffsetImm = 0; | 4493 OffsetImm = 0; |
| 4419 } | 4494 } |
| 4420 } | 4495 } |
| 4421 | 4496 |
| 4422 assert(BaseVar != nullptr); | 4497 assert(BaseVar != nullptr); |
| 4423 assert(OffsetImm == 0 || OffsetReg == nullptr); | 4498 assert(OffsetImm == 0 || OffsetReg == nullptr); |
| 4424 assert(OffsetReg == nullptr || CanHaveIndex); | 4499 assert(OffsetReg == nullptr || CanHaveIndex); |
| 4425 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm | 4500 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm |
| 4426 : (ValidImmMask & OffsetImm) == OffsetImm); | 4501 : (ValidImmMask & OffsetImm) == OffsetImm); |
| 4427 | 4502 |
| 4503 Variable *BaseR = makeReg(getPointerType()); |
| 4504 Context.insert(InstAssign::create(Func, BaseR, BaseVar)); |
| 4428 if (OffsetReg != nullptr) { | 4505 if (OffsetReg != nullptr) { |
| 4429 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetReg, ShiftKind, | 4506 Variable *OffsetR = makeReg(getPointerType()); |
| 4507 Context.insert(InstAssign::create(Func, OffsetR, OffsetReg)); |
| 4508 return OperandARM32Mem::create(Func, Ty, BaseR, OffsetR, ShiftKind, |
| 4430 OffsetRegShamt); | 4509 OffsetRegShamt); |
| 4431 } | 4510 } |
| 4432 | 4511 |
| 4433 return OperandARM32Mem::create( | 4512 return OperandARM32Mem::create( |
| 4434 Func, Ty, BaseVar, | 4513 Func, Ty, BaseR, |
| 4435 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); | 4514 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); |
| 4436 } | 4515 } |
| 4437 | 4516 |
| 4438 void TargetARM32::doAddressOptLoad() { | 4517 void TargetARM32::doAddressOptLoad() { |
| 4439 Inst *Instr = Context.getCur(); | 4518 Inst *Instr = Context.getCur(); |
| 4440 assert(llvm::isa<InstLoad>(Instr)); | 4519 assert(llvm::isa<InstLoad>(Instr)); |
| 4441 Variable *Dest = Instr->getDest(); | 4520 Variable *Dest = Instr->getDest(); |
| 4442 Operand *Addr = Instr->getSrc(0); | 4521 Operand *Addr = Instr->getSrc(0); |
| 4443 if (OperandARM32Mem *Mem = | 4522 if (OperandARM32Mem *Mem = |
| 4444 formAddressingMode(Dest->getType(), Func, Instr, Addr)) { | 4523 formAddressingMode(Dest->getType(), Func, Instr, Addr)) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4623 Type Ty = From->getType(); | 4702 Type Ty = From->getType(); |
| 4624 // Assert that a physical register is allowed. To date, all calls to | 4703 // Assert that a physical register is allowed. To date, all calls to |
| 4625 // legalize() allow a physical register. Legal_Flex converts registers to the | 4704 // legalize() allow a physical register. Legal_Flex converts registers to the |
| 4626 // right type OperandARM32FlexReg as needed. | 4705 // right type OperandARM32FlexReg as needed. |
| 4627 assert(Allowed & Legal_Reg); | 4706 assert(Allowed & Legal_Reg); |
| 4628 | 4707 |
| 4629 // Copied ipsis literis from TargetX86Base<Machine>. | 4708 // Copied ipsis literis from TargetX86Base<Machine>. |
| 4630 if (RegNum == Variable::NoRegister) { | 4709 if (RegNum == Variable::NoRegister) { |
| 4631 if (Variable *Subst = getContext().availabilityGet(From)) { | 4710 if (Variable *Subst = getContext().availabilityGet(From)) { |
| 4632 // At this point we know there is a potential substitution available. | 4711 // At this point we know there is a potential substitution available. |
| 4633 if (Subst->mustHaveReg() && !Subst->hasReg()) { | 4712 if (!Subst->isRematerializable() && Subst->mustHaveReg() && |
| 4713 !Subst->hasReg()) { |
| 4634 // At this point we know the substitution will have a register. | 4714 // At this point we know the substitution will have a register. |
| 4635 if (From->getType() == Subst->getType()) { | 4715 if (From->getType() == Subst->getType()) { |
| 4636 // At this point we know the substitution's register is compatible. | 4716 // At this point we know the substitution's register is compatible. |
| 4637 return Subst; | 4717 return Subst; |
| 4638 } | 4718 } |
| 4639 } | 4719 } |
| 4640 } | 4720 } |
| 4641 } | 4721 } |
| 4642 | 4722 |
| 4643 // Go through the various types of operands: OperandARM32Mem, | 4723 // Go through the various types of operands: OperandARM32Mem, |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4781 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | 4861 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
| 4782 Variable *BaseReg = makeReg(getPointerType()); | 4862 Variable *BaseReg = makeReg(getPointerType()); |
| 4783 _movw(BaseReg, Offset); | 4863 _movw(BaseReg, Offset); |
| 4784 _movt(BaseReg, Offset); | 4864 _movt(BaseReg, Offset); |
| 4785 From = formMemoryOperand(BaseReg, Ty); | 4865 From = formMemoryOperand(BaseReg, Ty); |
| 4786 return copyToReg(From, RegNum); | 4866 return copyToReg(From, RegNum); |
| 4787 } | 4867 } |
| 4788 } | 4868 } |
| 4789 | 4869 |
| 4790 if (auto *Var = llvm::dyn_cast<Variable>(From)) { | 4870 if (auto *Var = llvm::dyn_cast<Variable>(From)) { |
| 4871 if (Var->isRematerializable()) { |
| 4872 // TODO(jpp): We don't need to rematerialize Var if legalize() was invoked |
| 4873 // for a Variable in a Mem operand. |
| 4874 Variable *T = makeReg(Var->getType(), RegNum); |
| 4875 _mov(T, Var); |
| 4876 return T; |
| 4877 } |
| 4791 // Check if the variable is guaranteed a physical register. This can happen | 4878 // Check if the variable is guaranteed a physical register. This can happen |
| 4792 // either when the variable is pre-colored or when it is assigned infinite | 4879 // either when the variable is pre-colored or when it is assigned infinite |
| 4793 // weight. | 4880 // weight. |
| 4794 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | 4881 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
| 4795 // We need a new physical register for the operand if: | 4882 // We need a new physical register for the operand if: |
| 4796 // Mem is not allowed and Var isn't guaranteed a physical | 4883 // Mem is not allowed and Var isn't guaranteed a physical |
| 4797 // register, or | 4884 // register, or |
| 4798 // RegNum is required and Var->getRegNum() doesn't match. | 4885 // RegNum is required and Var->getRegNum() doesn't match. |
| 4799 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 4886 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 4800 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | 4887 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4837 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); | 4924 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); |
| 4838 // It may be the case that address mode optimization already creates an | 4925 // It may be the case that address mode optimization already creates an |
| 4839 // OperandARM32Mem, so in that case it wouldn't need another level of | 4926 // OperandARM32Mem, so in that case it wouldn't need another level of |
| 4840 // transformation. | 4927 // transformation. |
| 4841 if (Mem) { | 4928 if (Mem) { |
| 4842 return llvm::cast<OperandARM32Mem>(legalize(Mem)); | 4929 return llvm::cast<OperandARM32Mem>(legalize(Mem)); |
| 4843 } | 4930 } |
| 4844 // If we didn't do address mode optimization, then we only have a | 4931 // If we didn't do address mode optimization, then we only have a |
| 4845 // base/offset to work with. ARM always requires a base register, so | 4932 // base/offset to work with. ARM always requires a base register, so |
| 4846 // just use that to hold the operand. | 4933 // just use that to hold the operand. |
| 4847 Variable *Base = legalizeToReg(Operand); | 4934 Variable *BaseR = legalizeToReg(Operand); |
| 4848 return OperandARM32Mem::create( | 4935 return OperandARM32Mem::create( |
| 4849 Func, Ty, Base, | 4936 Func, Ty, BaseR, |
| 4850 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); | 4937 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); |
| 4851 } | 4938 } |
| 4852 | 4939 |
| 4853 Variable64On32 *TargetARM32::makeI64RegPair() { | 4940 Variable64On32 *TargetARM32::makeI64RegPair() { |
| 4854 Variable64On32 *Reg = | 4941 Variable64On32 *Reg = |
| 4855 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 4942 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 4856 Reg->setMustHaveReg(); | 4943 Reg->setMustHaveReg(); |
| 4857 Reg->initHiLo(Func); | 4944 Reg->initHiLo(Func); |
| 4858 Reg->getLo()->setMustNotHaveReg(); | 4945 Reg->getLo()->setMustNotHaveReg(); |
| 4859 Reg->getHi()->setMustNotHaveReg(); | 4946 Reg->getHi()->setMustNotHaveReg(); |
| 4860 return Reg; | 4947 return Reg; |
| 4861 } | 4948 } |
| 4862 | 4949 |
| 4863 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { | 4950 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { |
| 4864 // There aren't any 64-bit integer registers for ARM32. | 4951 // There aren't any 64-bit integer registers for ARM32. |
| 4865 assert(Type != IceType_i64); | 4952 assert(Type != IceType_i64); |
| 4953 assert(AllowTemporaryWithNoReg || RegNum != Variable::NoRegister); |
| 4866 Variable *Reg = Func->makeVariable(Type); | 4954 Variable *Reg = Func->makeVariable(Type); |
| 4867 if (RegNum == Variable::NoRegister) | 4955 if (RegNum == Variable::NoRegister) |
| 4868 Reg->setMustHaveReg(); | 4956 Reg->setMustHaveReg(); |
| 4869 else | 4957 else |
| 4870 Reg->setRegNum(RegNum); | 4958 Reg->setRegNum(RegNum); |
| 4871 return Reg; | 4959 return Reg; |
| 4872 } | 4960 } |
| 4873 | 4961 |
| 4874 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align) { | 4962 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align, |
| 4963 int32_t TmpRegNum) { |
| 4875 assert(llvm::isPowerOf2_32(Align)); | 4964 assert(llvm::isPowerOf2_32(Align)); |
| 4876 uint32_t RotateAmt; | 4965 uint32_t RotateAmt; |
| 4877 uint32_t Immed_8; | 4966 uint32_t Immed_8; |
| 4878 Operand *Mask; | 4967 Operand *Mask; |
| 4879 // Use AND or BIC to mask off the bits, depending on which immediate fits (if | 4968 // Use AND or BIC to mask off the bits, depending on which immediate fits (if |
| 4880 // it fits at all). Assume Align is usually small, in which case BIC works | 4969 // it fits at all). Assume Align is usually small, in which case BIC works |
| 4881 // better. Thus, this rounds down to the alignment. | 4970 // better. Thus, this rounds down to the alignment. |
| 4882 if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) { | 4971 if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) { |
| 4883 Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex); | 4972 Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex, |
| 4973 TmpRegNum); |
| 4884 _bic(Reg, Reg, Mask); | 4974 _bic(Reg, Reg, Mask); |
| 4885 } else { | 4975 } else { |
| 4886 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex); | 4976 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex, |
| 4977 TmpRegNum); |
| 4887 _and(Reg, Reg, Mask); | 4978 _and(Reg, Reg, Mask); |
| 4888 } | 4979 } |
| 4889 } | 4980 } |
| 4890 | 4981 |
| 4891 void TargetARM32::postLower() { | 4982 void TargetARM32::postLower() { |
| 4892 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 4983 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
| 4893 return; | 4984 return; |
| 4894 markRedefinitions(); | 4985 markRedefinitions(); |
| 4895 Context.availabilityUpdate(); | 4986 Context.availabilityUpdate(); |
| 4896 } | 4987 } |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5412 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 5503 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 5413 // However, for compatibility with current NaCl LLVM, don't claim that. | 5504 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 5414 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 5505 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 5415 } | 5506 } |
| 5416 | 5507 |
| 5417 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 5508 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
| 5418 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 5509 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 5419 llvm::SmallBitVector TargetARM32::ScratchRegs; | 5510 llvm::SmallBitVector TargetARM32::ScratchRegs; |
| 5420 | 5511 |
| 5421 } // end of namespace Ice | 5512 } // end of namespace Ice |
| OLD | NEW |