NeonEmitter.cpp revision 22229d6822324a42913d25f256045dbf348a53e9
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,
843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpEq,
853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpGe,
863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLe,
873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpGt,
883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLt,
893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNeg,
903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNot,
913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAnd,
923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpOr,
933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpXor,
943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAndNot,
953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpOrNot,
963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpCast,
973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpConcat,
983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpDup,
993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpDupLane,
1003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpHi,
1013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLo,
1023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSelect,
1033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev16,
1043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev32,
1053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev64,
1063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpReinterpret,
107097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAddhnHi,
108097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpRAddhnHi,
109097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpSubhnHi,
110097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpRSubhnHi,
1113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAbdl,
112097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAbdlHi,
1133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAba,
114b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OpAbal,
115097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpAbalHi,
116097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpQDMullHi,
117097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpQDMlalHi,
118097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  OpQDMlslHi,
119912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  OpDiv,
120912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  OpLongHi,
121912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  OpNarrowHi,
1222102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin  OpMovlHi,
12322229d6822324a42913d25f256045dbf348a53e9Kevin Qin  OpCopyLane,
12422229d6822324a42913d25f256045dbf348a53e9Kevin Qin  OpCopyQLane,
12522229d6822324a42913d25f256045dbf348a53e9Kevin Qin  OpCopyLaneQ
1263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum ClassKind {
1293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassNone,
1303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassI,           // generic integer instruction, e.g., "i8" suffix
1313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassS,           // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
1323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassW,           // width-specific instruction, e.g., "8" suffix
13321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassB,           // bitcast arguments with enum argument to specify type
13421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassL,           // Logical instructions which are op instructions
13521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // but we need to not emit any suffix for in our
13621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // tests.
13721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassNoTest       // Instructions which we do not test since they are
13821e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // not TRUE instructions.
1393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// NeonTypeFlags - Flags to identify the types for overloaded Neon
1423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// builtins.  These must be kept in sync with the flags in
1433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// include/clang/Basic/TargetBuiltins.h.
1443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonTypeFlags {
1463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum {
1473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    EltTypeMask = 0xf,
1483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    UnsignedFlag = 0x10,
1493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    QuadFlag = 0x20
1503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t Flags;
1523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
1543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum EltType {
1553cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int8,
1563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int16,
1573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int32,
1583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int64,
1593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly8,
1603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly16,
1613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Float16,
162b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Float32,
163b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Float64
1643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(unsigned F) : Flags(F) {}
1673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
1683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsUnsigned)
1693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= UnsignedFlag;
1703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsQuad)
1713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= QuadFlag;
1723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
1733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t getFlags() const { return Flags; }
1753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
1773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonEmitter {
1803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  RecordKeeper &Records;
1813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  StringMap<OpKind> OpMap;
1823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  DenseMap<Record*, ClassKind> ClassMap;
1833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
1853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(RecordKeeper &R) : Records(R) {
1863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NONE"]  = OpNone;
1873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_UNAVAILABLE"] = OpUnavailable;
1883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADD"]   = OpAdd;
1893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDL"]  = OpAddl;
190097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ADDLHi"] = OpAddlHi;
1913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDW"]  = OpAddw;
192097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ADDWHi"] = OpAddwHi;
1933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUB"]   = OpSub;
1943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBL"]  = OpSubl;
195097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_SUBLHi"] = OpSublHi;
1963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBW"]  = OpSubw;
197097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_SUBWHi"] = OpSubwHi;
1983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL"]   = OpMul;
1993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA"]   = OpMla;
2003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL"]  = OpMlal;
201097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_MULLHi"]  = OpMullHi;
202097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_MLALHi"]  = OpMlalHi;
2033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS"]   = OpMls;
2043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL"]  = OpMlsl;
205097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_MLSLHi"] = OpMlslHi;
2063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_N"] = OpMulN;
2073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_N"] = OpMlaN;
2083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_N"] = OpMlsN;
2093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_N"] = OpMlalN;
2103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_N"] = OpMlslN;
2113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_LN"]= OpMulLane;
2120aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MULX_LN"]= OpMulXLane;
2133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MULL_LN"] = OpMullLane;
2140aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MULLHi_LN"] = OpMullHiLane;
2153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_LN"]= OpMlaLane;
2163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_LN"]= OpMlsLane;
2173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_LN"] = OpMlalLane;
2180aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MLALHi_LN"] = OpMlalHiLane;
2193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_LN"] = OpMlslLane;
2200aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_MLSLHi_LN"] = OpMlslHiLane;
2213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULL_LN"] = OpQDMullLane;
2220aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_QDMULLHi_LN"] = OpQDMullHiLane;
2233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
2240aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_QDMLALHi_LN"] = OpQDMlalHiLane;
2253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
2260aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_QDMLSLHi_LN"] = OpQDMlslHiLane;
2273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
2283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
2290aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_FMS_LN"] = OpFMSLane;
2300aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    OpMap["OP_FMS_LNQ"] = OpFMSLaneQ;
2313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_EQ"]    = OpEq;
2323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GE"]    = OpGe;
2333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LE"]    = OpLe;
2343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GT"]    = OpGt;
2353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LT"]    = OpLt;
2363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NEG"]   = OpNeg;
2373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NOT"]   = OpNot;
2383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_AND"]   = OpAnd;
2393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_OR"]    = OpOr;
2403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_XOR"]   = OpXor;
2413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ANDN"]  = OpAndNot;
2423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ORN"]   = OpOrNot;
2433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CAST"]  = OpCast;
2443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CONC"]  = OpConcat;
2453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_HI"]    = OpHi;
2463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LO"]    = OpLo;
2473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP"]   = OpDup;
2483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP_LN"] = OpDupLane;
2493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SEL"]   = OpSelect;
2503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV16"] = OpRev16;
2513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV32"] = OpRev32;
2523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV64"] = OpRev64;
2533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REINT"] = OpReinterpret;
254097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ADDHNHi"] = OpAddhnHi;
255097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_RADDHNHi"] = OpRAddhnHi;
256097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_SUBHNHi"] = OpSubhnHi;
257097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_RSUBHNHi"] = OpRSubhnHi;
2583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABDL"]  = OpAbdl;
259097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ABDLHi"] = OpAbdlHi;
2603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABA"]   = OpAba;
2613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABAL"]  = OpAbal;
262097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_ABALHi"] = OpAbalHi;
263097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_QDMULLHi"] = OpQDMullHi;
264097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_QDMLALHi"] = OpQDMlalHi;
265097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    OpMap["OP_QDMLSLHi"] = OpQDMlslHi;
266b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OpMap["OP_DIV"] = OpDiv;
267912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    OpMap["OP_LONG_HI"] = OpLongHi;
268912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    OpMap["OP_NARROW_HI"] = OpNarrowHi;
269912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    OpMap["OP_MOVL_HI"] = OpMovlHi;
27022229d6822324a42913d25f256045dbf348a53e9Kevin Qin    OpMap["OP_COPY_LN"] = OpCopyLane;
27122229d6822324a42913d25f256045dbf348a53e9Kevin Qin    OpMap["OP_COPYQ_LN"] = OpCopyQLane;
27222229d6822324a42913d25f256045dbf348a53e9Kevin Qin    OpMap["OP_COPY_LNQ"] = OpCopyLaneQ;
2733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *SI = R.getClass("SInst");
2753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *II = R.getClass("IInst");
2763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *WI = R.getClass("WInst");
27721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *SOpI = R.getClass("SOpInst");
27821e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *IOpI = R.getClass("IOpInst");
27921e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *WOpI = R.getClass("WOpInst");
28021e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *LOpI = R.getClass("LOpInst");
28121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *NoTestOpI = R.getClass("NoTestOpInst");
28221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman
2833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[SI] = ClassS;
2843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[II] = ClassI;
2853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[WI] = ClassW;
28621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[SOpI] = ClassS;
28721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[IOpI] = ClassI;
28821e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[WOpI] = ClassW;
28921e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[LOpI] = ClassL;
29021e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[NoTestOpI] = ClassNoTest;
2913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
2923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // run - Emit arm_neon.h.inc
2943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void run(raw_ostream &o);
2953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runHeader - Emit all the __builtin prototypes used in arm_neon.h
2973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runHeader(raw_ostream &o);
2983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runTests - Emit tests for all the Neon intrinsics.
3003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runTests(raw_ostream &o);
3013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
3023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenprivate:
303b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void emitIntrinsic(raw_ostream &OS, Record *R,
304b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                     StringMap<ClassKind> &EmittedMap);
305b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genBuiltinsDef(raw_ostream &OS, StringMap<ClassKind> &A64IntrinsicMap,
306b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                      bool isA64GenBuiltinDef);
307b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genOverloadTypeCheckCode(raw_ostream &OS,
308b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                StringMap<ClassKind> &A64IntrinsicMap,
309b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                bool isA64TypeCheck);
310b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genIntrinsicRangeCheckCode(raw_ostream &OS,
311b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                  StringMap<ClassKind> &A64IntrinsicMap,
312b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                  bool isA64RangeCheck);
313b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  void genTargetTest(raw_ostream &OS, StringMap<OpKind> &EmittedMap,
314b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                     bool isA64TestGen);
3153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
3163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
3173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
31851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
31951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// which each StringRef representing a single type declared in the string.
32051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
32151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2xfloat and 4xfloat respectively.
32251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic void ParseTypes(Record *r, std::string &s,
32351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                       SmallVectorImpl<StringRef> &TV) {
32451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const char *data = s.data();
32551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  int len = 0;
32651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
32751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
32812cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U'
329944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin                         || data[len] == 'H' || data[len] == 'S')
33051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
33151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
33251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (data[len]) {
33351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'c':
33451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 's':
33551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'i':
33651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'l':
33751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'h':
33851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'f':
339b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      case 'd':
34051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
34151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      default:
34238859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger        PrintFatalError(r->getLoc(),
34351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      "Unexpected letter: " + std::string(data + len, 1));
34451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
34551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    TV.push_back(StringRef(data, len + 1));
34651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    data += len + 1;
34751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    len = -1;
34851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
34951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
35051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
35151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Widen - Convert a type code into the next wider type.  char -> short,
35251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// short -> int, etc.
35351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Widen(const char t) {
35451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
35551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
35651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
35751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
35851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
35951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
36051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'l';
36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'f';
36338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    default:
36438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type in widen!");
36551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
36651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
36751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
36851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Narrow - Convert a type code into the next smaller type.  short -> char,
36951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// float -> half float, etc.
37051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Narrow(const char t) {
37151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
37251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
37351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'c';
37451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
37551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
37651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
37751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
37851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
37951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'h';
38038859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    default:
38138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type in narrow!");
38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
38351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
38451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
385097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string GetNarrowTypestr(StringRef ty)
386097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu{
387097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
388097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  for (size_t i = 0, end = ty.size(); i < end; i++) {
389097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    switch (ty[i]) {
390097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      case 's':
391097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += 'c';
392097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
393097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      case 'i':
394097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += 's';
395097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
396097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      case 'l':
397097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += 'i';
398097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
399097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      default:
400097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        s += ty[i];
401097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu        break;
402097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    }
403097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
404097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
405097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
406097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
407097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// For a particular StringRef, return the base type code, and whether it has
40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// the quad-vector, polynomial, or unsigned modifiers set.
41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned off = 0;
412944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  // ignore scalar.
413944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if (ty[off] == 'S') {
414944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    ++off;
415944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember quad.
41712cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu  if (ty[off] == 'Q' || ty[off] == 'H') {
41851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    quad = true;
41951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
42051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
42151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
42251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember poly.
42351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'P') {
42451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = true;
42551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
42651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
42751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
42851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember unsigned.
42951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'U') {
43051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
43151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
43251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
43351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
43451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
43551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return ty[off];
43651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
43751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
43851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ModType - Transform a type code and its modifiers based on a mod code. The
43951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// mod code definitions may be found at the top of arm_neon.td.
44051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ModType(const char mod, char type, bool &quad, bool &poly,
44151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
44251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (mod) {
44351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 't':
44451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (poly) {
44551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        poly = false;
44651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        usgn = true;
44751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
44851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
449564020954e9eb01293d90802c89a02f87301e095Chad Rosier    case 'b':
450564020954e9eb01293d90802c89a02f87301e095Chad Rosier      scal = true;
45151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'u':
45251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
45351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
45451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
45551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
456b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (type == 'd')
457b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        type = 'l';
45851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
45951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'x':
46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
46351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
464912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      if (type == 'd')
465912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        type = 'l';
46651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
4676d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier    case 'o':
4686d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      scal = true;
4696d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      type = 'd';
4706d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      usgn = false;
4716d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      break;
4726d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier    case 'y':
4736d048e1a9768b594513e2ec7a6d3579787eb2505Chad Rosier      scal = true;
47451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = true;
47751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'f';
47851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
47951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'g':
48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = false;
48251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
4830aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    case 'j':
4840aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      quad = true;
4850aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      break;
48651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'w':
48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
48851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
48951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
49051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'n':
49151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
49251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
49351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
49451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'i';
49551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
49651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
49751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
49851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'l';
49951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
50051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
50151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
5024553a858e46299955333babfa052a512682869fdChad Rosier    case 'z':
5034553a858e46299955333babfa052a512682869fdChad Rosier      type = Narrow(type);
5044553a858e46299955333babfa052a512682869fdChad Rosier      scal = true;
5054553a858e46299955333babfa052a512682869fdChad Rosier      break;
5060391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu    case 'r':
5070391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu      type = Widen(type);
5084553a858e46299955333babfa052a512682869fdChad Rosier      scal = true;
5094553a858e46299955333babfa052a512682869fdChad Rosier      break;
51051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
51151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'a':
51251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
51351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
51451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'k':
51551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
51651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
51751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
51851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      cnst = true;
51951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'p':
52051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      pntr = true;
52151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
52251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
52351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
52451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
52551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
52651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = false;
52751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
528097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    case 'q':
529097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      type = Narrow(type);
530097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      quad = true;
531097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu      break;
53251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'e':
53351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
53451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
53551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
536912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    case 'm':
537912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      type = Narrow(type);
538912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      quad = false;
539912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu      break;
54051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
54151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
54251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
54351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return type;
54451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// TypeString - for a modifier and type, generate the name of the typedef for
54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// that type.  QUc -> uint8x8_t.
54851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string TypeString(const char mod, StringRef typestr) {
54951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
55051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
55151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
55251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
55451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
55551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
55651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
55751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "void";
55851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
55951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "int";
56051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
56251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
56351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
56551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
56751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallString<128> s;
56851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
56951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (usgn)
57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back('u');
57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
57451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly8" : "int8";
57551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
57651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
57751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x16" : "x8";
57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly16" : "int16";
58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
58451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
58551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int32";
58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
59151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
59251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int64";
59351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
59451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
59551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x2" : "x1";
59651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float16";
59951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
60051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
60151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
60251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
60351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
60451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float32";
60551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
60651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
60751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
60851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
609b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case 'd':
610b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      s += "float64";
611b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (scal)
612b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        break;
613b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      s += quad ? "x2" : "x1";
614b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
615b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
61738859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
61951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
62051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
62151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x2";
62251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
62351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x3";
62451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x4";
62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Append _t, finishing the type string typedef type.
62851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "_t";
62951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
63051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (cnst)
63151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " const";
63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr)
63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " *";
63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
63651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s.str();
63751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
63851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
63951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinTypeString - for a modifier and type, generate the clang
64051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinsARM.def prototype code for the function.  See the top of clang's
64151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Builtins.def for a description of the type strings.
64251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string BuiltinTypeString(const char mod, StringRef typestr,
64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                     ClassKind ck, bool ret) {
64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
64551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
64651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
64751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
64851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
64951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
65051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
65151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
65251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "v"; // void
65351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
65451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "i"; // int
65551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
65651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
65751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
65851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
65951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
66051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
66151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
66251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // All pointers are void* pointers.  Change type to 'v' now.
66351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr) {
66451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = false;
66551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = false;
66651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 'v';
66751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
66851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Treat half-float ('h') types as unsigned short ('s') types.
66951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (type == 'h') {
67051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 's';
67151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
67251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
6730aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) &&
6740aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu                         scal && type != 'f' && type != 'd');
67551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
67651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (scal) {
67751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallString<128> s;
67851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
67951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (usgn)
68051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('U');
68151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else if (type == 'c')
68251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('S'); // make chars explicitly signed
68351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (type == 'l') // 64-bit long
68551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "LLi";
68651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
68751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(type);
68851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (cnst)
69051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('C');
69151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (pntr)
69251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('*');
69351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return s.str();
69451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
69551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
69651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Since the return value must be one type, return a vector type of the
69751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // appropriate width which we will bitcast.  An exception is made for
69851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
69951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // fashion, storing them to a pointer arg.
70051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ret) {
70151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod >= '2' && mod <= '4')
70251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return "vv*"; // void result with void* first argument
70351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod == 'f' || (ck != ClassB && type == 'f'))
70451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4f" : "V2f";
7050aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    if (ck != ClassB && type == 'd')
7060aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      return quad ? "V2d" : "V1d";
70751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 's')
70851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V8s" : "V4s";
70951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'i')
71051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4i" : "V2i";
71151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'l')
71251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V2LLi" : "V1LLi";
71351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
71451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16Sc" : "V8Sc";
71551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
71651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
71751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Non-return array types are passed as individual vectors.
71851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
71951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
72051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
72151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
72251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
72351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
72451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'f' || (ck != ClassB && type == 'f'))
72651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4f" : "V2f";
7270aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  if (ck != ClassB && type == 'd')
7280aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    return quad ? "V2d" : "V1d";
72951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 's')
73051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V8s" : "V4s";
73151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'i')
73251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4i" : "V2i";
73351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'l')
73451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V2LLi" : "V1LLi";
73551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
73651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return quad ? "V16Sc" : "V8Sc";
73751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
73851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
739fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// InstructionTypeCode - Computes the ARM argument character code and
740fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// quad status for a specific type string and ClassKind.
741fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic void InstructionTypeCode(const StringRef &typeStr,
742fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                const ClassKind ck,
743fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                bool &quad,
744fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                std::string &typeCode) {
74551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
74651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
747fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  char type = ClassifyType(typeStr, quad, poly, usgn);
74851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
74951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
75051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c':
75151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
752fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = poly ? "p8" : usgn ? "u8" : "s8"; break;
753fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i8"; break;
754fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "8"; break;
75551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
75651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
75751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
75851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's':
75951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
760fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = poly ? "p16" : usgn ? "u16" : "s16"; break;
761fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i16"; break;
762fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "16"; break;
76351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
76451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
76551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
76651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i':
76751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
768fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = usgn ? "u32" : "s32"; break;
769fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i32"; break;
770fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "32"; break;
77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
77251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
77351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
77451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l':
77551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
776fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = usgn ? "u64" : "s64"; break;
777fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i64"; break;
778fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "64"; break;
77951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
78051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
78151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
78251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h':
78351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
78451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
785fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "f16"; break;
786fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "16"; break;
78751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
78851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
78951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
79051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f':
79151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
79251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
793fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "f32"; break;
794fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "32"; break;
79551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
79751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
798b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  case 'd':
799b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    switch (ck) {
800b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case ClassS:
801b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case ClassI:
802b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      typeCode += "f64";
803b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
804b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case ClassW:
805b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      PrintFatalError("unhandled type!");
806b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    default:
807b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
808b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
809b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    break;
81051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
81138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unhandled type!");
81251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
813fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman}
814fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
815944f09ff9b33637465906e1aeadcfa405d66331dKevin Qinstatic char Insert_BHSD_Suffix(StringRef typestr){
816944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  unsigned off = 0;
817944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if(typestr[off++] == 'S'){
818944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    while(typestr[off] == 'Q' || typestr[off] == 'H'||
819944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin          typestr[off] == 'P' || typestr[off] == 'U')
820944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ++off;
821944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    switch (typestr[off]){
822944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    default  : break;
823944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'c' : return 'b';
824944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 's' : return 'h';
825944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'i' :
826944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'f' : return 's';
827944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'l' :
828944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    case 'd' : return 'd';
829944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    }
830944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
831944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  return 0;
832944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin}
833944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin
834fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// MangleName - Append a type or width suffix to a base neon function name,
83512cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu/// and insert a 'q' in the appropriate location if type string starts with 'Q'.
83612cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu/// E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
837944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin/// Insert proper 'b' 'h' 's' 'd' if prefix 'S' is used.
838fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic std::string MangleName(const std::string &name, StringRef typestr,
839fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                              ClassKind ck) {
840fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  if (name == "vcvt_f32_f16")
841fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    return name;
842fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
843fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  bool quad = false;
844fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  std::string typeCode = "";
845fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
846fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  InstructionTypeCode(typestr, ck, quad, typeCode);
847fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
848fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  std::string s = name;
849fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
850fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  if (typeCode.size() > 0) {
851fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    s += "_" + typeCode;
852fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  }
853fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
85451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
85551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "_v";
85651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
85751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Insert a 'q' before the first '_' character so that it ends up before
85851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // _lane or _n on vector-scalar operations.
859944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if (typestr.find("Q") != StringRef::npos) {
86012cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu      size_t pos = s.find('_');
86112cd6a83f280bcab0e80230e8c7b1f989f3b4889Hao Liu      s = s.insert(pos, "q");
86251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
863944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  char ins = Insert_BHSD_Suffix(typestr);
864944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  if(ins){
865944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    size_t pos = s.find('_');
866944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    s = s.insert(pos, &ins, 1);
867944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
868c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
86951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
87051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
87151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
872c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void PreprocessInstruction(const StringRef &Name,
873c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const std::string &InstName,
874c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  std::string &Prefix,
875c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasNPostfix,
876c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasLanePostfix,
877c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasDupPostfix,
878c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &IsSpecialVCvt,
879c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  size_t &TBNumber) {
880c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // All of our instruction name fields from arm_neon.td are of the form
881c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  //   <instructionname>_...
882c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Thus we grab our instruction name via computation of said Prefix.
883c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const size_t PrefixEnd = Name.find_first_of('_');
884c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If InstName is passed in, we use that instead of our name Prefix.
885c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Prefix = InstName.size() == 0? Name.slice(0, PrefixEnd).str() : InstName;
886c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
887c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef Postfix = Name.slice(PrefixEnd, Name.size());
888c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
889c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasNPostfix = Postfix.count("_n");
890c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasLanePostfix = Postfix.count("_lane");
891c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasDupPostfix = Postfix.count("_dup");
892c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  IsSpecialVCvt = Postfix.size() != 0 && Name.count("vcvt");
893c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
894c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (InstName.compare("vtbl") == 0 ||
895c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      InstName.compare("vtbx") == 0) {
896c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a vtblN/vtbxN instruction, use the instruction's ASCII
897c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // encoding to get its true value.
898c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    TBNumber = Name[Name.size()-1] - 48;
899c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
900c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
901c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
902c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatternsForLoadStores - Given a bunch of data we have
903c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern for a Load Or Store
904c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void
905c327f8705ecb8753555822d479f899bd2234386dMichael GottesmanGenerateRegisterCheckPatternForLoadStores(const StringRef &NameRef,
906c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const std::string& OutTypeCode,
907c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &IsQuad,
908c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &HasDupPostfix,
909c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &HasLanePostfix,
910c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const size_t Count,
911c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          std::string &RegisterSuffix) {
912c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsLDSTOne = NameRef.count("vld1") || NameRef.count("vst1");
913c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If N == 3 || N == 4 and we are dealing with a quad instruction, Clang
914c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // will output a series of v{ld,st}1s, so we have to handle it specially.
915c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((Count == 3 || Count == 4) && IsQuad) {
916c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "{";
917c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < Count; i++) {
918c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}";
919c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasDupPostfix) {
920c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[]";
921c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
922c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
923c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[{{[0-9]+}}]";
924c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
925c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (i < Count-1) {
926c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", ";
927c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
928c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
929c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "}";
930c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else {
931c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
932c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Handle normal loads and stores.
933c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "{";
934c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < Count; i++) {
935c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}";
936c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasDupPostfix) {
937c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[]";
938c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
939c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
940c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[{{[0-9]+}}]";
941c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
942c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (IsQuad && !HasLanePostfix) {
943c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", d{{[0-9]+}}";
944c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        if (HasDupPostfix) {
945c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          RegisterSuffix += "[]";
946c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        }
947c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
948c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (i < Count-1) {
949c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", ";
950c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
951c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
952c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "}, [r{{[0-9]+}}";
953c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
954c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // We only include the alignment hint if we have a vld1.*64 or
955c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // a dup/lane instruction.
956c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (IsLDSTOne) {
957c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if ((HasLanePostfix || HasDupPostfix) && OutTypeCode != "8") {
958410c3f73cb0c78f72335dc712a9d887d77b8e7ceMichael Gottesman        RegisterSuffix += ":" + OutTypeCode;
959c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
960c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
961c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
962c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "]";
963c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
964c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
965c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
966c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool HasNPostfixAndScalarArgs(const StringRef &NameRef,
967c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                     const bool &HasNPostfix) {
968c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (NameRef.count("vmla") ||
969c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlal") ||
970c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlsl") ||
971c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmull") ||
972c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlal") ||
973c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlsl") ||
974c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmulh") ||
975c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmull") ||
976c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqrdmulh")) && HasNPostfix;
977c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
978c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
979c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsFiveOperandLaneAccumulator(const StringRef &NameRef,
980c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasLanePostfix) {
981c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (NameRef.count("vmla") ||
982c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmls") ||
983c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlal") ||
984c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlsl") ||
985c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          (NameRef.count("vmul") && NameRef.size() == 3)||
986c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlal") ||
987c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlsl") ||
988c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmulh") ||
989c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqrdmulh")) && HasLanePostfix;
990c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
991c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
992c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsSpecialLaneMultiply(const StringRef &NameRef,
993c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const bool &HasLanePostfix,
994c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const bool &IsQuad) {
995c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVMulOrMulh = (NameRef.count("vmul") || NameRef.count("mulh"))
996c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               && IsQuad;
997c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVMull = NameRef.count("mull") && !IsQuad;
998c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (IsVMulOrMulh || IsVMull) && HasLanePostfix;
999c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1000c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1001c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void NormalizeProtoForRegisterPatternCreation(const std::string &Name,
1002c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const std::string &Proto,
1003c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasNPostfix,
1004c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &IsQuad,
1005c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasLanePostfix,
1006c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasDupPostfix,
1007c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     std::string &NormedProto) {
1008c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Handle generic case.
1009c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
1010c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  for (size_t i = 0, end = Proto.size(); i < end; i++) {
1011c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    switch (Proto[i]) {
1012c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'u':
1013c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'f':
1014c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'd':
1015c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 's':
1016c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'x':
1017c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 't':
1018c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'n':
1019c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += IsQuad? 'q' : 'd';
1020c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1021c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'w':
1022c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'k':
1023c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += 'q';
1024c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1025c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'g':
10260aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    case 'j':
1027c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'h':
1028c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'e':
1029c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += 'd';
1030c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1031c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'i':
1032c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += HasLanePostfix? 'a' : 'i';
1033c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1034c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'a':
1035c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
1036c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += 'a';
1037c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else if (HasNPostfixAndScalarArgs(NameRef, HasNPostfix)) {
1038c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += IsQuad? 'q' : 'd';
1039c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else {
1040c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += 'i';
1041c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1042c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
1043c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1044c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1045c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1046c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Handle Special Cases.
1047c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsNotVExt = !NameRef.count("vext");
1048c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVPADAL = NameRef.count("vpadal");
1049c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool Is5OpLaneAccum = IsFiveOperandLaneAccumulator(NameRef,
1050c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                           HasLanePostfix);
1051c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsSpecialLaneMul = IsSpecialLaneMultiply(NameRef, HasLanePostfix,
1052c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                      IsQuad);
1053c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1054c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (IsSpecialLaneMul) {
1055c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If
1056c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto[2] = NormedProto[3];
1057c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto.erase(3);
1058c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (NormedProto.size() == 4 &&
1059c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman             NormedProto[0] == NormedProto[1] &&
1060c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman             IsNotVExt) {
1061c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If NormedProto.size() == 4 and the first two proto characters are the
1062c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // same, ignore the first.
1063c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = NormedProto.substr(1, 3);
1064c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (Is5OpLaneAccum) {
1065c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a 5 op lane accumulator operation, we take characters 1,2,4
1066c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string tmp = NormedProto.substr(1,2);
1067c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[4];
1068c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = tmp;
1069c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (IsVPADAL) {
1070c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have VPADAL, ignore the first character.
1071c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = NormedProto.substr(0, 2);
1072c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (NameRef.count("vdup") && NormedProto.size() > 2) {
1073c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If our instruction is a dup instruction, keep only the first and
1074c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // last characters.
1075c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string tmp = "";
1076c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[0];
1077c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[NormedProto.size()-1];
1078c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = tmp;
1079c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1080c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1081c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1082c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatterns - Given a bunch of data we have
1083c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern to check that an
1084c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// instruction's arguments are correct.
1085c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateRegisterCheckPattern(const std::string &Name,
1086c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const std::string &Proto,
1087c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const std::string &OutTypeCode,
1088c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasNPostfix,
1089c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &IsQuad,
1090c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasLanePostfix,
1091c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasDupPostfix,
1092c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const size_t &TBNumber,
1093c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         std::string &RegisterSuffix) {
1094c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1095c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  RegisterSuffix = "";
1096c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1097c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
1098c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef ProtoRef(Proto);
1099c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1100c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((NameRef.count("vdup") || NameRef.count("vmov")) && HasNPostfix) {
1101c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1102c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1103c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1104c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsLoadStore = NameRef.count("vld") || NameRef.count("vst");
1105c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsTBXOrTBL = NameRef.count("vtbl") || NameRef.count("vtbx");
1106c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1107c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (IsLoadStore) {
1108c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Grab N value from  v{ld,st}N using its ascii representation.
1109c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    const size_t Count = NameRef[3] - 48;
1110c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1111c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    GenerateRegisterCheckPatternForLoadStores(NameRef, OutTypeCode, IsQuad,
1112c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                              HasDupPostfix, HasLanePostfix,
1113c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                              Count, RegisterSuffix);
1114c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (IsTBXOrTBL) {
1115c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "d{{[0-9]+}}, {";
1116c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < TBNumber-1; i++) {
1117c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}, ";
1118c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1119c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "d{{[0-9]+}}}, d{{[0-9]+}}";
1120c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else {
1121c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Handle a normal instruction.
1122c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (NameRef.count("vget") || NameRef.count("vset"))
1123c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1124c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1125c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // We first normalize our proto, since we only need to emit 4
1126c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // different types of checks, yet have more than 4 proto types
1127c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // that map onto those 4 patterns.
1128c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string NormalizedProto("");
1129c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormalizeProtoForRegisterPatternCreation(Name, Proto, HasNPostfix, IsQuad,
1130c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                             HasLanePostfix, HasDupPostfix,
1131c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                             NormalizedProto);
1132c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1133c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0, end = NormalizedProto.size(); i < end; i++) {
1134c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      const char &c = NormalizedProto[i];
1135c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      switch (c) {
1136c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'q':
1137c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "q{{[0-9]+}}, ";
1138c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1139c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1140c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'd':
1141c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "d{{[0-9]+}}, ";
1142c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1143c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1144c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'i':
1145c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "#{{[0-9]+}}, ";
1146c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1147c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1148c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'a':
1149c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "d{{[0-9]+}}[{{[0-9]}}], ";
1150c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
1151c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1152c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1153c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1154c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Remove extra ", ".
1155c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix = RegisterSuffix.substr(0, RegisterSuffix.size()-2);
1156c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1157c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1158c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1159c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateChecksForIntrinsic - Given a specific instruction name +
1160c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// typestr + class kind, generate the proper set of FileCheck
1161c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// Patterns to check for. We could just return a string, but instead
1162c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// use a vector since it provides us with the extra flexibility of
1163c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// emitting multiple checks, which comes in handy for certain cases
1164c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// like mla where we want to check for 2 different instructions.
1165c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateChecksForIntrinsic(const std::string &Name,
1166c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       const std::string &Proto,
1167c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       StringRef &OutTypeStr,
1168c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       StringRef &InTypeStr,
1169c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       ClassKind Ck,
1170c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       const std::string &InstName,
1171c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       bool IsHiddenLOp,
1172c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       std::vector<std::string>& Result) {
1173c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1174c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If Ck is a ClassNoTest instruction, just return so no test is
1175c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // emitted.
1176c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if(Ck == ClassNoTest)
1177c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1178c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1179c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Name == "vcvt_f32_f16") {
1180c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back("vcvt.f32.f16");
1181c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1182c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1183c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1184c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1185c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Now we preprocess our instruction given the data we have to get the
1186c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // data that we need.
1187c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Create a StringRef for String Manipulation of our Name.
1188c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
1189c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Instruction Prefix.
1190c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string Prefix;
1191c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // The type code for our out type string.
1192c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string OutTypeCode;
1193c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // To handle our different cases, we need to check for different postfixes.
1194c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Is our instruction a quad instruction.
1195c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool IsQuad = false;
1196c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_n.
1197c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasNPostfix = false;
1198c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_lane.
1199c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasLanePostfix = false;
1200c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_dup.
1201c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasDupPostfix  = false;
1202c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is a vcvt instruction which requires special handling.
1203c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool IsSpecialVCvt = false;
1204c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have a vtbxN or vtblN instruction, this is set to N.
1205c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  size_t TBNumber = -1;
1206c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Register Suffix
1207c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string RegisterSuffix;
1208c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1209c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  PreprocessInstruction(NameRef, InstName, Prefix,
1210c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                        HasNPostfix, HasLanePostfix, HasDupPostfix,
1211c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                        IsSpecialVCvt, TBNumber);
1212c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1213c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  InstructionTypeCode(OutTypeStr, Ck, IsQuad, OutTypeCode);
1214c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  GenerateRegisterCheckPattern(Name, Proto, OutTypeCode, HasNPostfix, IsQuad,
1215c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               HasLanePostfix, HasDupPostfix, TBNumber,
1216c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               RegisterSuffix);
1217c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1218c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // In the following section, we handle a bunch of special cases. You can tell
1219c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // a special case by the fact we are returning early.
1220c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1221c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If our instruction is a logical instruction without postfix or a
1222c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // hidden LOp just return the current Prefix.
1223c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Ck == ClassL || IsHiddenLOp) {
1224c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back(Prefix + " " + RegisterSuffix);
1225c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1226c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1227c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1228c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have a vmov, due to the many different cases, some of which
1229c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // vary within the different intrinsics generated for a single
1230c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // instruction type, just output a vmov. (e.g. given an instruction
1231c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // A, A.u32 might be vmov and A.u8 might be vmov.8).
1232c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  //
1233c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // FIXME: Maybe something can be done about this. The two cases that we care
1234c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // about are vmov as an LType and vmov as a WType.
1235c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Prefix == "vmov") {
1236c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back(Prefix + " " + RegisterSuffix);
1237c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1238c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1239c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1240c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // In the following section, we handle special cases.
1241c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1242c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (OutTypeCode == "64") {
1243c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a 64 bit vdup/vext and are handling an uint64x1_t
1244c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // type, the intrinsic will be optimized away, so just return
1245c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // nothing.  On the other hand if we are handling an uint64x2_t
1246c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // (i.e. quad instruction), vdup/vmov instructions should be
1247c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // emitted.
1248c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (Prefix == "vdup" || Prefix == "vext") {
1249c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (IsQuad) {
1250c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{vmov|vdup}}");
1251c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1252c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1253c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1254c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1255c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // v{st,ld}{2,3,4}_{u,s}64 emit v{st,ld}1.64 instructions with
1256c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // multiple register operands.
1257c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    bool MultiLoadPrefix = Prefix == "vld2" || Prefix == "vld3"
1258c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                            || Prefix == "vld4";
1259c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    bool MultiStorePrefix = Prefix == "vst2" || Prefix == "vst3"
1260c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                            || Prefix == "vst4";
1261c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (MultiLoadPrefix || MultiStorePrefix) {
1262c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back(NameRef.slice(0, 3).str() + "1.64");
1263c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1264c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1265c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1266c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // v{st,ld}1_{lane,dup}_{u64,s64} use vldr/vstr/vmov/str instead of
1267c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // emitting said instructions. So return a check for
1268c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // vldr/vstr/vmov/str instead.
1269c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (HasLanePostfix || HasDupPostfix) {
1270c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (Prefix == "vst1") {
1271c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{str|vstr|vmov}}");
1272c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        return;
1273c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else if (Prefix == "vld1") {
1274c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{ldr|vldr|vmov}}");
1275c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        return;
1276c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1277c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1278c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1279c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1280c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // vzip.32/vuzp.32 are the same instruction as vtrn.32 and are
1281c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // sometimes disassembled as vtrn.32. We use a regex to handle both
1282c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // cases.
1283c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((Prefix == "vzip" || Prefix == "vuzp") && OutTypeCode == "32") {
1284c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back("{{vtrn|" + Prefix + "}}.32 " + RegisterSuffix);
1285c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1286c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1287c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1288c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Currently on most ARM processors, we do not use vmla/vmls for
1289c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // quad floating point operations. Instead we output vmul + vadd. So
1290c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // check if we have one of those instructions and just output a
1291c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // check for vmul.
1292c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (OutTypeCode == "f32") {
1293c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (Prefix == "vmls") {
1294c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix);
1295c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vsub." + OutTypeCode);
1296c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1297c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    } else if (Prefix == "vmla") {
1298c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix);
1299c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vadd." + OutTypeCode);
1300c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1301c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1302c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1303c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1304c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have vcvt, get the input type from the instruction name
1305c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // (which should be of the form instname_inputtype) and append it
1306c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // before the output type.
1307c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Prefix == "vcvt") {
1308c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    const std::string inTypeCode = NameRef.substr(NameRef.find_last_of("_")+1);
1309c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Prefix += "." + inTypeCode;
1310c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1311c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1312c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Append output type code to get our final mangled instruction.
1313c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Prefix += "." + OutTypeCode;
1314c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1315c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Result.push_back(Prefix + " " + RegisterSuffix);
1316c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1317c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
131851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// UseMacro - Examine the prototype string to determine if the intrinsic
131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// should be defined as a preprocessor macro instead of an inline function.
132051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool UseMacro(const std::string &proto) {
132151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin takes an immediate argument, we need to #define it rather
132251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // than use a standard declaration, so that SemaChecking can range check
132351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // the immediate passed by the user.
132451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('i') != std::string::npos)
132551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
132651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pointer arguments need to use macros to avoid hiding aligned attributes
132851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // from the pointer type.
132951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('p') != std::string::npos ||
133051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      proto.find('c') != std::string::npos)
133151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
133251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
133351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return false;
133451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
133551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
133651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
133751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// defined as a macro should be accessed directly instead of being first
133851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// assigned to a local temporary.
133951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
134051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // True for constant ints (i), pointers (p) and const pointers (c).
134151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
134251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
134351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
134451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the string "(argtype a, argtype b, ...)"
13452102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qinstatic std::string GenArgs(const std::string &proto, StringRef typestr,
13462102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin                           const std::string &name) {
134751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
134851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
134951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
135051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
135151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
135251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
135351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
135451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
135551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Some macro arguments are used directly instead of being assigned
135651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to local temporaries; prepend an underscore prefix to make their
135751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // names consistent with the local temporaries.
135851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (MacroArgUsedDirectly(proto, i))
135951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "__";
136051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
136151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += TypeString(proto[i], typestr) + " __";
136251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
136351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
13642102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    //To avoid argument being multiple defined, add extra number for renaming.
136522229d6822324a42913d25f256045dbf348a53e9Kevin Qin    if (name == "vcopy_lane" || name == "vcopy_laneq")
13662102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      s.push_back('1');
136751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
136851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
136951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
137051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
137251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
137351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
137451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Macro arguments are not type-checked like inline function arguments, so
137651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// assign them to local temporaries to get the right type checking.
13772102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qinstatic std::string GenMacroLocals(const std::string &proto, StringRef typestr,
13782102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin                                  const std::string &name ) {
137951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
138051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
138151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool generatedLocal = false;
138251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
138451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create a temporary for an immediate argument.
138551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // That would defeat the whole point of using a macro!
138651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (MacroArgUsedDirectly(proto, i))
138751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
138851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    generatedLocal = true;
13892102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    bool extranumber = false;
139022229d6822324a42913d25f256045dbf348a53e9Kevin Qin    if (name == "vcopy_lane" || name == "vcopy_laneq")
13912102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      extranumber = true;
139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += TypeString(proto[i], typestr) + " __";
139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
13952102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    if(extranumber)
13962102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      s.push_back('1');
139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " = (";
139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
13992102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    if(extranumber)
14002102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin      s.push_back('1');
140151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "); ";
140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (generatedLocal)
140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "\\\n  ";
140651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
140751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
140851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Use the vmovl builtin to sign-extend or zero-extend a vector.
1410097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string Extend(StringRef typestr, const std::string &a, bool h=0) {
1411097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s, high;
1412097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  high = h ? "_high" : "";
1413097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName("vmovl" + high, typestr, ClassS);
1414097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + a + ")";
1415097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1416097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1417097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1418097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Get the high 64-bit part of a vector
1419097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string GetHigh(const std::string &a, StringRef typestr) {
142051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
1421097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName("vget_high", typestr, ClassS);
142251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(" + a + ")";
142351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
142451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1426097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Gen operation with two operands and get high 64-bit for both of two operands.
1427097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string Gen2OpWith2High(StringRef typestr,
1428097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &op,
1429097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &a,
1430097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &b) {
1431097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
1432097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op1 = GetHigh(a, typestr);
1433097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op2 = GetHigh(b, typestr);
1434097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName(op, typestr, ClassS);
1435097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + Op1 + ", " + Op2 + ");";
1436097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1437097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1438097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1439097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Gen operation with three operands and get high 64-bit of the latter
1440097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// two operands.
1441097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string Gen3OpWith2High(StringRef typestr,
1442097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &op,
1443097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &a,
1444097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &b,
1445097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                                   const std::string &c) {
1446097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
1447097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op1 = GetHigh(b, typestr);
1448097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string Op2 = GetHigh(c, typestr);
1449097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName(op, typestr, ClassS);
1450097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + a + ", " + Op1 + ", " + Op2 + ");";
1451097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1452097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1453097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1454097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu// Gen combine operation by putting a on low 64-bit, and b on high 64-bit.
1455097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liustatic std::string GenCombine(std::string typestr,
1456097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                              const std::string &a,
1457097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu                              const std::string &b) {
1458097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  std::string s;
1459097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s = MangleName("vcombine", typestr, ClassS);
1460097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  s += "(" + a + ", " + b + ")";
1461097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  return s;
1462097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1463097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
146451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Duplicate(unsigned nElts, StringRef typestr,
146551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &a) {
146651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
146751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
146851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = "(" + TypeString('d', typestr) + "){ ";
146951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i != nElts; ++i) {
147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += a;
147151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < nElts)
147251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
147351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
147451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += " }";
147551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
147651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
147751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
147851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
147951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string SplatLane(unsigned nElts, const std::string &vec,
148051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &lane) {
148151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
148251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i < nElts; ++i)
148351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + lane;
148451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
148551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
148651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
148751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1488912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liustatic std::string RemoveHigh(const std::string &name) {
1489912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  std::string s = name;
1490912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  std::size_t found = s.find("_high_");
1491912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  if (found == std::string::npos)
1492912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    PrintFatalError("name should contain \"_high_\" for high intrinsics");
1493912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  s.replace(found, 5, "");
1494912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  return s;
1495912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu}
1496912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu
149751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNumElements(StringRef typestr, bool &quad) {
149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  quad = false;
149951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool dummy = false;
150051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
150151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = 0;
150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
150351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c': nElts = 8; break;
150451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's': nElts = 4; break;
150551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i': nElts = 2; break;
150651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l': nElts = 1; break;
150751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h': nElts = 4; break;
150851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f': nElts = 2; break;
1509b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  case 'd':
1510b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    nElts = 1;
1511b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    break;
151251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
151338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unhandled type!");
151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
151551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) nElts <<= 1;
151651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return nElts;
151751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
151851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
151951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
1520912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liustatic std::string GenOpString(const std::string &name, OpKind op,
1521912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu                               const std::string &proto, StringRef typestr) {
152251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad;
152351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = GetNumElements(typestr, quad);
152451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
152551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
152651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string ts = TypeString(proto[0], typestr);
152751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
152851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!define) {
152951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = "return ";
153051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
153151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
153251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch(op) {
153351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAdd:
153451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + __b;";
153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
153651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddl:
153751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
153851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1539097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAddlHi:
1540097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Extend(typestr, "__a", 1) + " + " + Extend(typestr, "__b", 1) + ";";
1541097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
154251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddw:
154351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + Extend(typestr, "__b") + ";";
154451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1545097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAddwHi:
1546097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += "__a + " + Extend(typestr, "__b", 1) + ";";
1547097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
154851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSub:
154951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - __b;";
155051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
155151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubl:
155251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
155351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1554097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpSublHi:
1555097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Extend(typestr, "__a", 1) + " - " + Extend(typestr, "__b", 1) + ";";
1556097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
155751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubw:
155851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + Extend(typestr, "__b") + ";";
155951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1560097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpSubwHi:
1561097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += "__a - " + Extend(typestr, "__b", 1) + ";";
1562097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
156351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulN:
156451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
156551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
156651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulLane:
156751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
156851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
15690aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMulXLane:
15700aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vmulx", typestr, ClassS) + "(__a, " +
15710aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      SplatLane(nElts, "__b", "__c") + ");";
15720aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMul:
157451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * __b;";
157551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMullLane:
157751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
157851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
157951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
15800aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMullHiLane:
15810aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vmull", typestr, ClassS) + "(" +
15820aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__a", typestr) + ", " + SplatLane(nElts, "__b", "__c") + ");";
15830aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
158451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaN:
158551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
158651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
158751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaLane:
158851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
158951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
159051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMla:
159151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * __c);";
159251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
159351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalN:
159451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
159551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
159651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
159751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalLane:
159851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
159951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
160051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16010aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMlalHiLane:
16020aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(" +
16030aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
16040aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
160551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlal:
160651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
160751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1608097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpMullHi:
1609097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen2OpWith2High(typestr, "vmull", "__a", "__b");
1610097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1611097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpMlalHi:
1612097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vmlal", "__a", "__b", "__c");
1613097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
161451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsN:
161551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
161651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
161751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsLane:
161851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16200aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpFMSLane:
16210aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[1], typestr) + " __a1 = __a; \\\n  ";
16220aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[2], typestr) + " __b1 = __b; \\\n  ";
16230aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[3], typestr) + " __c1 = __c; \\\n  ";
16240aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vfma_lane", typestr, ClassS) + "(__a1, __b1, -__c1, __d);";
16250aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
16260aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpFMSLaneQ:
16270aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[1], typestr) + " __a1 = __a; \\\n  ";
16280aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[2], typestr) + " __b1 = __b; \\\n  ";
16290aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += TypeString(proto[3], typestr) + " __c1 = __c; \\\n  ";
16300aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vfma_laneq", typestr, ClassS) + "(__a1, __b1, -__c1, __d);";
16310aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
163251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMls:
163351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * __c);";
163451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
163551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslN:
163651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
163751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
163851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslLane:
164051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
164251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16430aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpMlslHiLane:
16440aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(" +
16450aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
16460aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
164751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsl:
164851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
164951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1650097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpMlslHi:
1651097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vmlsl", "__a", "__b", "__c");
1652097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
165351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMullLane:
165451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
165551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
165651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16570aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpQDMullHiLane:
16580aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vqdmull", typestr, ClassS) + "(" +
16590aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__a", typestr) + ", " + SplatLane(nElts, "__b", "__c") + ");";
16600aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
166151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlalLane:
166251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
166351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
166451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16650aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpQDMlalHiLane:
16660aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, " +
16670aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
16680aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
166951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlslLane:
167051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
167151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
167251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
16730aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  case OpQDMlslHiLane:
16740aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, " +
16750aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      GetHigh("__b", typestr) + ", " + SplatLane(nElts, "__c", "__d") + ");";
16760aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    break;
167751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMulhLane:
167851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
167951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
168051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
168151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQRDMulhLane:
168251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
168351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
168451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpEq:
168651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a == __b);";
168751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
168851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGe:
168951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a >= __b);";
169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
169151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLe:
169251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a <= __b);";
169351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
169451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGt:
169551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a > __b);";
169651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
169751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLt:
169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a < __b);";
169951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
170051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNeg:
170151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " -__a;";
170251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNot:
170451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " ~__a;";
170551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
170651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAnd:
170751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & __b;";
170851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
170951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOr:
171051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | __b;";
171151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
171251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpXor:
171351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a ^ __b;";
171451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
171551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAndNot:
171651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & ~__b;";
171751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
171851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOrNot:
171951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | ~__b;";
172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
172151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpCast:
172251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__a;";
172351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpConcat:
172551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
172651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", (int64x1_t)__b, 0, 1);";
172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
172851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpHi:
1729cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    // nElts is for the result vector, so the source is twice that number.
1730cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s += "__builtin_shufflevector(__a, __a";
1731cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    for (unsigned i = nElts; i < nElts * 2; ++i)
1732cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach      s += ", " + utostr(i);
1733cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s+= ");";
173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
173551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLo:
1736cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s += "__builtin_shufflevector(__a, __a";
1737cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    for (unsigned i = 0; i < nElts; ++i)
1738cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach      s += ", " + utostr(i);
1739cd76539274cdc3907a61de28ba81a9e90f270a41Jim Grosbach    s+= ");";
174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
174151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDup:
174251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Duplicate(nElts, typestr, "__a") + ";";
174351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDupLane:
174551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += SplatLane(nElts, "__a", "__b") + ";";
174651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
174751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSelect:
174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // ((0 & 1) | (~0 & 2))
174951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")";
175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ts = TypeString(proto[1], typestr);
175151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "((__a & (" + ts + ")__b) | ";
175251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(~__a & (" + ts + ")__c));";
175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
175451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev16:
175551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 2; i <= nElts; i += 2)
175751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != 2; ++j)
175851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
175951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
176051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
176151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev32: {
176251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned WordElts = nElts >> (1 + (int)quad);
176351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
176451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = WordElts; i <= nElts; i += WordElts)
176551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != WordElts; ++j)
176651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
176751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
176851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
176951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
177051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev64: {
177151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned DblWordElts = nElts >> (int)quad;
177251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
177351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
177451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != DblWordElts; ++j)
177551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
177651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
177751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
177851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
177951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbdl: {
178051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
178151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
178251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
178351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
178451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
178551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
178651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
178751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
178851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
178951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
179051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
179151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1792097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAbdlHi:
1793097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen2OpWith2High(typestr, "vabdl", "__a", "__b");
1794097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1795097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAddhnHi: {
1796097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string addhn = MangleName("vaddhn", typestr, ClassS) + "(__b, __c)";
1797097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", addhn);
1798097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1799097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1800097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
1801097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpRAddhnHi: {
1802097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string raddhn = MangleName("vraddhn", typestr, ClassS) + "(__b, __c)";
1803097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", raddhn);
1804097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1805097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1806097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
1807097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpSubhnHi: {
1808097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string subhn = MangleName("vsubhn", typestr, ClassS) + "(__b, __c)";
1809097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", subhn);
1810097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1811097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1812097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
1813097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpRSubhnHi: {
1814097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    std::string rsubhn = MangleName("vrsubhn", typestr, ClassS) + "(__b, __c)";
1815097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += GenCombine(GetNarrowTypestr(typestr), "__a", rsubhn);
1816097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += ";";
1817097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1818097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
181951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAba:
182051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
182151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1822097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAbal:
1823097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += "__a + " + MangleName("vabdl", typestr, ClassS) + "(__b, __c);";
1824097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1825097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpAbalHi:
1826097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vabal", "__a", "__b", "__c");
1827097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1828097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpQDMullHi:
1829097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen2OpWith2High(typestr, "vqdmull", "__a", "__b");
1830097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1831097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpQDMlalHi:
1832097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vqdmlal", "__a", "__b", "__c");
1833097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    break;
1834097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  case OpQDMlslHi:
1835097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu    s += Gen3OpWith2High(typestr, "vqdmlsl", "__a", "__b", "__c");
183651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
1837b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  case OpDiv:
1838b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    s += "__a / __b;";
1839b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    break;
1840912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  case OpMovlHi: {
1841912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s = TypeString(proto[1], typestr.drop_front()) + " __a1 = " +
1842912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        MangleName("vget_high", typestr, ClassS) + "(__a);\n  " + s;
1843912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "(" + ts + ")" + MangleName("vshll_n", typestr, ClassS);
1844912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "(__a1, 0);";
1845912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    break;
1846912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  }
1847912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  case OpLongHi: {
1848912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    // Another local variable __a1 is needed for calling a Macro,
1849912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    // or using __a will have naming conflict when Macro expanding.
1850912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += TypeString(proto[1], typestr.drop_front()) + " __a1 = " +
1851912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu         MangleName("vget_high", typestr, ClassS) + "(__a); \\\n";
1852912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "  (" + ts + ")" + MangleName(RemoveHigh(name), typestr, ClassS) +
1853912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu         "(__a1, __b);";
1854912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    break;
1855912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  }
1856912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  case OpNarrowHi: {
1857912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += "(" + ts + ")" + MangleName("vcombine", typestr, ClassS) + "(__a, " +
1858912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu         MangleName(RemoveHigh(name), typestr, ClassS) + "(__b, __c));";
1859912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    break;
1860912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu  }
186122229d6822324a42913d25f256045dbf348a53e9Kevin Qin  case OpCopyLane: {
18622102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    s += TypeString('s', typestr) + " __c2 = " +
18632102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin         MangleName("vget_lane", typestr, ClassS) + "(__c1, __d1); \\\n  " +
18642102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin         MangleName("vset_lane", typestr, ClassS) + "(__c2, __a1, __b1);";
18652102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    break;
18662102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin  }
186722229d6822324a42913d25f256045dbf348a53e9Kevin Qin  case OpCopyQLane: {
186822229d6822324a42913d25f256045dbf348a53e9Kevin Qin    std::string typeCode = "";
186922229d6822324a42913d25f256045dbf348a53e9Kevin Qin    InstructionTypeCode(typestr, ClassS, quad, typeCode);
187022229d6822324a42913d25f256045dbf348a53e9Kevin Qin    s += TypeString('s', typestr) + " __c2 = vget_lane_" + typeCode +
187122229d6822324a42913d25f256045dbf348a53e9Kevin Qin         "(__c1, __d1); \\\n  vsetq_lane_" + typeCode + "(__c2, __a1, __b1);";
187222229d6822324a42913d25f256045dbf348a53e9Kevin Qin    break;
187322229d6822324a42913d25f256045dbf348a53e9Kevin Qin  }
187422229d6822324a42913d25f256045dbf348a53e9Kevin Qin  case OpCopyLaneQ: {
187522229d6822324a42913d25f256045dbf348a53e9Kevin Qin    std::string typeCode = "";
187622229d6822324a42913d25f256045dbf348a53e9Kevin Qin    InstructionTypeCode(typestr, ClassS, quad, typeCode);
187722229d6822324a42913d25f256045dbf348a53e9Kevin Qin    s += TypeString('s', typestr) + " __c2 = vgetq_lane_" + typeCode +
187822229d6822324a42913d25f256045dbf348a53e9Kevin Qin         "(__c1, __d1); \\\n  vset_lane_" + typeCode + "(__c2, __a1, __b1);";
187922229d6822324a42913d25f256045dbf348a53e9Kevin Qin    break;
188022229d6822324a42913d25f256045dbf348a53e9Kevin Qin  }
188151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
188238859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unknown OpKind!");
188351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
188451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
188551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
188651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
188751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
188851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned mod = proto[0];
188951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
189051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v' || mod == 'f')
189151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mod = proto[1];
189251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
189351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
189451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
189551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
189651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
189751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
189851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
189951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
190051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Base type to get the type string for.
190151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
190251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
190351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
190451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
190551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1906da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags::EltType ET;
190751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
190851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
1909da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
191051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
191151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
1912da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
191351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
191451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
1915da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int32;
191651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
191751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
1918da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int64;
191951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
192051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
1921da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float16;
192251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
192351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
1924da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float32;
192551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
1926b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    case 'd':
1927b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      ET = NeonTypeFlags::Float64;
1928b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
192951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
193038859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
193151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1932da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
1933da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  return Flags.getFlags();
193451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
193551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
19360391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liustatic bool ProtoHasScalar(const std::string proto)
19370391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu{
19380391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu  return (proto.find('s') != std::string::npos
19390391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu          || proto.find('r') != std::string::npos);
19400391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu}
19410391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu
194251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
194351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltin(const std::string &name, const std::string &proto,
194451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              StringRef typestr, ClassKind ck) {
194551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
194651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
194751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
194851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sret-like argument.
194951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool sret = (proto[0] >= '2' && proto[0] <= '4');
195051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
195151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
195251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
195351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Check if the prototype has a scalar operand with the type of the vector
195451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // elements.  If not, bitcasting the args will take care of arg checking.
195551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The actual signedness etc. will be taken care of with special enums.
19560391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu  if (!ProtoHasScalar(proto))
195751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
195851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
195951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v') {
196051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string ts = TypeString(proto[0], typestr);
196151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
196251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
196351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (sret)
196451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ts + " r; ";
196551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
196651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "(" + ts + ")";
196751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else if (sret) {
196851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ts + " r; ";
196951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
197051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "return (" + ts + ")";
197151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
197251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
197351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
197451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool splat = proto.find('a') != std::string::npos;
197551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
197651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "__builtin_neon_";
197751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (splat) {
197851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Call the non-splat builtin: chop off the "_n" suffix from the name.
197951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string vname(name, 0, name.size()-2);
198051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(vname, typestr, ck);
198151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
198251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(name, typestr, ck);
198351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
198451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
198551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
198651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pass the address of the return variable as the first argument to sret-like
198751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // builtins.
198851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (sret)
198951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "&r, ";
199051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
199151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
199251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
199351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string args = std::string(&arg, 1);
199451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
199551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Use the local temporaries instead of the macro arguments.
199651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    args = "__" + args;
199751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
199851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argQuad = false;
199951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argPoly = false;
200051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argUsgn = false;
200151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argScalar = false;
200251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy = false;
200351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
200451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
200551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      dummy, dummy);
200651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
200751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Handle multiple-vector values specially, emitting each subvector as an
200851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // argument to the __builtin.
200951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] >= '2' && proto[i] <= '4') {
201051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Check if an explicit cast is needed.
201151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argType != 'c' || argPoly || argUsgn)
201251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
201351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
201451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
201551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += args + ".val[" + utostr(vi) + "]";
201651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if ((vi + 1) < ve)
201751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          s += ", ";
201851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
201951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if ((i + 1) < e)
202051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", ";
202151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
202251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
202351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
202451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
202551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (splat && (i + 1) == e)
202651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
202751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
202851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check if an explicit cast is needed.
202951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((splat || !argScalar) &&
203051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
203151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string argTypeStr = "c";
203251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (ck != ClassB)
203351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = argType;
203451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argQuad)
203551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = "Q" + argTypeStr;
203651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = "(" + TypeString('d', argTypeStr) + ")" + args;
203751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
203851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
203951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += args;
204051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
204151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
204251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
204351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
204451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
204551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
204651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + utostr(GetNeonEnum(proto, typestr));
204751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
204851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");";
204951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
205051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v' && sret) {
205151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define)
205251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " r;";
205351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
205451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " return r;";
205551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
205651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
205751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
205851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
205951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltinDef(const std::string &name,
206051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 const std::string &proto,
206151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 StringRef typestr, ClassKind ck) {
206251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s("BUILTIN(__builtin_neon_");
206351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
206451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If all types are the same size, bitcasting the args will take care
206551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // of arg checking.  The actual signedness etc. will be taken care of with
206651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // special enums.
20670391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu  if (!ProtoHasScalar(proto))
206851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
206951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
207051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += MangleName(name, typestr, ck);
207151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ", \"";
207251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
207351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = proto.size(); i != e; ++i)
207451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
207551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
207651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
207751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
207851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "i";
207951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
208051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\", \"n\")";
208151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
208251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
208351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
208451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenIntrinsic(const std::string &name,
208551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                const std::string &proto,
208651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                StringRef outTypeStr, StringRef inTypeStr,
208751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                OpKind kind, ClassKind classKind) {
208851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
2089667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  bool define = UseMacro(proto) && kind != OpUnavailable;
209051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
209151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
209251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // static always inline + return type
209351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
209451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "#define ";
209551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
209651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
209751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
209851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
209951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
210051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
210151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
210251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
210351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
210451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
210551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
210651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
210751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
210851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName;
210951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
211051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function arguments
21112102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin  s += GenArgs(proto, inTypeStr, name);
211251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
211351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Definition.
211451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define) {
211551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " __extension__ ({ \\\n  ";
21162102a1dba460c99f97a0fdf1e5aee8c685e29ff8Kevin Qin    s += GenMacroLocals(proto, inTypeStr, name);
2117667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else if (kind == OpUnavailable) {
2118667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    s += " __attribute__((unavailable));\n";
2119667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    return s;
2120667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else
212166981c7ca1fcef529d7d5e5c53b07020ff23d8e3Jim Grosbach    s += " {\n  ";
212251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
212351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (kind != OpNone)
2124912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu    s += GenOpString(name, kind, proto, outTypeStr);
212551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
212651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenBuiltin(name, proto, outTypeStr, classKind);
212751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
212851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " })";
212951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
213051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " }";
213151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\n";
213251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
213351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
213451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
213551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
213651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// is comprised of type definitions and function declarations.
213751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::run(raw_ostream &OS) {
213851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
213951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
214051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
214151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
214251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * Permission is hereby granted, free of charge, to any person obtaining "
214351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "a copy\n"
214451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * of this software and associated documentation files (the \"Software\"),"
214551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " to deal\n"
214651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * in the Software without restriction, including without limitation the "
214751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "rights\n"
214851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * to use, copy, modify, merge, publish, distribute, sublicense, "
214951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "and/or sell\n"
215051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * copies of the Software, and to permit persons to whom the Software is\n"
215151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * furnished to do so, subject to the following conditions:\n"
215251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
215351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * The above copyright notice and this permission notice shall be "
215451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "included in\n"
215551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * all copies or substantial portions of the Software.\n"
215651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
215751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
215851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "EXPRESS OR\n"
215951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
216051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "MERCHANTABILITY,\n"
216151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
216251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "SHALL THE\n"
216351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
216451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "OTHER\n"
216551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
216651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "ARISING FROM,\n"
216751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
216851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "DEALINGS IN\n"
216951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE.\n"
217051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
217151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *===--------------------------------------------------------------------"
217251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
217351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " */\n\n";
217451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
217551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON_H\n";
217651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#define __ARM_NEON_H\n\n";
217751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2178b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#if !defined(__ARM_NEON__) && !defined(__AARCH_FEATURE_ADVSIMD)\n";
217951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#error \"NEON support not enabled\"\n";
218051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
218151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
218251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#include <stdint.h>\n\n";
218351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
218451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit NEON-specific scalar typedefs.
218551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef float float32_t;\n";
2186b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef __fp16 float16_t;\n";
2187b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2188b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#ifdef __aarch64__\n";
2189b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef double float64_t;\n";
2190b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#endif\n\n";
2191b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2192b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // For now, signedness of polynomial types depends on target
2193b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#ifdef __aarch64__\n";
2194b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef uint8_t poly8_t;\n";
2195b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "typedef uint16_t poly16_t;\n";
2196b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#else\n";
219751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int8_t poly8_t;\n";
219851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int16_t poly16_t;\n";
2199b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#endif\n";
220051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
220151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit Neon vector typedefs.
2202b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::string TypedefTypes(
22030aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      "cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPs");
220451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 24> TDTypeVec;
220551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(0, TypedefTypes, TDTypeVec);
220651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
220751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vector typedefs.
22080aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  bool isA64 = false;
220951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
221051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy, quad = false, poly = false;
2211b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    char type = ClassifyType(TDTypeVec[i], quad, poly, dummy);
22120aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    bool preinsert = false;
22130aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    bool postinsert = false;
2214b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
22150aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    if (type == 'd') {
22160aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      preinsert = isA64? false: true;
2217b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      isA64 = true;
22180aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    } else {
22190aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      postinsert = isA64? true: false;
22200aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      isA64 = false;
22210aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    }
22220aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    if (postinsert)
22230aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      OS << "#endif\n";
22240aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    if (preinsert)
2225b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << "#ifdef __aarch64__\n";
2226b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
222751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (poly)
222851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_polyvector_type(";
222951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
223051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_vector_type(";
223151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
223251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
223351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << utostr(nElts) << "))) ";
223451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (nElts < 10)
223551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << " ";
223651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
223751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << TypeString('s', TDTypeVec[i]);
223851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
2239b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
224051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
224151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
224251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
224351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit struct typedefs.
22440aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu  isA64 = false;
224551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned vi = 2; vi != 5; ++vi) {
224651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
2247b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      bool dummy, quad = false, poly = false;
2248b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      char type = ClassifyType(TDTypeVec[i], quad, poly, dummy);
22490aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      bool preinsert = false;
22500aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      bool postinsert = false;
2251b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
22520aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      if (type == 'd') {
22530aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        preinsert = isA64? false: true;
2254b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        isA64 = true;
22550aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      } else {
22560aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        postinsert = isA64? true: false;
22570aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        isA64 = false;
22580aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      }
22590aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      if (postinsert)
22600aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu        OS << "#endif\n";
22610aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu      if (preinsert)
2262b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "#ifdef __aarch64__\n";
2263b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
226451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string ts = TypeString('d', TDTypeVec[i]);
226551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
226651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef struct " << vs << " {\n";
226751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "  " << ts << " val";
226851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "[" << utostr(vi) << "]";
226951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ";\n} ";
2270b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << vs << ";\n";
2271b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << "\n";
227251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
227351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
227451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22751e8058f8d90fab1b9011adf62caa52e19e61382cBob Wilson  OS<<"#define __ai static inline __attribute__((__always_inline__, __nodebug__))\n\n";
227651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
227751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
227851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2279b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<ClassKind> EmittedMap;
2280b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
228151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
228251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // intrinsics.  (Some of the saturating multiply instructions are also
228351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // used to implement the corresponding "_lane" variants, but tablegen
228451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sorts the records into alphabetical order so that the "_lane" variants
228551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // come after the intrinsics they use.)
2286b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  emitIntrinsic(OS, Records.getDef("VMOVL"), EmittedMap);
2287b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  emitIntrinsic(OS, Records.getDef("VMULL"), EmittedMap);
2288b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  emitIntrinsic(OS, Records.getDef("VABD"), EmittedMap);
2289097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VABDL"), EmittedMap);
2290b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2291b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // ARM intrinsics must be emitted before AArch64 intrinsics to ensure
2292b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // common intrinsics appear only once in the output stream.
2293b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // The check for uniquiness is done in emitIntrinsic.
2294b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Emit ARM intrinsics.
229551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
229651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
2297b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2298b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Skip AArch64 intrinsics; they will be emitted at the end.
2299b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2300b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (isA64)
2301b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2302b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2303b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (R->getName() != "VMOVL" && R->getName() != "VMULL" &&
230451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VABD")
2305b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      emitIntrinsic(OS, R, EmittedMap);
230651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
230751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2308b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Emit AArch64-specific intrinsics.
2309b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#ifdef __aarch64__\n";
2310b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2311097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VMOVL_HIGH"), EmittedMap);
2312097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VMULL_HIGH"), EmittedMap);
2313097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  emitIntrinsic(OS, Records.getDef("VABDL_HIGH"), EmittedMap);
2314097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
2315b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
2316b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Record *R = RV[i];
2317b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2318b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Skip ARM intrinsics already included above.
2319b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2320b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64)
2321b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2322b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2323b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    emitIntrinsic(OS, R, EmittedMap);
2324b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  }
2325b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2326b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "#endif\n\n";
2327b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
232851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef __ai\n\n";
232951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif /* __ARM_NEON_H */\n";
233051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
233151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
233251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
2333b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// intrinsics specified by record R checking for intrinsic uniqueness.
2334b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R,
2335b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                StringMap<ClassKind> &EmittedMap) {
233651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string name = R->getValueAsString("Name");
233751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Proto = R->getValueAsString("Prototype");
233851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Types = R->getValueAsString("Types");
233951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
234051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 16> TypeVec;
234151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(R, Types, TypeVec);
234251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
234351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
234451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
234551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ClassKind classKind = ClassNone;
234651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (R->getSuperClasses().size() >= 2)
234751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    classKind = ClassMap[R->getSuperClasses()[1]];
234851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (classKind == ClassNone && kind == OpNone)
234938859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError(R->getLoc(), "Builtin has no class kind");
235051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
235151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
235251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (kind == OpReinterpret) {
235351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool outQuad = false;
235451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool dummy = false;
235551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
235651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned srcti = 0, srcte = TypeVec.size();
235751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne           srcti != srcte; ++srcti) {
235851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool inQuad = false;
235951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
236051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (srcti == ti || inQuad != outQuad)
236151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          continue;
2362b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        std::string s = GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
2363b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                     OpCast, ClassS);
2364b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        if (EmittedMap.count(s))
2365b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          continue;
2366b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        EmittedMap[s] = ClassS;
2367b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << s;
236851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
236951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
2370b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      std::string s =
2371b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti], kind, classKind);
2372b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (EmittedMap.count(s))
2373b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
2374b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      EmittedMap[s] = classKind;
2375b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << s;
237651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
237751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
237851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
237951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
238051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
238151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned RangeFromType(const char mod, StringRef typestr) {
238251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
238351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false, dummy = false;
238451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
238551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
238651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
238751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
238851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
238951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (8 << (int)quad) - 1;
239051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
239151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
239251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (4 << (int)quad) - 1;
239351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
239451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
239551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (2 << (int)quad) - 1;
23960aa1a88e19235574481e46e9e6e9ce66a9e6624fJiangning Liu    case 'd':
239751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
239851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (1 << (int)quad) - 1;
239951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
240038859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
240151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
240251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
240351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2404f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosierstatic unsigned RangeScalarShiftImm(const char mod, StringRef typestr) {
2405f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  // base type to get the type string for.
2406f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  bool dummy = false;
2407f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  char type = ClassifyType(typestr, dummy, dummy, dummy);
2408f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  type = ModType(mod, type, dummy, dummy, dummy, dummy, dummy, dummy);
2409f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2410f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  switch (type) {
2411f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'c':
2412f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 7;
2413f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'h':
2414f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 's':
2415f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 15;
2416f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'f':
2417f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'i':
2418f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 31;
2419f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'd':
2420f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    case 'l':
2421f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      return 63;
2422f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier    default:
2423f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      PrintFatalError("unhandled type!");
2424f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  }
2425f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier}
2426f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2427b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Generate the ARM and AArch64 intrinsic range checking code for
2428b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// shift/lane immediates, checking for unique declarations.
2429b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid
2430b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim NorthoverNeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
2431b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                        StringMap<ClassKind> &A64IntrinsicMap,
2432b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                        bool isA64RangeCheck) {
2433b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
243451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  StringMap<OpKind> EmittedMap;
243551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2436b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate the intrinsic range checking code for shift/lane immediates.
2437b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64RangeCheck)
2438b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_AARCH64_IMMEDIATE_CHECK\n";
2439b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  else
2440b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
2441b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
244251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
244351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
2444b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
244551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
244651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
244751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
244851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2449b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string name = R->getValueAsString("Name");
245051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
2451b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string Types = R->getValueAsString("Types");
2452944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = name + "@" + Proto;
245351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
245451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
245551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
245651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
245751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
245851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2459b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Functions which do not have an immediate do not need to have range
2460b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // checking code emitted.
2461b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    size_t immPos = Proto.find('i');
2462b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (immPos == std::string::npos)
2463b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2464b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
246551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
246651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
246751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
246851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
246938859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
247051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
247151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
247251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2473b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Do not include AArch64 range checks if not generating code for AArch64.
2474b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2475b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64RangeCheck && isA64)
2476b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2477b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2478b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Include ARM range checks in AArch64 but only if ARM intrinsics are not
2479b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // redefined by AArch64 to handle new types.
2480944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (isA64RangeCheck && !isA64 && A64IntrinsicMap.count(Rename)) {
2481944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ClassKind &A64CK = A64IntrinsicMap[Rename];
2482b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (A64CK == ck && ck != ClassNone)
2483b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
2484b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
2485b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
248651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
2487b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      std::string namestr, shiftstr, rangestr;
2488b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2489b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (R->getValueAsBit("isVCVT_N")) {
2490b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // VCVT between floating- and fixed-point values takes an immediate
2491912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        // in the range [1, 32] for f32, or [1, 64] for f64.
2492b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        ck = ClassB;
2493912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        if (name.find("32") != std::string::npos)
2494912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu          rangestr = "l = 1; u = 31"; // upper bound = l + u
2495912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        else if (name.find("64") != std::string::npos)
2496912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu          rangestr = "l = 1; u = 63";
2497912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu        else
2498912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu          PrintFatalError(R->getLoc(),
2499912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu              "Fixed point convert name should contains \"32\" or \"64\"");
2500f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2501f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier      } else if (R->getValueAsBit("isScalarShift")) {
2502f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier        // Right shifts have an 'r' in the name, left shifts do not.
2503f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier        if (name.find('r') != std::string::npos)
2504f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier          rangestr = "l = 1; ";
2505f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
2506f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier        rangestr += "u = " +
2507f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier          utostr(RangeScalarShiftImm(Proto[immPos - 1], TypeVec[ti]));
25080391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu      } else if (!ProtoHasScalar(Proto)) {
2509b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // Builtins which are overloaded by type will need to have their upper
2510b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // bound computed at Sema time based on the type constant.
2511b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        ck = ClassB;
2512b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        if (R->getValueAsBit("isShift")) {
2513b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          shiftstr = ", true";
2514b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2515b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          // Right shifts have an 'r' in the name, left shifts do not.
2516b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          if (name.find('r') != std::string::npos)
2517b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover            rangestr = "l = 1; ";
2518b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        }
2519b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        rangestr += "u = RFT(TV" + shiftstr + ")";
2520b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      } else {
2521b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        // The immediate generally refers to a lane in the preceding argument.
2522b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        assert(immPos > 0 && "unexpected immediate operand");
2523b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        rangestr =
2524b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover            "u = " + utostr(RangeFromType(Proto[immPos - 1], TypeVec[ti]));
2525b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      }
2526b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Make sure cases appear only once by uniquing them in a string map.
2527b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      namestr = MangleName(name, TypeVec[ti], ck);
2528b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (EmittedMap.count(namestr))
252951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
2530b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      EmittedMap[namestr] = OpNone;
253151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2532b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Calculate the index of the immediate that should be range checked.
2533b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      unsigned immidx = 0;
2534b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2535b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Builtins that return a struct of multiple vectors have an extra
2536b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // leading arg for the struct return.
2537b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (Proto[0] >= '2' && Proto[0] <= '4')
2538b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        ++immidx;
2539b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2540b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Add one to the index for each argument until we reach the immediate
2541b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // to be checked.  Structs of vectors are passed as multiple arguments.
2542b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
2543b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        switch (Proto[ii]) {
2544b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        default:
2545b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 1;
2546b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2547b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case '2':
2548b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 2;
2549b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2550b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case '3':
2551b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 3;
2552b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2553b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case '4':
2554b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          immidx += 4;
2555b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2556b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        case 'i':
2557b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          ie = ii + 1;
2558b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          break;
2559b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        }
2560b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      }
2561b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (isA64RangeCheck)
2562b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case AArch64::BI__builtin_neon_";
2563b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      else
2564b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case ARM::BI__builtin_neon_";
2565b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << MangleName(name, TypeVec[ti], ck) << ": i = " << immidx << "; "
2566b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover         << rangestr << "; break;\n";
256751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
256851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
256951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
2570b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2571b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2572b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Generate the ARM and AArch64 overloaded type checking code for
2573b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// SemaChecking.cpp, checking for unique builtin declarations.
2574b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid
2575b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim NorthoverNeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
2576b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                      StringMap<ClassKind> &A64IntrinsicMap,
2577b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                      bool isA64TypeCheck) {
2578b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2579b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<OpKind> EmittedMap;
258051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
258151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the overloaded type checking code for SemaChecking.cpp
2582b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64TypeCheck)
2583b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_AARCH64_OVERLOAD_CHECK\n";
2584b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  else
2585b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
2586b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
258751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
258851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
258951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
259051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
259151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
259251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
259351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
259451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
259551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
2596944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = name + "@" + Proto;
2597944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin
259851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
259951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
260051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
260151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
260251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
260351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which have a scalar argument cannot be overloaded, no need to
260451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // check them if we are emitting the type checking code.
26050391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu    if (ProtoHasScalar(Proto))
260651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
260751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
260851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
260951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
261051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
261151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
261238859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
261351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2614b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Do not include AArch64 type checks if not generating code for AArch64.
2615b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2616b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64TypeCheck && isA64)
2617b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2618b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2619b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Include ARM  type check in AArch64 but only if ARM intrinsics
2620b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // are not redefined in AArch64 to handle new types, e.g. "vabd" is a SIntr
2621b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // redefined in AArch64 to handle an additional 2 x f64 type.
2622b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
2623944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (isA64TypeCheck && !isA64 && A64IntrinsicMap.count(Rename)) {
2624944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ClassKind &A64CK = A64IntrinsicMap[Rename];
2625b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (A64CK == ck && ck != ClassNone)
2626b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
2627b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
2628b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
262951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    int si = -1, qi = -1;
2630f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith    uint64_t mask = 0, qmask = 0;
263151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
263251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the switch case(s) for this builtin for the type validation.
263351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool quad = false, poly = false, usgn = false;
263451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
263551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
263651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (quad) {
263751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        qi = ti;
2638f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
263951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
264051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        si = ti;
2641f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
264251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
264351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
26444648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
26454648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // Check if the builtin function has a pointer or const pointer argument.
26464648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    int PtrArgNum = -1;
26474648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    bool HasConstPtr = false;
26484648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) {
26494648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      char ArgType = Proto[arg];
26504648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'c') {
26514648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        HasConstPtr = true;
26524648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
26534648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
26544648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
26554648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'p') {
26564648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
26574648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
26584648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
26594648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    }
26604648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // For sret builtins, adjust the pointer argument index.
26614648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4'))
26624648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      PtrArgNum += 1;
26634648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
26649082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
26659082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // and vst1_lane intrinsics.  Using a pointer to the vector element
26669082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // type with one of those operations causes codegen to select an aligned
26679082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // load/store instruction.  If you want an unaligned operation,
26689082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // the pointer argument needs to have less alignment than element type,
26699082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // so just accept any pointer type.
26709082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") {
26719082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      PtrArgNum = -1;
26729082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      HasConstPtr = false;
26739082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    }
26749082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson
26756f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (mask) {
2676b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (isA64TypeCheck)
2677b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case AArch64::BI__builtin_neon_";
2678b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      else
2679b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case ARM::BI__builtin_neon_";
2680b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << MangleName(name, TypeVec[si], ClassB) << ": mask = "
2681b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover         << "0x" << utohexstr(mask) << "ULL";
26824648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
26834648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
26846f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
26856f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
26866f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
26876f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
26886f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (qmask) {
2689b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (isA64TypeCheck)
2690b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case AArch64::BI__builtin_neon_";
2691b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      else
2692b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << "case ARM::BI__builtin_neon_";
2693b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << MangleName(name, TypeVec[qi], ClassB) << ": mask = "
2694b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover         << "0x" << utohexstr(qmask) << "ULL";
26954648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
26964648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
26976f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
26986f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
26996f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
27006f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
270151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
270251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
2703b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2704b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2705b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// genBuiltinsDef: Generate the BuiltinsARM.def and  BuiltinsAArch64.def
2706b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// declaration of builtins, checking for unique builtin declarations.
2707b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::genBuiltinsDef(raw_ostream &OS,
2708b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                 StringMap<ClassKind> &A64IntrinsicMap,
2709b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                 bool isA64GenBuiltinDef) {
2710b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2711b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<OpKind> EmittedMap;
2712b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2713b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate BuiltinsARM.def and BuiltinsAArch64.def
2714b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64GenBuiltinDef)
2715b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_AARCH64_BUILTINS\n";
2716b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  else
2717b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    OS << "#ifdef GET_NEON_BUILTINS\n";
271851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
271951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
272051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
272151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
272251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
272351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
272451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
272551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
2726b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string name = R->getValueAsString("Name");
2727944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = name + "@" + Proto;
272851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
272951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
273051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
273151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
273251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
273351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2734b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string Types = R->getValueAsString("Types");
273551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
273651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
273751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
273851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
273938859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
274051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
274151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
274251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2743b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Do not include AArch64 BUILTIN() macros if not generating
2744b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // code for AArch64
2745b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2746b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64GenBuiltinDef && isA64)
2747b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
274851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2749b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // Include ARM  BUILTIN() macros  in AArch64 but only if ARM intrinsics
2750b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // are not redefined in AArch64 to handle new types, e.g. "vabd" is a SIntr
2751b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // redefined in AArch64 to handle an additional 2 x f64 type.
2752944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (isA64GenBuiltinDef && !isA64 && A64IntrinsicMap.count(Rename)) {
2753944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin      ClassKind &A64CK = A64IntrinsicMap[Rename];
2754b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (A64CK == ck && ck != ClassNone)
275551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
2756b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    }
275751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2758b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
2759b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // Generate the declaration for this builtin, ensuring
2760b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // that each unique BUILTIN() macro appears only once in the output
2761b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      // stream.
2762b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
2763b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      if (EmittedMap.count(bd))
2764b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        continue;
276551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2766b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      EmittedMap[bd] = OpNone;
2767b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      OS << bd << "\n";
276851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
276951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
277051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
277151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
277251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2773b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// runHeader - Emit a file with sections defining:
2774b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 1. the NEON section of BuiltinsARM.def and BuiltinsAArch64.def.
2775b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 2. the SemaChecking code for the type overload checking.
2776b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
2777b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::runHeader(raw_ostream &OS) {
2778b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2779b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2780b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // build a map of AArch64 intriniscs to be used in uniqueness checks.
2781b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<ClassKind> A64IntrinsicMap;
2782b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
2783b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    Record *R = RV[i];
2784b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2785b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2786b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64)
2787b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2788b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2789b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    ClassKind CK = ClassNone;
2790b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (R->getSuperClasses().size() >= 2)
2791b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      CK = ClassMap[R->getSuperClasses()[1]];
2792b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2793b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    std::string Name = R->getValueAsString("Name");
2794944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Proto = R->getValueAsString("Prototype");
2795944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    std::string Rename = Name + "@" + Proto;
2796944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    if (A64IntrinsicMap.count(Rename))
2797b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
2798944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    A64IntrinsicMap[Rename] = CK;
2799b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  }
2800b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2801b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate BuiltinsARM.def for ARM
2802b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genBuiltinsDef(OS, A64IntrinsicMap, false);
2803b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2804b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate BuiltinsAArch64.def for AArch64
2805b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genBuiltinsDef(OS, A64IntrinsicMap, true);
2806b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2807b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate ARM overloaded type checking code for SemaChecking.cpp
2808b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genOverloadTypeCheckCode(OS, A64IntrinsicMap, false);
2809b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2810b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate AArch64 overloaded type checking code for SemaChecking.cpp
2811b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genOverloadTypeCheckCode(OS, A64IntrinsicMap, true);
2812b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2813b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate ARM range checking code for shift/lane immediates.
2814b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genIntrinsicRangeCheckCode(OS, A64IntrinsicMap, false);
2815b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2816b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate the AArch64 range checking code for shift/lane immediates.
2817b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genIntrinsicRangeCheckCode(OS, A64IntrinsicMap, true);
2818b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2819b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
282051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// GenTest - Write out a test for the intrinsic specified by the name and
282151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// type strings, including the embedded patterns for FileCheck to match.
282251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenTest(const std::string &name,
282351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           const std::string &proto,
282451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           StringRef outTypeStr, StringRef inTypeStr,
28257200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                           bool isShift, bool isHiddenLOp,
2826b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                           ClassKind ck, const std::string &InstName,
2827b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover						   bool isA64,
2828b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover						   std::string & testFuncProto) {
282951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
283051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
283151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
283251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
283351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
283451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
283551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
283651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
283751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
283851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
283951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
284051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
284151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
284251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2843b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // todo: GenerateChecksForIntrinsic does not generate CHECK
2844b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // for aarch64 instructions yet
2845c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::vector<std::string> FileCheckPatterns;
2846b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (!isA64) {
2847b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	GenerateChecksForIntrinsic(name, proto, outTypeStr, inTypeStr, ck, InstName,
2848b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover							   isHiddenLOp, FileCheckPatterns);
2849b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	s+= "// CHECK_ARM: test_" + mangledName + "\n";
2850b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  }
2851b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  s += "// CHECK_AARCH64: test_" + mangledName + "\n";
2852c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
285351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the FileCheck patterns.
2854c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If for any reason we do not want to emit a check, mangledInst
2855c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // will be the empty string.
2856c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (FileCheckPatterns.size()) {
2857c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (std::vector<std::string>::const_iterator i = FileCheckPatterns.begin(),
2858c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                  e = FileCheckPatterns.end();
2859c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman         i != e;
2860c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman         ++i) {
2861b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      s += "// CHECK_ARM: " + *i + "\n";
2862c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
2863c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
286451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
286551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the start of the test function.
2866b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2867b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  testFuncProto = TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
286851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
286951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string comma;
287051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
287151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create arguments for values that must be immediate constants.
287251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i')
287351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
2874b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    testFuncProto += comma + TypeString(proto[i], inTypeStr) + " ";
2875b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    testFuncProto.push_back(arg);
287651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    comma = ", ";
287751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2878b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  testFuncProto += ")";
2879b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2880b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  s+= testFuncProto;
2881b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  s+= " {\n  ";
288251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
288351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v')
288451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "return ";
288551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName + "(";
288651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  arg = 'a';
288751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
288851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i') {
288951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // For immediate operands, test the maximum value.
289051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (isShift)
289151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "1"; // FIXME
289251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
289351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
289451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += utostr(RangeFromType(proto[i-1], inTypeStr));
289551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
289651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(arg);
289751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
289851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
289951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
290051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
290151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");\n}\n\n";
290251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
290351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
290451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2905b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Write out all intrinsic tests for the specified target, checking
2906b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// for intrinsic test uniqueness.
2907b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::genTargetTest(raw_ostream &OS, StringMap<OpKind> &EmittedMap,
2908b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                bool isA64GenTest) {
2909b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64GenTest)
2910b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	OS << "#ifdef __aarch64__\n";
291151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2912b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
291351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
291451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
291551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
291651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
291751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
291851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool isShift = R->getValueAsBit("isShift");
29197200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    std::string InstName = R->getValueAsString("InstName");
29207200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    bool isHiddenLOp = R->getValueAsBit("isHiddenLInst");
2921b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    bool isA64 = R->getValueAsBit("isA64");
2922b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2923b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // do not include AArch64 intrinsic test if not generating
2924b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    // code for AArch64
2925b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    if (!isA64GenTest && isA64)
2926b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      continue;
292751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
292851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
292951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
293051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
29317200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
293251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
2933667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    if (kind == OpUnavailable)
2934667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach      continue;
293551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
293651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (kind == OpReinterpret) {
293751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool outQuad = false;
293851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool dummy = false;
293951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
294051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        for (unsigned srcti = 0, srcte = TypeVec.size();
294151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne             srcti != srcte; ++srcti) {
294251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          bool inQuad = false;
294351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
294451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (srcti == ti || inQuad != outQuad)
294551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            continue;
2946b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover		  std::string testFuncProto;
2947b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          std::string s = GenTest(name, Proto, TypeVec[ti], TypeVec[srcti],
2948b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                  isShift, isHiddenLOp, ck, InstName, isA64,
2949b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover								  testFuncProto);
2950b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          if (EmittedMap.count(testFuncProto))
2951b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover            continue;
2952b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          EmittedMap[testFuncProto] = kind;
2953b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          OS << s << "\n";
295451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
295551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
2956b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover		std::string testFuncProto;
2957b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        std::string s = GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift,
2958b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover                                isHiddenLOp, ck, InstName, isA64, testFuncProto);
2959b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        if (EmittedMap.count(testFuncProto))
2960b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover          continue;
2961b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        EmittedMap[testFuncProto] = kind;
2962b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        OS << s << "\n";
296351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
296451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
296551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2966b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2967b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  if (isA64GenTest)
2968b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	OS << "#endif\n";
2969b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2970b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// runTests - Write out a complete set of tests for all of the Neon
2971b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// intrinsics.
2972b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::runTests(raw_ostream &OS) {
2973b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  OS << "// RUN: %clang_cc1 -triple thumbv7s-apple-darwin -target-abi "
2974b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "apcs-gnu\\\n"
2975b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "// RUN:  -target-cpu swift -ffreestanding -Os -S -o - %s\\\n"
2976b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "// RUN:  | FileCheck %s -check-prefix=CHECK_ARM\n"
2977b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover		"\n"
2978b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	    "// RUN: %clang_cc1 -triple aarch64-none-linux-gnu \\\n"
2979b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	    "// RUN -target-feature +neon  -ffreestanding -S -o - %s \\\n"
2980b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover	    "// RUN:  | FileCheck %s -check-prefix=CHECK_AARCH64\n"
2981b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "\n"
2982b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "// REQUIRES: long_tests\n"
2983b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "\n"
2984b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "#include <arm_neon.h>\n"
2985b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover        "\n";
2986b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2987b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // ARM tests must be emitted before AArch64 tests to ensure
2988b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // tests for intrinsics that are common to ARM and AArch64
2989b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // appear only once in the output stream.
2990b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // The check for uniqueness is done in genTargetTest.
2991b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  StringMap<OpKind> EmittedMap;
2992b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2993b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genTargetTest(OS, EmittedMap, false);
2994b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2995b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  genTargetTest(OS, EmittedMap, true);
299651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
299751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
29983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
29993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
30003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).run(OS);
30013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
30023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
30033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runHeader(OS);
30043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
30053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
30063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runTests(OS);
30073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
30083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang
3009