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

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: make presubmit fixes. 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
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::DivRemPreamble;
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 if (hasCPUFeature(TargetARM32Features::HWDivArm)) {
319 return;
320 }
321 InstCast::OpKind CastKind;
322 Operand *TargetHelper;
323 switch (Op) {
324 default:
325 return;
326 case InstArithmetic::Udiv:
327 TargetHelper = Ctx->getConstantExternSym(H_udiv_i32);
328 CastKind = InstCast::Zext;
329 break;
330 case InstArithmetic::Sdiv:
331 TargetHelper = Ctx->getConstantExternSym(H_sdiv_i32);
332 CastKind = InstCast::Sext;
333 break;
334 case InstArithmetic::Urem:
335 TargetHelper = Ctx->getConstantExternSym(H_urem_i32);
336 CastKind = InstCast::Zext;
337 break;
338 case InstArithmetic::Srem:
339 TargetHelper = Ctx->getConstantExternSym(H_srem_i32);
340 CastKind = InstCast::Sext;
341 break;
342 }
343 Operand *Src0 = Instr->getSrc(0);
344 Operand *Src1 = Instr->getSrc(1);
345 if (DestTy != IceType_i32) {
346 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0,
347 // we just insert a InstCast right before the call to the helper.
348 Variable *Src0_32 = Func->makeVariable(IceType_i32);
349 Context.insert(InstCast::create(Func, CastKind, Src0_32, Src0));
350 Src0 = Src0_32;
351
352 // For extending Src1, we will just insert an InstCast if Src1 is not a
353 // Constant. If it is, then we extend it here, and not during program
354 // runtime. This allows DivRemPreamble to optimize-out the div-by-0
355 // check.
356 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) {
357 const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24;
358 int32_t NewC = C->getValue();
359 if (CastKind == InstCast::Zext) {
360 NewC &= !(0x80000000 >> ShAmt);
Jim Stichnoth 2015/11/30 21:47:20 Did you mean "~" instead of "!" ? Also, what do y
John 2015/11/30 22:16:25 are you OK with 0x80000000l instead? I don't reall
Jim Stichnoth 2015/12/01 17:01:56 OK. I think at least the presence of a suffix hin
361 } else {
362 NewC = (NewC << ShAmt) >> ShAmt;
363 }
364 Src1 = Ctx->getConstantInt32(NewC);
365 } else {
366 Variable *Src1_32 = Func->makeVariable(IceType_i32);
367 Context.insert(InstCast::create(Func, CastKind, Src1_32, Src1));
368 Src1 = Src1_32;
369 }
370 }
371 assert(TargetHelper != nullptr);
372 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::DivRemPreamble;
373 constexpr SizeT MaxArgs = 2;
374 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
375 NoTailCall, IsTargetHelperCall);
376 assert(Src0->getType() == IceType_i32);
377 Call->addArg(Src0);
378 assert(Src1->getType() == IceType_i32);
379 Call->addArg(Src1);
380 Context.insert(Call);
381 Instr->setDeleted();
382 return;
383 }
384 case IceType_f64:
385 case IceType_f32: {
386 if (Op != InstArithmetic::Frem) {
387 return;
388 }
389 constexpr SizeT MaxArgs = 2;
390 Operand *TargetHelper = Ctx->getConstantExternSym(
391 DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64);
392 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
393 NoTailCall, IsTargetHelperCall);
394 Call->addArg(Instr->getSrc(0));
395 Call->addArg(Instr->getSrc(1));
396 Context.insert(Call);
397 Instr->setDeleted();
398 return;
399 }
400 }
401 llvm_unreachable("Control flow should never have reached here.");
Jim Stichnoth 2015/11/30 21:47:19 Except for vector instructions... How about makin
John 2015/11/30 22:16:25 Done.
Jim Stichnoth 2015/12/01 17:01:56 Thanks. I marked a few more cases that I think ou
402 }
403 case Inst::Cast: {
404 Variable *Dest = Instr->getDest();
405 Operand *Src0 = Instr->getSrc(0);
406 const Type DestTy = Dest->getType();
407 const InstCast::OpKind CastKind =
408 llvm::cast<InstCast>(Instr)->getCastKind();
409 switch (CastKind) {
410 default:
411 return;
412 case InstCast::Fptosi:
413 case InstCast::Fptoui: {
414 if (DestTy != IceType_i64) {
415 return;
416 }
417 const bool DestIsSigned = CastKind == InstCast::Fptosi;
418 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType());
419 Operand *TargetHelper = Ctx->getConstantExternSym(
420 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64)
421 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64));
422 static constexpr SizeT MaxArgs = 1;
423 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
424 NoTailCall, IsTargetHelperCall);
425 Call->addArg(Src0);
426 Context.insert(Call);
427 Instr->setDeleted();
428 return;
429 }
430 case InstCast::Sitofp:
431 case InstCast::Uitofp: {
432 if (Src0->getType() != IceType_i64) {
433 return;
434 }
435 const bool SourceIsSigned = CastKind == InstCast::Sitofp;
436 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
437 Operand *TargetHelper = Ctx->getConstantExternSym(
438 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32)
439 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64));
440 static constexpr SizeT MaxArgs = 1;
441 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
442 NoTailCall, IsTargetHelperCall);
443 Call->addArg(Src0);
444 Context.insert(Call);
445 Instr->setDeleted();
446 return;
447 }
448 }
449 llvm_unreachable("Control flow should never have reached here.");
450 }
451 case Inst::IntrinsicCall: {
452 Variable *Dest = Instr->getDest();
453 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr);
454 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID;
455 switch (ID) {
456 default:
457 return;
458 case Intrinsics::Ctpop: {
459 Operand *Src0 = IntrinsicCall->getArg(0);
460 Operand *TargetHelper = Ctx->getConstantExternSym(
461 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32
462 : H_call_ctpop_i64);
463 static constexpr SizeT MaxArgs = 1;
464 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
465 NoTailCall, IsTargetHelperCall);
466 Call->addArg(Src0);
467 Context.insert(Call);
468 Instr->setDeleted();
469 if (Src0->getType() == IceType_i64) {
470 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::Ctpop64Postamble;
471 }
472 return;
473 }
474 case Intrinsics::Longjmp: {
475 static constexpr SizeT MaxArgs = 2;
476 static constexpr Variable *NoDest = nullptr;
477 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp);
478 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
479 NoTailCall, IsTargetHelperCall);
480 Call->addArg(IntrinsicCall->getArg(0));
481 Call->addArg(IntrinsicCall->getArg(1));
482 Context.insert(Call);
483 Instr->setDeleted();
484 return;
485 }
486 case Intrinsics::Memcpy: {
487 // In the future, we could potentially emit an inline memcpy/memset, etc.
488 // for intrinsic calls w/ a known length.
489 static constexpr SizeT MaxArgs = 3;
490 static constexpr Variable *NoDest = nullptr;
491 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy);
492 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
493 NoTailCall, IsTargetHelperCall);
494 Call->addArg(IntrinsicCall->getArg(0));
495 Call->addArg(IntrinsicCall->getArg(1));
496 Call->addArg(IntrinsicCall->getArg(2));
497 Context.insert(Call);
498 Instr->setDeleted();
499 return;
500 }
501 case Intrinsics::Memmove: {
502 static constexpr SizeT MaxArgs = 3;
503 static constexpr Variable *NoDest = nullptr;
504 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove);
505 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
506 NoTailCall, IsTargetHelperCall);
507 Call->addArg(IntrinsicCall->getArg(0));
508 Call->addArg(IntrinsicCall->getArg(1));
509 Call->addArg(IntrinsicCall->getArg(2));
510 Context.insert(Call);
511 Instr->setDeleted();
512 return;
513 }
514 case Intrinsics::Memset: {
515 // The value operand needs to be extended to a stack slot size because the
516 // PNaCl ABI requires arguments to be at least 32 bits wide.
517 Operand *ValOp = IntrinsicCall->getArg(1);
518 assert(ValOp->getType() == IceType_i8);
519 Variable *ValExt = Func->makeVariable(stackSlotType());
520 Context.insert(InstCast::create(Func, InstCast::Zext, ValExt, ValOp));
521
522 // Technically, ARM has its own __aeabi_memset, but we can use plain
523 // memset too. The value and size argument need to be flipped if we ever
524 // decide to use __aeabi_memset.
525 static constexpr SizeT MaxArgs = 3;
526 static constexpr Variable *NoDest = nullptr;
527 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset);
528 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper,
529 NoTailCall, IsTargetHelperCall);
530 Call->addArg(IntrinsicCall->getArg(0));
531 Call->addArg(ValExt);
532 Call->addArg(IntrinsicCall->getArg(2));
533 Context.insert(Call);
534 Instr->setDeleted();
535 return;
536 }
537 case Intrinsics::NaClReadTP: {
538 if (Ctx->getFlags().getUseSandboxing()) {
539 UnimplementedError(Func->getContext()->getFlags());
540 return;
541 }
542 static constexpr SizeT MaxArgs = 0;
543 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp);
544 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
545 NoTailCall, IsTargetHelperCall);
546 Context.insert(Call);
547 Instr->setDeleted();
548 return;
549 }
550 case Intrinsics::Setjmp: {
551 static constexpr SizeT MaxArgs = 1;
552 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp);
553 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper,
554 NoTailCall, IsTargetHelperCall);
555 Call->addArg(IntrinsicCall->getArg(0));
556 Context.insert(Call);
557 Instr->setDeleted();
558 return;
559 }
560 }
561 llvm_unreachable("Control flow should never have reached here.");
562 }
563 }
564 }
565
268 void TargetARM32::findMaxStackOutArgsSize() { 566 void TargetARM32::findMaxStackOutArgsSize() {
269 // MinNeededOutArgsBytes should be updated if the Target ever creates a 567 // MinNeededOutArgsBytes should be updated if the Target ever creates a
270 // high-level InstCall that requires more stack bytes. 568 // high-level InstCall that requires more stack bytes.
271 constexpr size_t MinNeededOutArgsBytes = 0; 569 constexpr size_t MinNeededOutArgsBytes = 0;
272 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; 570 MaxOutArgsSizeBytes = MinNeededOutArgsBytes;
273 for (CfgNode *Node : Func->getNodes()) { 571 for (CfgNode *Node : Func->getNodes()) {
274 Context.init(Node); 572 Context.init(Node);
275 while (!Context.atEnd()) { 573 while (!Context.atEnd()) {
276 PostIncrLoweringContext PostIncrement(Context); 574 PostIncrLoweringContext PostIncrement(Context);
277 Inst *CurInstr = Context.getCur(); 575 Inst *CurInstr = Context.getCur();
(...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 } 1704 }
1407 } 1705 }
1408 InstARM32Label *Label = InstARM32Label::create(Func, this); 1706 InstARM32Label *Label = InstARM32Label::create(Func, this);
1409 _br(Label, CondARM32::NE); 1707 _br(Label, CondARM32::NE);
1410 _trap(); 1708 _trap();
1411 Context.insert(Label); 1709 Context.insert(Label);
1412 } 1710 }
1413 1711
1414 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, 1712 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R,
1415 Operand *Src1, ExtInstr ExtFunc, 1713 Operand *Src1, ExtInstr ExtFunc,
1416 DivInstr DivFunc, const char *DivHelperName, 1714 DivInstr DivFunc, bool IsRemainder) {
1417 bool IsRemainder) {
1418 div0Check(Dest->getType(), Src1, nullptr); 1715 div0Check(Dest->getType(), Src1, nullptr);
1419 Variable *Src1R = legalizeToReg(Src1); 1716 Variable *Src1R = legalizeToReg(Src1);
1420 Variable *T0R = Src0R; 1717 Variable *T0R = Src0R;
1421 Variable *T1R = Src1R; 1718 Variable *T1R = Src1R;
1422 if (Dest->getType() != IceType_i32) { 1719 if (Dest->getType() != IceType_i32) {
1423 T0R = makeReg(IceType_i32); 1720 T0R = makeReg(IceType_i32);
1424 (this->*ExtFunc)(T0R, Src0R, CondARM32::AL); 1721 (this->*ExtFunc)(T0R, Src0R, CondARM32::AL);
1425 T1R = makeReg(IceType_i32); 1722 T1R = makeReg(IceType_i32);
1426 (this->*ExtFunc)(T1R, Src1R, CondARM32::AL); 1723 (this->*ExtFunc)(T1R, Src1R, CondARM32::AL);
1427 } 1724 }
1428 if (hasCPUFeature(TargetARM32Features::HWDivArm)) { 1725 if (hasCPUFeature(TargetARM32Features::HWDivArm)) {
1429 (this->*DivFunc)(T, T0R, T1R, CondARM32::AL); 1726 (this->*DivFunc)(T, T0R, T1R, CondARM32::AL);
1430 if (IsRemainder) { 1727 if (IsRemainder) {
1431 Variable *T2 = makeReg(IceType_i32); 1728 Variable *T2 = makeReg(IceType_i32);
1432 _mls(T2, T, T1R, T0R); 1729 _mls(T2, T, T1R, T0R);
1433 T = T2; 1730 T = T2;
1434 } 1731 }
1435 _mov(Dest, T); 1732 _mov(Dest, T);
1436 } else { 1733 } else {
1437 constexpr SizeT MaxSrcs = 2; 1734 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 } 1735 }
1443 return;
1444 } 1736 }
1445 1737
1446 TargetARM32::SafeBoolChain 1738 TargetARM32::SafeBoolChain
1447 TargetARM32::lowerInt1Arithmetic(const InstArithmetic *Inst) { 1739 TargetARM32::lowerInt1Arithmetic(const InstArithmetic *Inst) {
1448 Variable *Dest = Inst->getDest(); 1740 Variable *Dest = Inst->getDest();
1449 assert(Dest->getType() == IceType_i1); 1741 assert(Dest->getType() == IceType_i1);
1450 1742
1451 // So folding didn't work for Inst. Not a problem: We just need to 1743 // 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 1744 // materialize the Sources, and perform the operation. We create regular
1453 // Variables (and not infinite-weight ones) because this call might recurse a 1745 // 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 } 1927 }
1636 1928
1637 Operand *invertedSrc1F(TargetARM32 *Target) const { 1929 Operand *invertedSrc1F(TargetARM32 *Target) const {
1638 return legalizeToRegOrFlex(Target, 1930 return legalizeToRegOrFlex(Target,
1639 Target->getCtx()->getConstantInt32( 1931 Target->getCtx()->getConstantInt32(
1640 ~static_cast<uint32_t>(getConstantValue()))); 1932 ~static_cast<uint32_t>(getConstantValue())));
1641 } 1933 }
1642 }; 1934 };
1643 } // end of anonymous namespace 1935 } // end of anonymous namespace
1644 1936
1937 void TargetARM32::DivRemPreamble(const InstCall *Instr) {
1938 Operand *Src1 = Instr->getArg(1);
1939
1940 switch (Src1->getType()) {
1941 default:
1942 llvm::report_fatal_error("Invalid type for idiv.");
1943 case IceType_i64: {
1944 if (auto *C = llvm::dyn_cast<ConstantInteger64>(Src1)) {
1945 if (C->getValue() == 0) {
1946 _trap();
1947 return;
1948 }
1949 }
1950 div0Check(IceType_i64, loOperand(Src1), hiOperand(Src1));
1951 return;
1952 }
1953 case IceType_i32: {
1954 // Src0 and Src1 have already been appropriately extended to an i32, so we
1955 // don't check for i8 and i16.
1956 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) {
1957 if (C->getValue() == 0) {
1958 _trap();
1959 return;
1960 }
1961 }
1962 div0Check(IceType_i32, Src1, nullptr);
1963 return;
1964 }
1965 }
1966 }
1967
1645 void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, 1968 void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op,
1646 Variable *Dest, Operand *Src0, 1969 Variable *Dest, Operand *Src0,
1647 Operand *Src1) { 1970 Operand *Src1) {
1648 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); 1971 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1));
1649 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); 1972 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1));
1650 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands()); 1973 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands());
1651 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand()); 1974 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand());
1652 1975
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)); 1976 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
1710 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); 1977 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
1711 Variable *T_Lo = makeReg(DestLo->getType()); 1978 Variable *T_Lo = makeReg(DestLo->getType());
1712 Variable *T_Hi = makeReg(DestHi->getType()); 1979 Variable *T_Hi = makeReg(DestHi->getType());
1713 1980
1714 switch (Op) { 1981 switch (Op) {
1715 case InstArithmetic::_num: 1982 case InstArithmetic::_num:
1716 llvm::report_fatal_error("Unknown arithmetic operator"); 1983 llvm::report_fatal_error("Unknown arithmetic operator");
1717 return; 1984 return;
1718 case InstArithmetic::Add: { 1985 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). 2490 // difficult to determine (constant may be moved to a register).
2224 // * Handle floating point arithmetic separately: they require Src1 to be 2491 // * Handle floating point arithmetic separately: they require Src1 to be
2225 // legalized to a register. 2492 // legalized to a register.
2226 switch (Inst->getOp()) { 2493 switch (Inst->getOp()) {
2227 default: 2494 default:
2228 break; 2495 break;
2229 case InstArithmetic::Udiv: { 2496 case InstArithmetic::Udiv: {
2230 constexpr bool NotRemainder = false; 2497 constexpr bool NotRemainder = false;
2231 Variable *Src0R = legalizeToReg(Src0); 2498 Variable *Src0R = legalizeToReg(Src0);
2232 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, 2499 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
2233 H_udiv_i32, NotRemainder); 2500 NotRemainder);
2234 return; 2501 return;
2235 } 2502 }
2236 case InstArithmetic::Sdiv: { 2503 case InstArithmetic::Sdiv: {
2237 constexpr bool NotRemainder = false; 2504 constexpr bool NotRemainder = false;
2238 Variable *Src0R = legalizeToReg(Src0); 2505 Variable *Src0R = legalizeToReg(Src0);
2239 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, 2506 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
2240 H_sdiv_i32, NotRemainder); 2507 NotRemainder);
2241 return; 2508 return;
2242 } 2509 }
2243 case InstArithmetic::Urem: { 2510 case InstArithmetic::Urem: {
2244 constexpr bool IsRemainder = true; 2511 constexpr bool IsRemainder = true;
2245 Variable *Src0R = legalizeToReg(Src0); 2512 Variable *Src0R = legalizeToReg(Src0);
2246 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, 2513 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
2247 H_urem_i32, IsRemainder); 2514 IsRemainder);
2248 return; 2515 return;
2249 } 2516 }
2250 case InstArithmetic::Srem: { 2517 case InstArithmetic::Srem: {
2251 constexpr bool IsRemainder = true; 2518 constexpr bool IsRemainder = true;
2252 Variable *Src0R = legalizeToReg(Src0); 2519 Variable *Src0R = legalizeToReg(Src0);
2253 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, 2520 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
2254 H_srem_i32, IsRemainder); 2521 IsRemainder);
2255 return; 2522 return;
2256 } 2523 }
2257 case InstArithmetic::Frem: { 2524 case InstArithmetic::Frem: {
2258 constexpr SizeT MaxSrcs = 2; 2525 if (!isScalarFloatingType(DestTy)) {
2259 Variable *Src0R = legalizeToReg(Src0); 2526 llvm::report_fatal_error("Unexpected type when lowering frem.");
2260 Type Ty = DestTy; 2527 }
2261 InstCall *Call = makeHelperCall( 2528 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 } 2529 }
2268 case InstArithmetic::Fadd: { 2530 case InstArithmetic::Fadd: {
2269 Variable *Src0R = legalizeToReg(Src0); 2531 Variable *Src0R = legalizeToReg(Src0);
2270 Variable *Src1R = legalizeToReg(Src1); 2532 Variable *Src1R = legalizeToReg(Src1);
2271 _vadd(T, Src0R, Src1R); 2533 _vadd(T, Src0R, Src1R);
2272 _mov(Dest, T); 2534 _mov(Dest, T);
2273 return; 2535 return;
2274 } 2536 }
2275 case InstArithmetic::Fsub: { 2537 case InstArithmetic::Fsub: {
2276 Variable *Src0R = legalizeToReg(Src0); 2538 Variable *Src0R = legalizeToReg(Src0);
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
2675 case CondARM32::kNone: 2937 case CondARM32::kNone:
2676 _br(TargetFalse); 2938 _br(TargetFalse);
2677 break; 2939 break;
2678 case CondARM32::AL: 2940 case CondARM32::AL:
2679 _br(TargetTrue); 2941 _br(TargetTrue);
2680 break; 2942 break;
2681 } 2943 }
2682 } 2944 }
2683 2945
2684 void TargetARM32::lowerCall(const InstCall *Instr) { 2946 void TargetARM32::lowerCall(const InstCall *Instr) {
2947 Operand *CallTarget = Instr->getCallTarget();
2948 if (Instr->isTargetHelperCall()) {
2949 auto TargetHelperPreamble = ARM32HelpersPreamble.find(CallTarget);
2950 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) {
2951 (this->*TargetHelperPreamble->second)(Instr);
2952 }
2953 }
2685 MaybeLeafFunc = false; 2954 MaybeLeafFunc = false;
2686 NeedsStackAlignment = true; 2955 NeedsStackAlignment = true;
2687 2956
2688 // Assign arguments to registers and stack. Also reserve stack. 2957 // Assign arguments to registers and stack. Also reserve stack.
2689 TargetARM32::CallingConv CC; 2958 TargetARM32::CallingConv CC;
2690 // Pair of Arg Operand -> GPR number assignments. 2959 // Pair of Arg Operand -> GPR number assignments.
2691 llvm::SmallVector<std::pair<Operand *, int32_t>, 2960 llvm::SmallVector<std::pair<Operand *, int32_t>,
2692 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; 2961 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs;
2693 llvm::SmallVector<std::pair<Operand *, int32_t>, 2962 llvm::SmallVector<std::pair<Operand *, int32_t>,
2694 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; 2963 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2797 case IceType_v8i1: 3066 case IceType_v8i1:
2798 case IceType_v16i1: 3067 case IceType_v16i1:
2799 case IceType_v16i8: 3068 case IceType_v16i8:
2800 case IceType_v8i16: 3069 case IceType_v8i16:
2801 case IceType_v4i32: 3070 case IceType_v4i32:
2802 case IceType_v4f32: 3071 case IceType_v4f32:
2803 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); 3072 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0);
2804 break; 3073 break;
2805 } 3074 }
2806 } 3075 }
2807 Operand *CallTarget = Instr->getCallTarget();
2808 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = 3076 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing =
2809 // Ctx->getFlags().getUseSandboxing(); 3077 // Ctx->getFlags().getUseSandboxing();
2810 3078
2811 // Allow ConstantRelocatable to be left alone as a direct call, but force 3079 // 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 3080 // other constants like ConstantInteger32 to be in a register and make it an
2813 // indirect call. 3081 // indirect call.
2814 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { 3082 if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
2815 CallTarget = legalize(CallTarget, Legal_Reg); 3083 CallTarget = legalize(CallTarget, Legal_Reg);
2816 } 3084 }
2817 3085
(...skipping 16 matching lines...) Expand all
2834 3102
2835 // Insert a register-kill pseudo instruction. 3103 // Insert a register-kill pseudo instruction.
2836 Context.insert(InstFakeKill::create(Func, NewCall)); 3104 Context.insert(InstFakeKill::create(Func, NewCall));
2837 3105
2838 // Generate a FakeUse to keep the call live if necessary. 3106 // Generate a FakeUse to keep the call live if necessary.
2839 if (Instr->hasSideEffects() && ReturnReg) { 3107 if (Instr->hasSideEffects() && ReturnReg) {
2840 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); 3108 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg);
2841 Context.insert(FakeUse); 3109 Context.insert(FakeUse);
2842 } 3110 }
2843 3111
2844 if (!Dest) 3112 if (Dest != nullptr) {
2845 return; 3113 // Assign the result of the call to Dest.
3114 if (ReturnReg != nullptr) {
3115 if (ReturnRegHi) {
3116 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest);
3117 Variable *DestLo = Dest64On32->getLo();
3118 Variable *DestHi = Dest64On32->getHi();
3119 _mov(DestLo, ReturnReg);
3120 _mov(DestHi, ReturnRegHi);
3121 } else {
3122 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) {
3123 _mov(Dest, ReturnReg);
3124 } else {
3125 assert(isIntegerType(Dest->getType()) &&
3126 typeWidthInBytes(Dest->getType()) <= 4);
3127 _mov(Dest, ReturnReg);
3128 }
3129 }
3130 }
3131 }
2846 3132
2847 // Assign the result of the call to Dest. 3133 if (Instr->isTargetHelperCall()) {
2848 if (ReturnReg) { 3134 auto TargetHelpersPostamble = ARM32HelpersPostamble.find(CallTarget);
2849 if (ReturnRegHi) { 3135 if (TargetHelpersPostamble != ARM32HelpersPostamble.end()) {
2850 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); 3136 (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 } 3137 }
2864 } 3138 }
2865 } 3139 }
2866 3140
2867 namespace { 3141 namespace {
2868 void configureBitcastTemporary(Variable64On32 *Var) { 3142 void configureBitcastTemporary(Variable64On32 *Var) {
2869 Var->setMustNotHaveReg(); 3143 Var->setMustNotHaveReg();
2870 Var->getHi()->setMustHaveReg(); 3144 Var->getHi()->setMustHaveReg();
2871 Var->getLo()->setMustHaveReg(); 3145 Var->getLo()->setMustHaveReg();
2872 } 3146 }
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
3029 Variable *T = makeReg(Dest->getType()); 3303 Variable *T = makeReg(Dest->getType());
3030 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); 3304 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
3031 _mov(Dest, T); 3305 _mov(Dest, T);
3032 UnimplementedError(Func->getContext()->getFlags()); 3306 UnimplementedError(Func->getContext()->getFlags());
3033 break; 3307 break;
3034 } 3308 }
3035 3309
3036 const bool DestIsSigned = CastKind == InstCast::Fptosi; 3310 const bool DestIsSigned = CastKind == InstCast::Fptosi;
3037 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); 3311 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType());
3038 if (llvm::isa<Variable64On32>(Dest)) { 3312 if (llvm::isa<Variable64On32>(Dest)) {
3039 const char *HelperName = 3313 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 } 3314 }
3048 // fptosi: 3315 // fptosi:
3049 // t1.fp = vcvt src0.fp 3316 // t1.fp = vcvt src0.fp
3050 // t2.i32 = vmov t1.fp 3317 // t2.i32 = vmov t1.fp
3051 // dest.int = conv t2.i32 @ Truncates the result if needed. 3318 // dest.int = conv t2.i32 @ Truncates the result if needed.
3052 // fptoui: 3319 // fptoui:
3053 // t1.fp = vcvt src0.fp 3320 // t1.fp = vcvt src0.fp
3054 // t2.u32 = vmov t1.fp 3321 // t2.u32 = vmov t1.fp
3055 // dest.uint = conv t2.u32 @ Truncates the result if needed. 3322 // dest.uint = conv t2.u32 @ Truncates the result if needed.
3056 Variable *Src0R = legalizeToReg(Src0); 3323 Variable *Src0R = legalizeToReg(Src0);
(...skipping 17 matching lines...) Expand all
3074 if (isVectorType(Dest->getType())) { 3341 if (isVectorType(Dest->getType())) {
3075 Variable *T = makeReg(Dest->getType()); 3342 Variable *T = makeReg(Dest->getType());
3076 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); 3343 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
3077 _mov(Dest, T); 3344 _mov(Dest, T);
3078 UnimplementedError(Func->getContext()->getFlags()); 3345 UnimplementedError(Func->getContext()->getFlags());
3079 break; 3346 break;
3080 } 3347 }
3081 const bool SourceIsSigned = CastKind == InstCast::Sitofp; 3348 const bool SourceIsSigned = CastKind == InstCast::Sitofp;
3082 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); 3349 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
3083 if (Src0->getType() == IceType_i64) { 3350 if (Src0->getType() == IceType_i64) {
3084 const char *HelperName = 3351 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 } 3352 }
3093 // sitofp: 3353 // sitofp:
3094 // t1.i32 = sext src.int @ sign-extends src0 if needed. 3354 // t1.i32 = sext src.int @ sign-extends src0 if needed.
3095 // t2.fp32 = vmov t1.i32 3355 // t2.fp32 = vmov t1.i32
3096 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 3356 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64
3097 // uitofp: 3357 // uitofp:
3098 // t1.i32 = zext src.int @ zero-extends src0 if needed. 3358 // t1.i32 = zext src.int @ zero-extends src0 if needed.
3099 // t2.fp32 = vmov t1.i32 3359 // t2.fp32 = vmov t1.i32
3100 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 3360 // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64
3101 if (Src0->getType() != IceType_i32) { 3361 if (Src0->getType() != IceType_i32) {
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
3767 } 4027 }
3768 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg)); 4028 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg));
3769 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { 4029 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
3770 Context.insert(InstFakeUse::create(Func, Dest64->getLo())); 4030 Context.insert(InstFakeUse::create(Func, Dest64->getLo()));
3771 Context.insert(InstFakeUse::create(Func, Dest64->getHi())); 4031 Context.insert(InstFakeUse::create(Func, Dest64->getHi()));
3772 } else { 4032 } else {
3773 Context.insert(InstFakeUse::create(Func, Dest)); 4033 Context.insert(InstFakeUse::create(Func, Dest));
3774 } 4034 }
3775 } 4035 }
3776 4036
4037 void TargetARM32::Ctpop64Postamble(const InstCall *Instr) {
4038 Operand *Arg0 = Instr->getArg(0);
4039 if (isInt32Asserting32Or64(Arg0->getType())) {
4040 return;
4041 }
4042 // The popcount helpers always return 32-bit values, while the intrinsic's
4043 // signature matches some 64-bit platform's native instructions and expect to
4044 // fill a 64-bit reg. Thus, clear the upper bits of the dest just in case the
4045 // user doesn't do that in the IR or doesn't toss the bits via truncate.
4046 Variable *DestHi = llvm::cast<Variable>(hiOperand(Instr->getDest()));
4047 Variable *T = makeReg(IceType_i32);
4048 Operand *_0 =
4049 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
4050 _mov(T, _0);
4051 _mov(DestHi, T);
4052 }
4053
3777 void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { 4054 void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
3778 Variable *Dest = Instr->getDest(); 4055 Variable *Dest = Instr->getDest();
3779 Type DestTy = (Dest != nullptr) ? Dest->getType() : IceType_void; 4056 Type DestTy = (Dest != nullptr) ? Dest->getType() : IceType_void;
3780 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID; 4057 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID;
3781 switch (ID) { 4058 switch (ID) {
3782 case Intrinsics::AtomicFence: 4059 case Intrinsics::AtomicFence:
3783 case Intrinsics::AtomicFenceAll: 4060 case Intrinsics::AtomicFenceAll:
3784 assert(Dest == nullptr); 4061 assert(Dest == nullptr);
3785 _dmb(); 4062 _dmb();
3786 return; 4063 return;
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
4083 _rev(T, ValR); 4360 _rev(T, ValR);
4084 if (Val->getType() == IceType_i16) { 4361 if (Val->getType() == IceType_i16) {
4085 Operand *_16 = shAmtImm(16); 4362 Operand *_16 = shAmtImm(16);
4086 _lsr(T, T, _16); 4363 _lsr(T, T, _16);
4087 } 4364 }
4088 _mov(Dest, T); 4365 _mov(Dest, T);
4089 } 4366 }
4090 return; 4367 return;
4091 } 4368 }
4092 case Intrinsics::Ctpop: { 4369 case Intrinsics::Ctpop: {
4093 Operand *Val = Instr->getArg(0); 4370 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 } 4371 }
4114 case Intrinsics::Ctlz: { 4372 case Intrinsics::Ctlz: {
4115 // The "is zero undef" parameter is ignored and we always return a 4373 // The "is zero undef" parameter is ignored and we always return a
4116 // well-defined value. 4374 // well-defined value.
4117 Operand *Val = Instr->getArg(0); 4375 Operand *Val = Instr->getArg(0);
4118 Variable *ValLoR; 4376 Variable *ValLoR;
4119 Variable *ValHiR = nullptr; 4377 Variable *ValHiR = nullptr;
4120 if (Val->getType() == IceType_i64) { 4378 if (Val->getType() == IceType_i64) {
4121 Val = legalizeUndef(Val); 4379 Val = legalizeUndef(Val);
4122 ValLoR = legalizeToReg(loOperand(Val)); 4380 ValLoR = legalizeToReg(loOperand(Val));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4159 Context.insert(InstFakeDef::create(Func, T)); 4417 Context.insert(InstFakeDef::create(Func, T));
4160 _mov(Dest, T); 4418 _mov(Dest, T);
4161 UnimplementedError(Func->getContext()->getFlags()); 4419 UnimplementedError(Func->getContext()->getFlags());
4162 return; 4420 return;
4163 } 4421 }
4164 _vabs(T, legalizeToReg(Instr->getArg(0))); 4422 _vabs(T, legalizeToReg(Instr->getArg(0)));
4165 _mov(Dest, T); 4423 _mov(Dest, T);
4166 return; 4424 return;
4167 } 4425 }
4168 case Intrinsics::Longjmp: { 4426 case Intrinsics::Longjmp: {
4169 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); 4427 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 } 4428 }
4175 case Intrinsics::Memcpy: { 4429 case Intrinsics::Memcpy: {
4176 // In the future, we could potentially emit an inline memcpy/memset, etc. 4430 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 } 4431 }
4185 case Intrinsics::Memmove: { 4432 case Intrinsics::Memmove: {
4186 InstCall *Call = makeHelperCall(H_call_memmove, nullptr, 3); 4433 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 } 4434 }
4193 case Intrinsics::Memset: { 4435 case Intrinsics::Memset: {
4194 // The value operand needs to be extended to a stack slot size because the 4436 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 } 4437 }
4210 case Intrinsics::NaClReadTP: { 4438 case Intrinsics::NaClReadTP: {
4211 if (Ctx->getFlags().getUseSandboxing()) { 4439 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 } 4440 }
4219 case Intrinsics::Setjmp: { 4441 case Intrinsics::Setjmp: {
4220 InstCall *Call = makeHelperCall(H_call_setjmp, Dest, 1); 4442 llvm::report_fatal_error("setjmp should have been prelowered.");
4221 Call->addArg(Instr->getArg(0));
4222 lowerCall(Call);
4223 return;
4224 } 4443 }
4225 case Intrinsics::Sqrt: { 4444 case Intrinsics::Sqrt: {
4226 Variable *Src = legalizeToReg(Instr->getArg(0)); 4445 Variable *Src = legalizeToReg(Instr->getArg(0));
4227 Variable *T = makeReg(Dest->getType()); 4446 Variable *T = makeReg(Dest->getType());
4228 _vsqrt(T, Src); 4447 _vsqrt(T, Src);
4229 _mov(Dest, T); 4448 _mov(Dest, T);
4230 return; 4449 return;
4231 } 4450 }
4232 case Intrinsics::Stacksave: { 4451 case Intrinsics::Stacksave: {
4233 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); 4452 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
(...skipping 1496 matching lines...) Expand 10 before | Expand all | Expand 10 after
5730 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 5949 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
5731 // However, for compatibility with current NaCl LLVM, don't claim that. 5950 // 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"; 5951 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
5733 } 5952 }
5734 5953
5735 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; 5954 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM];
5736 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; 5955 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
5737 llvm::SmallBitVector TargetARM32::ScratchRegs; 5956 llvm::SmallBitVector TargetARM32::ScratchRegs;
5738 5957
5739 } // end of namespace Ice 5958 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698