NeonEmitter.cpp revision c327f8705ecb8753555822d479f899bd2234386d
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, 433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpAddw, 443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpSub, 453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpSubl, 463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpSubw, 473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMul, 483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMla, 493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlal, 503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMls, 513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlsl, 523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMulN, 533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlaN, 543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlsN, 553cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlalN, 563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlslN, 573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMulLane, 583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMullLane, 593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlaLane, 603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlsLane, 613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlalLane, 623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMlslLane, 633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpQDMullLane, 643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpQDMlalLane, 653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpQDMlslLane, 663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpQDMulhLane, 673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpQRDMulhLane, 683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpEq, 693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpGe, 703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpLe, 713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpGt, 723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpLt, 733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpNeg, 743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpNot, 753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpAnd, 763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpOr, 773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpXor, 783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpAndNot, 793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpOrNot, 803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpCast, 813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpConcat, 823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpDup, 833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpDupLane, 843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpHi, 853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpLo, 863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpSelect, 873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpRev16, 883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpRev32, 893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpRev64, 903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpReinterpret, 913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpAbdl, 923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpAba, 933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpAbal 943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}; 953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum ClassKind { 973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassNone, 983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassI, // generic integer instruction, e.g., "i8" suffix 993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix 1003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassW, // width-specific instruction, e.g., "8" suffix 10121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassB, // bitcast arguments with enum argument to specify type 10221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassL, // Logical instructions which are op instructions 10321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman // but we need to not emit any suffix for in our 10421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman // tests. 10521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassNoTest // Instructions which we do not test since they are 10621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman // not TRUE instructions. 1073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}; 1083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 1093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// NeonTypeFlags - Flags to identify the types for overloaded Neon 1103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// builtins. These must be kept in sync with the flags in 1113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// include/clang/Basic/TargetBuiltins.h. 1123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace { 1133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonTypeFlags { 1143cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen enum { 1153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen EltTypeMask = 0xf, 1163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen UnsignedFlag = 0x10, 1173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen QuadFlag = 0x20 1183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen }; 1193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen uint32_t Flags; 1203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 1213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic: 1223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen enum EltType { 1233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Int8, 1243cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Int16, 1253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Int32, 1263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Int64, 1273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Poly8, 1283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Poly16, 1293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Float16, 1303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Float32 1313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen }; 1323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 1333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonTypeFlags(unsigned F) : Flags(F) {} 1343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) { 1353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen if (IsUnsigned) 1363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Flags |= UnsignedFlag; 1373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen if (IsQuad) 1383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Flags |= QuadFlag; 1393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen } 1403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 1413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen uint32_t getFlags() const { return Flags; } 1423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}; 1433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace 1443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 1453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace { 1463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonEmitter { 1473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen RecordKeeper &Records; 1483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen StringMap<OpKind> OpMap; 1493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen DenseMap<Record*, ClassKind> ClassMap; 1503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 1513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic: 1523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonEmitter(RecordKeeper &R) : Records(R) { 1533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_NONE"] = OpNone; 1543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_UNAVAILABLE"] = OpUnavailable; 1553cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ADD"] = OpAdd; 1563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ADDL"] = OpAddl; 1573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ADDW"] = OpAddw; 1583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_SUB"] = OpSub; 1593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_SUBL"] = OpSubl; 1603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_SUBW"] = OpSubw; 1613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MUL"] = OpMul; 1623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLA"] = OpMla; 1633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLAL"] = OpMlal; 1643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLS"] = OpMls; 1653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLSL"] = OpMlsl; 1663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MUL_N"] = OpMulN; 1673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLA_N"] = OpMlaN; 1683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLS_N"] = OpMlsN; 1693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLAL_N"] = OpMlalN; 1703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLSL_N"] = OpMlslN; 1713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MUL_LN"]= OpMulLane; 1723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MULL_LN"] = OpMullLane; 1733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLA_LN"]= OpMlaLane; 1743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLS_LN"]= OpMlsLane; 1753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLAL_LN"] = OpMlalLane; 1763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_MLSL_LN"] = OpMlslLane; 1773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_QDMULL_LN"] = OpQDMullLane; 1783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_QDMLAL_LN"] = OpQDMlalLane; 1793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_QDMLSL_LN"] = OpQDMlslLane; 1803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_QDMULH_LN"] = OpQDMulhLane; 1813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane; 1823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_EQ"] = OpEq; 1833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_GE"] = OpGe; 1843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_LE"] = OpLe; 1853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_GT"] = OpGt; 1863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_LT"] = OpLt; 1873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_NEG"] = OpNeg; 1883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_NOT"] = OpNot; 1893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_AND"] = OpAnd; 1903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_OR"] = OpOr; 1913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_XOR"] = OpXor; 1923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ANDN"] = OpAndNot; 1933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ORN"] = OpOrNot; 1943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_CAST"] = OpCast; 1953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_CONC"] = OpConcat; 1963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_HI"] = OpHi; 1973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_LO"] = OpLo; 1983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_DUP"] = OpDup; 1993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_DUP_LN"] = OpDupLane; 2003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_SEL"] = OpSelect; 2013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_REV16"] = OpRev16; 2023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_REV32"] = OpRev32; 2033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_REV64"] = OpRev64; 2043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_REINT"] = OpReinterpret; 2053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ABDL"] = OpAbdl; 2063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ABA"] = OpAba; 2073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen OpMap["OP_ABAL"] = OpAbal; 2083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 2093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Record *SI = R.getClass("SInst"); 2103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Record *II = R.getClass("IInst"); 2113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Record *WI = R.getClass("WInst"); 21221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *SOpI = R.getClass("SOpInst"); 21321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *IOpI = R.getClass("IOpInst"); 21421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *WOpI = R.getClass("WOpInst"); 21521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *LOpI = R.getClass("LOpInst"); 21621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *NoTestOpI = R.getClass("NoTestOpInst"); 21721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman 2183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassMap[SI] = ClassS; 2193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassMap[II] = ClassI; 2203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassMap[WI] = ClassW; 22121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[SOpI] = ClassS; 22221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[IOpI] = ClassI; 22321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[WOpI] = ClassW; 22421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[LOpI] = ClassL; 22521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[NoTestOpI] = ClassNoTest; 2263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen } 2273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 2283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen // run - Emit arm_neon.h.inc 2293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen void run(raw_ostream &o); 2303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 2313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen // runHeader - Emit all the __builtin prototypes used in arm_neon.h 2323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen void runHeader(raw_ostream &o); 2333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 2343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen // runTests - Emit tests for all the Neon intrinsics. 2353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen void runTests(raw_ostream &o); 2363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 2373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenprivate: 2383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen void emitIntrinsic(raw_ostream &OS, Record *R); 2393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}; 2403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace 2413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 24251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs, 24351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// which each StringRef representing a single type declared in the string. 24451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing 24551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2xfloat and 4xfloat respectively. 24651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic void ParseTypes(Record *r, std::string &s, 24751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallVectorImpl<StringRef> &TV) { 24851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne const char *data = s.data(); 24951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne int len = 0; 25051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 25151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) { 25251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U') 25351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 25451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 25551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (data[len]) { 25651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 25751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 25851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 25951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 26051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 26151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': 26251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 26351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 26438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError(r->getLoc(), 26551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "Unexpected letter: " + std::string(data + len, 1)); 26651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 26751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne TV.push_back(StringRef(data, len + 1)); 26851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne data += len + 1; 26951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne len = -1; 27051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 27151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 27251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 27351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Widen - Convert a type code into the next wider type. char -> short, 27451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// short -> int, etc. 27551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Widen(const char t) { 27651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (t) { 27751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 27851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 's'; 27951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 28051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 'i'; 28151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 28251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 'l'; 28351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 28451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 'f'; 28538859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger default: 28638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unhandled type in widen!"); 28751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 28851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 28951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 29051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Narrow - Convert a type code into the next smaller type. short -> char, 29151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// float -> half float, etc. 29251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Narrow(const char t) { 29351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (t) { 29451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 29551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 'c'; 29651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 29751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 's'; 29851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 29951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 'i'; 30051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': 30151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return 'h'; 30238859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger default: 30338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unhandled type in narrow!"); 30451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 30551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 30651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 30751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// For a particular StringRef, return the base type code, and whether it has 30851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// the quad-vector, polynomial, or unsigned modifiers set. 30951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) { 31051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned off = 0; 31151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 31251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // remember quad. 31351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ty[off] == 'Q') { 31451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne quad = true; 31551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ++off; 31651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 31751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 31851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // remember poly. 31951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ty[off] == 'P') { 32051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne poly = true; 32151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ++off; 32251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 32351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 32451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // remember unsigned. 32551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ty[off] == 'U') { 32651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = true; 32751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ++off; 32851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 32951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 33051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // base type to get the type string for. 33151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return ty[off]; 33251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 33351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 33451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ModType - Transform a type code and its modifiers based on a mod code. The 33551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// mod code definitions may be found at the top of arm_neon.td. 33651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ModType(const char mod, char type, bool &quad, bool &poly, 33751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool &usgn, bool &scal, bool &cnst, bool &pntr) { 33851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (mod) { 33951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 't': 34051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (poly) { 34151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne poly = false; 34251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = true; 34351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 34451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 34551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'u': 34651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = true; 34751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne poly = false; 34851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (type == 'f') 34951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = 'i'; 35051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 35151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'x': 35251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = false; 35351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne poly = false; 35451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (type == 'f') 35551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = 'i'; 35651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 35751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': 35851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (type == 'h') 35951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne quad = true; 36051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = 'f'; 36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = false; 36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 36351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'g': 36451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne quad = false; 36551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 36651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'w': 36751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = Widen(type); 36851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne quad = true; 36951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 37051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'n': 37151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = Widen(type); 37251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 37351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 37451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = 'i'; 37551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne scal = true; 37651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 37751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 37851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = 'l'; 37951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne scal = true; 38051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = true; 38151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 38351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'a': 38451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne scal = true; 38551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 38651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'k': 38751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne quad = true; 38851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 38951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 39051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne cnst = true; 39151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'p': 39251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne pntr = true; 39351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne scal = true; 39451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 39551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 39651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = Narrow(type); 39751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (type == 'h') 39851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne quad = false; 39951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 40051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'e': 40151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = Narrow(type); 40251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = true; 40351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 40451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 40551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 40651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 40751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return type; 40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// TypeString - for a modifier and type, generate the name of the typedef for 41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// that type. QUc -> uint8x8_t. 41251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string TypeString(const char mod, StringRef typestr) { 41351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool quad = false; 41451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool poly = false; 41551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool usgn = false; 41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool scal = false; 41751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool cnst = false; 41851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool pntr = false; 41951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 42051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == 'v') 42151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return "void"; 42251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == 'i') 42351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return "int"; 42451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 42551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // base type to get the type string for. 42651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char type = ClassifyType(typestr, quad, poly, usgn); 42751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 42851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Based on the modifying character, change the type and width if necessary. 42951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); 43051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 43151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallString<128> s; 43251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 43351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (usgn) 43451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back('u'); 43551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 43651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (type) { 43751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 43851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += poly ? "poly8" : "int8"; 43951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (scal) 44051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 44151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += quad ? "x16" : "x8"; 44251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 44351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 44451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += poly ? "poly16" : "int16"; 44551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (scal) 44651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 44751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += quad ? "x8" : "x4"; 44851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 44951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 45051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "int32"; 45151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (scal) 45251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 45351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += quad ? "x4" : "x2"; 45451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 45551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 45651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "int64"; 45751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (scal) 45851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 45951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += quad ? "x2" : "x1"; 46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "float16"; 46351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (scal) 46451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 46551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += quad ? "x8" : "x4"; 46651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 46751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': 46851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "float32"; 46951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (scal) 47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += quad ? "x4" : "x2"; 47251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 47351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 47438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unhandled type!"); 47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 47751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == '2') 47851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "x2"; 47951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == '3') 48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "x3"; 48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == '4') 48251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "x4"; 48351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 48451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Append _t, finishing the type string typedef type. 48551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "_t"; 48651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (cnst) 48851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " const"; 48951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 49051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (pntr) 49151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " *"; 49251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 49351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s.str(); 49451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 49551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 49651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinTypeString - for a modifier and type, generate the clang 49751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinsARM.def prototype code for the function. See the top of clang's 49851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Builtins.def for a description of the type strings. 49951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string BuiltinTypeString(const char mod, StringRef typestr, 50051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ClassKind ck, bool ret) { 50151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool quad = false; 50251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool poly = false; 50351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool usgn = false; 50451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool scal = false; 50551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool cnst = false; 50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool pntr = false; 50751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 50851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == 'v') 50951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return "v"; // void 51051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == 'i') 51151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return "i"; // int 51251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 51351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // base type to get the type string for. 51451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char type = ClassifyType(typestr, quad, poly, usgn); 51551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 51651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Based on the modifying character, change the type and width if necessary. 51751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); 51851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 51951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // All pointers are void* pointers. Change type to 'v' now. 52051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (pntr) { 52151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = false; 52251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne poly = false; 52351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = 'v'; 52451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 52551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Treat half-float ('h') types as unsigned short ('s') types. 52651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (type == 'h') { 52751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = 's'; 52851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = true; 52951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 53051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f'); 53151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 53251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (scal) { 53351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallString<128> s; 53451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 53551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (usgn) 53651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back('U'); 53751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (type == 'c') 53851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back('S'); // make chars explicitly signed 53951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 54051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (type == 'l') // 64-bit long 54151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "LLi"; 54251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 54351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back(type); 54451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (cnst) 54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back('C'); 54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (pntr) 54851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back('*'); 54951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s.str(); 55051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 55151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 55251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Since the return value must be one type, return a vector type of the 55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // appropriate width which we will bitcast. An exception is made for 55451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // returning structs of 2, 3, or 4 vectors which are returned in a sret-like 55551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // fashion, storing them to a pointer arg. 55651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ret) { 55751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod >= '2' && mod <= '4') 55851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return "vv*"; // void result with void* first argument 55951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == 'f' || (ck != ClassB && type == 'f')) 56051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V4f" : "V2f"; 56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck != ClassB && type == 's') 56251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V8s" : "V4s"; 56351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck != ClassB && type == 'i') 56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V4i" : "V2i"; 56551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck != ClassB && type == 'l') 56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V2LLi" : "V1LLi"; 56751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 56851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V16Sc" : "V8Sc"; 56951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Non-return array types are passed as individual vectors. 57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == '2') 57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V16ScV16Sc" : "V8ScV8Sc"; 57451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == '3') 57551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc"; 57651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == '4') 57751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc"; 57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == 'f' || (ck != ClassB && type == 'f')) 58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V4f" : "V2f"; 58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck != ClassB && type == 's') 58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V8s" : "V4s"; 58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck != ClassB && type == 'i') 58451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V4i" : "V2i"; 58551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck != ClassB && type == 'l') 58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V2LLi" : "V1LLi"; 58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return quad ? "V16Sc" : "V8Sc"; 58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 591fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// InstructionTypeCode - Computes the ARM argument character code and 592fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// quad status for a specific type string and ClassKind. 593fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic void InstructionTypeCode(const StringRef &typeStr, 594fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman const ClassKind ck, 595fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman bool &quad, 596fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman std::string &typeCode) { 59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool poly = false; 59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool usgn = false; 599fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman char type = ClassifyType(typeStr, quad, poly, usgn); 60051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 60151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (type) { 60251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 60351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (ck) { 604fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassS: typeCode = poly ? "p8" : usgn ? "u8" : "s8"; break; 605fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassI: typeCode = "i8"; break; 606fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassW: typeCode = "8"; break; 60751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: break; 60851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 60951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 61051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 61151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (ck) { 612fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassS: typeCode = poly ? "p16" : usgn ? "u16" : "s16"; break; 613fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassI: typeCode = "i16"; break; 614fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassW: typeCode = "16"; break; 61551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: break; 61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 61751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 61951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (ck) { 620fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassS: typeCode = usgn ? "u32" : "s32"; break; 621fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassI: typeCode = "i32"; break; 622fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassW: typeCode = "32"; break; 62351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: break; 62451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (ck) { 628fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassS: typeCode = usgn ? "u64" : "s64"; break; 629fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassI: typeCode = "i64"; break; 630fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassW: typeCode = "64"; break; 63151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: break; 63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (ck) { 63651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case ClassS: 637fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassI: typeCode = "f16"; break; 638fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassW: typeCode = "16"; break; 63951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: break; 64051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 64151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 64251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': 64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (ck) { 64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case ClassS: 645fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassI: typeCode = "f32"; break; 646fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman case ClassW: typeCode = "32"; break; 64751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: break; 64851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 64951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 65051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 65138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unhandled type!"); 65251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 653fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman} 654fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 655fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// MangleName - Append a type or width suffix to a base neon function name, 656fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// and insert a 'q' in the appropriate location if the operation works on 657fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc. 658fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic std::string MangleName(const std::string &name, StringRef typestr, 659fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman ClassKind ck) { 660fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman if (name == "vcvt_f32_f16") 661fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman return name; 662fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 663fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman bool quad = false; 664fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman std::string typeCode = ""; 665fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 666fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman InstructionTypeCode(typestr, ck, quad, typeCode); 667fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 668fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman std::string s = name; 669fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 670fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman if (typeCode.size() > 0) { 671fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman s += "_" + typeCode; 672fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman } 673fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 67451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck == ClassB) 67551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "_v"; 67651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 67751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Insert a 'q' before the first '_' character so that it ends up before 67851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // _lane or _n on vector-scalar operations. 67951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (quad) { 68051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne size_t pos = s.find('_'); 68151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s = s.insert(pos, "q"); 68251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 683c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 68451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 68551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 68651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 687c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void PreprocessInstruction(const StringRef &Name, 688c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string &InstName, 689c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string &Prefix, 690c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool &HasNPostfix, 691c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool &HasLanePostfix, 692c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool &HasDupPostfix, 693c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool &IsSpecialVCvt, 694c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman size_t &TBNumber) { 695c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // All of our instruction name fields from arm_neon.td are of the form 696c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // <instructionname>_... 697c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Thus we grab our instruction name via computation of said Prefix. 698c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const size_t PrefixEnd = Name.find_first_of('_'); 699c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If InstName is passed in, we use that instead of our name Prefix. 700c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Prefix = InstName.size() == 0? Name.slice(0, PrefixEnd).str() : InstName; 701c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 702c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const StringRef Postfix = Name.slice(PrefixEnd, Name.size()); 703c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 704c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasNPostfix = Postfix.count("_n"); 705c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasLanePostfix = Postfix.count("_lane"); 706c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasDupPostfix = Postfix.count("_dup"); 707c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman IsSpecialVCvt = Postfix.size() != 0 && Name.count("vcvt"); 708c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 709c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (InstName.compare("vtbl") == 0 || 710c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman InstName.compare("vtbx") == 0) { 711c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If we have a vtblN/vtbxN instruction, use the instruction's ASCII 712c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // encoding to get its true value. 713c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman TBNumber = Name[Name.size()-1] - 48; 714c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 715c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 716c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 717c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatternsForLoadStores - Given a bunch of data we have 718c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern for a Load Or Store 719c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void 720c327f8705ecb8753555822d479f899bd2234386dMichael GottesmanGenerateRegisterCheckPatternForLoadStores(const StringRef &NameRef, 721c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string& OutTypeCode, 722c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &IsQuad, 723c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasDupPostfix, 724c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasLanePostfix, 725c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const size_t Count, 726c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string &RegisterSuffix) { 727c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsLDSTOne = NameRef.count("vld1") || NameRef.count("vst1"); 728c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If N == 3 || N == 4 and we are dealing with a quad instruction, Clang 729c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // will output a series of v{ld,st}1s, so we have to handle it specially. 730c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if ((Count == 3 || Count == 4) && IsQuad) { 731c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "{"; 732c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman for (size_t i = 0; i < Count; i++) { 733c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "d{{[0-9]+}}"; 734c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (HasDupPostfix) { 735c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "[]"; 736c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 737c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (HasLanePostfix) { 738c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "[{{[0-9]+}}]"; 739c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 740c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (i < Count-1) { 741c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += ", "; 742c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 743c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 744c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "}"; 745c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else { 746c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 747c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Handle normal loads and stores. 748c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "{"; 749c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman for (size_t i = 0; i < Count; i++) { 750c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "d{{[0-9]+}}"; 751c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (HasDupPostfix) { 752c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "[]"; 753c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 754c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (HasLanePostfix) { 755c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "[{{[0-9]+}}]"; 756c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 757c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (IsQuad && !HasLanePostfix) { 758c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += ", d{{[0-9]+}}"; 759c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (HasDupPostfix) { 760c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "[]"; 761c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 762c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 763c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (i < Count-1) { 764c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += ", "; 765c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 766c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 767c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "}, [r{{[0-9]+}}"; 768c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 769c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // We only include the alignment hint if we have a vld1.*64 or 770c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // a dup/lane instruction. 771c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (IsLDSTOne) { 772c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if ((HasLanePostfix || HasDupPostfix) && OutTypeCode != "8") { 773c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += ", :" + OutTypeCode; 774c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (OutTypeCode == "64") { 775c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += ", :64"; 776c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 777c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 778c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 779c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "]"; 780c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 781c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 782c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 783c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool HasNPostfixAndScalarArgs(const StringRef &NameRef, 784c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasNPostfix) { 785c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return (NameRef.count("vmla") || 786c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vmlal") || 787c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vmlsl") || 788c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vmull") || 789c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqdmlal") || 790c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqdmlsl") || 791c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqdmulh") || 792c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqdmull") || 793c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqrdmulh")) && HasNPostfix; 794c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 795c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 796c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsFiveOperandLaneAccumulator(const StringRef &NameRef, 797c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasLanePostfix) { 798c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return (NameRef.count("vmla") || 799c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vmls") || 800c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vmlal") || 801c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vmlsl") || 802c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman (NameRef.count("vmul") && NameRef.size() == 3)|| 803c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqdmlal") || 804c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqdmlsl") || 805c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqdmulh") || 806c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NameRef.count("vqrdmulh")) && HasLanePostfix; 807c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 808c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 809c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsSpecialLaneMultiply(const StringRef &NameRef, 810c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasLanePostfix, 811c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &IsQuad) { 812c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsVMulOrMulh = (NameRef.count("vmul") || NameRef.count("mulh")) 813c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman && IsQuad; 814c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsVMull = NameRef.count("mull") && !IsQuad; 815c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return (IsVMulOrMulh || IsVMull) && HasLanePostfix; 816c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 817c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 818c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void NormalizeProtoForRegisterPatternCreation(const std::string &Name, 819c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string &Proto, 820c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasNPostfix, 821c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &IsQuad, 822c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasLanePostfix, 823c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasDupPostfix, 824c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string &NormedProto) { 825c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Handle generic case. 826c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const StringRef NameRef(Name); 827c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman for (size_t i = 0, end = Proto.size(); i < end; i++) { 828c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman switch (Proto[i]) { 829c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'u': 830c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'f': 831c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'd': 832c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 's': 833c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'x': 834c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 't': 835c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'n': 836c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto += IsQuad? 'q' : 'd'; 837c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 838c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'w': 839c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'k': 840c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto += 'q'; 841c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 842c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'g': 843c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'h': 844c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'e': 845c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto += 'd'; 846c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 847c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'i': 848c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto += HasLanePostfix? 'a' : 'i'; 849c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 850c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'a': 851c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (HasLanePostfix) { 852c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto += 'a'; 853c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (HasNPostfixAndScalarArgs(NameRef, HasNPostfix)) { 854c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto += IsQuad? 'q' : 'd'; 855c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else { 856c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto += 'i'; 857c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 858c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 859c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 860c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 861c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 862c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Handle Special Cases. 863c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsNotVExt = !NameRef.count("vext"); 864c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsVPADAL = NameRef.count("vpadal"); 865c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool Is5OpLaneAccum = IsFiveOperandLaneAccumulator(NameRef, 866c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasLanePostfix); 867c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsSpecialLaneMul = IsSpecialLaneMultiply(NameRef, HasLanePostfix, 868c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman IsQuad); 869c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 870c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (IsSpecialLaneMul) { 871c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If 872c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto[2] = NormedProto[3]; 873c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto.erase(3); 874c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (NormedProto.size() == 4 && 875c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto[0] == NormedProto[1] && 876c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman IsNotVExt) { 877c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If NormedProto.size() == 4 and the first two proto characters are the 878c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // same, ignore the first. 879c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto = NormedProto.substr(1, 3); 880c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (Is5OpLaneAccum) { 881c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If we have a 5 op lane accumulator operation, we take characters 1,2,4 882c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string tmp = NormedProto.substr(1,2); 883c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman tmp += NormedProto[4]; 884c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto = tmp; 885c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (IsVPADAL) { 886c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If we have VPADAL, ignore the first character. 887c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto = NormedProto.substr(0, 2); 888c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (NameRef.count("vdup") && NormedProto.size() > 2) { 889c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If our instruction is a dup instruction, keep only the first and 890c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // last characters. 891c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string tmp = ""; 892c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman tmp += NormedProto[0]; 893c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman tmp += NormedProto[NormedProto.size()-1]; 894c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormedProto = tmp; 895c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 896c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 897c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 898c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatterns - Given a bunch of data we have 899c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern to check that an 900c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// instruction's arguments are correct. 901c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateRegisterCheckPattern(const std::string &Name, 902c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string &Proto, 903c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string &OutTypeCode, 904c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasNPostfix, 905c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &IsQuad, 906c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasLanePostfix, 907c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool &HasDupPostfix, 908c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const size_t &TBNumber, 909c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string &RegisterSuffix) { 910c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 911c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix = ""; 912c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 913c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const StringRef NameRef(Name); 914c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const StringRef ProtoRef(Proto); 915c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 916c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if ((NameRef.count("vdup") || NameRef.count("vmov")) && HasNPostfix) { 917c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 918c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 919c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 920c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsLoadStore = NameRef.count("vld") || NameRef.count("vst"); 921c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const bool IsTBXOrTBL = NameRef.count("vtbl") || NameRef.count("vtbx"); 922c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 923c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (IsLoadStore) { 924c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Grab N value from v{ld,st}N using its ascii representation. 925c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const size_t Count = NameRef[3] - 48; 926c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 927c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman GenerateRegisterCheckPatternForLoadStores(NameRef, OutTypeCode, IsQuad, 928c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasDupPostfix, HasLanePostfix, 929c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Count, RegisterSuffix); 930c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (IsTBXOrTBL) { 931c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "d{{[0-9]+}}, {"; 932c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman for (size_t i = 0; i < TBNumber-1; i++) { 933c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "d{{[0-9]+}}, "; 934c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 935c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "d{{[0-9]+}}}, d{{[0-9]+}}"; 936c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else { 937c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Handle a normal instruction. 938c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (NameRef.count("vget") || NameRef.count("vset")) 939c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 940c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 941c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // We first normalize our proto, since we only need to emit 4 942c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // different types of checks, yet have more than 4 proto types 943c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // that map onto those 4 patterns. 944c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string NormalizedProto(""); 945c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormalizeProtoForRegisterPatternCreation(Name, Proto, HasNPostfix, IsQuad, 946c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasLanePostfix, HasDupPostfix, 947c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman NormalizedProto); 948c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 949c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman for (size_t i = 0, end = NormalizedProto.size(); i < end; i++) { 950c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const char &c = NormalizedProto[i]; 951c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman switch (c) { 952c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'q': 953c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "q{{[0-9]+}}, "; 954c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 955c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 956c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'd': 957c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "d{{[0-9]+}}, "; 958c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 959c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 960c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'i': 961c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "#{{[0-9]+}}, "; 962c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 963c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 964c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman case 'a': 965c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix += "d{{[0-9]+}}[{{[0-9]}}], "; 966c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman break; 967c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 968c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 969c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 970c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Remove extra ", ". 971c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix = RegisterSuffix.substr(0, RegisterSuffix.size()-2); 972c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 973c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 974c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 975c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateChecksForIntrinsic - Given a specific instruction name + 976c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// typestr + class kind, generate the proper set of FileCheck 977c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// Patterns to check for. We could just return a string, but instead 978c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// use a vector since it provides us with the extra flexibility of 979c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// emitting multiple checks, which comes in handy for certain cases 980c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// like mla where we want to check for 2 different instructions. 981c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateChecksForIntrinsic(const std::string &Name, 982c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string &Proto, 983c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman StringRef &OutTypeStr, 984c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman StringRef &InTypeStr, 985c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman ClassKind Ck, 986c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string &InstName, 987c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool IsHiddenLOp, 988c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::vector<std::string>& Result) { 989c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 990c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If Ck is a ClassNoTest instruction, just return so no test is 991c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // emitted. 992c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if(Ck == ClassNoTest) 993c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 994c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 995c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (Name == "vcvt_f32_f16") { 996c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("vcvt.f32.f16"); 997c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 998c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 999c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1000c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1001c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Now we preprocess our instruction given the data we have to get the 1002c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // data that we need. 1003c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Create a StringRef for String Manipulation of our Name. 1004c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const StringRef NameRef(Name); 1005c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Instruction Prefix. 1006c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string Prefix; 1007c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // The type code for our out type string. 1008c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string OutTypeCode; 1009c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // To handle our different cases, we need to check for different postfixes. 1010c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Is our instruction a quad instruction. 1011c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool IsQuad = false; 1012c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Our instruction is of the form <instructionname>_n. 1013c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool HasNPostfix = false; 1014c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Our instruction is of the form <instructionname>_lane. 1015c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool HasLanePostfix = false; 1016c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Our instruction is of the form <instructionname>_dup. 1017c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool HasDupPostfix = false; 1018c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Our instruction is a vcvt instruction which requires special handling. 1019c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool IsSpecialVCvt = false; 1020c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If we have a vtbxN or vtblN instruction, this is set to N. 1021c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman size_t TBNumber = -1; 1022c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Register Suffix 1023c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::string RegisterSuffix; 1024c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1025c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman PreprocessInstruction(NameRef, InstName, Prefix, 1026c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasNPostfix, HasLanePostfix, HasDupPostfix, 1027c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman IsSpecialVCvt, TBNumber); 1028c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1029c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman InstructionTypeCode(OutTypeStr, Ck, IsQuad, OutTypeCode); 1030c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman GenerateRegisterCheckPattern(Name, Proto, OutTypeCode, HasNPostfix, IsQuad, 1031c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman HasLanePostfix, HasDupPostfix, TBNumber, 1032c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman RegisterSuffix); 1033c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1034c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // In the following section, we handle a bunch of special cases. You can tell 1035c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // a special case by the fact we are returning early. 1036c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1037c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If our instruction is a logical instruction without postfix or a 1038c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // hidden LOp just return the current Prefix. 1039c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (Ck == ClassL || IsHiddenLOp) { 1040c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back(Prefix + " " + RegisterSuffix); 1041c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1042c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1043c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1044c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If we have a vmov, due to the many different cases, some of which 1045c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // vary within the different intrinsics generated for a single 1046c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // instruction type, just output a vmov. (e.g. given an instruction 1047c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // A, A.u32 might be vmov and A.u8 might be vmov.8). 1048c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // 1049c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // FIXME: Maybe something can be done about this. The two cases that we care 1050c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // about are vmov as an LType and vmov as a WType. 1051c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (Prefix == "vmov") { 1052c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back(Prefix + " " + RegisterSuffix); 1053c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1054c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1055c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1056c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // In the following section, we handle special cases. 1057c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1058c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (OutTypeCode == "64") { 1059c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If we have a 64 bit vdup/vext and are handling an uint64x1_t 1060c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // type, the intrinsic will be optimized away, so just return 1061c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // nothing. On the other hand if we are handling an uint64x2_t 1062c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // (i.e. quad instruction), vdup/vmov instructions should be 1063c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // emitted. 1064c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (Prefix == "vdup" || Prefix == "vext") { 1065c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (IsQuad) { 1066c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("{{vmov|vdup}}"); 1067c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1068c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1069c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1070c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1071c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // v{st,ld}{2,3,4}_{u,s}64 emit v{st,ld}1.64 instructions with 1072c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // multiple register operands. 1073c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool MultiLoadPrefix = Prefix == "vld2" || Prefix == "vld3" 1074c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman || Prefix == "vld4"; 1075c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman bool MultiStorePrefix = Prefix == "vst2" || Prefix == "vst3" 1076c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman || Prefix == "vst4"; 1077c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (MultiLoadPrefix || MultiStorePrefix) { 1078c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back(NameRef.slice(0, 3).str() + "1.64"); 1079c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1080c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1081c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1082c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // v{st,ld}1_{lane,dup}_{u64,s64} use vldr/vstr/vmov/str instead of 1083c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // emitting said instructions. So return a check for 1084c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // vldr/vstr/vmov/str instead. 1085c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (HasLanePostfix || HasDupPostfix) { 1086c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (Prefix == "vst1") { 1087c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("{{str|vstr|vmov}}"); 1088c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1089c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (Prefix == "vld1") { 1090c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("{{ldr|vldr|vmov}}"); 1091c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1092c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1093c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1094c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1095c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1096c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // vzip.32/vuzp.32 are the same instruction as vtrn.32 and are 1097c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // sometimes disassembled as vtrn.32. We use a regex to handle both 1098c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // cases. 1099c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if ((Prefix == "vzip" || Prefix == "vuzp") && OutTypeCode == "32") { 1100c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("{{vtrn|" + Prefix + "}}.32 " + RegisterSuffix); 1101c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1102c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1103c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1104c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Currently on most ARM processors, we do not use vmla/vmls for 1105c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // quad floating point operations. Instead we output vmul + vadd. So 1106c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // check if we have one of those instructions and just output a 1107c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // check for vmul. 1108c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (OutTypeCode == "f32") { 1109c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (Prefix == "vmls") { 1110c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix); 1111c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("vsub." + OutTypeCode); 1112c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1113c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } else if (Prefix == "vmla") { 1114c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix); 1115c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back("vadd." + OutTypeCode); 1116c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1117c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1118c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1119c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1120c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If we have vcvt, get the input type from the instruction name 1121c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // (which should be of the form instname_inputtype) and append it 1122c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // before the output type. 1123c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (Prefix == "vcvt") { 1124c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman const std::string inTypeCode = NameRef.substr(NameRef.find_last_of("_")+1); 1125c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Prefix += "." + inTypeCode; 1126c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1127c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1128c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // Append output type code to get our final mangled instruction. 1129c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Prefix += "." + OutTypeCode; 1130c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1131c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman Result.push_back(Prefix + " " + RegisterSuffix); 1132c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 1133c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 113451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// UseMacro - Examine the prototype string to determine if the intrinsic 113551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// should be defined as a preprocessor macro instead of an inline function. 113651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool UseMacro(const std::string &proto) { 113751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // If this builtin takes an immediate argument, we need to #define it rather 113851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // than use a standard declaration, so that SemaChecking can range check 113951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // the immediate passed by the user. 114051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto.find('i') != std::string::npos) 114151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return true; 114251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 114351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Pointer arguments need to use macros to avoid hiding aligned attributes 114451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // from the pointer type. 114551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto.find('p') != std::string::npos || 114651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne proto.find('c') != std::string::npos) 114751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return true; 114851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 114951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return false; 115051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 115151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 115251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is 115351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// defined as a macro should be accessed directly instead of being first 115451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// assigned to a local temporary. 115551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool MacroArgUsedDirectly(const std::string &proto, unsigned i) { 115651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // True for constant ints (i), pointers (p) and const pointers (c). 115751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c'); 115851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 115951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 116051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the string "(argtype a, argtype b, ...)" 116151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenArgs(const std::string &proto, StringRef typestr) { 116251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool define = UseMacro(proto); 116351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char arg = 'a'; 116451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 116551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 116651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "("; 116751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 116851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { 116951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (define) { 117051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Some macro arguments are used directly instead of being assigned 117151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // to local temporaries; prepend an underscore prefix to make their 117251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // names consistent with the local temporaries. 117351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (MacroArgUsedDirectly(proto, i)) 117451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__"; 117551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 117651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += TypeString(proto[i], typestr) + " __"; 117751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 117851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back(arg); 117951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if ((i + 1) < e) 118051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", "; 118151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 118251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 118351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ")"; 118451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 118551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 118651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 118751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Macro arguments are not type-checked like inline function arguments, so 118851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// assign them to local temporaries to get the right type checking. 118951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenMacroLocals(const std::string &proto, StringRef typestr) { 119051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char arg = 'a'; 119151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 119251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool generatedLocal = false; 119351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 119451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { 119551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Do not create a temporary for an immediate argument. 119651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // That would defeat the whole point of using a macro! 119751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (MacroArgUsedDirectly(proto, i)) 119851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 119951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne generatedLocal = true; 120051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 120151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += TypeString(proto[i], typestr) + " __"; 120251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back(arg); 120351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " = ("; 120451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back(arg); 120551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "); "; 120651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 120751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 120851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (generatedLocal) 120951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "\\\n "; 121051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 121151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 121251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 121351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Use the vmovl builtin to sign-extend or zero-extend a vector. 121451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Extend(StringRef typestr, const std::string &a) { 121551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 121651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s = MangleName("vmovl", typestr, ClassS); 121751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + a + ")"; 121851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 121951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 122051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 122151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Duplicate(unsigned nElts, StringRef typestr, 122251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne const std::string &a) { 122351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 122451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 122551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s = "(" + TypeString('d', typestr) + "){ "; 122651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0; i != nElts; ++i) { 122751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += a; 122851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if ((i + 1) < nElts) 122951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", "; 123051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 123151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " }"; 123251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 123351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 123451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 123551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 123651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string SplatLane(unsigned nElts, const std::string &vec, 123751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne const std::string &lane) { 123851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s = "__builtin_shufflevector(" + vec + ", " + vec; 123951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0; i < nElts; ++i) 124051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", " + lane; 124151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ")"; 124251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 124351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 124451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 124551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNumElements(StringRef typestr, bool &quad) { 124651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne quad = false; 124751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool dummy = false; 124851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char type = ClassifyType(typestr, quad, dummy, dummy); 124951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned nElts = 0; 125051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (type) { 125151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': nElts = 8; break; 125251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': nElts = 4; break; 125351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': nElts = 2; break; 125451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': nElts = 1; break; 125551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': nElts = 4; break; 125651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': nElts = 2; break; 125751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 125838859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unhandled type!"); 125951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 126051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (quad) nElts <<= 1; 126151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return nElts; 126251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 126351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 126451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd. 126551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenOpString(OpKind op, const std::string &proto, 126651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef typestr) { 126751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool quad; 126851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned nElts = GetNumElements(typestr, quad); 126951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool define = UseMacro(proto); 127051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 127151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string ts = TypeString(proto[0], typestr); 127251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 127351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (!define) { 127451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s = "return "; 127551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 127651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 127751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch(op) { 127851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAdd: 127951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + __b;"; 128051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 128151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAddl: 128251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";"; 128351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 128451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAddw: 128551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + " + Extend(typestr, "__b") + ";"; 128651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 128751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpSub: 128851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - __b;"; 128951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 129051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpSubl: 129151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";"; 129251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 129351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpSubw: 129451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - " + Extend(typestr, "__b") + ";"; 129551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 129651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMulN: 129751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a * " + Duplicate(nElts, typestr, "__b") + ";"; 129851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 129951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMulLane: 130051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a * " + SplatLane(nElts, "__b", "__c") + ";"; 130151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 130251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMul: 130351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a * __b;"; 130451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 130551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMullLane: 130651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName("vmull", typestr, ClassS) + "(__a, " + 130751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__b", "__c") + ");"; 130851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 130951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlaN: 131051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");"; 131151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 131251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlaLane: 131351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");"; 131451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 131551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMla: 131651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + (__b * __c);"; 131751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 131851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlalN: 131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " + 132051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Duplicate(nElts, typestr, "__c") + ");"; 132151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 132251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlalLane: 132351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " + 132451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__c", "__d") + ");"; 132551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 132651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlal: 132751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);"; 132851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 132951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlsN: 133051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");"; 133151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 133251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlsLane: 133351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");"; 133451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 133551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMls: 133651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - (__b * __c);"; 133751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 133851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlslN: 133951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " + 134051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Duplicate(nElts, typestr, "__c") + ");"; 134151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 134251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlslLane: 134351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " + 134451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__c", "__d") + ");"; 134551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 134651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpMlsl: 134751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);"; 134851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 134951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpQDMullLane: 135051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName("vqdmull", typestr, ClassS) + "(__a, " + 135151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__b", "__c") + ");"; 135251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 135351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpQDMlalLane: 135451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " + 135551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__c", "__d") + ");"; 135651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 135751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpQDMlslLane: 135851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " + 135951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__c", "__d") + ");"; 136051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 136151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpQDMulhLane: 136251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " + 136351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__b", "__c") + ");"; 136451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 136551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpQRDMulhLane: 136651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " + 136751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SplatLane(nElts, "__b", "__c") + ");"; 136851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 136951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpEq: 137051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")(__a == __b);"; 137151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 137251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpGe: 137351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")(__a >= __b);"; 137451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 137551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpLe: 137651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")(__a <= __b);"; 137751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 137851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpGt: 137951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")(__a > __b);"; 138051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 138151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpLt: 138251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")(__a < __b);"; 138351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 138451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpNeg: 138551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " -__a;"; 138651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 138751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpNot: 138851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " ~__a;"; 138951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 139051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAnd: 139151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a & __b;"; 139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpOr: 139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a | __b;"; 139551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 139651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpXor: 139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a ^ __b;"; 139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAndNot: 140051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a & ~__b;"; 140151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpOrNot: 140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a | ~__b;"; 140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpCast: 140651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")__a;"; 140751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 140851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpConcat: 140951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a"; 141051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", (int64x1_t)__b, 0, 1);"; 141151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 141251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpHi: 141351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + 141451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);"; 141551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 141651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpLo: 141751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + 141851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);"; 141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 142051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpDup: 142151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += Duplicate(nElts, typestr, "__a") + ";"; 142251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 142351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpDupLane: 142451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += SplatLane(nElts, "__a", "__b") + ";"; 142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 142651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpSelect: 142751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // ((0 & 1) | (~0 & 2)) 142851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")"; 142951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ts = TypeString(proto[1], typestr); 143051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "((__a & (" + ts + ")__b) | "; 143151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(~__a & (" + ts + ")__c));"; 143251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 143351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpRev16: 143451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__builtin_shufflevector(__a, __a"; 143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 2; i <= nElts; i += 2) 143651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned j = 0; j != 2; ++j) 143751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", " + utostr(i - j - 1); 143851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ");"; 143951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 144051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpRev32: { 144151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned WordElts = nElts >> (1 + (int)quad); 144251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__builtin_shufflevector(__a, __a"; 144351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = WordElts; i <= nElts; i += WordElts) 144451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned j = 0; j != WordElts; ++j) 144551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", " + utostr(i - j - 1); 144651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ");"; 144751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 144851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 144951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpRev64: { 145051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned DblWordElts = nElts >> (int)quad; 145151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__builtin_shufflevector(__a, __a"; 145251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts) 145351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned j = 0; j != DblWordElts; ++j) 145451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", " + utostr(i - j - 1); 145551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ");"; 145651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 145751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 145851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAbdl: { 145951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)"; 146051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (typestr[0] != 'U') { 146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // vabd results are always unsigned and must be zero-extended. 146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string utype = "U" + typestr.str(); 146351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + TypeString(proto[0], typestr) + ")"; 146451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne abd = "(" + TypeString('d', utype) + ")" + abd; 146551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += Extend(utype, abd) + ";"; 146651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 146751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += Extend(typestr, abd) + ";"; 146851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 146951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 147151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAba: 147251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);"; 147351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 147451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case OpAbal: { 147551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__a + "; 147651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)"; 147751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (typestr[0] != 'U') { 147851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // vabd results are always unsigned and must be zero-extended. 147951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string utype = "U" + typestr.str(); 148051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + TypeString(proto[0], typestr) + ")"; 148151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne abd = "(" + TypeString('d', utype) + ")" + abd; 148251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += Extend(utype, abd) + ";"; 148351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 148451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += Extend(typestr, abd) + ";"; 148551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 148651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 148751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 148851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 148938859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unknown OpKind!"); 149051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 149151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 149251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 149351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 149451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { 149551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned mod = proto[0]; 149651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 149751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (mod == 'v' || mod == 'f') 149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne mod = proto[1]; 149951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 150051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool quad = false; 150151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool poly = false; 150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool usgn = false; 150351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool scal = false; 150451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool cnst = false; 150551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool pntr = false; 150651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 150751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Base type to get the type string for. 150851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char type = ClassifyType(typestr, quad, poly, usgn); 150951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 151051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Based on the modifying character, change the type and width if necessary. 151151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); 151251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1513da95f73b59f9af964e33725c515139d34c90c863Bob Wilson NeonTypeFlags::EltType ET; 151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (type) { 151551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 1516da95f73b59f9af964e33725c515139d34c90c863Bob Wilson ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8; 151751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 151851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 1519da95f73b59f9af964e33725c515139d34c90c863Bob Wilson ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16; 152051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 152151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 1522da95f73b59f9af964e33725c515139d34c90c863Bob Wilson ET = NeonTypeFlags::Int32; 152351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 152451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 1525da95f73b59f9af964e33725c515139d34c90c863Bob Wilson ET = NeonTypeFlags::Int64; 152651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 152751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 1528da95f73b59f9af964e33725c515139d34c90c863Bob Wilson ET = NeonTypeFlags::Float16; 152951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 153051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': 1531da95f73b59f9af964e33725c515139d34c90c863Bob Wilson ET = NeonTypeFlags::Float32; 153251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 153351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 153438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unhandled type!"); 153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1536da95f73b59f9af964e33725c515139d34c90c863Bob Wilson NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g'); 1537da95f73b59f9af964e33725c515139d34c90c863Bob Wilson return Flags.getFlags(); 153851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 153951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 154051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a) 154151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltin(const std::string &name, const std::string &proto, 154251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef typestr, ClassKind ck) { 154351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 154451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 154551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit 154651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // sret-like argument. 154751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool sret = (proto[0] >= '2' && proto[0] <= '4'); 154851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 154951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool define = UseMacro(proto); 155051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 155151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Check if the prototype has a scalar operand with the type of the vector 155251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // elements. If not, bitcasting the args will take care of arg checking. 155351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // The actual signedness etc. will be taken care of with special enums. 155451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto.find('s') == std::string::npos) 155551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ck = ClassB; 155651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 155751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto[0] != 'v') { 155851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string ts = TypeString(proto[0], typestr); 155951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 156051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (define) { 156151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (sret) 156251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ts + " r; "; 156351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 156451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "(" + ts + ")"; 156551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else if (sret) { 156651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ts + " r; "; 156751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 156851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "return (" + ts + ")"; 156951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 157051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 157151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 157251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool splat = proto.find('a') != std::string::npos; 157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 157451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__builtin_neon_"; 157551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (splat) { 157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Call the non-splat builtin: chop off the "_n" suffix from the name. 157751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string vname(name, 0, name.size()-2); 157851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName(vname, typestr, ck); 157951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 158051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName(name, typestr, ck); 158151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 158251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "("; 158351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 158451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Pass the address of the return variable as the first argument to sret-like 158551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // builtins. 158651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (sret) 158751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "&r, "; 158851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 158951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char arg = 'a'; 159051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { 159151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string args = std::string(&arg, 1); 159251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 159351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Use the local temporaries instead of the macro arguments. 159451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne args = "__" + args; 159551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 159651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool argQuad = false; 159751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool argPoly = false; 159851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool argUsgn = false; 159951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool argScalar = false; 160051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool dummy = false; 160151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn); 160251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar, 160351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne dummy, dummy); 160451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 160551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Handle multiple-vector values specially, emitting each subvector as an 160651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // argument to the __builtin. 160751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto[i] >= '2' && proto[i] <= '4') { 160851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Check if an explicit cast is needed. 160951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (argType != 'c' || argPoly || argUsgn) 161051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args; 161151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 161251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) { 161351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += args + ".val[" + utostr(vi) + "]"; 161451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if ((vi + 1) < ve) 161551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", "; 161651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 161751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if ((i + 1) < e) 161851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", "; 161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 162051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 162151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 162251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 162351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (splat && (i + 1) == e) 162451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne args = Duplicate(GetNumElements(typestr, argQuad), typestr, args); 162551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 162651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Check if an explicit cast is needed. 162751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if ((splat || !argScalar) && 162851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) { 162951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string argTypeStr = "c"; 163051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck != ClassB) 163151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne argTypeStr = argType; 163251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (argQuad) 163351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne argTypeStr = "Q" + argTypeStr; 163451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne args = "(" + TypeString('d', argTypeStr) + ")" + args; 163551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 163651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 163751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += args; 163851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if ((i + 1) < e) 163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", "; 164051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 164251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Extra constant integer to hold type class enum for this function, e.g. s8 164351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck == ClassB) 164451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", " + utostr(GetNeonEnum(proto, typestr)); 164551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 164651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ");"; 164751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 164851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto[0] != 'v' && sret) { 164951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (define) 165051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " r;"; 165151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 165251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " return r;"; 165351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 165451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 165551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 165651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 165751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltinDef(const std::string &name, 165851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne const std::string &proto, 165951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef typestr, ClassKind ck) { 166051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s("BUILTIN(__builtin_neon_"); 166151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 166251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // If all types are the same size, bitcasting the args will take care 166351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // of arg checking. The actual signedness etc. will be taken care of with 166451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // special enums. 166551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto.find('s') == std::string::npos) 166651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ck = ClassB; 166751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 166851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += MangleName(name, typestr, ck); 166951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", \""; 167051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 167151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = proto.size(); i != e; ++i) 167251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += BuiltinTypeString(proto[i], typestr, ck, i == 0); 167351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 167451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Extra constant integer to hold type class enum for this function, e.g. s8 167551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ck == ClassB) 167651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "i"; 167751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 167851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "\", \"n\")"; 167951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 168051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 168151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 168251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenIntrinsic(const std::string &name, 168351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne const std::string &proto, 168451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef outTypeStr, StringRef inTypeStr, 168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OpKind kind, ClassKind classKind) { 168651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne assert(!proto.empty() && ""); 1687667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach bool define = UseMacro(proto) && kind != OpUnavailable; 168851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 168951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // static always inline + return type 169151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (define) 169251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "#define "; 169351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 169451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "__ai " + TypeString(proto[0], outTypeStr) + " "; 169551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 169651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Function name with type suffix 169751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string mangledName = MangleName(name, outTypeStr, ClassS); 169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (outTypeStr != inTypeStr) { 169951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // If the input type is different (e.g., for vreinterpret), append a suffix 170051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // for the input type. String off a "Q" (quad) prefix so that MangleName 170151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // does not insert another "q" in the name. 170251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0); 170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff); 170451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne mangledName = MangleName(mangledName, inTypeNoQuad, ClassS); 170551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 170651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += mangledName; 170751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 170851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Function arguments 170951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += GenArgs(proto, inTypeStr); 171051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 171151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Definition. 171251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (define) { 171351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " __extension__ ({ \\\n "; 171451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += GenMacroLocals(proto, inTypeStr); 1715667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach } else if (kind == OpUnavailable) { 1716667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach s += " __attribute__((unavailable));\n"; 1717667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach return s; 1718667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach } else 171966981c7ca1fcef529d7d5e5c53b07020ff23d8e3Jim Grosbach s += " {\n "; 172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 172151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (kind != OpNone) 172251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += GenOpString(kind, proto, outTypeStr); 172351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += GenBuiltin(name, proto, outTypeStr, classKind); 172551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (define) 172651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " })"; 172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 172851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += " }"; 172951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "\n"; 173051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 173151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 173251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 173351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h 173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// is comprised of type definitions and function declarations. 173551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::run(raw_ostream &OS) { 173651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << 173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------" 173851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "---===\n" 173951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " *\n" 174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * Permission is hereby granted, free of charge, to any person obtaining " 174151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "a copy\n" 174251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * of this software and associated documentation files (the \"Software\")," 174351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " to deal\n" 174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * in the Software without restriction, including without limitation the " 174551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "rights\n" 174651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * to use, copy, modify, merge, publish, distribute, sublicense, " 174751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "and/or sell\n" 174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * copies of the Software, and to permit persons to whom the Software is\n" 174951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * furnished to do so, subject to the following conditions:\n" 175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " *\n" 175151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * The above copyright notice and this permission notice shall be " 175251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "included in\n" 175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * all copies or substantial portions of the Software.\n" 175451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " *\n" 175551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, " 175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "EXPRESS OR\n" 175751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " 175851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "MERCHANTABILITY,\n" 175951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT " 176051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "SHALL THE\n" 176151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR " 176251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "OTHER\n" 176351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, " 176451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "ARISING FROM,\n" 176551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER " 176651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "DEALINGS IN\n" 176751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " * THE SOFTWARE.\n" 176851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " *\n" 176951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " *===--------------------------------------------------------------------" 177051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "---===\n" 177151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " */\n\n"; 177251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 177351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef __ARM_NEON_H\n"; 177451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#define __ARM_NEON_H\n\n"; 177551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 177651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef __ARM_NEON__\n"; 177751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#error \"NEON support not enabled\"\n"; 177851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 177951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 178051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#include <stdint.h>\n\n"; 178151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 178251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Emit NEON-specific scalar typedefs. 178351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "typedef float float32_t;\n"; 178451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "typedef int8_t poly8_t;\n"; 178551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "typedef int16_t poly16_t;\n"; 178651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "typedef uint16_t float16_t;\n"; 178751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 178851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Emit Neon vector typedefs. 178951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs"); 179051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallVector<StringRef, 24> TDTypeVec; 179151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ParseTypes(0, TypedefTypes, TDTypeVec); 179251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 179351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Emit vector typedefs. 179451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) { 179551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool dummy, quad = false, poly = false; 179651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne (void) ClassifyType(TDTypeVec[i], quad, poly, dummy); 179751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (poly) 179851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "typedef __attribute__((neon_polyvector_type("; 179951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 180051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "typedef __attribute__((neon_vector_type("; 180151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 180251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned nElts = GetNumElements(TDTypeVec[i], quad); 180351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << utostr(nElts) << "))) "; 180451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (nElts < 10) 180551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " "; 180651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 180751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << TypeString('s', TDTypeVec[i]); 180851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << TypeString('d', TDTypeVec[i]) << ";\n"; 180951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 181051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n"; 181151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 181251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Emit struct typedefs. 181351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned vi = 2; vi != 5; ++vi) { 181451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) { 181551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string ts = TypeString('d', TDTypeVec[i]); 181651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string vs = TypeString('0' + vi, TDTypeVec[i]); 181751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "typedef struct " << vs << " {\n"; 181851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << ts << " val"; 181951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "[" << utostr(vi) << "]"; 182051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << ";\n} "; 182151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << vs << ";\n\n"; 182251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 182351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 182451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 18251e8058f8d90fab1b9011adf62caa52e19e61382cBob Wilson OS<<"#define __ai static inline __attribute__((__always_inline__, __nodebug__))\n\n"; 182651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 182751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); 182851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 182951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Emit vmovl, vmull and vabd intrinsics first so they can be used by other 183051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // intrinsics. (Some of the saturating multiply instructions are also 183151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // used to implement the corresponding "_lane" variants, but tablegen 183251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // sorts the records into alphabetical order so that the "_lane" variants 183351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // come after the intrinsics they use.) 183451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne emitIntrinsic(OS, Records.getDef("VMOVL")); 183551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne emitIntrinsic(OS, Records.getDef("VMULL")); 183651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne emitIntrinsic(OS, Records.getDef("VABD")); 183751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 183851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = RV.size(); i != e; ++i) { 183951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *R = RV[i]; 184051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getName() != "VMOVL" && 184151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne R->getName() != "VMULL" && 184251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne R->getName() != "VABD") 184351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne emitIntrinsic(OS, R); 184451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 184551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 184651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#undef __ai\n\n"; 184751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif /* __ARM_NEON_H */\n"; 184851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 184951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 185051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// emitIntrinsic - Write out the arm_neon.h header file definitions for the 185151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics specified by record R. 185251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) { 185351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string name = R->getValueAsString("Name"); 185451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Proto = R->getValueAsString("Prototype"); 185551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Types = R->getValueAsString("Types"); 185651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 185751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallVector<StringRef, 16> TypeVec; 185851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ParseTypes(R, Types, TypeVec); 185951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 186051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()]; 186151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 186251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ClassKind classKind = ClassNone; 186351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getSuperClasses().size() >= 2) 186451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne classKind = ClassMap[R->getSuperClasses()[1]]; 186551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (classKind == ClassNone && kind == OpNone) 186638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError(R->getLoc(), "Builtin has no class kind"); 186751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 186851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { 186951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (kind == OpReinterpret) { 187051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool outQuad = false; 187151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool dummy = false; 187251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy); 187351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned srcti = 0, srcte = TypeVec.size(); 187451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne srcti != srcte; ++srcti) { 187551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool inQuad = false; 187651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy); 187751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (srcti == ti || inQuad != outQuad) 187851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 187951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti], 188051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OpCast, ClassS); 188151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 188251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 188351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti], 188451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne kind, classKind); 188551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 188651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 188751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n"; 188851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 188951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 189051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned RangeFromType(const char mod, StringRef typestr) { 189151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // base type to get the type string for. 189251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool quad = false, dummy = false; 189351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char type = ClassifyType(typestr, quad, dummy, dummy); 189451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy); 189551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 189651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (type) { 189751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 189851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return (8 << (int)quad) - 1; 189951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 190051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 190151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return (4 << (int)quad) - 1; 190251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'f': 190351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 190451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return (2 << (int)quad) - 1; 190551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 190651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return (1 << (int)quad) - 1; 190751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 190838859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError("unhandled type!"); 190951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 191051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 191151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 191251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runHeader - Emit a file with sections defining: 191351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 1. the NEON section of BuiltinsARM.def. 191451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2. the SemaChecking code for the type overload checking. 1915667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach/// 3. the SemaChecking code for validation of intrinsic immediate arguments. 191651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runHeader(raw_ostream &OS) { 191751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); 191851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 191951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringMap<OpKind> EmittedMap; 192051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 192151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Generate BuiltinsARM.def for NEON 192251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifdef GET_NEON_BUILTINS\n"; 192351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = RV.size(); i != e; ++i) { 192451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *R = RV[i]; 192551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; 192651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (k != OpNone) 192751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 192851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 192951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Proto = R->getValueAsString("Prototype"); 193051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 193151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions with 'a' (the splat code) in the type prototype should not get 193251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // their own builtin as they use the non-splat variant. 193351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (Proto.find('a') != std::string::npos) 193451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 193551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 193651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Types = R->getValueAsString("Types"); 193751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallVector<StringRef, 16> TypeVec; 193851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ParseTypes(R, Types, TypeVec); 193951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 194051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getSuperClasses().size() < 2) 194138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError(R->getLoc(), "Builtin has no class kind"); 194251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 194351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string name = R->getValueAsString("Name"); 194451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ClassKind ck = ClassMap[R->getSuperClasses()[1]]; 194551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 194651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { 194751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Generate the BuiltinsARM.def declaration for this builtin, ensuring 194851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // that each unique BUILTIN() macro appears only once in the output 194951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // stream. 195051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck); 195151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (EmittedMap.count(bd)) 195251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 195351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 195451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne EmittedMap[bd] = OpNone; 195551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << bd << "\n"; 195651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 195751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 195851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 195951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 196051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Generate the overloaded type checking code for SemaChecking.cpp 196151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n"; 196251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = RV.size(); i != e; ++i) { 196351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *R = RV[i]; 196451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; 196551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (k != OpNone) 196651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 196751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 196851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Proto = R->getValueAsString("Prototype"); 196951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Types = R->getValueAsString("Types"); 197051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string name = R->getValueAsString("Name"); 197151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 197251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions with 'a' (the splat code) in the type prototype should not get 197351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // their own builtin as they use the non-splat variant. 197451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (Proto.find('a') != std::string::npos) 197551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 197651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 197751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions which have a scalar argument cannot be overloaded, no need to 197851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // check them if we are emitting the type checking code. 197951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (Proto.find('s') != std::string::npos) 198051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 198151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 198251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallVector<StringRef, 16> TypeVec; 198351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ParseTypes(R, Types, TypeVec); 198451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 198551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getSuperClasses().size() < 2) 198638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError(R->getLoc(), "Builtin has no class kind"); 198751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 198851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne int si = -1, qi = -1; 1989f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith uint64_t mask = 0, qmask = 0; 199051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { 199151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Generate the switch case(s) for this builtin for the type validation. 199251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool quad = false, poly = false, usgn = false; 199351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne (void) ClassifyType(TypeVec[ti], quad, poly, usgn); 199451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 199551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (quad) { 199651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne qi = ti; 1997f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]); 199851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 199951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne si = ti; 2000f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]); 200151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 200251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 20034648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson 20044648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson // Check if the builtin function has a pointer or const pointer argument. 20054648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson int PtrArgNum = -1; 20064648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson bool HasConstPtr = false; 20074648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) { 20084648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson char ArgType = Proto[arg]; 20094648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson if (ArgType == 'c') { 20104648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson HasConstPtr = true; 20114648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson PtrArgNum = arg - 1; 20124648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson break; 20134648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson } 20144648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson if (ArgType == 'p') { 20154648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson PtrArgNum = arg - 1; 20164648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson break; 20174648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson } 20184648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson } 20194648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson // For sret builtins, adjust the pointer argument index. 20204648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4')) 20214648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson PtrArgNum += 1; 20224648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson 20239082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // Omit type checking for the pointer arguments of vld1_lane, vld1_dup, 20249082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // and vst1_lane intrinsics. Using a pointer to the vector element 20259082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // type with one of those operations causes codegen to select an aligned 20269082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // load/store instruction. If you want an unaligned operation, 20279082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // the pointer argument needs to have less alignment than element type, 20289082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // so just accept any pointer type. 20299082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") { 20309082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson PtrArgNum = -1; 20319082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson HasConstPtr = false; 20329082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson } 20339082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson 20346f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson if (mask) { 203551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "case ARM::BI__builtin_neon_" 203651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << MangleName(name, TypeVec[si], ClassB) 2037b27660a733d420967371bbf578a75db21116895cRichard Smith << ": mask = " << "0x" << utohexstr(mask) << "ULL"; 20384648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson if (PtrArgNum >= 0) 20394648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson OS << "; PtrArgNum = " << PtrArgNum; 20406f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson if (HasConstPtr) 20416f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson OS << "; HasConstPtr = true"; 20426f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson OS << "; break;\n"; 20436f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson } 20446f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson if (qmask) { 204551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "case ARM::BI__builtin_neon_" 204651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << MangleName(name, TypeVec[qi], ClassB) 2047b27660a733d420967371bbf578a75db21116895cRichard Smith << ": mask = " << "0x" << utohexstr(qmask) << "ULL"; 20484648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson if (PtrArgNum >= 0) 20494648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson OS << "; PtrArgNum = " << PtrArgNum; 20506f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson if (HasConstPtr) 20516f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson OS << "; HasConstPtr = true"; 20526f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson OS << "; break;\n"; 20536f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson } 205451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 205551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 205651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 205751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Generate the intrinsic range checking code for shift/lane immediates. 205851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n"; 205951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = RV.size(); i != e; ++i) { 206051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *R = RV[i]; 206151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 206251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; 206351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (k != OpNone) 206451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 206551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 206651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string name = R->getValueAsString("Name"); 206751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Proto = R->getValueAsString("Prototype"); 206851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Types = R->getValueAsString("Types"); 206951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 207051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions with 'a' (the splat code) in the type prototype should not get 207151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // their own builtin as they use the non-splat variant. 207251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (Proto.find('a') != std::string::npos) 207351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 207451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 207551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions which do not have an immediate do not need to have range 207651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // checking code emitted. 207751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne size_t immPos = Proto.find('i'); 207851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (immPos == std::string::npos) 207951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 208051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 208151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallVector<StringRef, 16> TypeVec; 208251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ParseTypes(R, Types, TypeVec); 208351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 208451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getSuperClasses().size() < 2) 208538859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger PrintFatalError(R->getLoc(), "Builtin has no class kind"); 208651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 208751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ClassKind ck = ClassMap[R->getSuperClasses()[1]]; 208851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 208951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { 209051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string namestr, shiftstr, rangestr; 209151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 209251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getValueAsBit("isVCVT_N")) { 209351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // VCVT between floating- and fixed-point values takes an immediate 209451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // in the range 1 to 32. 209551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ck = ClassB; 209651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne rangestr = "l = 1; u = 31"; // upper bound = l + u 209751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else if (Proto.find('s') == std::string::npos) { 209851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Builtins which are overloaded by type will need to have their upper 209951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // bound computed at Sema time based on the type constant. 210051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ck = ClassB; 210151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getValueAsBit("isShift")) { 210251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne shiftstr = ", true"; 210351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 210451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Right shifts have an 'r' in the name, left shifts do not. 210551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (name.find('r') != std::string::npos) 210651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne rangestr = "l = 1; "; 210751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 210851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne rangestr += "u = RFT(TV" + shiftstr + ")"; 210951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 211051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // The immediate generally refers to a lane in the preceding argument. 211151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne assert(immPos > 0 && "unexpected immediate operand"); 211251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti])); 211351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 211451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Make sure cases appear only once by uniquing them in a string map. 211551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne namestr = MangleName(name, TypeVec[ti], ck); 211651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (EmittedMap.count(namestr)) 211751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 211851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne EmittedMap[namestr] = OpNone; 211951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 212051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Calculate the index of the immediate that should be range checked. 212151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned immidx = 0; 212251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 212351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Builtins that return a struct of multiple vectors have an extra 212451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // leading arg for the struct return. 212551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (Proto[0] >= '2' && Proto[0] <= '4') 212651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ++immidx; 212751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 212851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Add one to the index for each argument until we reach the immediate 212951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // to be checked. Structs of vectors are passed as multiple arguments. 213051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) { 213151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne switch (Proto[ii]) { 213251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: immidx += 1; break; 213351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case '2': immidx += 2; break; 213451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case '3': immidx += 3; break; 213551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case '4': immidx += 4; break; 213651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': ie = ii + 1; break; 213751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 213851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 213951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck) 214051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << ": i = " << immidx << "; " << rangestr << "; break;\n"; 214151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 214251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 214351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 214451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 214551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 214651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// GenTest - Write out a test for the intrinsic specified by the name and 214751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// type strings, including the embedded patterns for FileCheck to match. 214851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenTest(const std::string &name, 214951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne const std::string &proto, 215051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef outTypeStr, StringRef inTypeStr, 21517200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman bool isShift, bool isHiddenLOp, 21527200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman ClassKind ck, const std::string &InstName) { 215351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne assert(!proto.empty() && ""); 215451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string s; 215551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 215651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Function name with type suffix 215751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string mangledName = MangleName(name, outTypeStr, ClassS); 215851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (outTypeStr != inTypeStr) { 215951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // If the input type is different (e.g., for vreinterpret), append a suffix 216051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // for the input type. String off a "Q" (quad) prefix so that MangleName 216151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // does not insert another "q" in the name. 216251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0); 216351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff); 216451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne mangledName = MangleName(mangledName, inTypeNoQuad, ClassS); 216551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 216651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2167c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman std::vector<std::string> FileCheckPatterns; 2168c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman GenerateChecksForIntrinsic(name, proto, outTypeStr, inTypeStr, ck, InstName, 2169c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman isHiddenLOp, FileCheckPatterns); 2170c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 217151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Emit the FileCheck patterns. 217251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "// CHECK: test_" + mangledName + "\n"; 2173c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // If for any reason we do not want to emit a check, mangledInst 2174c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman // will be the empty string. 2175c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman if (FileCheckPatterns.size()) { 2176c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman for (std::vector<std::string>::const_iterator i = FileCheckPatterns.begin(), 2177c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman e = FileCheckPatterns.end(); 2178c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman i != e; 2179c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman ++i) { 2180c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman s += "// CHECK: " + *i + "\n"; 2181c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 2182c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 218351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 218451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Emit the start of the test function. 218551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "("; 218651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne char arg = 'a'; 218751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string comma; 218851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { 218951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Do not create arguments for values that must be immediate constants. 219051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto[i] == 'i') 219151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 219251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += comma + TypeString(proto[i], inTypeStr) + " "; 219351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back(arg); 219451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne comma = ", "; 219551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 2196b4a542549c2e0c9eeb6ece3f95767ccdd141fa3eJim Grosbach s += ") {\n "; 219751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 219851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto[0] != 'v') 219951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "return "; 220051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += mangledName + "("; 220151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne arg = 'a'; 220251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { 220351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (proto[i] == 'i') { 220451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // For immediate operands, test the maximum value. 220551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (isShift) 220651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += "1"; // FIXME 220751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 220851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // The immediate generally refers to a lane in the preceding argument. 220951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += utostr(RangeFromType(proto[i-1], inTypeStr)); 221051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 221151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s.push_back(arg); 221251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 221351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if ((i + 1) < e) 221451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ", "; 221551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 221651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne s += ");\n}\n\n"; 221751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return s; 221851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 221951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 222051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runTests - Write out a complete set of tests for all of the Neon 222151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics. 222251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runTests(raw_ostream &OS) { 222351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << 222451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n" 2225fb9929ee2a0ed47d473a58b0ba5c7a7a7a095b73Michael Gottesman "// RUN: -target-cpu swift -ffreestanding -Os -S -o - %s\\\n" 2226fb9929ee2a0ed47d473a58b0ba5c7a7a7a095b73Michael Gottesman "// RUN: | FileCheck %s\n" 222751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "\n" 222851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "#include <arm_neon.h>\n" 222951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "\n"; 223051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 223151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); 223251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned i = 0, e = RV.size(); i != e; ++i) { 223351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *R = RV[i]; 223451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string name = R->getValueAsString("Name"); 223551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Proto = R->getValueAsString("Prototype"); 223651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Types = R->getValueAsString("Types"); 223751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool isShift = R->getValueAsBit("isShift"); 22387200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman std::string InstName = R->getValueAsString("InstName"); 22397200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman bool isHiddenLOp = R->getValueAsBit("isHiddenLInst"); 224051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 224151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne SmallVector<StringRef, 16> TypeVec; 224251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ParseTypes(R, Types, TypeVec); 224351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 22447200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman ClassKind ck = ClassMap[R->getSuperClasses()[1]]; 224551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()]; 2246667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach if (kind == OpUnavailable) 2247667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach continue; 224851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { 224951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (kind == OpReinterpret) { 225051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool outQuad = false; 225151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool dummy = false; 225251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy); 225351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (unsigned srcti = 0, srcte = TypeVec.size(); 225451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne srcti != srcte; ++srcti) { 225551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne bool inQuad = false; 225651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy); 225751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (srcti == ti || inQuad != outQuad) 225851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 22597200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], 22607200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman isShift, isHiddenLOp, ck, InstName); 226151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 226251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 22637200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], 22647200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman isShift, isHiddenLOp, ck, InstName); 226551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 226651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 226751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n"; 226851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 226951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 227051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 22713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang { 22723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) { 22733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonEmitter(Records).run(OS); 22743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} 22753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { 22763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonEmitter(Records).runHeader(OS); 22773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} 22783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { 22793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonEmitter(Records).runTests(OS); 22803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} 22813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang 2282