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

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1474883002: Subzero. ARM32. Pre-lowers calls to ARM32 Helpers. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: reverts lsl lit test. Created 5 years 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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 } 258 }
259 } 259 }
260 260
261 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); 261 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty);
262 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); 262 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty);
263 } 263 }
264 264
265 return applyStackAlignment(OutArgsSizeBytes); 265 return applyStackAlignment(OutArgsSizeBytes);
266 } 266 }
267 267
268 void TargetARM32::genTargetHelperCallFor(Inst *Instr) {
269 constexpr bool NoTailCall = false;
270 constexpr bool IsTargetHelperCall = true;
271
272 switch (Instr->getKind()) {
273 default:
274 return;
275 case Inst::Arithmetic: {
276 Variable *Dest = Instr->getDest();
277 const Type DestTy = Dest->getType();
278 const InstArithmetic::OpKind Op =
279 llvm::cast<InstArithmetic>(Instr)->getOp();
280 switch (DestTy) {
281 default:
282 return;
283 case IceType_i64: {
284 // Technically, ARM has its own aeabi routines, but we can use the
285 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses
286 // the more standard __moddi3 for rem.
287 Operand *TargetHelper = nullptr;
288 switch (Op) {
289 default:
290 return;
291 case InstArithmetic::Udiv:
292 TargetHelper = Ctx->getConstantExternSym(H_udiv_i64);
293 break;
294 case InstArithmetic::Sdiv:
295 TargetHelper = Ctx->getConstantExternSym(H_sdiv_i64);
296 break;
297 case InstArithmetic::Urem:
298 TargetHelper = Ctx->getConstantExternSym(H_urem_i64);
299 break;
300 case InstArithmetic::Srem:
301 TargetHelper = Ctx->getConstantExternSym(H_srem_i64);
302 break;
303 }
304 assert(TargetHelper != nullptr);
305 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem;
306 constexpr SizeT MaxArgs = 2;
307 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
308 NoTailCall, IsTargetHelperCall);
309 Call->addArg(Instr->getSrc(0));
310 Call->addArg(Instr->getSrc(1));
311 Context.insert(Call);
312 Instr->setDeleted();
313 return;
314 }
315 case IceType_i32:
316 case IceType_i16:
317 case IceType_i8: {
318 const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm);
319 InstCast::OpKind CastKind;
320 Operand *TargetHelper;
321 switch (Op) {
322 default:
323 return;
324 case InstArithmetic::Udiv:
325 TargetHelper =
326 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_udiv_i32);
327 CastKind = InstCast::Zext;
328 break;
329 case InstArithmetic::Sdiv:
330 TargetHelper =
331 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_sdiv_i32);
332 CastKind = InstCast::Sext;
333 break;
334 case InstArithmetic::Urem:
335 TargetHelper =
336 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_urem_i32);
337 CastKind = InstCast::Zext;
338 break;
339 case InstArithmetic::Srem:
340 TargetHelper =
341 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_srem_i32);
342 CastKind = InstCast::Sext;
343 break;
344 }
345 if (TargetHelper == nullptr) {
346 // TargetHelper should only ever be nullptr when the processor does not
347 // have a hardware divider. If any other helpers are ever introduced,
348 // the following assert will have to be modified.
349 assert(HasHWDiv);
350 return;
351 }
352 Operand *Src0 = Instr->getSrc(0);
353 Operand *Src1 = Instr->getSrc(1);
354 if (DestTy != IceType_i32) {
355 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0,
356 // we just insert a InstCast right before the call to the helper.
357 Variable *Src0_32 = Func->makeVariable(IceType_i32);
358 Context.insert(InstCast::create(Func, CastKind, Src0_32, Src0));
359 Src0 = Src0_32;
360
361 // For extending Src1, we will just insert an InstCast if Src1 is not a
362 // Constant. If it is, then we extend it here, and not during program
363 // runtime. This allows preambleDivRem to optimize-out the div-by-0
364 // check.
365 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) {
366 const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24;
367 int32_t NewC = C->getValue();
368 if (CastKind == InstCast::Zext) {
369 NewC &= ~(0x80000000l >> ShAmt);
370 } else {
371 NewC = (NewC << ShAmt) >> ShAmt;
372 }
373 Src1 = Ctx->getConstantInt32(NewC);
374 } else {
375 Variable *Src1_32 = Func->makeVariable(IceType_i32);
376 Context.insert(InstCast::create(Func, CastKind, Src1_32, Src1));
377 Src1 = Src1_32;
378 }
379 }
380 assert(TargetHelper != nullptr);
381 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem;
382 constexpr SizeT MaxArgs = 2;
383 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
384 NoTailCall, IsTargetHelperCall);
385 assert(Src0->getType() == IceType_i32);
386 Call->addArg(Src0);
387 assert(Src1->getType() == IceType_i32);
388 Call->addArg(Src1);
389 Context.insert(Call);
390 Instr->setDeleted();
391 return;
392 }
393 case IceType_f64:
394 case IceType_f32: {
395 if (Op != InstArithmetic::Frem) {
396 return;
397 }
398 constexpr SizeT MaxArgs = 2;
399 Operand *TargetHelper = Ctx->getConstantExternSym(
400 DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64);
401 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
402 NoTailCall, IsTargetHelperCall);
403 Call->addArg(Instr->getSrc(0));
404 Call->addArg(Instr->getSrc(1));
405 Context.insert(Call);
406 Instr->setDeleted();
407 return;
408 }
409 }
410 llvm::report_fatal_error("Control flow should never have reached here.");
411 }
412 case Inst::Cast: {
413 Variable *Dest = Instr->getDest();
414 Operand *Src0 = Instr->getSrc(0);
415 const Type DestTy = Dest->getType();
416 const InstCast::OpKind CastKind =
417 llvm::cast<InstCast>(Instr)->getCastKind();
418 switch (CastKind) {
419 default:
420 return;
421 case InstCast::Fptosi:
422 case InstCast::Fptoui: {
423 if (DestTy != IceType_i64) {
424 return;
425 }
426 const bool DestIsSigned = CastKind == InstCast::Fptosi;
427 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType());
428 Operand *TargetHelper = Ctx->getConstantExternSym(
429 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64)
430 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64));
431 static constexpr SizeT MaxArgs = 1;
432 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
433 NoTailCall, IsTargetHelperCall);
434 Call->addArg(Src0);
435 Context.insert(Call);
436 Instr->setDeleted();
437 return;
438 }
439 case InstCast::Sitofp:
440 case InstCast::Uitofp: {
441 if (Src0->getType() != IceType_i64) {
442 return;
443 }
444 const bool SourceIsSigned = CastKind == InstCast::Sitofp;
445 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
446 Operand *TargetHelper = Ctx->getConstantExternSym(
447 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32)
448 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64));
449 static constexpr SizeT MaxArgs = 1;
450 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
451 NoTailCall, IsTargetHelperCall);
452 Call->addArg(Src0);
453 Context.insert(Call);
454 Instr->setDeleted();
455 return;
456 }
457 }
458 llvm_unreachable("Control flow should never have reached here.");
459 }
460 case Inst::IntrinsicCall: {
461 Variable *Dest = Instr->getDest();
462 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr);
463 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID;
464 switch (ID) {
465 default:
466 return;
467 case Intrinsics::Ctpop: {
468 Operand *Src0 = IntrinsicCall->getArg(0);
469 Operand *TargetHelper = Ctx->getConstantExternSym(
470 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32
471 : H_call_ctpop_i64);
472 static constexpr SizeT MaxArgs = 1;
473 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
474 NoTailCall, IsTargetHelperCall);
475 Call->addArg(Src0);
476 Context.insert(Call);
477 Instr->setDeleted();
478 if (Src0->getType() == IceType_i64) {
479 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64;
480 }
481 return;
482 }
483 case Intrinsics::Longjmp: {
484 static constexpr SizeT MaxArgs = 2;
485 static constexpr Variable *NoDest = nullptr;
486 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp);
487 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
488 NoTailCall, IsTargetHelperCall);
489 Call->addArg(IntrinsicCall->getArg(0));
490 Call->addArg(IntrinsicCall->getArg(1));
491 Context.insert(Call);
492 Instr->setDeleted();
493 return;
494 }
495 case Intrinsics::Memcpy: {
496 // In the future, we could potentially emit an inline memcpy/memset, etc.
497 // for intrinsic calls w/ a known length.
498 static constexpr SizeT MaxArgs = 3;
499 static constexpr Variable *NoDest = nullptr;
500 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy);
501 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
502 NoTailCall, IsTargetHelperCall);
503 Call->addArg(IntrinsicCall->getArg(0));
504 Call->addArg(IntrinsicCall->getArg(1));
505 Call->addArg(IntrinsicCall->getArg(2));
506 Context.insert(Call);
507 Instr->setDeleted();
508 return;
509 }
510 case Intrinsics::Memmove: {
511 static constexpr SizeT MaxArgs = 3;
512 static constexpr Variable *NoDest = nullptr;
513 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove);
514 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
515 NoTailCall, IsTargetHelperCall);
516 Call->addArg(IntrinsicCall->getArg(0));
517 Call->addArg(IntrinsicCall->getArg(1));
518 Call->addArg(IntrinsicCall->getArg(2));
519 Context.insert(Call);
520 Instr->setDeleted();
521 return;
522 }
523 case Intrinsics::Memset: {
524 // The value operand needs to be extended to a stack slot size because the
525 // PNaCl ABI requires arguments to be at least 32 bits wide.
526 Operand *ValOp = IntrinsicCall->getArg(1);
527 assert(ValOp->getType() == IceType_i8);
528 Variable *ValExt = Func->makeVariable(stackSlotType());
529 Context.insert(InstCast::create(Func, InstCast::Zext, ValExt, ValOp));
530
531 // Technically, ARM has its own __aeabi_memset, but we can use plain
532 // memset too. The value and size argument need to be flipped if we ever
533 // decide to use __aeabi_memset.
534 static constexpr SizeT MaxArgs = 3;
535 static constexpr Variable *NoDest = nullptr;
536 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset);
537 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
538 NoTailCall, IsTargetHelperCall);
539 Call->addArg(IntrinsicCall->getArg(0));
540 Call->addArg(ValExt);
541 Call->addArg(IntrinsicCall->getArg(2));
542 Context.insert(Call);
543 Instr->setDeleted();
544 return;
545 }
546 case Intrinsics::NaClReadTP: {
547 if (Ctx->getFlags().getUseSandboxing()) {
548 UnimplementedError(Func->getContext()->getFlags());
549 return;
550 }
551 static constexpr SizeT MaxArgs = 0;
552 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp);
553 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
554 NoTailCall, IsTargetHelperCall);
555 Context.insert(Call);
556 Instr->setDeleted();
557 return;
558 }
559 case Intrinsics::Setjmp: {
560 static constexpr SizeT MaxArgs = 1;
561 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp);
562 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
563 NoTailCall, IsTargetHelperCall);
564 Call->addArg(IntrinsicCall->getArg(0));
565 Context.insert(Call);
566 Instr->setDeleted();
567 return;
568 }
569 }
570 llvm_unreachable("Control flow should never have reached here.");
571 }
572 }
573 }
574
268 void TargetARM32::findMaxStackOutArgsSize() { 575 void TargetARM32::findMaxStackOutArgsSize() {
269 // MinNeededOutArgsBytes should be updated if the Target ever creates a 576 // MinNeededOutArgsBytes should be updated if the Target ever creates a
270 // high-level InstCall that requires more stack bytes. 577 // high-level InstCall that requires more stack bytes.
271 constexpr size_t MinNeededOutArgsBytes = 0; 578 constexpr size_t MinNeededOutArgsBytes = 0;
272 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; 579 MaxOutArgsSizeBytes = MinNeededOutArgsBytes;
273 for (CfgNode *Node : Func->getNodes()) { 580 for (CfgNode *Node : Func->getNodes()) {
274 Context.init(Node); 581 Context.init(Node);
275 while (!Context.atEnd()) { 582 while (!Context.atEnd()) {
276 PostIncrLoweringContext PostIncrement(Context); 583 PostIncrLoweringContext PostIncrement(Context);
277 Inst *CurInstr = Context.getCur(); 584 Inst *CurInstr = Context.getCur();
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 if (Mem->isRegReg()) { 1506 if (Mem->isRegReg()) {
1200 Variable *IndexR = legalizeToReg(Mem->getIndex()); 1507 Variable *IndexR = legalizeToReg(Mem->getIndex());
1201 return OperandARM32Mem::create(Func, IceType_i32, BaseR, IndexR, 1508 return OperandARM32Mem::create(Func, IceType_i32, BaseR, IndexR,
1202 Mem->getShiftOp(), Mem->getShiftAmt(), 1509 Mem->getShiftOp(), Mem->getShiftAmt(),
1203 Mem->getAddrMode()); 1510 Mem->getAddrMode());
1204 } else { 1511 } else {
1205 return OperandARM32Mem::create(Func, IceType_i32, BaseR, Mem->getOffset(), 1512 return OperandARM32Mem::create(Func, IceType_i32, BaseR, Mem->getOffset(),
1206 Mem->getAddrMode()); 1513 Mem->getAddrMode());
1207 } 1514 }
1208 } 1515 }
1209 llvm_unreachable("Unsupported operand type"); 1516 llvm_unreachable("Unsupported operand type");
Jim Stichnoth 2015/12/01 17:01:56 report_fatal_error
John 2015/12/01 20:56:27 Done.
1210 return nullptr; 1517 return nullptr;
1211 } 1518 }
1212 1519
1213 Operand *TargetARM32::hiOperand(Operand *Operand) { 1520 Operand *TargetARM32::hiOperand(Operand *Operand) {
1214 assert(Operand->getType() == IceType_i64); 1521 assert(Operand->getType() == IceType_i64);
1215 if (Operand->getType() != IceType_i64) 1522 if (Operand->getType() != IceType_i64)
1216 return Operand; 1523 return Operand;
1217 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) 1524 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
1218 return Var64On32->getHi(); 1525 return Var64On32->getHi();
1219 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { 1526 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 Base = NewBase; 1566 Base = NewBase;
1260 } else { 1567 } else {
1261 Offset = 1568 Offset =
1262 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); 1569 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal));
1263 } 1570 }
1264 Variable *BaseR = legalizeToReg(Base); 1571 Variable *BaseR = legalizeToReg(Base);
1265 return OperandARM32Mem::create(Func, SplitType, BaseR, Offset, 1572 return OperandARM32Mem::create(Func, SplitType, BaseR, Offset,
1266 Mem->getAddrMode()); 1573 Mem->getAddrMode());
1267 } 1574 }
1268 } 1575 }
1269 llvm_unreachable("Unsupported operand type"); 1576 llvm_unreachable("Unsupported operand type");
Jim Stichnoth 2015/12/01 17:01:56 report_fatal_error
John 2015/12/01 20:56:27 Done.
1270 return nullptr; 1577 return nullptr;
1271 } 1578 }
1272 1579
1273 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, 1580 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include,
1274 RegSetMask Exclude) const { 1581 RegSetMask Exclude) const {
1275 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); 1582 llvm::SmallBitVector Registers(RegARM32::Reg_NUM);
1276 1583
1277 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ 1584 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
1278 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ 1585 isI64Pair, isFP32, isFP64, isVec128, alias_init) \
1279 if (scratch && (Include & RegSet_CallerSave)) \ 1586 if (scratch && (Include & RegSet_CallerSave)) \
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 } 1713 }
1407 } 1714 }
1408 InstARM32Label *Label = InstARM32Label::create(Func, this); 1715 InstARM32Label *Label = InstARM32Label::create(Func, this);
1409 _br(Label, CondARM32::NE); 1716 _br(Label, CondARM32::NE);
1410 _trap(); 1717 _trap();
1411 Context.insert(Label); 1718 Context.insert(Label);
1412 } 1719 }
1413 1720
1414 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, 1721 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R,
1415 Operand *Src1, ExtInstr ExtFunc, 1722 Operand *Src1, ExtInstr ExtFunc,
1416 DivInstr DivFunc, const char *DivHelperName, 1723 DivInstr DivFunc, bool IsRemainder) {
1417 bool IsRemainder) {
1418 div0Check(Dest->getType(), Src1, nullptr); 1724 div0Check(Dest->getType(), Src1, nullptr);
1419 Variable *Src1R = legalizeToReg(Src1); 1725 Variable *Src1R = legalizeToReg(Src1);
1420 Variable *T0R = Src0R; 1726 Variable *T0R = Src0R;
1421 Variable *T1R = Src1R; 1727 Variable *T1R = Src1R;
1422 if (Dest->getType() != IceType_i32) { 1728 if (Dest->getType() != IceType_i32) {
1423 T0R = makeReg(IceType_i32); 1729 T0R = makeReg(IceType_i32);
1424 (this->*ExtFunc)(T0R, Src0R, CondARM32::AL); 1730 (this->*ExtFunc)(T0R, Src0R, CondARM32::AL);
1425 T1R = makeReg(IceType_i32); 1731 T1R = makeReg(IceType_i32);
1426 (this->*ExtFunc)(T1R, Src1R, CondARM32::AL); 1732 (this->*ExtFunc)(T1R, Src1R, CondARM32::AL);
1427 } 1733 }
1428 if (hasCPUFeature(TargetARM32Features::HWDivArm)) { 1734 if (hasCPUFeature(TargetARM32Features::HWDivArm)) {
1429 (this->*DivFunc)(T, T0R, T1R, CondARM32::AL); 1735 (this->*DivFunc)(T, T0R, T1R, CondARM32::AL);
1430 if (IsRemainder) { 1736 if (IsRemainder) {
1431 Variable *T2 = makeReg(IceType_i32); 1737 Variable *T2 = makeReg(IceType_i32);
1432 _mls(T2, T, T1R, T0R); 1738 _mls(T2, T, T1R, T0R);
1433 T = T2; 1739 T = T2;
1434 } 1740 }
1435 _mov(Dest, T); 1741 _mov(Dest, T);
1436 } else { 1742 } else {
1437 constexpr SizeT MaxSrcs = 2; 1743 llvm::report_fatal_error("div should have already been turned into a call");
1438 InstCall *Call = makeHelperCall(DivHelperName, Dest, MaxSrcs);
1439 Call->addArg(T0R);
1440 Call->addArg(T1R);
1441 lowerCall(Call);
1442 } 1744 }
1443 return;
1444 } 1745 }
1445 1746
1446 TargetARM32::SafeBoolChain 1747 TargetARM32::SafeBoolChain
1447 TargetARM32::lowerInt1Arithmetic(const InstArithmetic *Inst) { 1748 TargetARM32::lowerInt1Arithmetic(const InstArithmetic *Inst) {
1448 Variable *Dest = Inst->getDest(); 1749 Variable *Dest = Inst->getDest();
1449 assert(Dest->getType() == IceType_i1); 1750 assert(Dest->getType() == IceType_i1);
1450 1751
1451 // So folding didn't work for Inst. Not a problem: We just need to 1752 // So folding didn't work for Inst. Not a problem: We just need to
1452 // materialize the Sources, and perform the operation. We create regular 1753 // materialize the Sources, and perform the operation. We create regular
1453 // Variables (and not infinite-weight ones) because this call might recurse a 1754 // Variables (and not infinite-weight ones) because this call might recurse a
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 } 1936 }
1636 1937
1637 Operand *invertedSrc1F(TargetARM32 *Target) const { 1938 Operand *invertedSrc1F(TargetARM32 *Target) const {
1638 return legalizeToRegOrFlex(Target, 1939 return legalizeToRegOrFlex(Target,
1639 Target->getCtx()->getConstantInt32( 1940 Target->getCtx()->getConstantInt32(
1640 ~static_cast<uint32_t>(getConstantValue()))); 1941 ~static_cast<uint32_t>(getConstantValue())));
1641 } 1942 }
1642 }; 1943 };
1643 } // end of anonymous namespace 1944 } // end of anonymous namespace
1644 1945
1946 void TargetARM32::preambleDivRem(const InstCall *Instr) {
1947 Operand *Src1 = Instr->getArg(1);
1948
1949 switch (Src1->getType()) {
1950 default:
1951 llvm::report_fatal_error("Invalid type for idiv.");
1952 case IceType_i64: {
1953 if (auto *C = llvm::dyn_cast<ConstantInteger64>(Src1)) {
1954 if (C->getValue() == 0) {
1955 _trap();
1956 return;
1957 }
1958 }
1959 div0Check(IceType_i64, loOperand(Src1), hiOperand(Src1));
1960 return;
1961 }
1962 case IceType_i32: {
1963 // Src0 and Src1 have already been appropriately extended to an i32, so we
1964 // don't check for i8 and i16.
1965 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) {
1966 if (C->getValue() == 0) {
1967 _trap();
1968 return;
1969 }
1970 }
1971 div0Check(IceType_i32, Src1, nullptr);
1972 return;
1973 }
1974 }
1975 }
1976
1645 void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, 1977 void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op,
1646 Variable *Dest, Operand *Src0, 1978 Variable *Dest, Operand *Src0,
1647 Operand *Src1) { 1979 Operand *Src1) {
1648 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); 1980 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1));
1649 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); 1981 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1));
1650 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands()); 1982 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands());
1651 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand()); 1983 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand());
1652 1984
1653 // These helper-call-involved instructions are lowered in this separate
1654 // switch. This is because we would otherwise assume that we need to
1655 // legalize Src0 to Src0RLo and Src0Hi. However, those go unused with
1656 // helper calls, and such unused/redundant instructions will fail liveness
1657 // analysis under -Om1 setting.
1658 switch (Op) {
1659 default:
1660 break;
1661 case InstArithmetic::Udiv:
1662 case InstArithmetic::Sdiv:
1663 case InstArithmetic::Urem:
1664 case InstArithmetic::Srem: {
1665 // Check for divide by 0 (ARM normally doesn't trap, but we want it to
1666 // trap for NaCl). Src1Lo and Src1Hi may have already been legalized to a
1667 // register, which will hide a constant source operand. Instead, check
1668 // the not-yet-legalized Src1 to optimize-out a divide by 0 check.
1669 if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) {
1670 if (SrcsLo.getConstantValue() == 0 && SrcsHi.getConstantValue() == 0) {
1671 _trap();
1672 return;
1673 }
1674 } else {
1675 Operand *Src1Lo = SrcsLo.unswappedSrc1R(this);
1676 Operand *Src1Hi = SrcsHi.unswappedSrc1R(this);
1677 div0Check(IceType_i64, Src1Lo, Src1Hi);
1678 }
1679 // Technically, ARM has its own aeabi routines, but we can use the
1680 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses
1681 // the more standard __moddi3 for rem.
1682 const char *HelperName = "";
1683 switch (Op) {
1684 default:
1685 llvm::report_fatal_error("Should have only matched div ops.");
1686 break;
1687 case InstArithmetic::Udiv:
1688 HelperName = H_udiv_i64;
1689 break;
1690 case InstArithmetic::Sdiv:
1691 HelperName = H_sdiv_i64;
1692 break;
1693 case InstArithmetic::Urem:
1694 HelperName = H_urem_i64;
1695 break;
1696 case InstArithmetic::Srem:
1697 HelperName = H_srem_i64;
1698 break;
1699 }
1700 constexpr SizeT MaxSrcs = 2;
1701 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
1702 Call->addArg(Src0);
1703 Call->addArg(Src1);
1704 lowerCall(Call);
1705 return;
1706 }
1707 }
1708
1709 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); 1985 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
1710 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); 1986 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
1711 Variable *T_Lo = makeReg(DestLo->getType()); 1987 Variable *T_Lo = makeReg(DestLo->getType());
1712 Variable *T_Hi = makeReg(DestHi->getType()); 1988 Variable *T_Hi = makeReg(DestHi->getType());
1713 1989
1714 switch (Op) { 1990 switch (Op) {
1715 case InstArithmetic::_num: 1991 case InstArithmetic::_num:
1716 llvm::report_fatal_error("Unknown arithmetic operator"); 1992 llvm::report_fatal_error("Unknown arithmetic operator");
1717 return; 1993 return;
1718 case InstArithmetic::Add: { 1994 case InstArithmetic::Add: {
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
2223 // difficult to determine (constant may be moved to a register). 2499 // difficult to determine (constant may be moved to a register).
2224 // * Handle floating point arithmetic separately: they require Src1 to be 2500 // * Handle floating point arithmetic separately: they require Src1 to be
2225 // legalized to a register. 2501 // legalized to a register.
2226 switch (Inst->getOp()) { 2502 switch (Inst->getOp()) {
2227 default: 2503 default:
2228 break; 2504 break;
2229 case InstArithmetic::Udiv: { 2505 case InstArithmetic::Udiv: {
2230 constexpr bool NotRemainder = false; 2506 constexpr bool NotRemainder = false;
2231 Variable *Src0R = legalizeToReg(Src0); 2507 Variable *Src0R = legalizeToReg(Src0);
2232 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, 2508 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
2233 H_udiv_i32, NotRemainder); 2509 NotRemainder);
2234 return; 2510 return;
2235 } 2511 }
2236 case InstArithmetic::Sdiv: { 2512 case InstArithmetic::Sdiv: {
2237 constexpr bool NotRemainder = false; 2513 constexpr bool NotRemainder = false;
2238 Variable *Src0R = legalizeToReg(Src0); 2514 Variable *Src0R = legalizeToReg(Src0);
2239 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, 2515 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
2240 H_sdiv_i32, NotRemainder); 2516 NotRemainder);
2241 return; 2517 return;
2242 } 2518 }
2243 case InstArithmetic::Urem: { 2519 case InstArithmetic::Urem: {
2244 constexpr bool IsRemainder = true; 2520 constexpr bool IsRemainder = true;
2245 Variable *Src0R = legalizeToReg(Src0); 2521 Variable *Src0R = legalizeToReg(Src0);
2246 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, 2522 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
2247 H_urem_i32, IsRemainder); 2523 IsRemainder);
2248 return; 2524 return;
2249 } 2525 }
2250 case InstArithmetic::Srem: { 2526 case InstArithmetic::Srem: {
2251 constexpr bool IsRemainder = true; 2527 constexpr bool IsRemainder = true;
2252 Variable *Src0R = legalizeToReg(Src0); 2528 Variable *Src0R = legalizeToReg(Src0);
2253 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, 2529 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
2254 H_srem_i32, IsRemainder); 2530 IsRemainder);
2255 return; 2531 return;
2256 } 2532 }
2257 case InstArithmetic::Frem: { 2533 case InstArithmetic::Frem: {
2258 constexpr SizeT MaxSrcs = 2; 2534 if (!isScalarFloatingType(DestTy)) {
2259 Variable *Src0R = legalizeToReg(Src0); 2535 llvm::report_fatal_error("Unexpected type when lowering frem.");
2260 Type Ty = DestTy; 2536 }
2261 InstCall *Call = makeHelperCall( 2537 llvm::report_fatal_error("Frem should have already been lowered.");
2262 isFloat32Asserting32Or64(Ty) ? H_frem_f32 : H_frem_f64, Dest, MaxSrcs);
2263 Call->addArg(Src0R);
2264 Call->addArg(Src1);
2265 lowerCall(Call);
2266 return;
2267 } 2538 }
2268 case InstArithmetic::Fadd: { 2539 case InstArithmetic::Fadd: {
2269 Variable *Src0R = legalizeToReg(Src0); 2540 Variable *Src0R = legalizeToReg(Src0);
2270 Variable *Src1R = legalizeToReg(Src1); 2541 Variable *Src1R = legalizeToReg(Src1);
2271 _vadd(T, Src0R, Src1R); 2542 _vadd(T, Src0R, Src1R);
2272 _mov(Dest, T); 2543 _mov(Dest, T);
2273 return; 2544 return;
2274 } 2545 }
2275 case InstArithmetic::Fsub: { 2546 case InstArithmetic::Fsub: {
2276 Variable *Src0R = legalizeToReg(Src0); 2547 Variable *Src0R = legalizeToReg(Src0);
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
2675 case CondARM32::kNone: 2946 case CondARM32::kNone:
2676 _br(TargetFalse); 2947 _br(TargetFalse);
2677 break; 2948 break;
2678 case CondARM32::AL: 2949 case CondARM32::AL:
2679 _br(TargetTrue); 2950 _br(TargetTrue);
2680 break; 2951 break;
2681 } 2952 }
2682 } 2953 }
2683 2954
2684 void TargetARM32::lowerCall(const InstCall *Instr) { 2955 void TargetARM32::lowerCall(const InstCall *Instr) {
2956 Operand *CallTarget = Instr->getCallTarget();
2957 if (Instr->isTargetHelperCall()) {
2958 auto TargetHelperPreamble = ARM32HelpersPreamble.find(CallTarget);
2959 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) {
2960 (this->*TargetHelperPreamble->second)(Instr);
2961 }
2962 }
2685 MaybeLeafFunc = false; 2963 MaybeLeafFunc = false;
2686 NeedsStackAlignment = true; 2964 NeedsStackAlignment = true;
2687 2965
2688 // Assign arguments to registers and stack. Also reserve stack. 2966 // Assign arguments to registers and stack. Also reserve stack.
2689 TargetARM32::CallingConv CC; 2967 TargetARM32::CallingConv CC;
2690 // Pair of Arg Operand -> GPR number assignments. 2968 // Pair of Arg Operand -> GPR number assignments.
2691 llvm::SmallVector<std::pair<Operand *, int32_t>, 2969 llvm::SmallVector<std::pair<Operand *, int32_t>,
2692 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; 2970 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs;
2693 llvm::SmallVector<std::pair<Operand *, int32_t>, 2971 llvm::SmallVector<std::pair<Operand *, int32_t>,
2694 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; 2972 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2797 case IceType_v8i1: 3075 case IceType_v8i1:
2798 case IceType_v16i1: 3076 case IceType_v16i1:
2799 case IceType_v16i8: 3077 case IceType_v16i8:
2800 case IceType_v8i16: 3078 case IceType_v8i16:
2801 case IceType_v4i32: 3079 case IceType_v4i32:
2802 case IceType_v4f32: 3080 case IceType_v4f32:
2803 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); 3081 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0);
2804 break; 3082 break;
2805 } 3083 }
2806 } 3084 }
2807 Operand *CallTarget = Instr->getCallTarget();
2808 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = 3085 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing =
2809 // Ctx->getFlags().getUseSandboxing(); 3086 // Ctx->getFlags().getUseSandboxing();
2810 3087
2811 // Allow ConstantRelocatable to be left alone as a direct call, but force 3088 // Allow ConstantRelocatable to be left alone as a direct call, but force
2812 // other constants like ConstantInteger32 to be in a register and make it an 3089 // other constants like ConstantInteger32 to be in a register and make it an
2813 // indirect call. 3090 // indirect call.
2814 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { 3091 if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
2815 CallTarget = legalize(CallTarget, Legal_Reg); 3092 CallTarget = legalize(CallTarget, Legal_Reg);
2816 } 3093 }
2817 3094
(...skipping 16 matching lines...) Expand all
2834 3111
2835 // Insert a register-kill pseudo instruction. 3112 // Insert a register-kill pseudo instruction.
2836 Context.insert(InstFakeKill::create(Func, NewCall)); 3113 Context.insert(InstFakeKill::create(Func, NewCall));
2837 3114
2838 // Generate a FakeUse to keep the call live if necessary. 3115 // Generate a FakeUse to keep the call live if necessary.
2839 if (Instr->hasSideEffects() && ReturnReg) { 3116 if (Instr->hasSideEffects() && ReturnReg) {
2840 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); 3117 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg);
2841 Context.insert(FakeUse); 3118 Context.insert(FakeUse);
2842 } 3119 }
2843 3120
2844 if (!Dest) 3121 if (Dest != nullptr) {
2845 return; 3122 // Assign the result of the call to Dest.
3123 if (ReturnReg != nullptr) {
3124 if (ReturnRegHi) {
3125 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest);
3126 Variable *DestLo = Dest64On32->getLo();
3127 Variable *DestHi = Dest64On32->getHi();
3128 _mov(DestLo, ReturnReg);
3129 _mov(DestHi, ReturnRegHi);
3130 } else {
3131 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) {
3132 _mov(Dest, ReturnReg);
3133 } else {
3134 assert(isIntegerType(Dest->getType()) &&
3135 typeWidthInBytes(Dest->getType()) <= 4);
3136 _mov(Dest, ReturnReg);
3137 }
3138 }
3139 }
3140 }
2846 3141
2847 // Assign the result of the call to Dest. 3142 if (Instr->isTargetHelperCall()) {
2848 if (ReturnReg) { 3143 auto TargetHelpersPostamble = ARM32HelpersPostamble.find(CallTarget);
2849 if (ReturnRegHi) { 3144 if (TargetHelpersPostamble != ARM32HelpersPostamble.end()) {
2850 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); 3145 (this->*TargetHelpersPostamble->second)(Instr);
2851 Variable *DestLo = Dest64On32->getLo();
2852 Variable *DestHi = Dest64On32->getHi();
2853 _mov(DestLo, ReturnReg);
2854 _mov(DestHi, ReturnRegHi);
2855 } else {
2856 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) {
2857 _mov(Dest, ReturnReg);
2858 } else {
2859 assert(isIntegerType(Dest->getType()) &&
2860 typeWidthInBytes(Dest->getType()) <= 4);
2861 _mov(Dest, ReturnReg);
2862 }
2863 } 3146 }
2864 } 3147 }
2865 } 3148 }
2866 3149
2867 namespace { 3150 namespace {
2868 void configureBitcastTemporary(Variable64On32 *Var) { 3151 void configureBitcastTemporary(Variable64On32 *Var) {
2869 Var->setMustNotHaveReg(); 3152 Var->setMustNotHaveReg();
2870 Var->getHi()->setMustHaveReg(); 3153 Var->getHi()->setMustHaveReg();
2871 Var->getLo()->setMustHaveReg(); 3154 Var->getLo()->setMustHaveReg();
2872 } 3155 }
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
3029 Variable *T = makeReg(Dest->getType()); 3312 Variable *T = makeReg(Dest->getType());
3030 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); 3313 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
3031 _mov(Dest, T); 3314 _mov(Dest, T);
3032 UnimplementedError(Func->getContext()->getFlags()); 3315 UnimplementedError(Func->getContext()->getFlags());
3033 break; 3316 break;
3034 } 3317 }
3035 3318
3036 const bool DestIsSigned = CastKind == InstCast::Fptosi; 3319 const bool DestIsSigned = CastKind == InstCast::Fptosi;
3037 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); 3320 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType());
3038 if (llvm::isa<Variable64On32>(Dest)) { 3321 if (llvm::isa<Variable64On32>(Dest)) {
3039 const char *HelperName = 3322 llvm::report_fatal_error("fp-to-i64 should have been pre-lowered.");
3040 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64)
3041 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64);
3042 static constexpr SizeT MaxSrcs = 1;
3043 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
3044 Call->addArg(Src0);
3045 lowerCall(Call);
3046 break;
3047 } 3323 }
3048 // fptosi: 3324 // fptosi:
3049 // t1.fp = vcvt src0.fp 3325 // t1.fp = vcvt src0.fp
3050 // t2.i32 = vmov t1.fp 3326 // t2.i32 = vmov t1.fp
3051 // dest.int = conv t2.i32 @ Truncates the result if needed. 3327 // dest.int = conv t2.i32 @ Truncates the result if needed.
3052 // fptoui: 3328 // fptoui:
3053 // t1.fp = vcvt src0.fp 3329 // t1.fp = vcvt src0.fp
3054 // t2.u32 = vmov t1.fp 3330 // t2.u32 = vmov t1.fp
3055 // dest.uint = conv t2.u32 @ Truncates the result if needed. 3331 // dest.uint = conv t2.u32 @ Truncates the result if needed.
3056 Variable *Src0R = legalizeToReg(Src0); 3332 Variable *Src0R = legalizeToReg(Src0);
(...skipping 17 matching lines...) Expand all
3074 if (isVectorType(Dest->getType())) { 3350 if (isVectorType(Dest->getType())) {
3075 Variable *T = makeReg(Dest->getType()); 3351 Variable *T = makeReg(Dest->getType());
3076 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); 3352 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
3077 _mov(Dest, T); 3353 _mov(Dest, T);
3078 UnimplementedError(Func->getContext()->getFlags()); 3354 UnimplementedError(Func->getContext()->getFlags());
3079 break; 3355 break;
3080 } 3356 }
3081 const bool SourceIsSigned = CastKind == InstCast::Sitofp; 3357 const bool SourceIsSigned = CastKind == InstCast::Sitofp;
3082 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); 3358 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
3083 if (Src0->getType() == IceType_i64) { 3359 if (Src0->getType() == IceType_i64) {
3084 const char *HelperName = 3360 llvm::report_fatal_error("i64-to-fp should have been pre-lowered.");
3085 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32)
3086 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64);
3087 static constexpr SizeT MaxSrcs = 1;
3088 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
3089 Call->addArg(Src0);
3090 lowerCall(Call);
3091 break;
3092 } 3361 }
3093 // sitofp: 3362 // sitofp:
3094 // t1.i32 = sext src.int @ sign-extends src0 if needed. 3363 // t1.i32 = sext src.int @ sign-extends src0 if needed.
3095 // t2.fp32 = vmov t1.i32 3364 // t2.fp32 = vmov t1.i32
3096 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 3365 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64
3097 // uitofp: 3366 // uitofp:
3098 // t1.i32 = zext src.int @ zero-extends src0 if needed. 3367 // t1.i32 = zext src.int @ zero-extends src0 if needed.
3099 // t2.fp32 = vmov t1.i32 3368 // t2.fp32 = vmov t1.i32
3100 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 3369 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64
3101 if (Src0->getType() != IceType_i32) { 3370 if (Src0->getType() != IceType_i32) {
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
3767 } 4036 }
3768 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg)); 4037 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg));
3769 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { 4038 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
3770 Context.insert(InstFakeUse::create(Func, Dest64->getLo())); 4039 Context.insert(InstFakeUse::create(Func, Dest64->getLo()));
3771 Context.insert(InstFakeUse::create(Func, Dest64->getHi())); 4040 Context.insert(InstFakeUse::create(Func, Dest64->getHi()));
3772 } else { 4041 } else {
3773 Context.insert(InstFakeUse::create(Func, Dest)); 4042 Context.insert(InstFakeUse::create(Func, Dest));
3774 } 4043 }
3775 } 4044 }
3776 4045
4046 void TargetARM32::postambleCtpop64(const InstCall *Instr) {
4047 Operand *Arg0 = Instr->getArg(0);
4048 if (isInt32Asserting32Or64(Arg0->getType())) {
4049 return;
4050 }
4051 // The popcount helpers always return 32-bit values, while the intrinsic's
4052 // signature matches some 64-bit platform's native instructions and expect to
4053 // fill a 64-bit reg. Thus, clear the upper bits of the dest just in case the
4054 // user doesn't do that in the IR or doesn't toss the bits via truncate.
4055 Variable *DestHi = llvm::cast<Variable>(hiOperand(Instr->getDest()));
4056 Variable *T = makeReg(IceType_i32);
4057 Operand *_0 =
4058 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
4059 _mov(T, _0);
4060 _mov(DestHi, T);
4061 }
4062
3777 void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { 4063 void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
3778 Variable *Dest = Instr->getDest(); 4064 Variable *Dest = Instr->getDest();
3779 Type DestTy = (Dest != nullptr) ? Dest->getType() : IceType_void; 4065 Type DestTy = (Dest != nullptr) ? Dest->getType() : IceType_void;
3780 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID; 4066 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID;
3781 switch (ID) { 4067 switch (ID) {
3782 case Intrinsics::AtomicFence: 4068 case Intrinsics::AtomicFence:
3783 case Intrinsics::AtomicFenceAll: 4069 case Intrinsics::AtomicFenceAll:
3784 assert(Dest == nullptr); 4070 assert(Dest == nullptr);
3785 _dmb(); 4071 _dmb();
3786 return; 4072 return;
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
4083 _rev(T, ValR); 4369 _rev(T, ValR);
4084 if (Val->getType() == IceType_i16) { 4370 if (Val->getType() == IceType_i16) {
4085 Operand *_16 = shAmtImm(16); 4371 Operand *_16 = shAmtImm(16);
4086 _lsr(T, T, _16); 4372 _lsr(T, T, _16);
4087 } 4373 }
4088 _mov(Dest, T); 4374 _mov(Dest, T);
4089 } 4375 }
4090 return; 4376 return;
4091 } 4377 }
4092 case Intrinsics::Ctpop: { 4378 case Intrinsics::Ctpop: {
4093 Operand *Val = Instr->getArg(0); 4379 llvm::report_fatal_error("Ctpop should have been prelowered.");
4094 InstCall *Call = makeHelperCall(isInt32Asserting32Or64(Val->getType())
4095 ? H_call_ctpop_i32
4096 : H_call_ctpop_i64,
4097 Dest, 1);
4098 Call->addArg(Val);
4099 lowerCall(Call);
4100 // The popcount helpers always return 32-bit values, while the intrinsic's
4101 // signature matches some 64-bit platform's native instructions and expect
4102 // to fill a 64-bit reg. Thus, clear the upper bits of the dest just in
4103 // case the user doesn't do that in the IR or doesn't toss the bits via
4104 // truncate.
4105 if (Val->getType() == IceType_i64) {
4106 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
4107 Constant *Zero = Ctx->getConstantZero(IceType_i32);
4108 Variable *T = makeReg(Zero->getType());
4109 _mov(T, Zero);
4110 _mov(DestHi, T);
4111 }
4112 return;
4113 } 4380 }
4114 case Intrinsics::Ctlz: { 4381 case Intrinsics::Ctlz: {
4115 // The "is zero undef" parameter is ignored and we always return a 4382 // The "is zero undef" parameter is ignored and we always return a
4116 // well-defined value. 4383 // well-defined value.
4117 Operand *Val = Instr->getArg(0); 4384 Operand *Val = Instr->getArg(0);
4118 Variable *ValLoR; 4385 Variable *ValLoR;
4119 Variable *ValHiR = nullptr; 4386 Variable *ValHiR = nullptr;
4120 if (Val->getType() == IceType_i64) { 4387 if (Val->getType() == IceType_i64) {
4121 Val = legalizeUndef(Val); 4388 Val = legalizeUndef(Val);
4122 ValLoR = legalizeToReg(loOperand(Val)); 4389 ValLoR = legalizeToReg(loOperand(Val));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4159 Context.insert(InstFakeDef::create(Func, T)); 4426 Context.insert(InstFakeDef::create(Func, T));
4160 _mov(Dest, T); 4427 _mov(Dest, T);
4161 UnimplementedError(Func->getContext()->getFlags()); 4428 UnimplementedError(Func->getContext()->getFlags());
4162 return; 4429 return;
4163 } 4430 }
4164 _vabs(T, legalizeToReg(Instr->getArg(0))); 4431 _vabs(T, legalizeToReg(Instr->getArg(0)));
4165 _mov(Dest, T); 4432 _mov(Dest, T);
4166 return; 4433 return;
4167 } 4434 }
4168 case Intrinsics::Longjmp: { 4435 case Intrinsics::Longjmp: {
4169 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); 4436 llvm::report_fatal_error("longjmp should have been prelowered.");
4170 Call->addArg(Instr->getArg(0));
4171 Call->addArg(Instr->getArg(1));
4172 lowerCall(Call);
4173 return;
4174 } 4437 }
4175 case Intrinsics::Memcpy: { 4438 case Intrinsics::Memcpy: {
4176 // In the future, we could potentially emit an inline memcpy/memset, etc. 4439 llvm::report_fatal_error("memcpy should have been prelowered.");
4177 // for intrinsic calls w/ a known length.
4178 InstCall *Call = makeHelperCall(H_call_memcpy, nullptr, 3);
4179 Call->addArg(Instr->getArg(0));
4180 Call->addArg(Instr->getArg(1));
4181 Call->addArg(Instr->getArg(2));
4182 lowerCall(Call);
4183 return;
4184 } 4440 }
4185 case Intrinsics::Memmove: { 4441 case Intrinsics::Memmove: {
4186 InstCall *Call = makeHelperCall(H_call_memmove, nullptr, 3); 4442 llvm::report_fatal_error("memmove should have been prelowered.");
4187 Call->addArg(Instr->getArg(0));
4188 Call->addArg(Instr->getArg(1));
4189 Call->addArg(Instr->getArg(2));
4190 lowerCall(Call);
4191 return;
4192 } 4443 }
4193 case Intrinsics::Memset: { 4444 case Intrinsics::Memset: {
4194 // The value operand needs to be extended to a stack slot size because the 4445 llvm::report_fatal_error("memmove should have been prelowered.");
4195 // PNaCl ABI requires arguments to be at least 32 bits wide.
4196 Operand *ValOp = Instr->getArg(1);
4197 assert(ValOp->getType() == IceType_i8);
4198 Variable *ValExt = Func->makeVariable(stackSlotType());
4199 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp));
4200 // Technically, ARM has their own __aeabi_memset, but we can use plain
4201 // memset too. The value and size argument need to be flipped if we ever
4202 // decide to use __aeabi_memset.
4203 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3);
4204 Call->addArg(Instr->getArg(0));
4205 Call->addArg(ValExt);
4206 Call->addArg(Instr->getArg(2));
4207 lowerCall(Call);
4208 return;
4209 } 4446 }
4210 case Intrinsics::NaClReadTP: { 4447 case Intrinsics::NaClReadTP: {
4211 if (Ctx->getFlags().getUseSandboxing()) { 4448 llvm::report_fatal_error("nacl-read-tp should have been prelowered.");
4212 UnimplementedError(Func->getContext()->getFlags());
4213 } else {
4214 InstCall *Call = makeHelperCall(H_call_read_tp, Dest, 0);
4215 lowerCall(Call);
4216 }
4217 return;
4218 } 4449 }
4219 case Intrinsics::Setjmp: { 4450 case Intrinsics::Setjmp: {
4220 InstCall *Call = makeHelperCall(H_call_setjmp, Dest, 1); 4451 llvm::report_fatal_error("setjmp should have been prelowered.");
4221 Call->addArg(Instr->getArg(0));
4222 lowerCall(Call);
4223 return;
4224 } 4452 }
4225 case Intrinsics::Sqrt: { 4453 case Intrinsics::Sqrt: {
4226 Variable *Src = legalizeToReg(Instr->getArg(0)); 4454 Variable *Src = legalizeToReg(Instr->getArg(0));
4227 Variable *T = makeReg(Dest->getType()); 4455 Variable *T = makeReg(Dest->getType());
4228 _vsqrt(T, Src); 4456 _vsqrt(T, Src);
4229 _mov(Dest, T); 4457 _mov(Dest, T);
4230 return; 4458 return;
4231 } 4459 }
4232 case Intrinsics::Stacksave: { 4460 case Intrinsics::Stacksave: {
4233 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); 4461 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
5109 // We need a new physical register for the operand if: 5337 // We need a new physical register for the operand if:
5110 // Mem is not allowed and Var isn't guaranteed a physical 5338 // Mem is not allowed and Var isn't guaranteed a physical
5111 // register, or 5339 // register, or
5112 // RegNum is required and Var->getRegNum() doesn't match. 5340 // RegNum is required and Var->getRegNum() doesn't match.
5113 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || 5341 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
5114 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { 5342 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
5115 From = copyToReg(From, RegNum); 5343 From = copyToReg(From, RegNum);
5116 } 5344 }
5117 return From; 5345 return From;
5118 } 5346 }
5119 llvm_unreachable("Unhandled operand kind in legalize()"); 5347 llvm_unreachable("Unhandled operand kind in legalize()");
Jim Stichnoth 2015/12/01 17:01:56 report_fatal_error
John 2015/12/01 20:56:27 Done.
5120 5348
5121 return From; 5349 return From;
5122 } 5350 }
5123 5351
5124 /// Provide a trivial wrapper to legalize() for this common usage. 5352 /// Provide a trivial wrapper to legalize() for this common usage.
5125 Variable *TargetARM32::legalizeToReg(Operand *From, int32_t RegNum) { 5353 Variable *TargetARM32::legalizeToReg(Operand *From, int32_t RegNum) {
5126 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); 5354 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
5127 } 5355 }
5128 5356
5129 /// Legalize undef values to concrete values. 5357 /// Legalize undef values to concrete values.
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after
5730 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 5958 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
5731 // However, for compatibility with current NaCl LLVM, don't claim that. 5959 // However, for compatibility with current NaCl LLVM, don't claim that.
5732 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 5960 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
5733 } 5961 }
5734 5962
5735 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; 5963 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM];
5736 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; 5964 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
5737 llvm::SmallBitVector TargetARM32::ScratchRegs; 5965 llvm::SmallBitVector TargetARM32::ScratchRegs;
5738 5966
5739 } // end of namespace Ice 5967 } // 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