NeonEmitter.cpp revision 51cc0172a173599b769968696e20638754d1dcd6
151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//                     The LLVM Compiler Infrastructure
451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// This file is distributed under the University of Illinois Open Source
651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// License. See LICENSE.TXT for details.
751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// This tablegen backend is responsible for emitting arm_neon.h, which includes
1151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// a declaration and definition of each function specified by the ARM NEON
1251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// compiler interface.  See ARM document DUI0348B.
1351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Each NEON instruction is implemented in terms of 1 or more functions which
1551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// are suffixed with the element type of the input vectors.  Functions may be
1651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// implemented in terms of generic vector operations such as +, *, -, etc. or
1751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// by calling a __builtin_-prefixed function which will be handled by clang's
1851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// CodeGen library.
1951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
2051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Additional validation code can be generated by this file when runHeader() is
2151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// called, rather than the normal run() entry point.  A complete set of tests
2251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// for Neon intrinsics can be generated by calling the runTests() entry point.
2351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
2451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
2551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/DenseMap.h"
2751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallString.h"
2851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallVector.h"
2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/StringExtras.h"
303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/StringMap.h"
317530c034c0c71a64c5a9173206d9742ae847af8bDavid Blaikie#include "llvm/Support/ErrorHandling.h"
323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Error.h"
333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Record.h"
343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h"
3551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <string>
3651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm;
3751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum OpKind {
393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNone,
403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpUnavailable,
413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAdd,
423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAddl,
43097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAddlHi,
443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAddw,
45097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAddwHi,
463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSub,
473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSubl,
48097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpSublHi,
493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSubw,
50097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpSubwHi,
513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMul,
523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMla,
533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlal,
54097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpMullHi,
55097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpMlalHi,
563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMls,
573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlsl,
58097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpMlslHi,
593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMulN,
603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlaN,
613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlsN,
623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlalN,
633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlslN,
643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMulLane,
650aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpMulXLane,
663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMullLane,
670aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpMullHiLane,
683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlaLane,
693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlsLane,
703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlalLane,
710aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpMlalHiLane,
723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlslLane,
730aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpMlslHiLane,
743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMullLane,
750aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpQDMullHiLane,
763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMlalLane,
770aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpQDMlalHiLane,
783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMlslLane,
790aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpQDMlslHiLane,
803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMulhLane,
813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQRDMulhLane,
820aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpFMSLane,
830aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  OpFMSLaneQ,
84bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  OpTrn1,
85bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  OpZip1,
86bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  OpUzp1,
87bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  OpTrn2,
88bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  OpZip2,
89bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  OpUzp2,
903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpEq,
913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpGe,
923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLe,
933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpGt,
943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLt,
953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNeg,
963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNot,
973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAnd,
983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpOr,
993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpXor,
1003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAndNot,
1013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpOrNot,
1023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpCast,
1033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpConcat,
1043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpDup,
1053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpDupLane,
1063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpHi,
1073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLo,
1083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSelect,
1093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev16,
1103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev32,
1113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev64,
1128137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  OpXtnHi,
1138137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  OpSqxtunHi,
1148137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  OpQxtnHi,
1158137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  OpFcvtnHi,
1168137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  OpFcvtlHi,
1178137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  OpFcvtxnHi,
1183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpReinterpret,
119097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAddhnHi,
120097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpRAddhnHi,
121097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpSubhnHi,
122097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpRSubhnHi,
1233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAbdl,
124097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAbdlHi,
1253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAba,
126b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OpAbal,
127097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAbalHi,
128097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpQDMullHi,
129097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpQDMlalHi,
130097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpQDMlslHi,
131912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  OpDiv,
132912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  OpLongHi,
133912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  OpNarrowHi,
1342102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin  OpMovlHi,
13522229d6822324a42913d25f256045dbf348a53e9Kevin Qin  OpCopyLane,
13622229d6822324a42913d25f256045dbf348a53e9Kevin Qin  OpCopyQLane,
13751cc0172a173599b769968696e20638754d1dcd6Ana Pazos  OpCopyLaneQ,
13851cc0172a173599b769968696e20638754d1dcd6Ana Pazos  OpScalarMulLane,
13951cc0172a173599b769968696e20638754d1dcd6Ana Pazos  OpScalarMulLaneQ,
14051cc0172a173599b769968696e20638754d1dcd6Ana Pazos  OpScalarMulXLane,
14151cc0172a173599b769968696e20638754d1dcd6Ana Pazos  OpScalarMulXLaneQ,
14251cc0172a173599b769968696e20638754d1dcd6Ana Pazos  OpScalarVMulXLane,
14351cc0172a173599b769968696e20638754d1dcd6Ana Pazos  OpScalarVMulXLaneQ
1443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum ClassKind {
1473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassNone,
1483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassI,           // generic integer instruction, e.g., "i8" suffix
1493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassS,           // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
1503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassW,           // width-specific instruction, e.g., "8" suffix
15121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassB,           // bitcast arguments with enum argument to specify type
15221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassL,           // Logical instructions which are op instructions
15321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // but we need to not emit any suffix for in our
15421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // tests.
15521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassNoTest       // Instructions which we do not test since they are
15621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // not TRUE instructions.
1573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// NeonTypeFlags - Flags to identify the types for overloaded Neon
1603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// builtins.  These must be kept in sync with the flags in
1613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// include/clang/Basic/TargetBuiltins.h.
1623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonTypeFlags {
1643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum {
1653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    EltTypeMask = 0xf,
1663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    UnsignedFlag = 0x10,
1673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    QuadFlag = 0x20
1683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t Flags;
1703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
1723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum EltType {
1733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int8,
1743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int16,
1753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int32,
1763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int64,
1773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly8,
1783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly16,
179624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin    Poly64,
1803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Float16,
181b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Float32,
182b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Float64
1833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(unsigned F) : Flags(F) {}
1863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
1873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsUnsigned)
1883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= UnsignedFlag;
1893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsQuad)
1903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= QuadFlag;
1913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
1923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t getFlags() const { return Flags; }
1943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
1963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonEmitter {
1993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  RecordKeeper &Records;
2003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  StringMap<OpKind> OpMap;
2013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  DenseMap<Record*, ClassKind> ClassMap;
2023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
2043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(RecordKeeper &R) : Records(R) {
2053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NONE"]  = OpNone;
2063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_UNAVAILABLE"] = OpUnavailable;
2073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADD"]   = OpAdd;
2083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDL"]  = OpAddl;
209097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ADDLHi"] = OpAddlHi;
2103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDW"]  = OpAddw;
211097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ADDWHi"] = OpAddwHi;
2123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUB"]   = OpSub;
2133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBL"]  = OpSubl;
214097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_SUBLHi"] = OpSublHi;
2153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBW"]  = OpSubw;
216097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_SUBWHi"] = OpSubwHi;
2173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL"]   = OpMul;
2183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA"]   = OpMla;
2193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL"]  = OpMlal;
220097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_MULLHi"]  = OpMullHi;
221097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_MLALHi"]  = OpMlalHi;
2223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS"]   = OpMls;
2233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL"]  = OpMlsl;
224097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_MLSLHi"] = OpMlslHi;
2253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_N"] = OpMulN;
2263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_N"] = OpMlaN;
2273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_N"] = OpMlsN;
2283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_N"] = OpMlalN;
2293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_N"] = OpMlslN;
2303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_LN"]= OpMulLane;
2310aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MULX_LN"]= OpMulXLane;
2323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MULL_LN"] = OpMullLane;
2330aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MULLHi_LN"] = OpMullHiLane;
2343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_LN"]= OpMlaLane;
2353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_LN"]= OpMlsLane;
2363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_LN"] = OpMlalLane;
2370aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MLALHi_LN"] = OpMlalHiLane;
2383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_LN"] = OpMlslLane;
2390aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MLSLHi_LN"] = OpMlslHiLane;
2403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULL_LN"] = OpQDMullLane;
2410aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_QDMULLHi_LN"] = OpQDMullHiLane;
2423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
2430aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_QDMLALHi_LN"] = OpQDMlalHiLane;
2443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
2450aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_QDMLSLHi_LN"] = OpQDMlslHiLane;
2463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
2473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
2480aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_FMS_LN"] = OpFMSLane;
2490aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_FMS_LNQ"] = OpFMSLaneQ;
250bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    OpMap["OP_TRN1"]  = OpTrn1;
251bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    OpMap["OP_ZIP1"]  = OpZip1;
252bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    OpMap["OP_UZP1"]  = OpUzp1;
253bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    OpMap["OP_TRN2"]  = OpTrn2;
254bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    OpMap["OP_ZIP2"]  = OpZip2;
255bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    OpMap["OP_UZP2"]  = OpUzp2;
2563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_EQ"]    = OpEq;
2573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GE"]    = OpGe;
2583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LE"]    = OpLe;
2593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GT"]    = OpGt;
2603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LT"]    = OpLt;
2613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NEG"]   = OpNeg;
2623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NOT"]   = OpNot;
2633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_AND"]   = OpAnd;
2643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_OR"]    = OpOr;
2653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_XOR"]   = OpXor;
2663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ANDN"]  = OpAndNot;
2673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ORN"]   = OpOrNot;
2683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CAST"]  = OpCast;
2693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CONC"]  = OpConcat;
2703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_HI"]    = OpHi;
2713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LO"]    = OpLo;
2723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP"]   = OpDup;
2733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP_LN"] = OpDupLane;
2743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SEL"]   = OpSelect;
2753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV16"] = OpRev16;
2763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV32"] = OpRev32;
2773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV64"] = OpRev64;
2788137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    OpMap["OP_XTN"] = OpXtnHi;
2798137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    OpMap["OP_SQXTUN"] = OpSqxtunHi;
2808137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    OpMap["OP_QXTN"] = OpQxtnHi;
2818137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    OpMap["OP_VCVT_NA_HI"] = OpFcvtnHi;
2828137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    OpMap["OP_VCVT_EX_HI"] = OpFcvtlHi;
2838137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    OpMap["OP_VCVTX_HI"] = OpFcvtxnHi;
2843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REINT"] = OpReinterpret;
285097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ADDHNHi"] = OpAddhnHi;
286097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_RADDHNHi"] = OpRAddhnHi;
287097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_SUBHNHi"] = OpSubhnHi;
288097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_RSUBHNHi"] = OpRSubhnHi;
2893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABDL"]  = OpAbdl;
290097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ABDLHi"] = OpAbdlHi;
2913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABA"]   = OpAba;
2923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABAL"]  = OpAbal;
293097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ABALHi"] = OpAbalHi;
294097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_QDMULLHi"] = OpQDMullHi;
295097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_QDMLALHi"] = OpQDMlalHi;
296097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_QDMLSLHi"] = OpQDMlslHi;
297b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OpMap["OP_DIV"] = OpDiv;
298912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    OpMap["OP_LONG_HI"] = OpLongHi;
299912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    OpMap["OP_NARROW_HI"] = OpNarrowHi;
300912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    OpMap["OP_MOVL_HI"] = OpMovlHi;
30122229d6822324a42913d25f256045dbf348a53e9Kevin Qin    OpMap["OP_COPY_LN"] = OpCopyLane;
30222229d6822324a42913d25f256045dbf348a53e9Kevin Qin    OpMap["OP_COPYQ_LN"] = OpCopyQLane;
30322229d6822324a42913d25f256045dbf348a53e9Kevin Qin    OpMap["OP_COPY_LNQ"] = OpCopyLaneQ;
30451cc0172a173599b769968696e20638754d1dcd6Ana Pazos    OpMap["OP_SCALAR_MUL_LN"]= OpScalarMulLane;
30551cc0172a173599b769968696e20638754d1dcd6Ana Pazos    OpMap["OP_SCALAR_MUL_LNQ"]= OpScalarMulLaneQ;
30651cc0172a173599b769968696e20638754d1dcd6Ana Pazos    OpMap["OP_SCALAR_MULX_LN"]= OpScalarMulXLane;
30751cc0172a173599b769968696e20638754d1dcd6Ana Pazos    OpMap["OP_SCALAR_MULX_LNQ"]= OpScalarMulXLaneQ;
30851cc0172a173599b769968696e20638754d1dcd6Ana Pazos    OpMap["OP_SCALAR_VMULX_LN"]= OpScalarVMulXLane;
30951cc0172a173599b769968696e20638754d1dcd6Ana Pazos    OpMap["OP_SCALAR_VMULX_LNQ"]= OpScalarVMulXLaneQ;
3103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
3113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *SI = R.getClass("SInst");
3123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *II = R.getClass("IInst");
3133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *WI = R.getClass("WInst");
31421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *SOpI = R.getClass("SOpInst");
31521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *IOpI = R.getClass("IOpInst");
31621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *WOpI = R.getClass("WOpInst");
31721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *LOpI = R.getClass("LOpInst");
31821e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *NoTestOpI = R.getClass("NoTestOpInst");
31921e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman
3203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[SI] = ClassS;
3213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[II] = ClassI;
3223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[WI] = ClassW;
32321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[SOpI] = ClassS;
32421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[IOpI] = ClassI;
32521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[WOpI] = ClassW;
32621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[LOpI] = ClassL;
32721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[NoTestOpI] = ClassNoTest;
3283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
3293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
3303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // run - Emit arm_neon.h.inc
3313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void run(raw_ostream &o);
3323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
3333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runHeader - Emit all the __builtin prototypes used in arm_neon.h
3343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runHeader(raw_ostream &o);
3353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
3363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runTests - Emit tests for all the Neon intrinsics.
3373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runTests(raw_ostream &o);
3383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
3393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenprivate:
340b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void emitIntrinsic(raw_ostream &OS, Record *R,
341b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                     StringMap<ClassKind> &EmittedMap);
342b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genBuiltinsDef(raw_ostream &OS, StringMap<ClassKind> &A64IntrinsicMap,
343b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                      bool isA64GenBuiltinDef);
344b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genOverloadTypeCheckCode(raw_ostream &OS,
345b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                StringMap<ClassKind> &A64IntrinsicMap,
346b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                bool isA64TypeCheck);
347b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genIntrinsicRangeCheckCode(raw_ostream &OS,
348b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                  StringMap<ClassKind> &A64IntrinsicMap,
349b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                  bool isA64RangeCheck);
350b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genTargetTest(raw_ostream &OS, StringMap<OpKind> &EmittedMap,
351b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                     bool isA64TestGen);
3523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
3533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
3543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
35551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
35651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// which each StringRef representing a single type declared in the string.
35751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
35851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2xfloat and 4xfloat respectively.
35951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic void ParseTypes(Record *r, std::string &s,
36051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                       SmallVectorImpl<StringRef> &TV) {
36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const char *data = s.data();
36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  int len = 0;
36351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
36451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
36512cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U'
366944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin                         || data[len] == 'H' || data[len] == 'S')
36751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
36851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
36951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (data[len]) {
37051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'c':
37151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 's':
37251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'i':
37351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'l':
37451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'h':
37551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'f':
376b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      case 'd':
37751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
37851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      default:
37938859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger        PrintFatalError(r->getLoc(),
38051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      "Unexpected letter: " + std::string(data + len, 1));
38151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    TV.push_back(StringRef(data, len + 1));
38351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    data += len + 1;
38451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    len = -1;
38551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
38651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
38751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
38851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Widen - Convert a type code into the next wider type.  char -> short,
38951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// short -> int, etc.
39051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Widen(const char t) {
39151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
39251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
39351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
39451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
39551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
39651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
39751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'l';
39851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
39951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'f';
4008137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    case 'f':
4018137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin      return 'd';
40238859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    default:
40338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type in widen!");
40451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
40551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
40651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
40751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Narrow - Convert a type code into the next smaller type.  short -> char,
40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// float -> half float, etc.
40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Narrow(const char t) {
41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
41251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'c';
41351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
41451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
41551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
41751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
41851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'h';
4198137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    case 'd':
4208137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin      return 'f';
42138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    default:
42238859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type in narrow!");
42351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
42451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
42551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
426097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string GetNarrowTypestr(StringRef ty)
427097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu{
428097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
429097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  for (size_t i = 0, end = ty.size(); i < end; i++) {
430097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    switch (ty[i]) {
431097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      case 's':
432097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += 'c';
433097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
434097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      case 'i':
435097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += 's';
436097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
437097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      case 'l':
438097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += 'i';
439097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
440097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      default:
441097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += ty[i];
442097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
443097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    }
444097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
445097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
446097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
447097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
448097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
44951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// For a particular StringRef, return the base type code, and whether it has
45051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// the quad-vector, polynomial, or unsigned modifiers set.
45151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
45251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned off = 0;
453944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  // ignore scalar.
454944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if (ty[off] == 'S') {
455944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    ++off;
456944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
45751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember quad.
45812cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu  if (ty[off] == 'Q' || ty[off] == 'H') {
45951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    quad = true;
46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
46351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember poly.
46451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'P') {
46551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = true;
46651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
46751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
46851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
46951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember unsigned.
47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'U') {
47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
47251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
47351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
47451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return ty[off];
47751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
47851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ModType - Transform a type code and its modifiers based on a mod code. The
48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// mod code definitions may be found at the top of arm_neon.td.
48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ModType(const char mod, char type, bool &quad, bool &poly,
48251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
48351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (mod) {
48451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 't':
48551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (poly) {
48651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        poly = false;
48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        usgn = true;
48851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
48951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
490564020954e9eb01293d90802c89a02f87301e095Chad Rosier    case 'b':
491564020954e9eb01293d90802c89a02f87301e095Chad Rosier      scal = true;
49251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'u':
49351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
49451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
49551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
49651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
497b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (type == 'd')
498b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        type = 'l';
49951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
5009473c1945f9f1dfa143e172622f16e4264e2628bChad Rosier    case '$':
5019473c1945f9f1dfa143e172622f16e4264e2628bChad Rosier      scal = true;
50251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'x':
50351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
50451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
50551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
507912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      if (type == 'd')
508912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        type = 'l';
50951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
5106d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier    case 'o':
5116d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      scal = true;
5126d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      type = 'd';
5136d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      usgn = false;
5146d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      break;
5156d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier    case 'y':
5166d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      scal = true;
51751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
51851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
51951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = true;
52051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'f';
52151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
52251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
52351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'g':
52451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = false;
52551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
5262e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    case 'B':
5272e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    case 'C':
5282e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    case 'D':
5290aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    case 'j':
5300aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      quad = true;
5310aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      break;
53251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'w':
53351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
53451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
53551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
53651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'n':
53751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
53851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
53951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
54051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'i';
54151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
54251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
54351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
54451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'l';
54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
5484553a858e46299955333babfa052a512682869fdChad Rosier    case 'z':
5494553a858e46299955333babfa052a512682869fdChad Rosier      type = Narrow(type);
5504553a858e46299955333babfa052a512682869fdChad Rosier      scal = true;
5514553a858e46299955333babfa052a512682869fdChad Rosier      break;
5520391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu    case 'r':
5530391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu      type = Widen(type);
5544553a858e46299955333babfa052a512682869fdChad Rosier      scal = true;
5554553a858e46299955333babfa052a512682869fdChad Rosier      break;
55651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
55751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'a':
55851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
55951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
56051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'k':
56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
56251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
56351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      cnst = true;
56551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'p':
56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      pntr = true;
56751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
56851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
56951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = false;
57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
574097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    case 'q':
575097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      type = Narrow(type);
576097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      quad = true;
577097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      break;
57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'e':
57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
582912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    case 'm':
583912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      type = Narrow(type);
584912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      quad = false;
585912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      break;
58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return type;
59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
59151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
5922e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liustatic bool IsMultiVecProto(const char p) {
5932e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  return ((p >= '2' && p <= '4') || (p >= 'B' && p <= 'D'));
5942e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu}
5952e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu
59651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// TypeString - for a modifier and type, generate the name of the typedef for
59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// that type.  QUc -> uint8x8_t.
59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string TypeString(const char mod, StringRef typestr) {
59951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
60051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
60151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
60251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
60351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
60451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
60551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
60651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
60751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "void";
60851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
60951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "int";
61051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
61251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
61351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
61551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallString<128> s;
61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (usgn)
62051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back('u');
62151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
62251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
62351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
62451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly8" : "int8";
62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x16" : "x8";
62851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
62951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
63051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly16" : "int16";
63151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
63651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int32";
63751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
63851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
63951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
64051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
64151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
642624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin      s += (poly && !usgn)? "poly64" : "int64";
64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
64551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x2" : "x1";
64651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
64751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
64851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float16";
64951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
65051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
65151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
65251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
65351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
65451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float32";
65551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
65651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
65751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
65851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
659b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case 'd':
660b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      s += "float64";
661b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (scal)
662b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        break;
663b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      s += quad ? "x2" : "x1";
664b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
665b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
66651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
66738859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
66851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
66951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
6702e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  if (mod == '2' || mod == 'B')
67151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x2";
6722e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  if (mod == '3' || mod == 'C')
67351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x3";
6742e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  if (mod == '4' || mod == 'D')
67551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x4";
67651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
67751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Append _t, finishing the type string typedef type.
67851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "_t";
67951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (cnst)
68151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " const";
68251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr)
68451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " *";
68551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s.str();
68751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
68851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinTypeString - for a modifier and type, generate the clang
69051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinsARM.def prototype code for the function.  See the top of clang's
69151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Builtins.def for a description of the type strings.
69251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string BuiltinTypeString(const char mod, StringRef typestr,
69351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                     ClassKind ck, bool ret) {
69451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
69551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
69651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
69751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
69851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
69951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
70051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
70151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
70251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "v"; // void
70351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
70451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "i"; // int
70551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
70651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
70751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
70851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
70951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
71051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
71151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
71251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // All pointers are void* pointers.  Change type to 'v' now.
71351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr) {
71451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = false;
71551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = false;
71651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 'v';
71751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
71851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Treat half-float ('h') types as unsigned short ('s') types.
71951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (type == 'h') {
72051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 's';
72151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
72251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
7230aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) &&
7240aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu                         scal && type != 'f' && type != 'd');
72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
72651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (scal) {
72751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallString<128> s;
72851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
72951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (usgn)
73051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('U');
73151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else if (type == 'c')
73251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('S'); // make chars explicitly signed
73351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
73451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (type == 'l') // 64-bit long
73551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "LLi";
73651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
73751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(type);
73851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
73951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (cnst)
74051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('C');
74151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (pntr)
74251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('*');
74351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return s.str();
74451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
74551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
74651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Since the return value must be one type, return a vector type of the
74751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // appropriate width which we will bitcast.  An exception is made for
74851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
74951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // fashion, storing them to a pointer arg.
75051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ret) {
7512e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    if (IsMultiVecProto(mod))
75251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return "vv*"; // void result with void* first argument
75351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod == 'f' || (ck != ClassB && type == 'f'))
75451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4f" : "V2f";
7550aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    if (ck != ClassB && type == 'd')
7560aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      return quad ? "V2d" : "V1d";
75751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 's')
75851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V8s" : "V4s";
75951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'i')
76051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4i" : "V2i";
76151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'l')
76251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V2LLi" : "V1LLi";
76351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
76451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16Sc" : "V8Sc";
76551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
76651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
76751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Non-return array types are passed as individual vectors.
7682e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  if (mod == '2' || mod == 'B')
76951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
7702e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  if (mod == '3' || mod == 'C')
77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
7722e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  if (mod == '4' || mod == 'D')
77351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
77451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
77551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'f' || (ck != ClassB && type == 'f'))
77651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4f" : "V2f";
7770aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  if (ck != ClassB && type == 'd')
7780aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    return quad ? "V2d" : "V1d";
77951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 's')
78051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V8s" : "V4s";
78151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'i')
78251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4i" : "V2i";
78351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'l')
78451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V2LLi" : "V1LLi";
78551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
78651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return quad ? "V16Sc" : "V8Sc";
78751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
78851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
789fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// InstructionTypeCode - Computes the ARM argument character code and
790fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// quad status for a specific type string and ClassKind.
791fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic void InstructionTypeCode(const StringRef &typeStr,
792fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                const ClassKind ck,
793fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                bool &quad,
794fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                std::string &typeCode) {
79551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
797fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  char type = ClassifyType(typeStr, quad, poly, usgn);
79851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
79951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c':
80151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
802fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = poly ? "p8" : usgn ? "u8" : "s8"; break;
803fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i8"; break;
804fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "8"; break;
80551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
80651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
80751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
80851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's':
80951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
810fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = poly ? "p16" : usgn ? "u16" : "s16"; break;
811fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i16"; break;
812fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "16"; break;
81351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
81451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
81551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
81651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i':
81751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
818fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = usgn ? "u32" : "s32"; break;
819fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i32"; break;
820fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "32"; break;
82151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
82251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
82351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
82451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l':
82551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
826624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin    case ClassS: typeCode = poly ? "p64" : usgn ? "u64" : "s64"; break;
827fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i64"; break;
828fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "64"; break;
82951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
83051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
83151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h':
83351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
83451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
835fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "f16"; break;
836fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "16"; break;
83751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
83851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
83951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
84051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f':
84151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
84251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
843fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "f32"; break;
844fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "32"; break;
84551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
84651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
84751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
848b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  case 'd':
849b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    switch (ck) {
850b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case ClassS:
851b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case ClassI:
852b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      typeCode += "f64";
853b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
854b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case ClassW:
855b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      PrintFatalError("unhandled type!");
856b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    default:
857b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
858b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
859b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    break;
86051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
86138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unhandled type!");
86251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
863fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman}
864fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
865944f09ff9b33637465906e1aeadcfa405d66331dKevin Qinstatic char Insert_BHSD_Suffix(StringRef typestr){
866944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  unsigned off = 0;
867944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if(typestr[off++] == 'S'){
868944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    while(typestr[off] == 'Q' || typestr[off] == 'H'||
869944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin          typestr[off] == 'P' || typestr[off] == 'U')
870944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ++off;
871944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    switch (typestr[off]){
872944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    default  : break;
873944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'c' : return 'b';
874944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 's' : return 'h';
875944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'i' :
876944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'f' : return 's';
877944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'l' :
878944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'd' : return 'd';
879944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    }
880944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
881944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  return 0;
882944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin}
883944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin
884fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// MangleName - Append a type or width suffix to a base neon function name,
88512cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu/// and insert a 'q' in the appropriate location if type string starts with 'Q'.
88612cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu/// E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
887944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin/// Insert proper 'b' 'h' 's' 'd' if prefix 'S' is used.
888fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic std::string MangleName(const std::string &name, StringRef typestr,
889fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                              ClassKind ck) {
8908137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  if (name == "vcvt_f32_f16" || name == "vcvt_f32_f64")
891fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    return name;
892fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
893fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  bool quad = false;
894fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  std::string typeCode = "";
895fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
896fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  InstructionTypeCode(typestr, ck, quad, typeCode);
897fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
898fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  std::string s = name;
899fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
900fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  if (typeCode.size() > 0) {
901fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    s += "_" + typeCode;
902fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  }
903fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
90451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
90551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "_v";
90651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
90751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Insert a 'q' before the first '_' character so that it ends up before
90851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // _lane or _n on vector-scalar operations.
909944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if (typestr.find("Q") != StringRef::npos) {
91012cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu      size_t pos = s.find('_');
91112cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu      s = s.insert(pos, "q");
91251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
913944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  char ins = Insert_BHSD_Suffix(typestr);
914944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if(ins){
915944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    size_t pos = s.find('_');
916944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    s = s.insert(pos, &ins, 1);
917944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
918c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
91951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
92051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
92151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
922c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void PreprocessInstruction(const StringRef &Name,
923c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const std::string &InstName,
924c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  std::string &Prefix,
925c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasNPostfix,
926c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasLanePostfix,
927c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasDupPostfix,
928c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &IsSpecialVCvt,
929c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  size_t &TBNumber) {
930c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // All of our instruction name fields from arm_neon.td are of the form
931c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  //   <instructionname>_...
932c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Thus we grab our instruction name via computation of said Prefix.
933c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const size_t PrefixEnd = Name.find_first_of('_');
934c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If InstName is passed in, we use that instead of our name Prefix.
935c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Prefix = InstName.size() == 0? Name.slice(0, PrefixEnd).str() : InstName;
936c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
937c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef Postfix = Name.slice(PrefixEnd, Name.size());
938c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
939c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasNPostfix = Postfix.count("_n");
940c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasLanePostfix = Postfix.count("_lane");
941c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasDupPostfix = Postfix.count("_dup");
942c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  IsSpecialVCvt = Postfix.size() != 0 && Name.count("vcvt");
943c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
944c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (InstName.compare("vtbl") == 0 ||
945c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      InstName.compare("vtbx") == 0) {
946c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a vtblN/vtbxN instruction, use the instruction's ASCII
947c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // encoding to get its true value.
948c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    TBNumber = Name[Name.size()-1] - 48;
949c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
950c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
951c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
952c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatternsForLoadStores - Given a bunch of data we have
953c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern for a Load Or Store
954c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void
955c327f8705ecb8753555822d479f899bd2234386dMichael GottesmanGenerateRegisterCheckPatternForLoadStores(const StringRef &NameRef,
956c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const std::string& OutTypeCode,
957c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &IsQuad,
958c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &HasDupPostfix,
959c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &HasLanePostfix,
960c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const size_t Count,
961c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          std::string &RegisterSuffix) {
962c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsLDSTOne = NameRef.count("vld1") || NameRef.count("vst1");
963c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If N == 3 || N == 4 and we are dealing with a quad instruction, Clang
964c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // will output a series of v{ld,st}1s, so we have to handle it specially.
965c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((Count == 3 || Count == 4) && IsQuad) {
966c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "{";
967c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < Count; i++) {
968c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}";
969c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasDupPostfix) {
970c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[]";
971c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
972c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
973c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[{{[0-9]+}}]";
974c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
975c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (i < Count-1) {
976c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", ";
977c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
978c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
979c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "}";
980c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else {
981c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
982c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Handle normal loads and stores.
983c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "{";
984c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < Count; i++) {
985c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}";
986c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasDupPostfix) {
987c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[]";
988c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
989c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
990c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[{{[0-9]+}}]";
991c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
992c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (IsQuad && !HasLanePostfix) {
993c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", d{{[0-9]+}}";
994c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        if (HasDupPostfix) {
995c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          RegisterSuffix += "[]";
996c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        }
997c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
998c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (i < Count-1) {
999c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", ";
1000c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1001c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1002c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "}, [r{{[0-9]+}}";
1003c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1004c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // We only include the alignment hint if we have a vld1.*64 or
1005c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // a dup/lane instruction.
1006c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (IsLDSTOne) {
1007c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if ((HasLanePostfix || HasDupPostfix) && OutTypeCode != "8") {
1008410c3f73cb0c78f72335dc712a9d887d77b8e7ceMichael Gottesman        RegisterSuffix += ":" + OutTypeCode;
1009c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1010c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1011c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1012c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "]";
1013c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1014c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1015c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1016c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool HasNPostfixAndScalarArgs(const StringRef &NameRef,
1017c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                     const bool &HasNPostfix) {
1018c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (NameRef.count("vmla") ||
1019c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlal") ||
1020c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlsl") ||
1021c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmull") ||
1022c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlal") ||
1023c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlsl") ||
1024c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmulh") ||
1025c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmull") ||
1026c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqrdmulh")) && HasNPostfix;
1027c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1028c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1029c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsFiveOperandLaneAccumulator(const StringRef &NameRef,
1030c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasLanePostfix) {
1031c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (NameRef.count("vmla") ||
1032c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmls") ||
1033c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlal") ||
1034c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlsl") ||
1035c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          (NameRef.count("vmul") && NameRef.size() == 3)||
1036c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlal") ||
1037c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlsl") ||
1038c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmulh") ||
1039c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqrdmulh")) && HasLanePostfix;
1040c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1041c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1042c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsSpecialLaneMultiply(const StringRef &NameRef,
1043c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const bool &HasLanePostfix,
1044c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const bool &IsQuad) {
1045c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVMulOrMulh = (NameRef.count("vmul") || NameRef.count("mulh"))
1046c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               && IsQuad;
1047c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVMull = NameRef.count("mull") && !IsQuad;
1048c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (IsVMulOrMulh || IsVMull) && HasLanePostfix;
1049c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1050c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1051c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void NormalizeProtoForRegisterPatternCreation(const std::string &Name,
1052c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const std::string &Proto,
1053c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasNPostfix,
1054c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &IsQuad,
1055c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasLanePostfix,
1056c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasDupPostfix,
1057c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     std::string &NormedProto) {
1058c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Handle generic case.
1059c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
1060c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  for (size_t i = 0, end = Proto.size(); i < end; i++) {
1061c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    switch (Proto[i]) {
1062c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'u':
1063c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'f':
1064c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'd':
1065c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 's':
1066c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'x':
1067c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 't':
1068c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'n':
1069c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += IsQuad? 'q' : 'd';
1070c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1071c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'w':
1072c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'k':
1073c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += 'q';
1074c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1075c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'g':
10760aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    case 'j':
1077c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'h':
1078c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'e':
1079c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += 'd';
1080c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1081c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'i':
1082c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += HasLanePostfix? 'a' : 'i';
1083c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1084c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'a':
1085c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
1086c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += 'a';
1087c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else if (HasNPostfixAndScalarArgs(NameRef, HasNPostfix)) {
1088c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += IsQuad? 'q' : 'd';
1089c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else {
1090c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += 'i';
1091c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1092c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1093c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1094c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1095c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1096c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Handle Special Cases.
1097c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsNotVExt = !NameRef.count("vext");
1098c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVPADAL = NameRef.count("vpadal");
1099c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool Is5OpLaneAccum = IsFiveOperandLaneAccumulator(NameRef,
1100c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                           HasLanePostfix);
1101c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsSpecialLaneMul = IsSpecialLaneMultiply(NameRef, HasLanePostfix,
1102c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                      IsQuad);
1103c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1104c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (IsSpecialLaneMul) {
1105c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If
1106c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto[2] = NormedProto[3];
1107c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto.erase(3);
1108c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (NormedProto.size() == 4 &&
1109c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman             NormedProto[0] == NormedProto[1] &&
1110c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman             IsNotVExt) {
1111c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If NormedProto.size() == 4 and the first two proto characters are the
1112c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // same, ignore the first.
1113c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = NormedProto.substr(1, 3);
1114c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (Is5OpLaneAccum) {
1115c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a 5 op lane accumulator operation, we take characters 1,2,4
1116c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string tmp = NormedProto.substr(1,2);
1117c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[4];
1118c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = tmp;
1119c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (IsVPADAL) {
1120c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have VPADAL, ignore the first character.
1121c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = NormedProto.substr(0, 2);
1122c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (NameRef.count("vdup") && NormedProto.size() > 2) {
1123c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If our instruction is a dup instruction, keep only the first and
1124c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // last characters.
1125c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string tmp = "";
1126c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[0];
1127c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[NormedProto.size()-1];
1128c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = tmp;
1129c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1130c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1131c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1132c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatterns - Given a bunch of data we have
1133c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern to check that an
1134c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// instruction's arguments are correct.
1135c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateRegisterCheckPattern(const std::string &Name,
1136c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const std::string &Proto,
1137c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const std::string &OutTypeCode,
1138c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasNPostfix,
1139c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &IsQuad,
1140c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasLanePostfix,
1141c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasDupPostfix,
1142c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const size_t &TBNumber,
1143c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         std::string &RegisterSuffix) {
1144c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1145c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  RegisterSuffix = "";
1146c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1147c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
1148c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef ProtoRef(Proto);
1149c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1150c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((NameRef.count("vdup") || NameRef.count("vmov")) && HasNPostfix) {
1151c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1152c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1153c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1154c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsLoadStore = NameRef.count("vld") || NameRef.count("vst");
1155c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsTBXOrTBL = NameRef.count("vtbl") || NameRef.count("vtbx");
1156c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1157c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (IsLoadStore) {
1158c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Grab N value from  v{ld,st}N using its ascii representation.
1159c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    const size_t Count = NameRef[3] - 48;
1160c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1161c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    GenerateRegisterCheckPatternForLoadStores(NameRef, OutTypeCode, IsQuad,
1162c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                              HasDupPostfix, HasLanePostfix,
1163c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                              Count, RegisterSuffix);
1164c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (IsTBXOrTBL) {
1165c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "d{{[0-9]+}}, {";
1166c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < TBNumber-1; i++) {
1167c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}, ";
1168c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1169c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "d{{[0-9]+}}}, d{{[0-9]+}}";
1170c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else {
1171c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Handle a normal instruction.
1172c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (NameRef.count("vget") || NameRef.count("vset"))
1173c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1174c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1175c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // We first normalize our proto, since we only need to emit 4
1176c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // different types of checks, yet have more than 4 proto types
1177c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // that map onto those 4 patterns.
1178c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string NormalizedProto("");
1179c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormalizeProtoForRegisterPatternCreation(Name, Proto, HasNPostfix, IsQuad,
1180c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                             HasLanePostfix, HasDupPostfix,
1181c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                             NormalizedProto);
1182c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1183c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0, end = NormalizedProto.size(); i < end; i++) {
1184c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      const char &c = NormalizedProto[i];
1185c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      switch (c) {
1186c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'q':
1187c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "q{{[0-9]+}}, ";
1188c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1189c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1190c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'd':
1191c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "d{{[0-9]+}}, ";
1192c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1193c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1194c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'i':
1195c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "#{{[0-9]+}}, ";
1196c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1197c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1198c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'a':
1199c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "d{{[0-9]+}}[{{[0-9]}}], ";
1200c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1201c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1202c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1203c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1204c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Remove extra ", ".
1205c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix = RegisterSuffix.substr(0, RegisterSuffix.size()-2);
1206c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1207c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1208c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1209c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateChecksForIntrinsic - Given a specific instruction name +
1210c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// typestr + class kind, generate the proper set of FileCheck
1211c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// Patterns to check for. We could just return a string, but instead
1212c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// use a vector since it provides us with the extra flexibility of
1213c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// emitting multiple checks, which comes in handy for certain cases
1214c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// like mla where we want to check for 2 different instructions.
1215c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateChecksForIntrinsic(const std::string &Name,
1216c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       const std::string &Proto,
1217c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       StringRef &OutTypeStr,
1218c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       StringRef &InTypeStr,
1219c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       ClassKind Ck,
1220c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       const std::string &InstName,
1221c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       bool IsHiddenLOp,
1222c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       std::vector<std::string>& Result) {
1223c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1224c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If Ck is a ClassNoTest instruction, just return so no test is
1225c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // emitted.
1226c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if(Ck == ClassNoTest)
1227c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1228c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1229c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Name == "vcvt_f32_f16") {
1230c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back("vcvt.f32.f16");
1231c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1232c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1233c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1234c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1235c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Now we preprocess our instruction given the data we have to get the
1236c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // data that we need.
1237c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Create a StringRef for String Manipulation of our Name.
1238c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
1239c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Instruction Prefix.
1240c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string Prefix;
1241c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // The type code for our out type string.
1242c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string OutTypeCode;
1243c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // To handle our different cases, we need to check for different postfixes.
1244c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Is our instruction a quad instruction.
1245c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool IsQuad = false;
1246c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_n.
1247c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasNPostfix = false;
1248c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_lane.
1249c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasLanePostfix = false;
1250c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_dup.
1251c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasDupPostfix  = false;
1252c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is a vcvt instruction which requires special handling.
1253c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool IsSpecialVCvt = false;
1254c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have a vtbxN or vtblN instruction, this is set to N.
1255c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  size_t TBNumber = -1;
1256c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Register Suffix
1257c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string RegisterSuffix;
1258c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1259c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  PreprocessInstruction(NameRef, InstName, Prefix,
1260c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                        HasNPostfix, HasLanePostfix, HasDupPostfix,
1261c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                        IsSpecialVCvt, TBNumber);
1262c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1263c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  InstructionTypeCode(OutTypeStr, Ck, IsQuad, OutTypeCode);
1264c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  GenerateRegisterCheckPattern(Name, Proto, OutTypeCode, HasNPostfix, IsQuad,
1265c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               HasLanePostfix, HasDupPostfix, TBNumber,
1266c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               RegisterSuffix);
1267c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1268c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // In the following section, we handle a bunch of special cases. You can tell
1269c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // a special case by the fact we are returning early.
1270c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1271c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If our instruction is a logical instruction without postfix or a
1272c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // hidden LOp just return the current Prefix.
1273c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Ck == ClassL || IsHiddenLOp) {
1274c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back(Prefix + " " + RegisterSuffix);
1275c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1276c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1277c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1278c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have a vmov, due to the many different cases, some of which
1279c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // vary within the different intrinsics generated for a single
1280c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // instruction type, just output a vmov. (e.g. given an instruction
1281c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // A, A.u32 might be vmov and A.u8 might be vmov.8).
1282c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  //
1283c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // FIXME: Maybe something can be done about this. The two cases that we care
1284c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // about are vmov as an LType and vmov as a WType.
1285c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Prefix == "vmov") {
1286c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back(Prefix + " " + RegisterSuffix);
1287c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1288c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1289c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1290c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // In the following section, we handle special cases.
1291c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1292c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (OutTypeCode == "64") {
1293c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a 64 bit vdup/vext and are handling an uint64x1_t
1294c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // type, the intrinsic will be optimized away, so just return
1295c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // nothing.  On the other hand if we are handling an uint64x2_t
1296c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // (i.e. quad instruction), vdup/vmov instructions should be
1297c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // emitted.
1298c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (Prefix == "vdup" || Prefix == "vext") {
1299c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (IsQuad) {
1300c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{vmov|vdup}}");
1301c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1302c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1303c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1304c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1305c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // v{st,ld}{2,3,4}_{u,s}64 emit v{st,ld}1.64 instructions with
1306c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // multiple register operands.
1307c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    bool MultiLoadPrefix = Prefix == "vld2" || Prefix == "vld3"
1308c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                            || Prefix == "vld4";
1309c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    bool MultiStorePrefix = Prefix == "vst2" || Prefix == "vst3"
1310c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                            || Prefix == "vst4";
1311c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (MultiLoadPrefix || MultiStorePrefix) {
1312c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back(NameRef.slice(0, 3).str() + "1.64");
1313c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1314c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1315c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1316c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // v{st,ld}1_{lane,dup}_{u64,s64} use vldr/vstr/vmov/str instead of
1317c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // emitting said instructions. So return a check for
1318c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // vldr/vstr/vmov/str instead.
1319c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (HasLanePostfix || HasDupPostfix) {
1320c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (Prefix == "vst1") {
1321c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{str|vstr|vmov}}");
1322c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        return;
1323c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else if (Prefix == "vld1") {
1324c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{ldr|vldr|vmov}}");
1325c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        return;
1326c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1327c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1328c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1329c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1330c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // vzip.32/vuzp.32 are the same instruction as vtrn.32 and are
1331c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // sometimes disassembled as vtrn.32. We use a regex to handle both
1332c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // cases.
1333c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((Prefix == "vzip" || Prefix == "vuzp") && OutTypeCode == "32") {
1334c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back("{{vtrn|" + Prefix + "}}.32 " + RegisterSuffix);
1335c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1336c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1337c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1338c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Currently on most ARM processors, we do not use vmla/vmls for
1339c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // quad floating point operations. Instead we output vmul + vadd. So
1340c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // check if we have one of those instructions and just output a
1341c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // check for vmul.
1342c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (OutTypeCode == "f32") {
1343c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (Prefix == "vmls") {
1344c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix);
1345c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vsub." + OutTypeCode);
1346c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1347c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    } else if (Prefix == "vmla") {
1348c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix);
1349c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vadd." + OutTypeCode);
1350c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1351c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1352c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1353c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1354c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have vcvt, get the input type from the instruction name
1355c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // (which should be of the form instname_inputtype) and append it
1356c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // before the output type.
1357c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Prefix == "vcvt") {
1358c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    const std::string inTypeCode = NameRef.substr(NameRef.find_last_of("_")+1);
1359c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Prefix += "." + inTypeCode;
1360c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1361c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1362c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Append output type code to get our final mangled instruction.
1363c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Prefix += "." + OutTypeCode;
1364c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1365c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Result.push_back(Prefix + " " + RegisterSuffix);
1366c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1367c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
136851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// UseMacro - Examine the prototype string to determine if the intrinsic
136951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// should be defined as a preprocessor macro instead of an inline function.
137051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool UseMacro(const std::string &proto) {
137151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin takes an immediate argument, we need to #define it rather
137251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // than use a standard declaration, so that SemaChecking can range check
137351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // the immediate passed by the user.
137451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('i') != std::string::npos)
137551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
137651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pointer arguments need to use macros to avoid hiding aligned attributes
137851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // from the pointer type.
137951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('p') != std::string::npos ||
138051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      proto.find('c') != std::string::npos)
138151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
138251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return false;
138451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
138551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
138751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// defined as a macro should be accessed directly instead of being first
138851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// assigned to a local temporary.
138951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
139051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // True for constant ints (i), pointers (p) and const pointers (c).
139151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the string "(argtype a, argtype b, ...)"
13952102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qinstatic std::string GenArgs(const std::string &proto, StringRef typestr,
13962102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin                           const std::string &name) {
139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
140151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Some macro arguments are used directly instead of being assigned
140651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to local temporaries; prepend an underscore prefix to make their
140751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // names consistent with the local temporaries.
140851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (MacroArgUsedDirectly(proto, i))
140951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "__";
141051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
141151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += TypeString(proto[i], typestr) + " __";
141251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
141351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
14142102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    //To avoid argument being multiple defined, add extra number for renaming.
141522229d6822324a42913d25f256045dbf348a53e9Kevin Qin    if (name == "vcopy_lane" || name == "vcopy_laneq")
14162102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      s.push_back('1');
141751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
141851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
142051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
142151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
142251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
142351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
142451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Macro arguments are not type-checked like inline function arguments, so
142651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// assign them to local temporaries to get the right type checking.
14272102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qinstatic std::string GenMacroLocals(const std::string &proto, StringRef typestr,
14282102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin                                  const std::string &name ) {
142951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
143051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
143151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool generatedLocal = false;
143251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
143351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
143451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create a temporary for an immediate argument.
143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // That would defeat the whole point of using a macro!
143651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (MacroArgUsedDirectly(proto, i))
143751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
143851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    generatedLocal = true;
14392102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    bool extranumber = false;
144022229d6822324a42913d25f256045dbf348a53e9Kevin Qin    if (name == "vcopy_lane" || name == "vcopy_laneq")
14412102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      extranumber = true;
144251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
144351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += TypeString(proto[i], typestr) + " __";
144451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
14452102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    if(extranumber)
14462102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      s.push_back('1');
144751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " = (";
144851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
14492102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    if(extranumber)
14502102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      s.push_back('1');
145151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "); ";
145251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
145351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
145451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (generatedLocal)
145551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "\\\n  ";
145651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
145751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
145851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
145951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Use the vmovl builtin to sign-extend or zero-extend a vector.
1460097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string Extend(StringRef typestr, const std::string &a, bool h=0) {
1461097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s, high;
1462097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  high = h ? "_high" : "";
1463097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName("vmovl" + high, typestr, ClassS);
1464097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + a + ")";
1465097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1466097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1467097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1468097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Get the high 64-bit part of a vector
1469097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string GetHigh(const std::string &a, StringRef typestr) {
147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
1471097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName("vget_high", typestr, ClassS);
147251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(" + a + ")";
147351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
147451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
147551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1476097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Gen operation with two operands and get high 64-bit for both of two operands.
1477097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string Gen2OpWith2High(StringRef typestr,
1478097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &op,
1479097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &a,
1480097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &b) {
1481097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
1482097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op1 = GetHigh(a, typestr);
1483097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op2 = GetHigh(b, typestr);
1484097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName(op, typestr, ClassS);
1485097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + Op1 + ", " + Op2 + ");";
1486097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1487097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1488097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1489097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Gen operation with three operands and get high 64-bit of the latter
1490097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// two operands.
1491097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string Gen3OpWith2High(StringRef typestr,
1492097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &op,
1493097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &a,
1494097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &b,
1495097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &c) {
1496097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
1497097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op1 = GetHigh(b, typestr);
1498097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op2 = GetHigh(c, typestr);
1499097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName(op, typestr, ClassS);
1500097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + a + ", " + Op1 + ", " + Op2 + ");";
1501097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1502097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1503097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1504097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Gen combine operation by putting a on low 64-bit, and b on high 64-bit.
1505097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string GenCombine(std::string typestr,
1506097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                              const std::string &a,
1507097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                              const std::string &b) {
1508097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
1509097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName("vcombine", typestr, ClassS);
1510097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + a + ", " + b + ")";
1511097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1512097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1513097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Duplicate(unsigned nElts, StringRef typestr,
151551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &a) {
151651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
151751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
151851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = "(" + TypeString('d', typestr) + "){ ";
151951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i != nElts; ++i) {
152051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += a;
152151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < nElts)
152251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
152351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
152451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += " }";
152551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
152651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
152751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
152851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
152951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string SplatLane(unsigned nElts, const std::string &vec,
153051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &lane) {
153151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
153251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i < nElts; ++i)
153351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + lane;
153451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
153651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
153751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1538912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liustatic std::string RemoveHigh(const std::string &name) {
1539912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  std::string s = name;
1540912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  std::size_t found = s.find("_high_");
1541912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  if (found == std::string::npos)
1542912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    PrintFatalError("name should contain \"_high_\" for high intrinsics");
1543912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  s.replace(found, 5, "");
1544912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  return s;
1545912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu}
1546912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu
154751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNumElements(StringRef typestr, bool &quad) {
154851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  quad = false;
154951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool dummy = false;
155051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
155151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = 0;
155251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
155351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c': nElts = 8; break;
155451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's': nElts = 4; break;
155551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i': nElts = 2; break;
155651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l': nElts = 1; break;
155751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h': nElts = 4; break;
155851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f': nElts = 2; break;
1559b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  case 'd':
1560b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    nElts = 1;
1561b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    break;
156251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
156338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unhandled type!");
156451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
156551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) nElts <<= 1;
156651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return nElts;
156751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
156851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
156951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
1570912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liustatic std::string GenOpString(const std::string &name, OpKind op,
1571912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu                               const std::string &proto, StringRef typestr) {
157251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad;
157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = GetNumElements(typestr, quad);
157451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
157551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string ts = TypeString(proto[0], typestr);
157751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
157851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!define) {
157951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = "return ";
158051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
158151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
158251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch(op) {
158351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAdd:
158451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + __b;";
158551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
158651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddl:
158751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
158851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1589097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAddlHi:
1590097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Extend(typestr, "__a", 1) + " + " + Extend(typestr, "__b", 1) + ";";
1591097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
159251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddw:
159351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + Extend(typestr, "__b") + ";";
159451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1595097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAddwHi:
1596097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += "__a + " + Extend(typestr, "__b", 1) + ";";
1597097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
159851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSub:
159951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - __b;";
160051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
160151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubl:
160251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
160351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1604097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpSublHi:
1605097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Extend(typestr, "__a", 1) + " - " + Extend(typestr, "__b", 1) + ";";
1606097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
160751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubw:
160851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + Extend(typestr, "__b") + ";";
160951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1610097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpSubwHi:
1611097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += "__a - " + Extend(typestr, "__b", 1) + ";";
1612097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
161351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulN:
161451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
161551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
161651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulLane:
161751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
161851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16190aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMulXLane:
16200aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vmulx", typestr, ClassS) + "(__a, " +
16210aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      SplatLane(nElts, "__b", "__c") + ");";
16220aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
162351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMul:
162451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * __b;";
162551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
162651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMullLane:
162751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
162851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
162951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16300aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMullHiLane:
16310aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vmull", typestr, ClassS) + "(" +
16320aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__a", typestr) + ", " + SplatLane(nElts, "__b", "__c") + ");";
16330aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
163451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaN:
163551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
163651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
163751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaLane:
163851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
164051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMla:
164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * __c);";
164251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
164351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalN:
164451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
164551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
164651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
164751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalLane:
164851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
164951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
165051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16510aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMlalHiLane:
16520aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(" +
16530aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
16540aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
165551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlal:
165651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
165751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1658097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpMullHi:
1659097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen2OpWith2High(typestr, "vmull", "__a", "__b");
1660097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1661097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpMlalHi:
1662097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vmlal", "__a", "__b", "__c");
1663097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
166451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsN:
166551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
166651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
166751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsLane:
166851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
166951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16700aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpFMSLane:
16710aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[1], typestr) + " __a1 = __a; \\\n  ";
16720aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[2], typestr) + " __b1 = __b; \\\n  ";
16730aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[3], typestr) + " __c1 = __c; \\\n  ";
16740aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vfma_lane", typestr, ClassS) + "(__a1, __b1, -__c1, __d);";
16750aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
16760aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpFMSLaneQ:
16770aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[1], typestr) + " __a1 = __a; \\\n  ";
16780aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[2], typestr) + " __b1 = __b; \\\n  ";
16790aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[3], typestr) + " __c1 = __c; \\\n  ";
16800aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vfma_laneq", typestr, ClassS) + "(__a1, __b1, -__c1, __d);";
16810aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
168251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMls:
168351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * __c);";
168451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslN:
168651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
168751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
168851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
168951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslLane:
169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
169151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
169251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16930aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMlslHiLane:
16940aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(" +
16950aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
16960aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
169751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsl:
169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
169951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1700097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpMlslHi:
1701097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vmlsl", "__a", "__b", "__c");
1702097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMullLane:
170451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
170551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
170651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
17070aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpQDMullHiLane:
17080aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vqdmull", typestr, ClassS) + "(" +
17090aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__a", typestr) + ", " + SplatLane(nElts, "__b", "__c") + ");";
17100aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
171151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlalLane:
171251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
171351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
171451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
17150aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpQDMlalHiLane:
17160aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, " +
17170aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
17180aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
171951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlslLane:
172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
172151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
172251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
17230aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpQDMlslHiLane:
17240aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, " +
17250aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
17260aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMulhLane:
172851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
172951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
173051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
173151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQRDMulhLane:
173251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
173351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
173551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpEq:
173651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a == __b);";
173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
173851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGe:
173951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a >= __b);";
174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
174151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLe:
174251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a <= __b);";
174351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGt:
174551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a > __b);";
174651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
174751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLt:
174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a < __b);";
174951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNeg:
175151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " -__a;";
175251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNot:
175451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " ~__a;";
175551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAnd:
175751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & __b;";
175851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
175951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOr:
176051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | __b;";
176151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
176251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpXor:
176351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a ^ __b;";
176451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
176551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAndNot:
176651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & ~__b;";
176751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
176851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOrNot:
176951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | ~__b;";
177051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
177151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpCast:
177251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__a;";
177351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
177451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpConcat:
177551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
177651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", (int64x1_t)__b, 0, 1);";
177751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
177851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpHi:
1779cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    // nElts is for the result vector, so the source is twice that number.
1780cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s += "__builtin_shufflevector(__a, __a";
1781cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    for (unsigned i = nElts; i < nElts * 2; ++i)
1782cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach      s += ", " + utostr(i);
1783cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s+= ");";
178451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
178551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLo:
1786cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s += "__builtin_shufflevector(__a, __a";
1787cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    for (unsigned i = 0; i < nElts; ++i)
1788cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach      s += ", " + utostr(i);
1789cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s+= ");";
179051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
179151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDup:
179251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Duplicate(nElts, typestr, "__a") + ";";
179351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
179451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDupLane:
179551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += SplatLane(nElts, "__a", "__b") + ";";
179651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
179751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSelect:
179851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // ((0 & 1) | (~0 & 2))
179951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")";
180051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ts = TypeString(proto[1], typestr);
180151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "((__a & (" + ts + ")__b) | ";
180251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(~__a & (" + ts + ")__c));";
180351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
180451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev16:
180551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
180651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 2; i <= nElts; i += 2)
180751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != 2; ++j)
180851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
180951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
181051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
181151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev32: {
181251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned WordElts = nElts >> (1 + (int)quad);
181351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
181451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = WordElts; i <= nElts; i += WordElts)
181551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != WordElts; ++j)
181651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
181751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
181851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
181951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
182051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev64: {
182151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned DblWordElts = nElts >> (int)quad;
182251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
182351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
182451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != DblWordElts; ++j)
182551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
182651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
182751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
182851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
18298137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  case OpXtnHi: {
18308137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s = TypeString(proto[1], typestr) + " __a1 = " +
18318137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        MangleName("vmovn", typestr, ClassS) + "(__b);\n  " +
18328137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        "return __builtin_shufflevector(__a, __a1";
18338137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    for (unsigned i = 0; i < nElts * 4; ++i)
18348137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin      s += ", " + utostr(i);
18358137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s += ");";
18368137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    break;
18378137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  }
18388137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  case OpSqxtunHi: {
18398137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s = TypeString(proto[1], typestr) + " __a1 = " +
18408137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        MangleName("vqmovun", typestr, ClassS) + "(__b);\n  " +
18418137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        "return __builtin_shufflevector(__a, __a1";
18428137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    for (unsigned i = 0; i < nElts * 4; ++i)
18438137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin      s += ", " + utostr(i);
18448137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s += ");";
18458137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    break;
18468137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  }
18478137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  case OpQxtnHi: {
18488137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s = TypeString(proto[1], typestr) + " __a1 = " +
18498137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        MangleName("vqmovn", typestr, ClassS) + "(__b);\n  " +
18508137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        "return __builtin_shufflevector(__a, __a1";
18518137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    for (unsigned i = 0; i < nElts * 4; ++i)
18528137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin      s += ", " + utostr(i);
18538137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s += ");";
18548137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    break;
18558137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  }
18568137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  case OpFcvtnHi: {
18578137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    std::string FName = (nElts == 1) ? "vcvt_f32" : "vcvt_f16";
18588137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s = TypeString(proto[1], typestr) + " __a1 = " +
18598137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        MangleName(FName, typestr, ClassS) + "(__b);\n  " +
18608137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        "return __builtin_shufflevector(__a, __a1";
18618137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    for (unsigned i = 0; i < nElts * 4; ++i)
18628137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin      s += ", " + utostr(i);
18638137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s += ");";
18648137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    break;
18658137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  }
18668137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  case OpFcvtlHi: {
18678137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    std::string FName = (nElts == 2) ? "vcvt_f64" : "vcvt_f32";
18688137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s = TypeString('d', typestr) + " __a1 = " + GetHigh("__a", typestr) +
18698137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        ";\n  return " + MangleName(FName, typestr, ClassS) + "(__a1);";
18708137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    break;
18718137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  }
18728137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  case OpFcvtxnHi: {
18738137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s = TypeString(proto[1], typestr) + " __a1 = " +
18748137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        MangleName("vcvtx_f32", typestr, ClassS) + "(__b);\n  " +
18758137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin        "return __builtin_shufflevector(__a, __a1";
18768137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    for (unsigned i = 0; i < nElts * 4; ++i)
18778137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin      s += ", " + utostr(i);
18788137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    s += ");";
18798137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin    break;
18808137a607eebe799d95fd05226fb91119a5b054b0Kevin Qin  }
1881bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  case OpUzp1:
1882bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += "__builtin_shufflevector(__a, __b";
1883bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    for (unsigned i = 0; i < nElts; i++)
1884bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu      s += ", " + utostr(2*i);
1885bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += ");";
1886bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    break;
1887bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  case OpUzp2:
1888bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += "__builtin_shufflevector(__a, __b";
1889bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    for (unsigned i = 0; i < nElts; i++)
1890bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu      s += ", " + utostr(2*i+1);
1891bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += ");";
1892bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    break;
1893bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  case OpZip1:
1894bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += "__builtin_shufflevector(__a, __b";
1895bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    for (unsigned i = 0; i < (nElts/2); i++)
1896bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu       s += ", " + utostr(i) + ", " + utostr(i+nElts);
1897bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += ");";
1898bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    break;
1899bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  case OpZip2:
1900bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += "__builtin_shufflevector(__a, __b";
1901bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    for (unsigned i = nElts/2; i < nElts; i++)
1902bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu       s += ", " + utostr(i) + ", " + utostr(i+nElts);
1903bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += ");";
1904bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    break;
1905bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  case OpTrn1:
1906bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += "__builtin_shufflevector(__a, __b";
1907bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    for (unsigned i = 0; i < (nElts/2); i++)
1908bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu       s += ", " + utostr(2*i) + ", " + utostr(2*i+nElts);
1909bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += ");";
1910bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    break;
1911bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu  case OpTrn2:
1912bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += "__builtin_shufflevector(__a, __b";
1913bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    for (unsigned i = 0; i < (nElts/2); i++)
1914bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu       s += ", " + utostr(2*i+1) + ", " + utostr(2*i+1+nElts);
1915bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    s += ");";
1916bf3bc5d37eff88b578d5990f507a87db33f30a6eJiangning Liu    break;
191751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbdl: {
191851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
191951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
192051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
192151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
192251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
192351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
192451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
192551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
192651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
192751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
192851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
192951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1930097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAbdlHi:
1931097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen2OpWith2High(typestr, "vabdl", "__a", "__b");
1932097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1933097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAddhnHi: {
1934097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string addhn = MangleName("vaddhn", typestr, ClassS) + "(__b, __c)";
1935097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", addhn);
1936097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1937097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1938097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
1939097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpRAddhnHi: {
1940097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string raddhn = MangleName("vraddhn", typestr, ClassS) + "(__b, __c)";
1941097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", raddhn);
1942097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1943097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1944097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
1945097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpSubhnHi: {
1946097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string subhn = MangleName("vsubhn", typestr, ClassS) + "(__b, __c)";
1947097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", subhn);
1948097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1949097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1950097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
1951097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpRSubhnHi: {
1952097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string rsubhn = MangleName("vrsubhn", typestr, ClassS) + "(__b, __c)";
1953097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", rsubhn);
1954097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1955097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1956097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
195751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAba:
195851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
195951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1960097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAbal:
1961097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += "__a + " + MangleName("vabdl", typestr, ClassS) + "(__b, __c);";
1962097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1963097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAbalHi:
1964097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vabal", "__a", "__b", "__c");
1965097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1966097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpQDMullHi:
1967097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen2OpWith2High(typestr, "vqdmull", "__a", "__b");
1968097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1969097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpQDMlalHi:
1970097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vqdmlal", "__a", "__b", "__c");
1971097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1972097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpQDMlslHi:
1973097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vqdmlsl", "__a", "__b", "__c");
197451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1975b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  case OpDiv:
1976b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    s += "__a / __b;";
1977b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    break;
1978912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  case OpMovlHi: {
1979912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s = TypeString(proto[1], typestr.drop_front()) + " __a1 = " +
1980912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        MangleName("vget_high", typestr, ClassS) + "(__a);\n  " + s;
1981912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "(" + ts + ")" + MangleName("vshll_n", typestr, ClassS);
1982912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "(__a1, 0);";
1983912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    break;
1984912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  }
1985912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  case OpLongHi: {
1986912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    // Another local variable __a1 is needed for calling a Macro,
1987912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    // or using __a will have naming conflict when Macro expanding.
1988912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += TypeString(proto[1], typestr.drop_front()) + " __a1 = " +
1989912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu         MangleName("vget_high", typestr, ClassS) + "(__a); \\\n";
1990912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "  (" + ts + ")" + MangleName(RemoveHigh(name), typestr, ClassS) +
1991912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu         "(__a1, __b);";
1992912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    break;
1993912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  }
1994912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  case OpNarrowHi: {
1995912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "(" + ts + ")" + MangleName("vcombine", typestr, ClassS) + "(__a, " +
1996912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu         MangleName(RemoveHigh(name), typestr, ClassS) + "(__b, __c));";
1997912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    break;
1998912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  }
199922229d6822324a42913d25f256045dbf348a53e9Kevin Qin  case OpCopyLane: {
20002102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    s += TypeString('s', typestr) + " __c2 = " +
20012102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin         MangleName("vget_lane", typestr, ClassS) + "(__c1, __d1); \\\n  " +
20022102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin         MangleName("vset_lane", typestr, ClassS) + "(__c2, __a1, __b1);";
20032102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    break;
20042102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin  }
200522229d6822324a42913d25f256045dbf348a53e9Kevin Qin  case OpCopyQLane: {
200622229d6822324a42913d25f256045dbf348a53e9Kevin Qin    std::string typeCode = "";
200722229d6822324a42913d25f256045dbf348a53e9Kevin Qin    InstructionTypeCode(typestr, ClassS, quad, typeCode);
200822229d6822324a42913d25f256045dbf348a53e9Kevin Qin    s += TypeString('s', typestr) + " __c2 = vget_lane_" + typeCode +
200922229d6822324a42913d25f256045dbf348a53e9Kevin Qin         "(__c1, __d1); \\\n  vsetq_lane_" + typeCode + "(__c2, __a1, __b1);";
201022229d6822324a42913d25f256045dbf348a53e9Kevin Qin    break;
201122229d6822324a42913d25f256045dbf348a53e9Kevin Qin  }
201222229d6822324a42913d25f256045dbf348a53e9Kevin Qin  case OpCopyLaneQ: {
201322229d6822324a42913d25f256045dbf348a53e9Kevin Qin    std::string typeCode = "";
201422229d6822324a42913d25f256045dbf348a53e9Kevin Qin    InstructionTypeCode(typestr, ClassS, quad, typeCode);
201522229d6822324a42913d25f256045dbf348a53e9Kevin Qin    s += TypeString('s', typestr) + " __c2 = vgetq_lane_" + typeCode +
201622229d6822324a42913d25f256045dbf348a53e9Kevin Qin         "(__c1, __d1); \\\n  vset_lane_" + typeCode + "(__c2, __a1, __b1);";
201722229d6822324a42913d25f256045dbf348a53e9Kevin Qin    break;
201822229d6822324a42913d25f256045dbf348a53e9Kevin Qin  }
201951cc0172a173599b769968696e20638754d1dcd6Ana Pazos  case OpScalarMulLane: {
202051cc0172a173599b769968696e20638754d1dcd6Ana Pazos    std::string typeCode = "";
202151cc0172a173599b769968696e20638754d1dcd6Ana Pazos    InstructionTypeCode(typestr, ClassS, quad, typeCode);
202251cc0172a173599b769968696e20638754d1dcd6Ana Pazos	s += TypeString('s', typestr) + " __d1 = vget_lane_" + typeCode +
202351cc0172a173599b769968696e20638754d1dcd6Ana Pazos	  "(__b, __c);\\\n  __a * __d1;";
202451cc0172a173599b769968696e20638754d1dcd6Ana Pazos    break;
202551cc0172a173599b769968696e20638754d1dcd6Ana Pazos  }
202651cc0172a173599b769968696e20638754d1dcd6Ana Pazos  case OpScalarMulLaneQ: {
202751cc0172a173599b769968696e20638754d1dcd6Ana Pazos    std::string typeCode = "";
202851cc0172a173599b769968696e20638754d1dcd6Ana Pazos    InstructionTypeCode(typestr, ClassS, quad, typeCode);
202951cc0172a173599b769968696e20638754d1dcd6Ana Pazos        s += TypeString('s', typestr) + " __d1 = vgetq_lane_" + typeCode +
203051cc0172a173599b769968696e20638754d1dcd6Ana Pazos          "(__b, __c);\\\n  __a * __d1;";
203151cc0172a173599b769968696e20638754d1dcd6Ana Pazos    break;
203251cc0172a173599b769968696e20638754d1dcd6Ana Pazos  }
203351cc0172a173599b769968696e20638754d1dcd6Ana Pazos  case OpScalarMulXLane: {
203451cc0172a173599b769968696e20638754d1dcd6Ana Pazos    bool dummy = false;
203551cc0172a173599b769968696e20638754d1dcd6Ana Pazos    char type = ClassifyType(typestr, dummy, dummy, dummy);
203651cc0172a173599b769968696e20638754d1dcd6Ana Pazos    if (type == 'f') type = 's';
203751cc0172a173599b769968696e20638754d1dcd6Ana Pazos    std::string typeCode = "";
203851cc0172a173599b769968696e20638754d1dcd6Ana Pazos    InstructionTypeCode(typestr, ClassS, quad, typeCode);
203951cc0172a173599b769968696e20638754d1dcd6Ana Pazos    s += TypeString('s', typestr) + " __d1 = vget_lane_" + typeCode +
204051cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "(__b, __c);\\\n  vmulx" + type + "_" +
204151cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode +  "(__a, __d1);";
204251cc0172a173599b769968696e20638754d1dcd6Ana Pazos    break;
204351cc0172a173599b769968696e20638754d1dcd6Ana Pazos  }
204451cc0172a173599b769968696e20638754d1dcd6Ana Pazos  case OpScalarMulXLaneQ: {
204551cc0172a173599b769968696e20638754d1dcd6Ana Pazos    bool dummy = false;
204651cc0172a173599b769968696e20638754d1dcd6Ana Pazos    char type = ClassifyType(typestr, dummy, dummy, dummy);
204751cc0172a173599b769968696e20638754d1dcd6Ana Pazos    if (type == 'f') type = 's';
204851cc0172a173599b769968696e20638754d1dcd6Ana Pazos    std::string typeCode = "";
204951cc0172a173599b769968696e20638754d1dcd6Ana Pazos    InstructionTypeCode(typestr, ClassS, quad, typeCode);
205051cc0172a173599b769968696e20638754d1dcd6Ana Pazos    s += TypeString('s', typestr) + " __d1 = vgetq_lane_" +
205151cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode + "(__b, __c);\\\n  vmulx" + type +
205251cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "_" + typeCode +  "(__a, __d1);";
205351cc0172a173599b769968696e20638754d1dcd6Ana Pazos    break;
205451cc0172a173599b769968696e20638754d1dcd6Ana Pazos  }
205551cc0172a173599b769968696e20638754d1dcd6Ana Pazos
205651cc0172a173599b769968696e20638754d1dcd6Ana Pazos  case OpScalarVMulXLane: {
205751cc0172a173599b769968696e20638754d1dcd6Ana Pazos    bool dummy = false;
205851cc0172a173599b769968696e20638754d1dcd6Ana Pazos    char type = ClassifyType(typestr, dummy, dummy, dummy);
205951cc0172a173599b769968696e20638754d1dcd6Ana Pazos    if (type == 'f') type = 's';
206051cc0172a173599b769968696e20638754d1dcd6Ana Pazos    std::string typeCode = "";
206151cc0172a173599b769968696e20638754d1dcd6Ana Pazos    InstructionTypeCode(typestr, ClassS, quad, typeCode);
206251cc0172a173599b769968696e20638754d1dcd6Ana Pazos    s += TypeString('s', typestr) + " __d1 = vget_lane_" +
206351cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode + "(__a, 0);\\\n" +
206451cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  " + TypeString('s', typestr) + " __e1 = vget_lane_" +
206551cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode + "(__b, __c);\\\n" +
206651cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  " + TypeString('s', typestr) + " __f1 = vmulx" + type + "_" +
206751cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode + "(__d1, __e1);\\\n" +
206851cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  " + TypeString('d', typestr) + " __g1;\\\n" +
206951cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  vset_lane_" + typeCode + "(__f1, __g1, __c);";
207051cc0172a173599b769968696e20638754d1dcd6Ana Pazos    break;
207151cc0172a173599b769968696e20638754d1dcd6Ana Pazos  }
207251cc0172a173599b769968696e20638754d1dcd6Ana Pazos
207351cc0172a173599b769968696e20638754d1dcd6Ana Pazos  case OpScalarVMulXLaneQ: {
207451cc0172a173599b769968696e20638754d1dcd6Ana Pazos    bool dummy = false;
207551cc0172a173599b769968696e20638754d1dcd6Ana Pazos    char type = ClassifyType(typestr, dummy, dummy, dummy);
207651cc0172a173599b769968696e20638754d1dcd6Ana Pazos    if (type == 'f') type = 's';
207751cc0172a173599b769968696e20638754d1dcd6Ana Pazos    std::string typeCode = "";
207851cc0172a173599b769968696e20638754d1dcd6Ana Pazos    InstructionTypeCode(typestr, ClassS, quad, typeCode);
207951cc0172a173599b769968696e20638754d1dcd6Ana Pazos    s += TypeString('s', typestr) + " __d1 = vget_lane_" +
208051cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode + "(__a, 0);\\\n" +
208151cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  " + TypeString('s', typestr) + " __e1 = vgetq_lane_" +
208251cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode + "(__b, __c);\\\n" +
208351cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  " + TypeString('s', typestr) + " __f1 = vmulx" + type + "_" +
208451cc0172a173599b769968696e20638754d1dcd6Ana Pazos      typeCode + "(__d1, __e1);\\\n" +
208551cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  " + TypeString('d', typestr) + " __g1;\\\n" +
208651cc0172a173599b769968696e20638754d1dcd6Ana Pazos      "  vset_lane_" + typeCode + "(__f1, __g1, 0);";
208751cc0172a173599b769968696e20638754d1dcd6Ana Pazos    break;
208851cc0172a173599b769968696e20638754d1dcd6Ana Pazos  }
208951cc0172a173599b769968696e20638754d1dcd6Ana Pazos
209051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
209138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unknown OpKind!");
209251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
209351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
209451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
209551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
209651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
209751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned mod = proto[0];
209851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
209951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v' || mod == 'f')
210051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mod = proto[1];
210151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
210251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
210351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
210451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
210551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
210651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
210751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
210851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
210951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Base type to get the type string for.
211051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
211151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
211251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
211351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
211451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2115da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags::EltType ET;
211651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
211751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
2118da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
211951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
212051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
2121da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
212251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
212351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
2124da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int32;
212551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
212651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
2127624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin      ET = poly ? NeonTypeFlags::Poly64 : NeonTypeFlags::Int64;
212851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
212951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
2130da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float16;
213151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
213251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
2133da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float32;
213451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
2135b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case 'd':
2136b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      ET = NeonTypeFlags::Float64;
2137b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
213851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
213938859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
214051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2141da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
2142da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  return Flags.getFlags();
214351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
214451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
21450391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liustatic bool ProtoHasScalar(const std::string proto)
21460391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu{
21470391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu  return (proto.find('s') != std::string::npos
21480391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu          || proto.find('r') != std::string::npos);
21490391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu}
21500391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu
215151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
215251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltin(const std::string &name, const std::string &proto,
215351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              StringRef typestr, ClassKind ck) {
215451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
215551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
215651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
215751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sret-like argument.
21582e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu  bool sret = IsMultiVecProto(proto[0]);
215951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
216051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
216151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
216251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Check if the prototype has a scalar operand with the type of the vector
216351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // elements.  If not, bitcasting the args will take care of arg checking.
216451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The actual signedness etc. will be taken care of with special enums.
21650391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu  if (!ProtoHasScalar(proto))
216651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
216751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
216851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v') {
216951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string ts = TypeString(proto[0], typestr);
217051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
217151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
217251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (sret)
217351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ts + " r; ";
217451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
217551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "(" + ts + ")";
217651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else if (sret) {
217751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ts + " r; ";
217851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
217951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "return (" + ts + ")";
218051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
218151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
218251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
218351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool splat = proto.find('a') != std::string::npos;
218451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
218551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "__builtin_neon_";
218651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (splat) {
218751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Call the non-splat builtin: chop off the "_n" suffix from the name.
218851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string vname(name, 0, name.size()-2);
218951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(vname, typestr, ck);
219051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
219151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(name, typestr, ck);
219251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
219351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
219451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
219551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pass the address of the return variable as the first argument to sret-like
219651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // builtins.
219751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (sret)
219851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "&r, ";
219951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
220051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
220151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
220251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string args = std::string(&arg, 1);
220351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
220451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Use the local temporaries instead of the macro arguments.
220551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    args = "__" + args;
220651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
220751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argQuad = false;
220851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argPoly = false;
220951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argUsgn = false;
221051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argScalar = false;
221151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy = false;
221251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
221351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
221451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      dummy, dummy);
221551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
221651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Handle multiple-vector values specially, emitting each subvector as an
221751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // argument to the __builtin.
22182e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    unsigned NumOfVec = 0;
221951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] >= '2' && proto[i] <= '4') {
22202e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu      NumOfVec = proto[i] - '0';
22212e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    } else if (proto[i] >= 'B' && proto[i] <= 'D') {
22222e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu      NumOfVec = proto[i] - 'A' + 1;
22232e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    }
22242e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu
22252e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    if (NumOfVec > 0) {
222651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Check if an explicit cast is needed.
222751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argType != 'c' || argPoly || argUsgn)
222851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
222951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22302e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu      for (unsigned vi = 0, ve = NumOfVec; vi != ve; ++vi) {
223151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += args + ".val[" + utostr(vi) + "]";
223251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if ((vi + 1) < ve)
223351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          s += ", ";
223451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
223551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if ((i + 1) < e)
223651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", ";
223751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
223851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
223951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
224051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
224151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (splat && (i + 1) == e)
224251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
224351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
224451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check if an explicit cast is needed.
224551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((splat || !argScalar) &&
224651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
224751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string argTypeStr = "c";
224851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (ck != ClassB)
224951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = argType;
225051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argQuad)
225151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = "Q" + argTypeStr;
225251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = "(" + TypeString('d', argTypeStr) + ")" + args;
225351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
225451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
225551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += args;
225651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
225751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
225851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
225951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
226051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
226151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
226251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + utostr(GetNeonEnum(proto, typestr));
226351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
226451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");";
226551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
226651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v' && sret) {
226751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define)
226851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " r;";
226951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
227051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " return r;";
227151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
227251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
227351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
227451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
227551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltinDef(const std::string &name,
227651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 const std::string &proto,
227751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 StringRef typestr, ClassKind ck) {
227851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s("BUILTIN(__builtin_neon_");
227951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
228051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If all types are the same size, bitcasting the args will take care
228151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // of arg checking.  The actual signedness etc. will be taken care of with
228251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // special enums.
22830391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu  if (!ProtoHasScalar(proto))
228451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
228551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
228651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += MangleName(name, typestr, ck);
228751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ", \"";
228851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
228951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = proto.size(); i != e; ++i)
229051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
229151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
229251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
229351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
229451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "i";
229551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
229651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\", \"n\")";
229751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
229851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
229951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
230051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenIntrinsic(const std::string &name,
230151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                const std::string &proto,
230251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                StringRef outTypeStr, StringRef inTypeStr,
230351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                OpKind kind, ClassKind classKind) {
230451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
2305667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  bool define = UseMacro(proto) && kind != OpUnavailable;
230651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
230751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
230851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // static always inline + return type
230951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
231051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "#define ";
231151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
231251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
231351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
231451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
231551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
231651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
231751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
231851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
231951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
232051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
232151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
232251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
232351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
232451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName;
232551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
232651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function arguments
23272102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin  s += GenArgs(proto, inTypeStr, name);
232851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
232951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Definition.
233051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define) {
233151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " __extension__ ({ \\\n  ";
23322102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    s += GenMacroLocals(proto, inTypeStr, name);
2333667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else if (kind == OpUnavailable) {
2334667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    s += " __attribute__((unavailable));\n";
2335667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    return s;
2336667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else
233766981c7ca1fcef529d7d5e5c53b07020ff23d8e3Jim Grosbach    s += " {\n  ";
233851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
233951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (kind != OpNone)
2340912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += GenOpString(name, kind, proto, outTypeStr);
234151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
234251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenBuiltin(name, proto, outTypeStr, classKind);
234351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
234451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " })";
234551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
234651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " }";
234751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\n";
234851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
234951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
235051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
235151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
235251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// is comprised of type definitions and function declarations.
235351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::run(raw_ostream &OS) {
235451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
235551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
235651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
235751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
235851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * Permission is hereby granted, free of charge, to any person obtaining "
235951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "a copy\n"
236051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * of this software and associated documentation files (the \"Software\"),"
236151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " to deal\n"
236251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * in the Software without restriction, including without limitation the "
236351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "rights\n"
236451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * to use, copy, modify, merge, publish, distribute, sublicense, "
236551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "and/or sell\n"
236651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * copies of the Software, and to permit persons to whom the Software is\n"
236751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * furnished to do so, subject to the following conditions:\n"
236851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
236951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * The above copyright notice and this permission notice shall be "
237051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "included in\n"
237151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * all copies or substantial portions of the Software.\n"
237251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
237351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
237451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "EXPRESS OR\n"
237551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
237651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "MERCHANTABILITY,\n"
237751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
237851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "SHALL THE\n"
237951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
238051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "OTHER\n"
238151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
238251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "ARISING FROM,\n"
238351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
238451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "DEALINGS IN\n"
238551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE.\n"
238651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
238751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *===--------------------------------------------------------------------"
238851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
238951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " */\n\n";
239051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
239151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON_H\n";
239251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#define __ARM_NEON_H\n\n";
239351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2394b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#if !defined(__ARM_NEON__) && !defined(__AARCH_FEATURE_ADVSIMD)\n";
239551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#error \"NEON support not enabled\"\n";
239651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
239751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
239851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#include <stdint.h>\n\n";
239951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
240051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit NEON-specific scalar typedefs.
240151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef float float32_t;\n";
2402b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef __fp16 float16_t;\n";
2403b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2404b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#ifdef __aarch64__\n";
2405b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef double float64_t;\n";
2406b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#endif\n\n";
2407b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2408b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // For now, signedness of polynomial types depends on target
2409b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#ifdef __aarch64__\n";
2410b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef uint8_t poly8_t;\n";
2411b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef uint16_t poly16_t;\n";
2412624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  OS << "typedef uint64_t poly64_t;\n";
2413b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#else\n";
241451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int8_t poly8_t;\n";
241551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int16_t poly16_t;\n";
2416b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#endif\n";
241751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
241851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit Neon vector typedefs.
2419b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::string TypedefTypes(
2420624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin      "cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl");
242151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 24> TDTypeVec;
242251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(0, TypedefTypes, TDTypeVec);
242351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
242451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vector typedefs.
24250aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  bool isA64 = false;
2426624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  bool preinsert;
2427624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  bool postinsert;
242851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
242951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy, quad = false, poly = false;
2430b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    char type = ClassifyType(TDTypeVec[i], quad, poly, dummy);
2431624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin    preinsert = false;
2432624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin    postinsert = false;
2433b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2434624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin    if (type == 'd' || (type == 'l' && poly)) {
24350aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      preinsert = isA64? false: true;
2436b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      isA64 = true;
24370aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    } else {
24380aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      postinsert = isA64? true: false;
24390aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      isA64 = false;
24400aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    }
24410aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    if (postinsert)
24420aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      OS << "#endif\n";
24430aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    if (preinsert)
2444b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << "#ifdef __aarch64__\n";
2445b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
244651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (poly)
244751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_polyvector_type(";
244851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
244951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_vector_type(";
245051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
245151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
245251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << utostr(nElts) << "))) ";
245351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (nElts < 10)
245451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << " ";
245551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
245651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << TypeString('s', TDTypeVec[i]);
245751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
2458b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
245951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2460624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  postinsert = isA64? true: false;
2461624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  if (postinsert)
2462624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin    OS << "#endif\n";
246351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
246451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
246551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit struct typedefs.
24660aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  isA64 = false;
246751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned vi = 2; vi != 5; ++vi) {
246851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
2469b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      bool dummy, quad = false, poly = false;
2470b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      char type = ClassifyType(TDTypeVec[i], quad, poly, dummy);
2471624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin      preinsert = false;
2472624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin      postinsert = false;
2473b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2474624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin      if (type == 'd' || (type == 'l' && poly)) {
24750aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        preinsert = isA64? false: true;
2476b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        isA64 = true;
24770aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      } else {
24780aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        postinsert = isA64? true: false;
24790aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        isA64 = false;
24800aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      }
24810aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      if (postinsert)
24820aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        OS << "#endif\n";
24830aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      if (preinsert)
2484b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "#ifdef __aarch64__\n";
2485b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
248651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string ts = TypeString('d', TDTypeVec[i]);
248751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
248851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef struct " << vs << " {\n";
248951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "  " << ts << " val";
249051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "[" << utostr(vi) << "]";
249151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ";\n} ";
2492b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << vs << ";\n";
2493b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << "\n";
249451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
249551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2496624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  postinsert = isA64? true: false;
2497624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  if (postinsert)
2498624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin    OS << "#endif\n";
2499624bb5e59dbcc24efeee7dff12c9b48d2b5077e9Kevin Qin  OS << "\n";
250051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
25011e8058f8d90fab1b9011adf62caa52e19e61382cBob Wilson  OS<<"#define __ai static inline __attribute__((__always_inline__, __nodebug__))\n\n";
250251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
250351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
250451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2505b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<ClassKind> EmittedMap;
2506b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
250751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
250851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // intrinsics.  (Some of the saturating multiply instructions are also
250951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // used to implement the corresponding "_lane" variants, but tablegen
251051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sorts the records into alphabetical order so that the "_lane" variants
251151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // come after the intrinsics they use.)
2512b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  emitIntrinsic(OS, Records.getDef("VMOVL"), EmittedMap);
2513b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  emitIntrinsic(OS, Records.getDef("VMULL"), EmittedMap);
2514b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  emitIntrinsic(OS, Records.getDef("VABD"), EmittedMap);
2515097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VABDL"), EmittedMap);
2516b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2517b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // ARM intrinsics must be emitted before AArch64 intrinsics to ensure
2518b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // common intrinsics appear only once in the output stream.
2519b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // The check for uniquiness is done in emitIntrinsic.
2520b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Emit ARM intrinsics.
252151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
252251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
2523b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2524b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Skip AArch64 intrinsics; they will be emitted at the end.
2525b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2526b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (isA64)
2527b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2528b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2529b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (R->getName() != "VMOVL" && R->getName() != "VMULL" &&
253051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VABD")
2531b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      emitIntrinsic(OS, R, EmittedMap);
253251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
253351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2534b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Emit AArch64-specific intrinsics.
2535b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#ifdef __aarch64__\n";
2536b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2537097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VMOVL_HIGH"), EmittedMap);
2538097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VMULL_HIGH"), EmittedMap);
2539097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VABDL_HIGH"), EmittedMap);
2540097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
2541b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
2542b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Record *R = RV[i];
2543b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2544b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Skip ARM intrinsics already included above.
2545b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2546b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64)
2547b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2548b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2549b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    emitIntrinsic(OS, R, EmittedMap);
2550b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  }
2551b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2552b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#endif\n\n";
2553b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
255451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef __ai\n\n";
255551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif /* __ARM_NEON_H */\n";
255651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
255751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
255851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
2559b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// intrinsics specified by record R checking for intrinsic uniqueness.
2560b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R,
2561b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                StringMap<ClassKind> &EmittedMap) {
256251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string name = R->getValueAsString("Name");
256351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Proto = R->getValueAsString("Prototype");
256451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Types = R->getValueAsString("Types");
256551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
256651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 16> TypeVec;
256751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(R, Types, TypeVec);
256851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
256951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
257051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
257151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ClassKind classKind = ClassNone;
257251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (R->getSuperClasses().size() >= 2)
257351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    classKind = ClassMap[R->getSuperClasses()[1]];
257451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (classKind == ClassNone && kind == OpNone)
257538859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError(R->getLoc(), "Builtin has no class kind");
257651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
257751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
257851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (kind == OpReinterpret) {
257951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool outQuad = false;
258051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool dummy = false;
258151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
258251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned srcti = 0, srcte = TypeVec.size();
258351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne           srcti != srcte; ++srcti) {
258451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool inQuad = false;
258551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
258651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (srcti == ti || inQuad != outQuad)
258751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          continue;
2588b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        std::string s = GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
2589b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                     OpCast, ClassS);
2590b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        if (EmittedMap.count(s))
2591b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          continue;
2592b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        EmittedMap[s] = ClassS;
2593b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << s;
259451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
259551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
2596b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      std::string s =
2597b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti], kind, classKind);
2598b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (EmittedMap.count(s))
2599b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
2600b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      EmittedMap[s] = classKind;
2601b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << s;
260251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
260351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
260451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
260551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
260651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
260751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned RangeFromType(const char mod, StringRef typestr) {
260851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
260951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false, dummy = false;
261051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
261151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
261251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
261351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
261451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
261551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (8 << (int)quad) - 1;
261651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
261751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
261851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (4 << (int)quad) - 1;
261951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
262051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
262151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (2 << (int)quad) - 1;
26220aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    case 'd':
262351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
262451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (1 << (int)quad) - 1;
262551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
262638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
262751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
262851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
262951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2630f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosierstatic unsigned RangeScalarShiftImm(const char mod, StringRef typestr) {
2631f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  // base type to get the type string for.
2632f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  bool dummy = false;
2633f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  char type = ClassifyType(typestr, dummy, dummy, dummy);
2634f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  type = ModType(mod, type, dummy, dummy, dummy, dummy, dummy, dummy);
2635f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2636f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  switch (type) {
2637f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'c':
2638f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 7;
2639f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'h':
2640f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 's':
2641f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 15;
2642f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'f':
2643f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'i':
2644f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 31;
2645f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'd':
2646f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'l':
2647f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 63;
2648f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    default:
2649f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      PrintFatalError("unhandled type!");
2650f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  }
2651f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier}
2652f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2653b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Generate the ARM and AArch64 intrinsic range checking code for
2654b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// shift/lane immediates, checking for unique declarations.
2655b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid
2656b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim NorthoverNeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
2657b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                        StringMap<ClassKind> &A64IntrinsicMap,
2658b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                        bool isA64RangeCheck) {
2659b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
266051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  StringMap<OpKind> EmittedMap;
266151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2662b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate the intrinsic range checking code for shift/lane immediates.
2663b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64RangeCheck)
2664b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_AARCH64_IMMEDIATE_CHECK\n";
2665b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  else
2666b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
2667b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
266851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
266951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
2670b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
267151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
267251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
267351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
267451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2675b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string name = R->getValueAsString("Name");
267651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
2677b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string Types = R->getValueAsString("Types");
2678944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = name + "@" + Proto;
267951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
268051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
268151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
268251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
268351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
268451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2685b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Functions which do not have an immediate do not need to have range
2686b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // checking code emitted.
2687b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    size_t immPos = Proto.find('i');
2688b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (immPos == std::string::npos)
2689b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2690b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
269151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
269251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
269351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
269451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
269538859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
269651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
269751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
269851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2699b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Do not include AArch64 range checks if not generating code for AArch64.
2700b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2701b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64RangeCheck && isA64)
2702b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2703b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2704b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Include ARM range checks in AArch64 but only if ARM intrinsics are not
2705b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // redefined by AArch64 to handle new types.
2706944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (isA64RangeCheck && !isA64 && A64IntrinsicMap.count(Rename)) {
2707944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ClassKind &A64CK = A64IntrinsicMap[Rename];
2708b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (A64CK == ck && ck != ClassNone)
2709b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
2710b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
2711b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
271251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
2713b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      std::string namestr, shiftstr, rangestr;
2714b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2715b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (R->getValueAsBit("isVCVT_N")) {
2716b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // VCVT between floating- and fixed-point values takes an immediate
2717912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        // in the range [1, 32] for f32, or [1, 64] for f64.
2718b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        ck = ClassB;
2719912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        if (name.find("32") != std::string::npos)
2720912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu          rangestr = "l = 1; u = 31"; // upper bound = l + u
2721912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        else if (name.find("64") != std::string::npos)
2722912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu          rangestr = "l = 1; u = 63";
2723912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        else
2724912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu          PrintFatalError(R->getLoc(),
2725912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu              "Fixed point convert name should contains \"32\" or \"64\"");
2726f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2727f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      } else if (R->getValueAsBit("isScalarShift")) {
27289473c1945f9f1dfa143e172622f16e4264e2628bChad Rosier        // Right shifts have an 'r' in the name, left shifts do not.  Convert
27299473c1945f9f1dfa143e172622f16e4264e2628bChad Rosier        // instructions have the same bounds and right shifts.
27309473c1945f9f1dfa143e172622f16e4264e2628bChad Rosier        if (name.find('r') != std::string::npos ||
27319473c1945f9f1dfa143e172622f16e4264e2628bChad Rosier            name.find("cvt") != std::string::npos)
2732f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier          rangestr = "l = 1; ";
2733f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2734f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier        rangestr += "u = " +
2735f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier          utostr(RangeScalarShiftImm(Proto[immPos - 1], TypeVec[ti]));
27360391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu      } else if (!ProtoHasScalar(Proto)) {
2737b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // Builtins which are overloaded by type will need to have their upper
2738b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // bound computed at Sema time based on the type constant.
2739b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        ck = ClassB;
2740b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        if (R->getValueAsBit("isShift")) {
2741b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          shiftstr = ", true";
2742b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2743b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          // Right shifts have an 'r' in the name, left shifts do not.
2744b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          if (name.find('r') != std::string::npos)
2745b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover            rangestr = "l = 1; ";
2746b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        }
2747b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        rangestr += "u = RFT(TV" + shiftstr + ")";
2748b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      } else {
2749b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // The immediate generally refers to a lane in the preceding argument.
2750b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        assert(immPos > 0 && "unexpected immediate operand");
2751b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        rangestr =
2752b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover            "u = " + utostr(RangeFromType(Proto[immPos - 1], TypeVec[ti]));
2753b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      }
2754b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Make sure cases appear only once by uniquing them in a string map.
2755b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      namestr = MangleName(name, TypeVec[ti], ck);
2756b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (EmittedMap.count(namestr))
275751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
2758b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      EmittedMap[namestr] = OpNone;
275951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2760b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Calculate the index of the immediate that should be range checked.
2761b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      unsigned immidx = 0;
2762b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2763b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Builtins that return a struct of multiple vectors have an extra
2764b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // leading arg for the struct return.
27652e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu      if (IsMultiVecProto(Proto[0]))
2766b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        ++immidx;
2767b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2768b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Add one to the index for each argument until we reach the immediate
2769b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // to be checked.  Structs of vectors are passed as multiple arguments.
2770b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
2771b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        switch (Proto[ii]) {
2772b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        default:
2773b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 1;
2774b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2775b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case '2':
27762e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu        case 'B':
2777b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 2;
2778b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2779b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case '3':
27802e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu        case 'C':
2781b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 3;
2782b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2783b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case '4':
27842e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu        case 'D':
2785b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 4;
2786b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2787b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case 'i':
2788b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          ie = ii + 1;
2789b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2790b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        }
2791b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      }
2792b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (isA64RangeCheck)
2793b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case AArch64::BI__builtin_neon_";
2794b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      else
2795b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case ARM::BI__builtin_neon_";
2796b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << MangleName(name, TypeVec[ti], ck) << ": i = " << immidx << "; "
2797b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover         << rangestr << "; break;\n";
279851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
279951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
280051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
2801b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2802b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2803b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Generate the ARM and AArch64 overloaded type checking code for
2804b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// SemaChecking.cpp, checking for unique builtin declarations.
2805b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid
2806b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim NorthoverNeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
2807b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                      StringMap<ClassKind> &A64IntrinsicMap,
2808b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                      bool isA64TypeCheck) {
2809b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2810b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<OpKind> EmittedMap;
281151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
281251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the overloaded type checking code for SemaChecking.cpp
2813b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64TypeCheck)
2814b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_AARCH64_OVERLOAD_CHECK\n";
2815b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  else
2816b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
2817b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
281851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
281951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
282051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
282151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
282251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
282351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
282451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
282551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
282651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
2827944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = name + "@" + Proto;
2828944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin
282951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
283051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
283151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
283251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
283351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
283451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which have a scalar argument cannot be overloaded, no need to
283551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // check them if we are emitting the type checking code.
28360391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu    if (ProtoHasScalar(Proto))
283751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
283851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
283951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
284051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
284151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
284251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
284338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
284451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2845b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Do not include AArch64 type checks if not generating code for AArch64.
2846b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2847b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64TypeCheck && isA64)
2848b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2849b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2850b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Include ARM  type check in AArch64 but only if ARM intrinsics
2851b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // are not redefined in AArch64 to handle new types, e.g. "vabd" is a SIntr
2852b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // redefined in AArch64 to handle an additional 2 x f64 type.
2853b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
2854944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (isA64TypeCheck && !isA64 && A64IntrinsicMap.count(Rename)) {
2855944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ClassKind &A64CK = A64IntrinsicMap[Rename];
2856b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (A64CK == ck && ck != ClassNone)
2857b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
2858b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
2859b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
286051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    int si = -1, qi = -1;
2861f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith    uint64_t mask = 0, qmask = 0;
286251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
286351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the switch case(s) for this builtin for the type validation.
286451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool quad = false, poly = false, usgn = false;
286551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
286651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
286751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (quad) {
286851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        qi = ti;
2869f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
287051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
287151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        si = ti;
2872f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
287351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
287451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
28754648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
28764648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // Check if the builtin function has a pointer or const pointer argument.
28774648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    int PtrArgNum = -1;
28784648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    bool HasConstPtr = false;
28794648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) {
28804648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      char ArgType = Proto[arg];
28814648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'c') {
28824648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        HasConstPtr = true;
28834648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
28844648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
28854648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
28864648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'p') {
28874648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
28884648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
28894648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
28904648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    }
28914648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // For sret builtins, adjust the pointer argument index.
28922e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    if (PtrArgNum >= 0 && IsMultiVecProto(Proto[0]))
28934648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      PtrArgNum += 1;
28944648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
28959082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
28969082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // and vst1_lane intrinsics.  Using a pointer to the vector element
28979082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // type with one of those operations causes codegen to select an aligned
28989082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // load/store instruction.  If you want an unaligned operation,
28999082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // the pointer argument needs to have less alignment than element type,
29009082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // so just accept any pointer type.
29019082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") {
29029082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      PtrArgNum = -1;
29039082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      HasConstPtr = false;
29049082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    }
29059082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson
29066f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (mask) {
2907b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (isA64TypeCheck)
2908b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case AArch64::BI__builtin_neon_";
2909b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      else
2910b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case ARM::BI__builtin_neon_";
2911b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << MangleName(name, TypeVec[si], ClassB) << ": mask = "
2912b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover         << "0x" << utohexstr(mask) << "ULL";
29134648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
29144648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
29156f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
29166f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
29176f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
29186f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
29196f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (qmask) {
2920b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (isA64TypeCheck)
2921b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case AArch64::BI__builtin_neon_";
2922b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      else
2923b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case ARM::BI__builtin_neon_";
2924b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << MangleName(name, TypeVec[qi], ClassB) << ": mask = "
2925b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover         << "0x" << utohexstr(qmask) << "ULL";
29264648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
29274648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
29286f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
29296f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
29306f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
29316f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
293251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
293351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
2934b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2935b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2936b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// genBuiltinsDef: Generate the BuiltinsARM.def and  BuiltinsAArch64.def
2937b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// declaration of builtins, checking for unique builtin declarations.
2938b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::genBuiltinsDef(raw_ostream &OS,
2939b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                 StringMap<ClassKind> &A64IntrinsicMap,
2940b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                 bool isA64GenBuiltinDef) {
2941b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2942b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<OpKind> EmittedMap;
2943b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2944b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate BuiltinsARM.def and BuiltinsAArch64.def
2945b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64GenBuiltinDef)
2946b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_AARCH64_BUILTINS\n";
2947b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  else
2948b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_BUILTINS\n";
294951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
295051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
295151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
295251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
295351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
295451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
295551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
295651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
2957b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string name = R->getValueAsString("Name");
2958944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = name + "@" + Proto;
295951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
296051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
296151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
296251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
296351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
296451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2965b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string Types = R->getValueAsString("Types");
296651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
296751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
296851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
296951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
297038859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
297151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
297251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
297351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2974b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Do not include AArch64 BUILTIN() macros if not generating
2975b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // code for AArch64
2976b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2977b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64GenBuiltinDef && isA64)
2978b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
297951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2980b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Include ARM  BUILTIN() macros  in AArch64 but only if ARM intrinsics
2981b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // are not redefined in AArch64 to handle new types, e.g. "vabd" is a SIntr
2982b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // redefined in AArch64 to handle an additional 2 x f64 type.
2983944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (isA64GenBuiltinDef && !isA64 && A64IntrinsicMap.count(Rename)) {
2984944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ClassKind &A64CK = A64IntrinsicMap[Rename];
2985b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (A64CK == ck && ck != ClassNone)
298651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
2987b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
298851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2989b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
2990b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Generate the declaration for this builtin, ensuring
2991b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // that each unique BUILTIN() macro appears only once in the output
2992b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // stream.
2993b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
2994b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (EmittedMap.count(bd))
2995b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
299651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2997b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      EmittedMap[bd] = OpNone;
2998b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << bd << "\n";
299951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
300051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
300151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
300251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
300351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3004b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// runHeader - Emit a file with sections defining:
3005b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 1. the NEON section of BuiltinsARM.def and BuiltinsAArch64.def.
3006b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 2. the SemaChecking code for the type overload checking.
3007b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
3008b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::runHeader(raw_ostream &OS) {
3009b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
3010b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3011b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // build a map of AArch64 intriniscs to be used in uniqueness checks.
3012b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<ClassKind> A64IntrinsicMap;
3013b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
3014b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Record *R = RV[i];
3015b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3016b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
3017b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64)
3018b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
3019b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3020b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    ClassKind CK = ClassNone;
3021b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (R->getSuperClasses().size() >= 2)
3022b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      CK = ClassMap[R->getSuperClasses()[1]];
3023b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3024b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string Name = R->getValueAsString("Name");
3025944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Proto = R->getValueAsString("Prototype");
3026944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = Name + "@" + Proto;
3027944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (A64IntrinsicMap.count(Rename))
3028b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
3029944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    A64IntrinsicMap[Rename] = CK;
3030b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  }
3031b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3032b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate BuiltinsARM.def for ARM
3033b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genBuiltinsDef(OS, A64IntrinsicMap, false);
3034b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3035b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate BuiltinsAArch64.def for AArch64
3036b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genBuiltinsDef(OS, A64IntrinsicMap, true);
3037b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3038b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate ARM overloaded type checking code for SemaChecking.cpp
3039b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genOverloadTypeCheckCode(OS, A64IntrinsicMap, false);
3040b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3041b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate AArch64 overloaded type checking code for SemaChecking.cpp
3042b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genOverloadTypeCheckCode(OS, A64IntrinsicMap, true);
3043b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3044b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate ARM range checking code for shift/lane immediates.
3045b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genIntrinsicRangeCheckCode(OS, A64IntrinsicMap, false);
3046b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3047b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate the AArch64 range checking code for shift/lane immediates.
3048b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genIntrinsicRangeCheckCode(OS, A64IntrinsicMap, true);
3049b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
3050b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
305151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// GenTest - Write out a test for the intrinsic specified by the name and
305251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// type strings, including the embedded patterns for FileCheck to match.
305351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenTest(const std::string &name,
305451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           const std::string &proto,
305551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           StringRef outTypeStr, StringRef inTypeStr,
30567200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                           bool isShift, bool isHiddenLOp,
3057b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                           ClassKind ck, const std::string &InstName,
305851cc0172a173599b769968696e20638754d1dcd6Ana Pazos                           bool isA64,
305951cc0172a173599b769968696e20638754d1dcd6Ana Pazos                           std::string & testFuncProto) {
306051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
306151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
306251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
306351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
306451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
306551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
306651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
306751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
306851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
306951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
307051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
307151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
307251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
307351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3074b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // todo: GenerateChecksForIntrinsic does not generate CHECK
3075b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // for aarch64 instructions yet
3076c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::vector<std::string> FileCheckPatterns;
3077b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (!isA64) {
3078b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	GenerateChecksForIntrinsic(name, proto, outTypeStr, inTypeStr, ck, InstName,
3079b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover							   isHiddenLOp, FileCheckPatterns);
3080b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	s+= "// CHECK_ARM: test_" + mangledName + "\n";
3081b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  }
3082b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  s += "// CHECK_AARCH64: test_" + mangledName + "\n";
3083c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
308451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the FileCheck patterns.
3085c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If for any reason we do not want to emit a check, mangledInst
3086c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // will be the empty string.
3087c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (FileCheckPatterns.size()) {
3088c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (std::vector<std::string>::const_iterator i = FileCheckPatterns.begin(),
3089c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                  e = FileCheckPatterns.end();
3090c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman         i != e;
3091c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman         ++i) {
3092b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      s += "// CHECK_ARM: " + *i + "\n";
3093c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
3094c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
309551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
309651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the start of the test function.
3097b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3098b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  testFuncProto = TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
309951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
310051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string comma;
310151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
310251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create arguments for values that must be immediate constants.
310351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i')
310451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
3105b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    testFuncProto += comma + TypeString(proto[i], inTypeStr) + " ";
3106b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    testFuncProto.push_back(arg);
310751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    comma = ", ";
310851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
3109b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  testFuncProto += ")";
3110b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3111b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  s+= testFuncProto;
3112b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  s+= " {\n  ";
311351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
311451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v')
311551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "return ";
311651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName + "(";
311751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  arg = 'a';
311851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
311951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i') {
312051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // For immediate operands, test the maximum value.
312151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (isShift)
312251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "1"; // FIXME
312351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
312451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
312551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += utostr(RangeFromType(proto[i-1], inTypeStr));
312651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
312751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(arg);
312851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
312951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
313051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
313151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
313251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");\n}\n\n";
313351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
313451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
313551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3136b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Write out all intrinsic tests for the specified target, checking
3137b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// for intrinsic test uniqueness.
3138b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::genTargetTest(raw_ostream &OS, StringMap<OpKind> &EmittedMap,
3139b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                bool isA64GenTest) {
3140b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64GenTest)
3141b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	OS << "#ifdef __aarch64__\n";
314251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3143b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
314451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
314551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
314651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
314751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
314851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
314951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool isShift = R->getValueAsBit("isShift");
31507200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    std::string InstName = R->getValueAsString("InstName");
31517200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    bool isHiddenLOp = R->getValueAsBit("isHiddenLInst");
3152b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
3153b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3154b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // do not include AArch64 intrinsic test if not generating
3155b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // code for AArch64
3156b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64GenTest && isA64)
3157b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
315851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
315951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
316051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
316151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
31627200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
316351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
3164667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    if (kind == OpUnavailable)
3165667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach      continue;
316651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
316751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (kind == OpReinterpret) {
316851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool outQuad = false;
316951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool dummy = false;
317051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
317151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        for (unsigned srcti = 0, srcte = TypeVec.size();
317251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne             srcti != srcte; ++srcti) {
317351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          bool inQuad = false;
317451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
317551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (srcti == ti || inQuad != outQuad)
317651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            continue;
3177b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover		  std::string testFuncProto;
3178b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          std::string s = GenTest(name, Proto, TypeVec[ti], TypeVec[srcti],
3179b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                  isShift, isHiddenLOp, ck, InstName, isA64,
3180b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover								  testFuncProto);
3181b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          if (EmittedMap.count(testFuncProto))
3182b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover            continue;
3183b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          EmittedMap[testFuncProto] = kind;
3184b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          OS << s << "\n";
318551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
318651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
3187b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover		std::string testFuncProto;
3188b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        std::string s = GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift,
3189b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                isHiddenLOp, ck, InstName, isA64, testFuncProto);
3190b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        if (EmittedMap.count(testFuncProto))
3191b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          continue;
3192b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        EmittedMap[testFuncProto] = kind;
3193b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << s << "\n";
319451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
319551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
319651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
3197b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3198b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64GenTest)
3199b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	OS << "#endif\n";
3200b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
3201b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// runTests - Write out a complete set of tests for all of the Neon
3202b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// intrinsics.
3203b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::runTests(raw_ostream &OS) {
3204b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "// RUN: %clang_cc1 -triple thumbv7s-apple-darwin -target-abi "
3205b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "apcs-gnu\\\n"
3206b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "// RUN:  -target-cpu swift -ffreestanding -Os -S -o - %s\\\n"
3207b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "// RUN:  | FileCheck %s -check-prefix=CHECK_ARM\n"
3208b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover		"\n"
3209b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	    "// RUN: %clang_cc1 -triple aarch64-none-linux-gnu \\\n"
3210b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	    "// RUN -target-feature +neon  -ffreestanding -S -o - %s \\\n"
3211b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	    "// RUN:  | FileCheck %s -check-prefix=CHECK_AARCH64\n"
3212b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "\n"
3213b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "// REQUIRES: long_tests\n"
3214b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "\n"
3215b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "#include <arm_neon.h>\n"
3216b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "\n";
3217b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3218b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // ARM tests must be emitted before AArch64 tests to ensure
3219b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // tests for intrinsics that are common to ARM and AArch64
3220b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // appear only once in the output stream.
3221b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // The check for uniqueness is done in genTargetTest.
3222b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<OpKind> EmittedMap;
3223b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3224b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genTargetTest(OS, EmittedMap, false);
3225b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
3226b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genTargetTest(OS, EmittedMap, true);
322751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
322851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
32293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
32303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
32313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).run(OS);
32323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
32333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
32343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runHeader(OS);
32353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
32363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
32373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runTests(OS);
32383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
32393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang
3240