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

Side by Side Diff: src/IceInstARM32.cpp

Issue 1438773004: Subzero. ARM32. Improve constant lowering. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceTargetLoweringARM32.h » ('j') | 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/IceInstARM32.cpp - ARM32 instruction implementation ----===// 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===//
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 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot); 277 uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot);
278 if (Imm8 <= 0xFF) { 278 if (Imm8 <= 0xFF) {
279 *RotateAmt = Rot; 279 *RotateAmt = Rot;
280 *Immed_8 = Imm8; 280 *Immed_8 = Imm8;
281 return true; 281 return true;
282 } 282 }
283 } 283 }
284 return false; 284 return false;
285 } 285 }
286 286
287 OperandARM32FlexFpImm::OperandARM32FlexFpImm(Cfg * /*Func*/, Type Ty,
288 uint32_t ModifiedImm)
289 : OperandARM32Flex(kFlexFpImm, Ty), ModifiedImm(ModifiedImm) {}
290
291 bool OperandARM32FlexFpImm::canHoldImm(Operand *C, uint32_t *ModifiedImm) {
292 switch (C->getType()) {
293 default:
294 llvm::report_fatal_error("Unhandled fp constant type.");
295 case IceType_f32: {
296 // We violate llvm naming conventions a bit here so that the constants are
297 // named after the bit fields they represent. See "A7.5.1 Operation of
298 // modified immediate constants, Floating-point" in the ARM ARM.
299 static constexpr uint32_t a = 0x80000000u;
300 static constexpr uint32_t B = 0x40000000;
301 static constexpr uint32_t bbbbb = 0x3E000000;
302 static constexpr uint32_t cdefgh = 0x01F80000;
303 static constexpr uint32_t AllowedBits = a | B | bbbbb | cdefgh;
304 static_assert(AllowedBits == 0xFFF80000u,
305 "Invalid mask for f32 modified immediates.");
306 const float F32 = llvm::cast<ConstantFloat>(C)->getValue();
307 const uint32_t I32 = *reinterpret_cast<const uint32_t *>(&F32);
308 if (I32 & ~AllowedBits) {
309 // constant has disallowed bits.
310 return false;
311 }
312
313 if ((I32 & bbbbb) != bbbbb && (I32 & bbbbb)) {
314 // not all bbbbb bits are 0 or 1.
315 return false;
316 }
317
318 if (((I32 & B) != 0) == ((I32 & bbbbb) != 0)) {
319 // B ^ b = 0;
320 return false;
321 }
322
323 *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) | ((I32 & bbbbb) ? 0x40 : 0x00) |
324 ((I32 & cdefgh) >> 19);
325 return true;
326 }
327 case IceType_f64: {
328 static constexpr uint32_t a = 0x80000000u;
329 static constexpr uint32_t B = 0x40000000;
330 static constexpr uint32_t bbbbbbbb = 0x3FC00000;
331 static constexpr uint32_t cdefgh = 0x003F0000;
332 static constexpr uint32_t AllowedBits = a | B | bbbbbbbb | cdefgh;
333 static_assert(AllowedBits == 0xFFFF0000u,
334 "Invalid mask for f64 modified immediates.");
335 const double F64 = llvm::cast<ConstantDouble>(C)->getValue();
336 const uint64_t I64 = *reinterpret_cast<const uint64_t *>(&F64);
337 if (I64 & 0xFFFFFFFFu) {
338 // constant has disallowed bits.
339 return false;
340 }
341 const uint32_t I32 = I64 >> 32;
342
343 if (I32 & ~AllowedBits) {
344 // constant has disallowed bits.
345 return false;
346 }
347
348 if ((I32 & bbbbbbbb) != bbbbbbbb && (I32 & bbbbbbbb)) {
349 // not all bbbbb bits are 0 or 1.
350 return false;
351 }
352
353 if (((I32 & B) != 0) == ((I32 & bbbbbbbb) != 0)) {
354 // B ^ b = 0;
355 return false;
356 }
357
358 *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) |
359 ((I32 & bbbbbbbb) ? 0x40 : 0x00) | ((I32 & cdefgh) >> 16);
360 return true;
361 }
362 }
363 }
364
365 OperandARM32FlexFpZero::OperandARM32FlexFpZero(Cfg * /*Func*/, Type Ty)
366 : OperandARM32Flex(kFlexFpZero, Ty) {}
367
287 OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, 368 OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg,
288 ShiftKind ShiftOp, Operand *ShiftAmt) 369 ShiftKind ShiftOp, Operand *ShiftAmt)
289 : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp), 370 : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp),
290 ShiftAmt(ShiftAmt) { 371 ShiftAmt(ShiftAmt) {
291 NumVars = 1; 372 NumVars = 1;
292 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt); 373 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt);
293 if (ShiftVar) 374 if (ShiftVar)
294 ++NumVars; 375 ++NumVars;
295 Vars = Func->allocateArrayOf<Variable *>(NumVars); 376 Vars = Func->allocateArrayOf<Variable *>(NumVars);
296 Vars[0] = Reg; 377 Vars[0] = Reg;
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 } 631 }
551 632
552 template <> void InstARM32Tst::emitIAS(const Cfg *Func) const { 633 template <> void InstARM32Tst::emitIAS(const Cfg *Func) const {
553 assert(getSrcSize() == 2); 634 assert(getSrcSize() == 2);
554 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); 635 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
555 Asm->tst(getSrc(0), getSrc(1), getPredicate()); 636 Asm->tst(getSrc(0), getSrc(1), getPredicate());
556 if (Asm->needsTextFixup()) 637 if (Asm->needsTextFixup())
557 emitUsingTextFixup(Func); 638 emitUsingTextFixup(Func);
558 } 639 }
559 640
560 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, 641 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
561 CondARM32::Cond Predicate) 642 CondARM32::Cond Predicate)
562 : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { 643 : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) {
644 HasSideEffects = true;
563 addSource(Src0); 645 addSource(Src0);
564 addSource(Src1); 646 addSource(Src1);
565 } 647 }
566 648
567 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate) 649 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate)
568 : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {} 650 : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {
651 HasSideEffects = true;
652 }
569 653
570 InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src, 654 InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
571 CondARM32::Cond Predicate) 655 CondARM32::Cond Predicate)
572 : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) { 656 : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) {
573 addSource(Src); 657 addSource(Src);
574 } 658 }
575 659
576 InstARM32Dmb::InstARM32Dmb(Cfg *Func) 660 InstARM32Dmb::InstARM32Dmb(Cfg *Func)
577 : InstARM32Pred(Func, InstARM32::Dmb, 0, nullptr, CondARM32::AL) {} 661 : InstARM32Pred(Func, InstARM32::Dmb, 0, nullptr, CondARM32::AL) {}
578 662
(...skipping 19 matching lines...) Expand all
598 template <> const char *InstARM32Add::Opcode = "add"; 682 template <> const char *InstARM32Add::Opcode = "add";
599 template <> const char *InstARM32And::Opcode = "and"; 683 template <> const char *InstARM32And::Opcode = "and";
600 template <> const char *InstARM32Asr::Opcode = "asr"; 684 template <> const char *InstARM32Asr::Opcode = "asr";
601 template <> const char *InstARM32Bic::Opcode = "bic"; 685 template <> const char *InstARM32Bic::Opcode = "bic";
602 template <> const char *InstARM32Eor::Opcode = "eor"; 686 template <> const char *InstARM32Eor::Opcode = "eor";
603 template <> const char *InstARM32Lsl::Opcode = "lsl"; 687 template <> const char *InstARM32Lsl::Opcode = "lsl";
604 template <> const char *InstARM32Lsr::Opcode = "lsr"; 688 template <> const char *InstARM32Lsr::Opcode = "lsr";
605 template <> const char *InstARM32Mul::Opcode = "mul"; 689 template <> const char *InstARM32Mul::Opcode = "mul";
606 template <> const char *InstARM32Orr::Opcode = "orr"; 690 template <> const char *InstARM32Orr::Opcode = "orr";
607 template <> const char *InstARM32Rsb::Opcode = "rsb"; 691 template <> const char *InstARM32Rsb::Opcode = "rsb";
692 template <> const char *InstARM32Rsc::Opcode = "rsc";
608 template <> const char *InstARM32Sbc::Opcode = "sbc"; 693 template <> const char *InstARM32Sbc::Opcode = "sbc";
609 template <> const char *InstARM32Sdiv::Opcode = "sdiv"; 694 template <> const char *InstARM32Sdiv::Opcode = "sdiv";
610 template <> const char *InstARM32Sub::Opcode = "sub"; 695 template <> const char *InstARM32Sub::Opcode = "sub";
611 template <> const char *InstARM32Udiv::Opcode = "udiv"; 696 template <> const char *InstARM32Udiv::Opcode = "udiv";
612 // FP 697 // FP
613 template <> const char *InstARM32Vadd::Opcode = "vadd"; 698 template <> const char *InstARM32Vadd::Opcode = "vadd";
614 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; 699 template <> const char *InstARM32Vdiv::Opcode = "vdiv";
615 template <> const char *InstARM32Vmul::Opcode = "vmul"; 700 template <> const char *InstARM32Vmul::Opcode = "vmul";
701 template <> const char *InstARM32Veor::Opcode = "veor";
616 template <> const char *InstARM32Vsub::Opcode = "vsub"; 702 template <> const char *InstARM32Vsub::Opcode = "vsub";
617 // Four-addr ops 703 // Four-addr ops
618 template <> const char *InstARM32Mla::Opcode = "mla"; 704 template <> const char *InstARM32Mla::Opcode = "mla";
619 template <> const char *InstARM32Mls::Opcode = "mls"; 705 template <> const char *InstARM32Mls::Opcode = "mls";
620 // Cmp-like ops 706 // Cmp-like ops
707 template <> const char *InstARM32Cmn::Opcode = "cmn";
621 template <> const char *InstARM32Cmp::Opcode = "cmp"; 708 template <> const char *InstARM32Cmp::Opcode = "cmp";
622 template <> const char *InstARM32Tst::Opcode = "tst"; 709 template <> const char *InstARM32Tst::Opcode = "tst";
623 710
624 void InstARM32::dump(const Cfg *Func) const { 711 void InstARM32::dump(const Cfg *Func) const {
625 if (!BuildDefs::dump()) 712 if (!BuildDefs::dump())
626 return; 713 return;
627 Ostream &Str = Func->getContext()->getStrDump(); 714 Ostream &Str = Func->getContext()->getStrDump();
628 Str << "[ARM32] "; 715 Str << "[ARM32] ";
629 Inst::dump(Func); 716 Inst::dump(Func);
630 } 717 }
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
1694 } 1781 }
1695 1782
1696 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const { 1783 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
1697 if (!BuildDefs::dump()) 1784 if (!BuildDefs::dump())
1698 return; 1785 return;
1699 uint32_t Imm = getImm(); 1786 uint32_t Imm = getImm();
1700 uint32_t RotateAmt = getRotateAmt(); 1787 uint32_t RotateAmt = getRotateAmt();
1701 Str << "#(" << Imm << " ror 2*" << RotateAmt << ")"; 1788 Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
1702 } 1789 }
1703 1790
1791 namespace {
1792 static constexpr uint32_t a = 0x80;
1793 static constexpr uint32_t b = 0x40;
1794 static constexpr uint32_t cdefgh = 0x3F;
1795 static constexpr uint32_t AllowedBits = a | b | cdefgh;
1796 static_assert(AllowedBits == 0xFF,
1797 "Invalid mask for f32/f64 constant rematerialization.");
1798
1799 // There's no loss in always returning the modified immediate as float.
1800 // TODO(jpp): returning a double causes problems when outputting the constants
1801 // for filetype=asm. Why?
1802 float materializeFloatImmediate(uint32_t ModifiedImm) {
1803 const uint32_t Ret = ((ModifiedImm & a) ? 0x80000000 : 0) |
1804 ((ModifiedImm & b) ? 0x3E000000 : 0x40000000) |
1805 ((ModifiedImm & cdefgh) << 19);
1806 return *reinterpret_cast<const float *>(&Ret);
1807 }
1808
1809 } // end of anonymous namespace
1810
1811 void OperandARM32FlexFpImm::emit(const Cfg *Func) const {
1812 if (!BuildDefs::dump())
1813 return;
1814 Ostream &Str = Func->getContext()->getStrEmit();
1815 switch (Ty) {
1816 default:
1817 llvm::report_fatal_error("Invalid flex fp imm type.");
1818 case IceType_f64:
1819 case IceType_f32:
1820 Str << "#" << materializeFloatImmediate(ModifiedImm)
1821 << " @ Modified: " << ModifiedImm;
1822 break;
1823 }
1824 }
1825
1826 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const {
1827 if (!BuildDefs::dump())
1828 return;
1829 Str << "#" << materializeFloatImmediate(ModifiedImm)
1830 << InstARM32::getVecWidthString(Ty);
1831 }
1832
1833 void OperandARM32FlexFpZero::emit(const Cfg *Func) const {
1834 if (!BuildDefs::dump())
1835 return;
1836 Ostream &Str = Func->getContext()->getStrEmit();
1837 switch (Ty) {
1838 default:
1839 llvm::report_fatal_error("Invalid flex fp imm type.");
1840 case IceType_f64:
1841 case IceType_f32:
1842 Str << "#0.0";
1843 }
1844 }
1845
1846 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const {
1847 if (!BuildDefs::dump())
1848 return;
1849 Str << "#0.0" << InstARM32::getVecWidthString(Ty);
1850 }
1851
1704 void OperandARM32FlexReg::emit(const Cfg *Func) const { 1852 void OperandARM32FlexReg::emit(const Cfg *Func) const {
1705 if (!BuildDefs::dump()) 1853 if (!BuildDefs::dump())
1706 return; 1854 return;
1707 Ostream &Str = Func->getContext()->getStrEmit(); 1855 Ostream &Str = Func->getContext()->getStrEmit();
1708 getReg()->emit(Func); 1856 getReg()->emit(Func);
1709 if (getShiftOp() != kNoShift) { 1857 if (getShiftOp() != kNoShift) {
1710 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; 1858 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
1711 getShiftAmt()->emit(Func); 1859 getShiftAmt()->emit(Func);
1712 } 1860 }
1713 } 1861 }
(...skipping 20 matching lines...) Expand all
1734 template class InstARM32ThreeAddrGPR<InstARM32::Add>; 1882 template class InstARM32ThreeAddrGPR<InstARM32::Add>;
1735 template class InstARM32ThreeAddrGPR<InstARM32::And>; 1883 template class InstARM32ThreeAddrGPR<InstARM32::And>;
1736 template class InstARM32ThreeAddrGPR<InstARM32::Asr>; 1884 template class InstARM32ThreeAddrGPR<InstARM32::Asr>;
1737 template class InstARM32ThreeAddrGPR<InstARM32::Bic>; 1885 template class InstARM32ThreeAddrGPR<InstARM32::Bic>;
1738 template class InstARM32ThreeAddrGPR<InstARM32::Eor>; 1886 template class InstARM32ThreeAddrGPR<InstARM32::Eor>;
1739 template class InstARM32ThreeAddrGPR<InstARM32::Lsl>; 1887 template class InstARM32ThreeAddrGPR<InstARM32::Lsl>;
1740 template class InstARM32ThreeAddrGPR<InstARM32::Lsr>; 1888 template class InstARM32ThreeAddrGPR<InstARM32::Lsr>;
1741 template class InstARM32ThreeAddrGPR<InstARM32::Mul>; 1889 template class InstARM32ThreeAddrGPR<InstARM32::Mul>;
1742 template class InstARM32ThreeAddrGPR<InstARM32::Orr>; 1890 template class InstARM32ThreeAddrGPR<InstARM32::Orr>;
1743 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>; 1891 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>;
1892 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>;
1744 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>; 1893 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>;
1745 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; 1894 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
1746 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; 1895 template class InstARM32ThreeAddrGPR<InstARM32::Sub>;
1747 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; 1896 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>;
1748 1897
1749 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; 1898 template class InstARM32ThreeAddrFP<InstARM32::Vadd>;
1750 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; 1899 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>;
1751 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; 1900 template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
1901 template class InstARM32ThreeAddrFP<InstARM32::Veor>;
1752 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; 1902 template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
1753 1903
1754 template class InstARM32LoadBase<InstARM32::Ldr>; 1904 template class InstARM32LoadBase<InstARM32::Ldr>;
1755 template class InstARM32LoadBase<InstARM32::Ldrex>; 1905 template class InstARM32LoadBase<InstARM32::Ldrex>;
1756 1906
1757 template class InstARM32TwoAddrGPR<InstARM32::Movt>; 1907 template class InstARM32TwoAddrGPR<InstARM32::Movt>;
1758 1908
1759 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; 1909 template class InstARM32UnaryopGPR<InstARM32::Movw, false>;
1760 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; 1910 template class InstARM32UnaryopGPR<InstARM32::Clz, false>;
1761 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; 1911 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>;
1762 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; 1912 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>;
1763 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; 1913 template class InstARM32UnaryopGPR<InstARM32::Rev, false>;
1764 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; 1914 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>;
1765 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; 1915 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>;
1766 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; 1916 template class InstARM32UnaryopFP<InstARM32::Vsqrt>;
1767 1917
1768 template class InstARM32FourAddrGPR<InstARM32::Mla>; 1918 template class InstARM32FourAddrGPR<InstARM32::Mla>;
1769 template class InstARM32FourAddrGPR<InstARM32::Mls>; 1919 template class InstARM32FourAddrGPR<InstARM32::Mls>;
1770 1920
1921 template class InstARM32CmpLike<InstARM32::Cmn>;
1771 template class InstARM32CmpLike<InstARM32::Cmp>; 1922 template class InstARM32CmpLike<InstARM32::Cmp>;
1772 template class InstARM32CmpLike<InstARM32::Tst>; 1923 template class InstARM32CmpLike<InstARM32::Tst>;
1773 1924
1774 } // end of namespace Ice 1925 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceTargetLoweringARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698