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 21c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// called, rather than the normal run() entry point. 22c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// 23c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// See also the documentation in include/clang/Basic/arm_neon.td. 2451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// 2551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===// 2651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/DenseMap.h" 28b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h" 2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallString.h" 3051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallVector.h" 3151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/StringExtras.h" 323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/StringMap.h" 337530c034c0c71a64c5a9173206d9742ae847af8bDavid Blaikie#include "llvm/Support/ErrorHandling.h" 343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Error.h" 353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Record.h" 36c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include "llvm/TableGen/SetTheory.h" 373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h" 380e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <algorithm> 3987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar#include <deque> 400e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <map> 41c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include <sstream> 420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <string> 434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include <utility> 44c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include <vector> 4551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm; 4651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 47c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesnamespace { 48c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 49c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// While globals are generally bad, this one allows us to perform assertions 50c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// liberally and somehow still trace them back to the def they indirectly 51c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// came from. 52c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstatic Record *CurrentRecord = nullptr; 53c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstatic void assert_with_loc(bool Assertion, const std::string &Str) { 54c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Assertion) { 55c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (CurrentRecord) 56c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines PrintFatalError(CurrentRecord->getLoc(), Str); 57c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 58c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines PrintFatalError(Str); 59c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 60c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum ClassKind { 633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassNone, 64c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassI, // generic integer instruction, e.g., "i8" suffix 65c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix 66c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassW, // width-specific instruction, e.g., "8" suffix 67c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassB, // bitcast arguments with enum argument to specify type 68c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassL, // Logical instructions which are op instructions 69c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // but we need to not emit any suffix for in our 70c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // tests. 71c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassNoTest // Instructions which we do not test since they are 72c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // not TRUE instructions. 733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}; 743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// NeonTypeFlags - Flags to identify the types for overloaded Neon 763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// builtins. These must be kept in sync with the flags in 773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// include/clang/Basic/TargetBuiltins.h. 78c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesnamespace NeonTypeFlags { 79c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesenum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 }; 80c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 81c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesenum EltType { 82c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Int8, 83c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Int16, 84c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Int32, 85c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Int64, 86c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly8, 87c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly16, 88c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly64, 89c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly128, 90c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float16, 91c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float32, 92c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float64 93c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}; 94c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 95c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 96c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Intrinsic; 97c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass NeonEmitter; 98c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Type; 99c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Variable; 1003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 101c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 102c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// TypeSpec 103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 105c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A TypeSpec is just a simple wrapper around a string, but gets its own type 106c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// for strong typing purposes. 107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// 108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A TypeSpec can be used to create a type. 109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass TypeSpec : public std::string { 1103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic: 111c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines static std::vector<TypeSpec> fromTypeSpecs(StringRef Str) { 112c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<TypeSpec> Ret; 113c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines TypeSpec Acc; 114c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (char I : Str.str()) { 115c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (islower(I)) { 116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Acc.push_back(I); 117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Ret.push_back(TypeSpec(Acc)); 118c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Acc.clear(); 119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 120c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Acc.push_back(I); 121c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 122c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 123c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Ret; 124c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}; 126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 128c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Type 129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 130c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 131c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A Type. Not much more to say here. 132c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Type { 133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesprivate: 134c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines TypeSpec TS; 135c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 136b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar bool Float, Signed, Immediate, Void, Poly, Constant, Pointer; 137c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // ScalarForMangling and NoManglingQ are really not suited to live here as 138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // they are not related to the type. But they live in the TypeSpec (not the 139c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // prototype), so this is really the only place to store them. 140c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool ScalarForMangling, NoManglingQ; 141c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Bitwidth, ElementBitwidth, NumVectors; 142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 143c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic: 144c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type() 145b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar : Float(false), Signed(false), Immediate(false), Void(true), Poly(false), 146b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Constant(false), Pointer(false), ScalarForMangling(false), 147b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} 148c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 149c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type(TypeSpec TS, char CharMod) 1504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar : TS(std::move(TS)), Float(false), Signed(false), Immediate(false), 1514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Void(false), Poly(false), Constant(false), Pointer(false), 1524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ScalarForMangling(false), NoManglingQ(false), Bitwidth(0), 1534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ElementBitwidth(0), NumVectors(0) { 154c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines applyModifier(CharMod); 155c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 156c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 157c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Returns a type representing "void". 158c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines static Type getVoid() { return Type(); } 1593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 160c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool operator==(const Type &Other) const { return str() == Other.str(); } 161c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool operator!=(const Type &Other) const { return !operator==(Other); } 162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 163c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 164c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Query functions 165c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 166c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isScalarForMangling() const { return ScalarForMangling; } 167c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool noManglingQ() const { return NoManglingQ; } 168c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 169c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isPointer() const { return Pointer; } 170c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isFloating() const { return Float; } 171c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isInteger() const { return !Float && !Poly; } 172c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isSigned() const { return Signed; } 173b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar bool isImmediate() const { return Immediate; } 174c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isScalar() const { return NumVectors == 0; } 175c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isVector() const { return NumVectors > 0; } 176c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isFloat() const { return Float && ElementBitwidth == 32; } 177c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isDouble() const { return Float && ElementBitwidth == 64; } 178c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isHalf() const { return Float && ElementBitwidth == 16; } 179c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isPoly() const { return Poly; } 180c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isChar() const { return ElementBitwidth == 8; } 181c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isShort() const { return !Float && ElementBitwidth == 16; } 182c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isInt() const { return !Float && ElementBitwidth == 32; } 183c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isLong() const { return !Float && ElementBitwidth == 64; } 184c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool isVoid() const { return Void; } 185c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getNumElements() const { return Bitwidth / ElementBitwidth; } 186c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getSizeInBits() const { return Bitwidth; } 187c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getElementSizeInBits() const { return ElementBitwidth; } 188c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getNumVectors() const { return NumVectors; } 189c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 191c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Mutator functions 192c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 193c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void makeUnsigned() { Signed = false; } 194c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void makeSigned() { Signed = true; } 195c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void makeInteger(unsigned ElemWidth, bool Sign) { 196c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = false; 197c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = false; 198c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = Sign; 199b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Immediate = false; 200b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ElementBitwidth = ElemWidth; 201b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } 202b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar void makeImmediate(unsigned ElemWidth) { 203b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Float = false; 204b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Poly = false; 205b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Signed = true; 206b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Immediate = true; 207c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = ElemWidth; 208c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 209c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void makeScalar() { 210c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth; 211c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 212c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 213c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void makeOneVector() { 214c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(isVector()); 215c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 1; 2163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen } 217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void doubleLanes() { 218c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!"); 219c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = 128; 220c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 221c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void halveLanes() { 222c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!"); 223c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = 64; 224c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 225c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 226c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the C string representation of a type, which is the typename 227c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// defined in stdint.h or arm_neon.h. 228c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string str() const; 229c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 230c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the string representation of a type, which is an encoded 231c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// string for passing to the BUILTIN() macro in Builtins.def. 232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string builtin_str() const; 2333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the value in NeonTypeFlags for this type. 235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getNeonEnum() const; 236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Parse a type from a stdint.h or arm_neon.h typedef name, 238c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// for example uint32x2_t or int64_t. 239c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines static Type fromTypedefName(StringRef Name); 240c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 241c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesprivate: 242c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Creates the type based on the typespec string in TS. 243c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Sets "Quad" to true if the "Q" or "H" modifiers were 244c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// seen. This is needed by applyModifier as some modifiers 245c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// only take effect if the type size was changed by "Q" or "H". 246c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void applyTypespec(bool &Quad); 247c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Applies a prototype modifier to the type. 248c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void applyModifier(char Mod); 2493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}; 2503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 251c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 252c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Variable 253c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 254c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 255c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A variable is a simple class that just has a type and a name. 256c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Variable { 257c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T; 258c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string N; 259c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 260c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic: 261c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable() : T(Type::getVoid()), N("") {} 2624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Variable(Type T, std::string N) : T(std::move(T)), N(std::move(N)) {} 263c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 264c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type getType() const { return T; } 265c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string getName() const { return "__" + N; } 266c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}; 267c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 268c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 269c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Intrinsic 270c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 271c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 272c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// The main grunt class. This represents an instantiation of an intrinsic with 273c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// a particular typespec and prototype. 274c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Intrinsic { 275c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines friend class DagEmitter; 276c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 277c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The Record this intrinsic was created from. 278c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Record *R; 279c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The unmangled name and prototype. 280c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name, Proto; 281c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The input and output typespecs. InTS == OutTS except when 282c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// CartesianProductOfTypes is 1 - this is the case for vreinterpret. 283c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines TypeSpec OutTS, InTS; 284c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The base class kind. Most intrinsics use ClassS, which has full type 285c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// info for integers (s32/u32). Some use ClassI, which doesn't care about 286c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// signedness (i32), while some (ClassB) have no type at all, only a width 287c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// (32). 288c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassKind CK; 289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The list of DAGs for the body. May be empty, in which case we should 290c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// emit a builtin call. 291c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ListInit *Body; 292c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The architectural #ifdef guard. 293c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Guard; 294c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Set if the Unvailable bit is 1. This means we don't generate a body, 295c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// just an "unavailable" attribute on a declaration. 296c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool IsUnavailable; 297c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Is this intrinsic safe for big-endian? or does it need its arguments 298c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// reversing? 299c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool BigEndianSafe; 300c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 301c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The types of return value [0] and parameters [1..]. 302c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<Type> Types; 303c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The local variables defined. 304c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::map<std::string, Variable> Variables; 305c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// NeededEarly - set if any other intrinsic depends on this intrinsic. 306c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool NeededEarly; 307c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// UseMacro - set if we should implement using a macro or unset for a 308c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// function. 309c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool UseMacro; 310c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The set of intrinsics that this intrinsic uses/requires. 311c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::set<Intrinsic *> Dependencies; 312c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The "base type", which is Type('d', OutTS). InBaseType is only 313c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// different if CartesianProductOfTypes = 1 (for vreinterpret). 314c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type BaseType, InBaseType; 315c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// The return variable. 316c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable RetVar; 317c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// A postfix to apply to every variable. Defaults to "". 318c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string VariablePostfix; 319c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 320c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NeonEmitter &Emitter; 321c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::stringstream OS; 322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 323c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic: 324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS, 325c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter, 326c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines StringRef Guard, bool IsUnavailable, bool BigEndianSafe) 327c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines : R(R), Name(Name.str()), Proto(Proto.str()), OutTS(OutTS), InTS(InTS), 328c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CK(CK), Body(Body), Guard(Guard.str()), IsUnavailable(IsUnavailable), 329c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines BigEndianSafe(BigEndianSafe), NeededEarly(false), UseMacro(false), 330c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines BaseType(OutTS, 'd'), InBaseType(InTS, 'd'), Emitter(Emitter) { 331c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // If this builtin takes an immediate argument, we need to #define it rather 332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // than use a standard declaration, so that SemaChecking can range check 333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // the immediate passed by the user. 334c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Proto.find('i') != std::string::npos) 335c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UseMacro = true; 336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 337c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Pointer arguments need to use macros to avoid hiding aligned attributes 338c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // from the pointer type. 339c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Proto.find('p') != std::string::npos || 340c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('c') != std::string::npos) 341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UseMacro = true; 342c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 343c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // It is not permitted to pass or return an __fp16 by value, so intrinsics 344c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // taking a scalar float16_t must be implemented as macros. 345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (OutTS.find('h') != std::string::npos && 346c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('s') != std::string::npos) 347c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UseMacro = true; 348c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Modify the TypeSpec per-argument to get a concrete Type, and create 350c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // known variables for each. 351c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Types[0] is the return value. 352b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Types.emplace_back(OutTS, Proto[0]); 353c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 1; I < Proto.size(); ++I) 354b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Types.emplace_back(InTS, Proto[I]); 355c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 356c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 357c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Get the Record that this intrinsic is based off. 358c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Record *getRecord() const { return R; } 359c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Get the set of Intrinsics that this intrinsic calls. 360c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// this is the set of immediate dependencies, NOT the 361c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// transitive closure. 362c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines const std::set<Intrinsic *> &getDependencies() const { return Dependencies; } 363c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Get the architectural guard string (#ifdef). 364c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string getGuard() const { return Guard; } 365c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Get the non-mangled name. 366c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string getName() const { return Name; } 367c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return true if the intrinsic takes an immediate operand. 369c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool hasImmediate() const { 370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Proto.find('i') != std::string::npos; 371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the parameter index of the immediate operand. 373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getImmediateIdx() const { 374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(hasImmediate()); 375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Idx = Proto.find('i'); 376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Idx > 0 && "Can't return an immediate!"); 377c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Idx - 1; 378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return true if the intrinsic takes an splat operand. 381c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool hasSplat() const { return Proto.find('a') != std::string::npos; } 382c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the parameter index of the splat operand. 383c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getSplatIdx() const { 384c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(hasSplat()); 385c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Idx = Proto.find('a'); 386c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Idx > 0 && "Can't return a splat!"); 387c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Idx - 1; 388c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 389c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 390c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getNumParams() const { return Proto.size() - 1; } 391c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type getReturnType() const { return Types[0]; } 392c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type getParamType(unsigned I) const { return Types[I + 1]; } 393c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type getBaseType() const { return BaseType; } 394c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the raw prototype string. 395c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string getProto() const { return Proto; } 396c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 397c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return true if the prototype has a scalar argument. 398c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// This does not return true for the "splat" code ('a'). 39987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar bool protoHasScalar() const; 400c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 401c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the index that parameter PIndex will sit at 402c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// in a generated function call. This is often just PIndex, 403c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// but may not be as things such as multiple-vector operands 404c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// and sret parameters need to be taken into accont. 405c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getGeneratedParamIdx(unsigned PIndex) { 406c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Idx = 0; 407c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (getReturnType().getNumVectors() > 1) 408c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Multiple vectors are passed as sret. 409c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ++Idx; 410c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 411c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < PIndex; ++I) 412c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Idx += std::max(1U, getParamType(I).getNumVectors()); 413c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 414c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Idx; 415c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 416c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 417c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool hasBody() const { return Body && Body->getValues().size() > 0; } 418c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 419c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void setNeededEarly() { NeededEarly = true; } 420c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 421c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool operator<(const Intrinsic &Other) const { 422c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Sort lexicographically on a two-tuple (Guard, Name) 423c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Guard != Other.Guard) 424c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Guard < Other.Guard; 425c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Name < Other.Name; 426c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 427c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 428c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassKind getClassKind(bool UseClassBIfScalar = false) { 429c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (UseClassBIfScalar && !protoHasScalar()) 430c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return ClassB; 431c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return CK; 432c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 433c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 434c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the name, mangled with type information. 435c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// If ForceClassS is true, use ClassS (u32/s32) instead 436c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// of the intrinsic's own type class. 43787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar std::string getMangledName(bool ForceClassS = false) const; 438c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the type code for a builtin function call. 43987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar std::string getInstTypeCode(Type T, ClassKind CK) const; 440c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Return the type string for a BUILTIN() macro in Builtins.def. 441c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string getBuiltinTypeStr(); 442c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 443c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Generate the intrinsic, returning code. 444c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string generate(); 445c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Perform type checking and populate the dependency graph, but 446c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// don't generate code yet. 447c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void indexBody(); 448c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 449c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesprivate: 45087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar std::string mangleName(std::string Name, ClassKind CK) const; 451c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 452c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void initVariables(); 453c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string replaceParamsIn(std::string S); 454c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 455c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitBodyAsBuiltinCall(); 456c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 457c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void generateImpl(bool ReverseArguments, 458c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines StringRef NamePrefix, StringRef CallPrefix); 459c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitReturn(); 460c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitBody(StringRef CallPrefix); 461c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitShadowedArgs(); 462c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitArgumentReversal(); 463c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitReturnReversal(); 464c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitReverseVariable(Variable &Dest, Variable &Src); 465c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitNewLine(); 466c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitClosingBrace(); 467c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitOpeningBrace(); 468c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void emitPrototype(StringRef NamePrefix); 469c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 470c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines class DagEmitter { 471c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intrinsic &Intr; 472c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines StringRef CallPrefix; 473c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 474c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines public: 475c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DagEmitter(Intrinsic &Intr, StringRef CallPrefix) : 476c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intr(Intr), CallPrefix(CallPrefix) { 477c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 478c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagArg(Init *Arg, std::string ArgName); 479c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagSaveTemp(DagInit *DI); 480c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagSplat(DagInit *DI); 481c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagDup(DagInit *DI); 482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagShuffle(DagInit *DI); 483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagCast(DagInit *DI, bool IsBitCast); 484c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagCall(DagInit *DI); 485c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagNameReplace(DagInit *DI); 486c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagLiteral(DagInit *DI); 487c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDagOp(DagInit *DI); 488c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> emitDag(DagInit *DI); 489c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines }; 490c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 491c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}; 492c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 493c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 494c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// NeonEmitter 495c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 496c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 4973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonEmitter { 4983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen RecordKeeper &Records; 499c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DenseMap<Record *, ClassKind> ClassMap; 50087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar std::map<std::string, std::deque<Intrinsic>> IntrinsicMap; 501c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned UniqueNumber; 502c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 503c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out); 504c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void genBuiltinsDef(raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs); 505c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void genOverloadTypeCheckCode(raw_ostream &OS, 506c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVectorImpl<Intrinsic *> &Defs); 507c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines void genIntrinsicRangeCheckCode(raw_ostream &OS, 508c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVectorImpl<Intrinsic *> &Defs); 5093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 5103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic: 511c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Called by Intrinsic - this attempts to get an intrinsic that takes 512c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// the given types as arguments. 51387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Intrinsic &getIntrinsic(StringRef Name, ArrayRef<Type> Types); 514c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 515c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines /// Called by Intrinsic - returns a globally-unique number. 516c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned getUniqueNumber() { return UniqueNumber++; } 5173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 518c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NeonEmitter(RecordKeeper &R) : Records(R), UniqueNumber(0) { 5193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Record *SI = R.getClass("SInst"); 5203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Record *II = R.getClass("IInst"); 5213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen Record *WI = R.getClass("WInst"); 52221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *SOpI = R.getClass("SOpInst"); 52321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *IOpI = R.getClass("IOpInst"); 52421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *WOpI = R.getClass("WOpInst"); 52521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *LOpI = R.getClass("LOpInst"); 52621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman Record *NoTestOpI = R.getClass("NoTestOpInst"); 52721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman 5283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassMap[SI] = ClassS; 5293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassMap[II] = ClassI; 5303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen ClassMap[WI] = ClassW; 53121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[SOpI] = ClassS; 53221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[IOpI] = ClassI; 53321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[WOpI] = ClassW; 53421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[LOpI] = ClassL; 53521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman ClassMap[NoTestOpI] = ClassNoTest; 5363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen } 5373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 5383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen // run - Emit arm_neon.h.inc 5393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen void run(raw_ostream &o); 5403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 5413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen // runHeader - Emit all the __builtin prototypes used in arm_neon.h 5423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen void runHeader(raw_ostream &o); 5433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 5443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen // runTests - Emit tests for all the Neon intrinsics. 5453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen void runTests(raw_ostream &o); 5463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}; 547c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 5483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace 5493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 550c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 551c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Type implementation 552c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 554c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Type::str() const { 555c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Void) 556c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return "void"; 557c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S; 558c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 559c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Signed && isInteger()) 560c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "u"; 561c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 562c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Poly) 563c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "poly"; 564c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else if (Float) 565c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "float"; 566c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 567c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "int"; 568c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 569c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += utostr(ElementBitwidth); 570c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (isVector()) 571c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "x" + utostr(getNumElements()); 572c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (NumVectors > 1) 573c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "x" + utostr(NumVectors); 574c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "_t"; 575c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 576c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Constant) 577c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += " const"; 578c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Pointer) 579c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += " *"; 580c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 581c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return S; 58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 584c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Type::builtin_str() const { 585c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S; 586c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (isVoid()) 587c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return "v"; 588c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 589c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Pointer) 590c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // All pointers are void pointers. 591c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "v"; 592c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else if (isInteger()) 593c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines switch (ElementBitwidth) { 594c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 8: S += "c"; break; 595c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 16: S += "s"; break; 596c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 32: S += "i"; break; 597c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 64: S += "Wi"; break; 598c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 128: S += "LLLi"; break; 599c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines default: llvm_unreachable("Unhandled case!"); 600c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 601c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 602c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines switch (ElementBitwidth) { 603c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 16: S += "h"; break; 604c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 32: S += "f"; break; 605c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 64: S += "d"; break; 606c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines default: llvm_unreachable("Unhandled case!"); 607c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 608c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 609c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (isChar() && !Pointer) 610c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Make chars explicitly signed. 611c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S = "S" + S; 612c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else if (isInteger() && !Pointer && !Signed) 613c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S = "U" + S; 614c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 615b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // Constant indices are "int", but have the "constant expression" modifier. 616b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (isImmediate()) { 617b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar assert(isInteger() && isSigned()); 618b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar S = "I" + S; 619b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } 620b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 621c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (isScalar()) { 622c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Constant) S += "C"; 623c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Pointer) S += "*"; 624c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return S; 62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 626c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 627c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Ret; 628c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < NumVectors; ++I) 629c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Ret += "V" + utostr(getNumElements()) + S; 630c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 631c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Ret; 63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 634c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesunsigned Type::getNeonEnum() const { 635c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Addend; 636c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines switch (ElementBitwidth) { 637c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 8: Addend = 0; break; 638c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 16: Addend = 1; break; 639c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 32: Addend = 2; break; 640c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 64: Addend = 3; break; 641c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 128: Addend = 4; break; 642c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines default: llvm_unreachable("Unhandled element bitwidth!"); 64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 645c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Base = (unsigned)NeonTypeFlags::Int8 + Addend; 646c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Poly) { 647c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Adjustment needed because Poly32 doesn't exist. 648c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Addend >= 2) 649c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines --Addend; 650c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Base = (unsigned)NeonTypeFlags::Poly8 + Addend; 651097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu } 652c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Float) { 653c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Addend != 0 && "Float8 doesn't exist!"); 654c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1); 655c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 656c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 657c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Bitwidth == 128) 658c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Base |= (unsigned)NeonTypeFlags::QuadFlag; 659c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (isInteger() && !Signed) 660c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Base |= (unsigned)NeonTypeFlags::UnsignedFlag; 661097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu 662c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Base; 663097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu} 664097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu 665c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesType Type::fromTypedefName(StringRef Name) { 666c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T; 667c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Void = false; 668c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Float = false; 669c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Poly = false; 670c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 671c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Name.front() == 'u') { 672c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Signed = false; 673c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(); 674c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 675c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Signed = true; 676944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin } 677c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 678c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Name.startswith("float")) { 679c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Float = true; 680c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(5); 681c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (Name.startswith("poly")) { 682c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Poly = true; 683c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(4); 684c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 685c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Name.startswith("int")); 686c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(3); 68751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 68851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 689c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned I = 0; 690c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (I = 0; I < Name.size(); ++I) { 691c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!isdigit(Name[I])) 692c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 69351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 694c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name.substr(0, I).getAsInteger(10, T.ElementBitwidth); 695c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(I); 696c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 697c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Bitwidth = T.ElementBitwidth; 698c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.NumVectors = 1; 69951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 700c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Name.front() == 'x') { 701c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(); 702c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned I = 0; 703c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (I = 0; I < Name.size(); ++I) { 704c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!isdigit(Name[I])) 705c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 706c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 707c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned NumLanes; 708c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name.substr(0, I).getAsInteger(10, NumLanes); 709c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(I); 710c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.Bitwidth = T.ElementBitwidth * NumLanes; 711c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 712c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Was scalar. 713c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.NumVectors = 0; 714c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 715c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Name.front() == 'x') { 716c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(); 717c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned I = 0; 718c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (I = 0; I < Name.size(); ++I) { 719c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!isdigit(Name[I])) 720c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 721c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 722c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name.substr(0, I).getAsInteger(10, T.NumVectors); 723c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name = Name.drop_front(I); 72451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 726c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Name.startswith("_t") && "Malformed typedef!"); 727c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return T; 72851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 72951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 730c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Type::applyTypespec(bool &Quad) { 731c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = TS; 732c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ScalarForMangling = false; 733c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Void = false; 734c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = Float = false; 735c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = ~0U; 736c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = true; 737c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 1; 738c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 739c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (char I : S) { 740c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines switch (I) { 741c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'S': 742c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ScalarForMangling = true; 74351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 744c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'H': 745c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NoManglingQ = true; 746c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Quad = true; 7474553a858e46299955333babfa052a512682869fdChad Rosier break; 748c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'Q': 749c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Quad = true; 7504553a858e46299955333babfa052a512682869fdChad Rosier break; 751c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'P': 752c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = true; 75351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 754c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'U': 755c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = false; 75651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 75751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'c': 758c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = 8; 75951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 76051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 761c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = true; 762c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Fall through 76351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 's': 764c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = 16; 76551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 766c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'f': 767c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = true; 768c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Fall through 76951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 770c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = 32; 77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 772c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'd': 773c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = true; 774c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Fall through 77551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 776c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = 64; 77751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case 'k': 779c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = 128; 780c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Poly doesn't have a 128x1 type. 781c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Poly) 782c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 783b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover break; 78451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 785c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm_unreachable("Unhandled type code!"); 786c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 78751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 788c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(ElementBitwidth != ~0U && "Bad element bitwidth!"); 78951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 790c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = Quad ? 128 : 64; 79151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 79251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 793c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Type::applyModifier(char Mod) { 794c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool AppliedQuad = false; 795c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines applyTypespec(AppliedQuad); 79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 797c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines switch (Mod) { 798c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'v': 799c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Void = true; 80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 801c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 't': 802c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Poly) { 803c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = false; 804c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = false; 80551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 80651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 807c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'b': 808c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = false; 809c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = false; 810c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = false; 811c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 812c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth; 813c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 814c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case '$': 815c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = true; 816c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = false; 817c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = false; 818c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 819c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth; 820c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 821c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'u': 822c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = false; 823c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = false; 824c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = false; 825c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 826c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'x': 827c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = true; 828c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(!Poly && "'u' can't be used with poly types!"); 829c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = false; 830c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 831c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'o': 832c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth = 64; 833c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 834c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = true; 835c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 836c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'y': 837c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth = 32; 838c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 839c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = true; 840c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 841c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'f': 842c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = true; 843c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = 32; 844c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 845c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'F': 846c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = true; 847c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = 64; 848c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 849c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'g': 850c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (AppliedQuad) 851c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth /= 2; 852c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 853c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'j': 854c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!AppliedQuad) 855c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth *= 2; 856c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 857c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'w': 858c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth *= 2; 859c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth *= 2; 860c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 861c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'n': 862c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth *= 2; 863c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 86451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'i': 865c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = false; 866c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = false; 867c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = Bitwidth = 32; 868c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 869c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = true; 870b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Immediate = true; 87151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 87251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'l': 873c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Float = false; 874c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Poly = false; 875c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth = Bitwidth = 64; 876c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 877c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = false; 878b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Immediate = true; 879c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 880c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'z': 881c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth /= 2; 882c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth; 883c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 884c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 885c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'r': 886c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth *= 2; 887c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth; 888c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 889c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 890c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 's': 891c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'a': 892c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth; 893c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 89451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case 'k': 896c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth *= 2; 897c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 898c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'c': 899c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Constant = true; 900c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Fall through 901c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'p': 902c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Pointer = true; 903c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth = ElementBitwidth; 904c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 0; 905651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 90651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne case 'h': 907c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth /= 2; 90851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 909c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'q': 910c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth /= 2; 911c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth *= 2; 912c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 913c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'e': 914c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth /= 2; 915c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Signed = false; 916c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 917c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'm': 918c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ElementBitwidth /= 2; 919c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth /= 2; 92051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 921b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover case 'd': 922c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 923c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case '2': 924c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 2; 925c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 926c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case '3': 927c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 3; 928c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 929c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case '4': 930c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 4; 931c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 932c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'B': 933c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 2; 934c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!AppliedQuad) 935c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth *= 2; 936c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 937c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'C': 938c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 3; 939c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!AppliedQuad) 940c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth *= 2; 941c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 942c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'D': 943c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NumVectors = 4; 944c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!AppliedQuad) 945c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Bitwidth *= 2; 946b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover break; 94751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne default: 948c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm_unreachable("Unhandled character!"); 94951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 950fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman} 951fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 952c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 953c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Intrinsic implementation 954c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 955c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 95687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const { 957c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines char typeCode = '\0'; 958c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool printNumber = true; 959c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 960c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (CK == ClassB) 961c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return ""; 962c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 963c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.isPoly()) 964c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines typeCode = 'p'; 965c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else if (T.isInteger()) 966c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines typeCode = T.isSigned() ? 's' : 'u'; 967c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 968c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines typeCode = 'f'; 969c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 970c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (CK == ClassI) { 971c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines switch (typeCode) { 972c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines default: 973c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 974c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 's': 975c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'u': 976c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 'p': 977c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines typeCode = 'i'; 978c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 979944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin } 980944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin } 981c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (CK == ClassB) { 982c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines typeCode = '\0'; 983dd12780e86575795fa912529a911b01e2abc4677Hao Liu } 984c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 985c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S; 986c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (typeCode != '\0') 987c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.push_back(typeCode); 988c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (printNumber) 989c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += utostr(T.getElementSizeInBits()); 990c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 991c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return S; 992dd12780e86575795fa912529a911b01e2abc4677Hao Liu} 993dd12780e86575795fa912529a911b01e2abc4677Hao Liu 99487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstatic bool isFloatingPointProtoModifier(char Mod) { 99587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return Mod == 'F' || Mod == 'f'; 99687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 99787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 998c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Intrinsic::getBuiltinTypeStr() { 999c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassKind LocalCK = getClassKind(true); 1000c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S; 1001fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 1002c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type RetT = getReturnType(); 1003c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() && 1004c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines !RetT.isFloating()) 1005c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines RetT.makeInteger(RetT.getElementSizeInBits(), false); 1006fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 1007c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Since the return value must be one type, return a vector type of the 1008c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // appropriate width which we will bitcast. An exception is made for 1009c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // returning structs of 2, 3, or 4 vectors which are returned in a sret-like 1010c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // fashion, storing them to a pointer arg. 1011c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (RetT.getNumVectors() > 1) { 1012c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "vv*"; // void result with void* first argument 1013c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 1014c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (RetT.isPoly()) 1015c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines RetT.makeInteger(RetT.getElementSizeInBits(), false); 1016c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!RetT.isScalar() && !RetT.isSigned()) 1017c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines RetT.makeSigned(); 1018fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 101987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar bool ForcedVectorFloatingType = isFloatingPointProtoModifier(Proto[0]); 1020c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (LocalCK == ClassB && !RetT.isScalar() && !ForcedVectorFloatingType) 1021c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Cast to vector of 8-bit elements. 1022c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines RetT.makeInteger(8, true); 1023fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 1024c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += RetT.builtin_str(); 1025fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman } 1026fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman 1027c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < getNumParams(); ++I) { 1028c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T = getParamType(I); 1029c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.isPoly()) 1030c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.makeInteger(T.getElementSizeInBits(), false); 103151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 103287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar bool ForcedFloatingType = isFloatingPointProtoModifier(Proto[I + 1]); 1033c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (LocalCK == ClassB && !T.isScalar() && !ForcedFloatingType) 1034c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.makeInteger(8, true); 1035c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Halves always get converted to 8-bit elements. 1036c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.isHalf() && T.isVector() && !T.isScalarForMangling()) 1037c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.makeInteger(8, true); 1038c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1039c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (LocalCK == ClassI) 1040c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.makeSigned(); 104151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1042c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (hasImmediate() && getImmediateIdx() == I) 1043b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar T.makeImmediate(32); 1044c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1045c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += T.builtin_str(); 1046c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1047c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1048c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Extra constant integer to hold type class enum for this function, e.g. s8 1049c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (LocalCK == ClassB) 1050c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "i"; 1051c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1052c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return S; 1053c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 1054c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 105587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::string Intrinsic::getMangledName(bool ForceClassS) const { 1056c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Check if the prototype has a scalar operand with the type of the vector 1057c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // elements. If not, bitcasting the args will take care of arg checking. 1058c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // The actual signedness etc. will be taken care of with special enums. 1059c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassKind LocalCK = CK; 1060c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!protoHasScalar()) 1061c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines LocalCK = ClassB; 1062c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1063c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return mangleName(Name, ForceClassS ? ClassS : LocalCK); 1064c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 1065c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 106687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const { 1067c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string typeCode = getInstTypeCode(BaseType, LocalCK); 1068c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = Name; 1069c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 107087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (Name == "vcvt_f16_f32" || Name == "vcvt_f32_f16" || 107187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32") 1072c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return Name; 1073c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1074c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (typeCode.size() > 0) { 1075c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN. 1076c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Name.size() >= 3 && isdigit(Name.back()) && 1077c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_') 1078c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.insert(S.length() - 3, "_" + typeCode); 1079c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1080c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "_" + typeCode; 1081c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1082c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1083c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (BaseType != InBaseType) { 1084c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // A reinterpret - out the input base type at the end. 1085c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "_" + getInstTypeCode(InBaseType, LocalCK); 1086c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1087c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1088c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (LocalCK == ClassB) 1089c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "_v"; 1090c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1091c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Insert a 'q' before the first '_' character so that it ends up before 1092c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // _lane or _n on vector-scalar operations. 1093c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (BaseType.getSizeInBits() == 128 && !BaseType.noManglingQ()) { 1094c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines size_t Pos = S.find('_'); 1095c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.insert(Pos, "q"); 1096c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1097c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1098c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines char Suffix = '\0'; 1099c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (BaseType.isScalarForMangling()) { 1100c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines switch (BaseType.getElementSizeInBits()) { 1101c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 8: Suffix = 'b'; break; 1102c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 16: Suffix = 'h'; break; 1103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 32: Suffix = 's'; break; 1104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines case 64: Suffix = 'd'; break; 1105c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines default: llvm_unreachable("Bad suffix!"); 1106c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Suffix != '\0') { 1109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines size_t Pos = S.find('_'); 1110c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.insert(Pos, &Suffix, 1); 1111c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1112c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1113c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return S; 1114c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1115c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Intrinsic::replaceParamsIn(std::string S) { 1117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines while (S.find('$') != std::string::npos) { 1118c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines size_t Pos = S.find('$'); 1119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines size_t End = Pos + 1; 1120c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines while (isalpha(S[End])) 1121c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ++End; 1122c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1123c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string VarName = S.substr(Pos + 1, End - Pos - 1); 1124c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Variables.find(VarName) != Variables.end(), 1125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Variable not defined!"); 1126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.replace(Pos, End - Pos, Variables.find(VarName)->second.getName()); 1127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1128c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return S; 1130c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1131c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1132c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::initVariables() { 1133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variables.clear(); 1134c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1135c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Modify the TypeSpec per-argument to get a concrete Type, and create 1136c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // known variables for each. 1137c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 1; I < Proto.size(); ++I) { 1138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines char NameC = '0' + (I - 1); 1139c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name = "p"; 1140c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name.push_back(NameC); 1141c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variables[Name] = Variable(Types[I], Name + VariablePostfix); 1143c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1144c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines RetVar = Variable(Types[0], "ret" + VariablePostfix); 1145c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman} 1146c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1147c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitPrototype(StringRef NamePrefix) { 1148c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (UseMacro) 1149c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#define "; 1150c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1151c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "__ai " << Types[0].str() << " "; 1152c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1153c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << NamePrefix.str() << mangleName(Name, ClassS) << "("; 1154c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1155c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < getNumParams(); ++I) { 1156c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (I != 0) 1157c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << ", "; 1158c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1159c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines char NameC = '0' + I; 1160c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name = "p"; 1161c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Name.push_back(NameC); 1162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Variables.find(Name) != Variables.end()); 1163c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable &V = Variables[Name]; 1164c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1165c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!UseMacro) 1166c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << V.getType().str() << " "; 1167c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << V.getName(); 1168c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1169c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1170c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << ")"; 1171c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1172c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1173c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitOpeningBrace() { 1174c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (UseMacro) 1175c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " __extension__ ({"; 1176c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1177c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " {"; 1178c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1179c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1180c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1181c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitClosingBrace() { 1182c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (UseMacro) 1183c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "})"; 1184c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1185c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "}"; 1186c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1187c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1188c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitNewLine() { 1189c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (UseMacro) 1190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " \\\n"; 1191c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1192c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "\n"; 1193c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1194c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1195c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) { 1196c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Dest.getType().getNumVectors() > 1) { 1197c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1198c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1199c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned K = 0; K < Dest.getType().getNumVectors(); ++K) { 12004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar OS << " " << Dest.getName() << ".val[" << K << "] = " 1201c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines << "__builtin_shufflevector(" 12024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << Src.getName() << ".val[" << K << "], " 12034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar << Src.getName() << ".val[" << K << "]"; 1204c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) 12054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar OS << ", " << J; 1206c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << ");"; 1207c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1208c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1209c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 1210c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << Dest.getName() 1211c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines << " = __builtin_shufflevector(" << Src.getName() << ", " << Src.getName(); 1212c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) 12134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar OS << ", " << J; 1214c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << ");"; 1215c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1216c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 1217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1218c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1219c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitArgumentReversal() { 1220c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (BigEndianSafe) 1221c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman return; 1222c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1223c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Reverse all vector arguments. 1224c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < getNumParams(); ++I) { 1225c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name = "p" + utostr(I); 1226c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string NewName = "rev" + utostr(I); 1227c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1228c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable &V = Variables[Name]; 1229c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable NewV(V.getType(), NewName + VariablePostfix); 1230c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1231c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!NewV.getType().isVector() || NewV.getType().getNumElements() == 1) 1232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines continue; 1233c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman 1234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << NewV.getType().str() << " " << NewV.getName() << ";"; 1235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitReverseVariable(NewV, V); 1236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines V = NewV; 1237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 123851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 123951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1240c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitReturnReversal() { 1241c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (BigEndianSafe) 1242c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return; 1243c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!getReturnType().isVector() || getReturnType().isVoid() || 1244c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines getReturnType().getNumElements() == 1) 1245c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return; 1246c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitReverseVariable(RetVar, RetVar); 124751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 124851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 124951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1250c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitShadowedArgs() { 1251c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Macro arguments are not type-checked like inline function arguments, 1252c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // so assign them to local temporaries to get the right type checking. 1253c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!UseMacro) 1254c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return; 125551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1256c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < getNumParams(); ++I) { 125751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Do not create a temporary for an immediate argument. 125851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // That would defeat the whole point of using a macro! 1259c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (hasImmediate() && Proto[I+1] == 'i') 1260c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines continue; 1261c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Do not create a temporary for pointer arguments. The input 1262c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // pointer may have an alignment hint. 1263c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (getParamType(I).isPointer()) 126451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 126551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1266c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name = "p" + utostr(I); 126751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1268c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Variables.find(Name) != Variables.end()); 1269c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable &V = Variables[Name]; 1270097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu 1271c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string NewName = "s" + utostr(I); 1272c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable V2(V.getType(), NewName + VariablePostfix); 127351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1274c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << V2.getType().str() << " " << V2.getName() << " = " 1275c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines << V.getName() << ";"; 1276c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1277097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu 1278c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines V = V2; 1279c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1280097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu} 1281097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu 1282c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// We don't check 'a' in this function, because for builtin function the 1283c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// argument matching to 'a' uses a vector type splatted from a scalar type. 128487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarbool Intrinsic::protoHasScalar() const { 1285c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return (Proto.find('s') != std::string::npos || 1286c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('z') != std::string::npos || 1287c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('r') != std::string::npos || 1288c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('b') != std::string::npos || 1289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('$') != std::string::npos || 1290c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('y') != std::string::npos || 1291c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Proto.find('o') != std::string::npos); 1292097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu} 1293097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu 1294c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitBodyAsBuiltinCall() { 1295c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S; 129651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1297c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit 1298c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // sret-like argument. 1299c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool SRet = getReturnType().getNumVectors() >= 2; 1300c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1301c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines StringRef N = Name; 1302c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (hasSplat()) { 1303c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Call the non-splat builtin: chop off the "_n" suffix from the name. 1304c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(N.endswith("_n")); 1305c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines N = N.drop_back(2); 130651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 130751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1308c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassKind LocalCK = CK; 1309c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!protoHasScalar()) 1310c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines LocalCK = ClassB; 131151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1312c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!getReturnType().isVoid() && !SRet) 1313c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "(" + RetVar.getType().str() + ") "; 131451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1315c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "__builtin_neon_" + mangleName(N, LocalCK) + "("; 1316912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu 1317c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (SRet) 1318c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "&" + RetVar.getName() + ", "; 131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1320c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < getNumParams(); ++I) { 1321c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable &V = Variables["p" + utostr(I)]; 1322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T = V.getType(); 132351cc0172a173599b769968696e20638754d1dcd6Ana Pazos 1324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Handle multiple-vector values specially, emitting each subvector as an 1325c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // argument to the builtin. 1326c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.getNumVectors() > 1) { 1327c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Check if an explicit cast is needed. 1328c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Cast; 1329c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.isChar() || T.isPoly() || !T.isSigned()) { 1330c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T2 = T; 1331c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T2.makeOneVector(); 1332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T2.makeInteger(8, /*Signed=*/true); 1333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Cast = "(" + T2.str() + ")"; 1334c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 133551cc0172a173599b769968696e20638754d1dcd6Ana Pazos 1336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned J = 0; J < T.getNumVectors(); ++J) 1337c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += Cast + V.getName() + ".val[" + utostr(J) + "], "; 1338c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines continue; 1339c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Arg; 1342c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type CastToType = T; 1343c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (hasSplat() && I == getSplatIdx()) { 1344c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Arg = "(" + BaseType.str() + ") {"; 1345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned J = 0; J < BaseType.getNumElements(); ++J) { 1346c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (J != 0) 1347c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Arg += ", "; 1348c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Arg += V.getName(); 1349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1350c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Arg += "}"; 1351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1352c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CastToType = BaseType; 1353c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 1354c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Arg = V.getName(); 1355c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1357c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Check if an explicit cast is needed. 1358c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (CastToType.isVector()) { 1359c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CastToType.makeInteger(8, true); 1360c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Arg = "(" + CastToType.str() + ")" + Arg; 1361c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1362651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1363c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += Arg + ", "; 1364696e2d735c38eb73f1628d9b6166565fec4b9f1bBill Wendling } 1365651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1366c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Extra constant integer to hold type class enum for this function, e.g. s8 1367c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (getClassKind(true) == ClassB) { 1368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type ThisTy = getReturnType(); 136987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (Proto[0] == 'v' || isFloatingPointProtoModifier(Proto[0])) 1370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ThisTy = getParamType(0); 1371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (ThisTy.isPointer()) 1372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ThisTy = getParamType(1); 1373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += utostr(ThisTy.getNeonEnum()); 1375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 1376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Remove extraneous ", ". 1377c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.pop_back(); 1378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.pop_back(); 1379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ");"; 1381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1382c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string RetExpr; 1383c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!SRet && !RetVar.getType().isVoid()) 1384c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines RetExpr = RetVar.getName() + " = "; 1385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1386c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << RetExpr << S; 1387c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1388c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1390c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitBody(StringRef CallPrefix) { 1391c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<std::string> Lines; 1392696e2d735c38eb73f1628d9b6166565fec4b9f1bBill Wendling 1393c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(RetVar.getType() == Types[0]); 1394c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Create a return variable, if we're not void. 1395c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!RetVar.getType().isVoid()) { 1396c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << RetVar.getType().str() << " " << RetVar.getName() << ";"; 1397c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1400c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Body || Body->getValues().size() == 0) { 1401c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Nothing specific to output - must output a builtin. 1402c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitBodyAsBuiltinCall(); 1403c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return; 1404c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1406c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // We have a list of "things to output". The last should be returned. 1407c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *I : Body->getValues()) { 1408c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (StringInit *SI = dyn_cast<StringInit>(I)) { 1409c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Lines.push_back(replaceParamsIn(SI->getAsString())); 1410c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (DagInit *DI = dyn_cast<DagInit>(I)) { 1411c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DagEmitter DE(*this, CallPrefix); 1412c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Lines.push_back(DE.emitDag(DI).second + ";"); 1413c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1414c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 141551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 14160e2c34f92f00628d48968dfea096d36381f494cbStephen Hines assert(!Lines.empty() && "Empty def?"); 1417c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!RetVar.getType().isVoid()) 1418c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Lines.back().insert(0, RetVar.getName() + " = "); 141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1420c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto &L : Lines) { 1421c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << L; 1422c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1423c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1424c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1426c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitReturn() { 1427c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (RetVar.getType().isVoid()) 1428c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return; 1429c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (UseMacro) 1430c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << RetVar.getName() << ";"; 1431c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1432c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " return " << RetVar.getName() << ";"; 1433c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitNewLine(); 1434c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1436c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDag(DagInit *DI) { 1437c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // At this point we should only be seeing a def. 1438c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DefInit *DefI = cast<DefInit>(DI->getOperator()); 1439c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Op = DefI->getAsString(); 1440c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1441c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "cast" || Op == "bitcast") 1442c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagCast(DI, Op == "bitcast"); 1443c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "shuffle") 1444c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagShuffle(DI); 1445c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "dup") 1446c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagDup(DI); 1447c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "splat") 1448c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagSplat(DI); 1449c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "save_temp") 1450c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagSaveTemp(DI); 1451c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "op") 1452c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagOp(DI); 1453c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "call") 1454c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagCall(DI); 1455c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "name_replace") 1456c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagNameReplace(DI); 1457c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Op == "literal") 1458c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDagLiteral(DI); 1459c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(false, "Unknown operation!"); 1460c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(Type::getVoid(), ""); 146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1463c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagOp(DagInit *DI) { 1464c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Op = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1465c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (DI->getNumArgs() == 2) { 1466c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Unary op. 1467c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> R = 1468c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitDagArg(DI->getArg(1), DI->getArgName(1)); 1469c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(R.first, Op + R.second); 1470c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 1471c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!"); 1472c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> R1 = 1473c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitDagArg(DI->getArg(1), DI->getArgName(1)); 1474c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> R2 = 1475c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitDagArg(DI->getArg(2), DI->getArgName(2)); 1476c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(R1.first == R2.first, "Argument type mismatch!"); 1477c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second); 1478c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 14790391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu} 14800391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu 1481c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) { 1482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<Type> Types; 1483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<std::string> Values; 1484c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { 1485c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> R = 1486c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitDagArg(DI->getArg(I + 1), DI->getArgName(I + 1)); 1487c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Types.push_back(R.first); 1488c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Values.push_back(R.second); 1489c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 149051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1491c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Look up the called intrinsic. 1492c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string N; 1493c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (StringInit *SI = dyn_cast<StringInit>(DI->getArg(0))) 1494c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines N = SI->getAsUnquotedString(); 1495c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1496c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines N = emitDagArg(DI->getArg(0), "").second; 149787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types); 149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1499c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Make sure the callee is known as an early def. 150087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Callee.setNeededEarly(); 150187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Intr.Dependencies.insert(&Callee); 150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1503c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Now create the call itself. 150487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar std::string S = CallPrefix.str() + Callee.getMangledName(true) + "("; 1505c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { 1506c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (I != 0) 1507c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ", "; 1508c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += Values[I]; 1509c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1510c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ")"; 151151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 151287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return std::make_pair(Callee.getReturnType(), S); 1513c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1515c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI, 1516c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool IsBitCast){ 1517c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // (cast MOD* VAL) -> cast VAL to type given by MOD. 1518c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> R = emitDagArg( 1519c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DI->getArg(DI->getNumArgs() - 1), DI->getArgName(DI->getNumArgs() - 1)); 1520c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type castToType = R.first; 1521c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) { 1522c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1523c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // MOD can take several forms: 1524c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 1. $X - take the type of parameter / variable X. 1525c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 2. The value "R" - take the type of the return type. 1526c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 3. a type string 1527c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 4. The value "U" or "S" to switch the signedness. 1528c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 5. The value "H" or "D" to half or double the bitwidth. 1529c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 6. The value "8" to convert to 8-bit (signed) integer lanes. 1530c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (DI->getArgName(ArgIdx).size()) { 1531c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Intr.Variables.find(DI->getArgName(ArgIdx)) != 1532c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intr.Variables.end(), 1533c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Variable not found"); 1534c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType = Intr.Variables[DI->getArgName(ArgIdx)].getType(); 153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 1536c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx)); 1537c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(SI, "Expected string type or $Name for cast type"); 1538c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1539c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (SI->getAsUnquotedString() == "R") { 1540c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType = Intr.getReturnType(); 1541c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (SI->getAsUnquotedString() == "U") { 1542c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType.makeUnsigned(); 1543c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (SI->getAsUnquotedString() == "S") { 1544c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType.makeSigned(); 1545c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (SI->getAsUnquotedString() == "H") { 1546c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType.halveLanes(); 1547c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (SI->getAsUnquotedString() == "D") { 1548c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType.doubleLanes(); 1549c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (SI->getAsUnquotedString() == "8") { 1550c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType.makeInteger(8, true); 1551c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 1552c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines castToType = Type::fromTypedefName(SI->getAsUnquotedString()); 1553c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(!castToType.isVoid(), "Unknown typedef"); 1554c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 155551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 155651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 155751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1558c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S; 1559c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (IsBitCast) { 1560c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Emit a reinterpret cast. The second operand must be an lvalue, so create 1561c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // a temporary. 1562c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string N = "reint"; 1563c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned I = 0; 1564c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines while (Intr.Variables.find(N) != Intr.Variables.end()) 1565c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines N = "reint" + utostr(++I); 1566c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intr.Variables[N] = Variable(R.first, N + Intr.VariablePostfix); 156751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1568c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intr.OS << R.first.str() << " " << Intr.Variables[N].getName() << " = " 1569c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines << R.second << ";"; 1570c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intr.emitNewLine(); 1571c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1572c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S = "*(" + castToType.str() + " *) &" + Intr.Variables[N].getName() + ""; 157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 1574c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Emit a normal (static) cast. 1575c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S = "(" + castToType.str() + ")(" + R.second + ")"; 157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 157751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1578c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(castToType, S); 1579c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 158051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1581c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ 1582c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // See the documentation in arm_neon.td for a description of these operators. 1583c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines class LowHalf : public SetTheory::Operator { 1584c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines public: 158558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 158658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar ArrayRef<SMLoc> Loc) override { 1587c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SetTheory::RecSet Elts2; 1588c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc); 1589c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2)); 15902e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu } 1591c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines }; 1592c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines class HighHalf : public SetTheory::Operator { 1593c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines public: 159458878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 159558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar ArrayRef<SMLoc> Loc) override { 1596c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SetTheory::RecSet Elts2; 1597c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc); 1598c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end()); 1599c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1600c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines }; 1601c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines class Rev : public SetTheory::Operator { 1602c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned ElementSize; 1603c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1604c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines public: 1605c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Rev(unsigned ElementSize) : ElementSize(ElementSize) {} 160658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 160758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar ArrayRef<SMLoc> Loc) override { 1608c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SetTheory::RecSet Elts2; 1609c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Elts2, Loc); 1610c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1611c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines int64_t VectorSize = cast<IntInit>(Expr->getArg(0))->getValue(); 1612c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines VectorSize /= ElementSize; 1613c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1614c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<Record *> Revved; 1615c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned VI = 0; VI < Elts2.size(); VI += VectorSize) { 1616c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (int LI = VectorSize - 1; LI >= 0; --LI) { 1617c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Revved.push_back(Elts2[VI + LI]); 1618c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 162051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1621c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Elts.insert(Revved.begin(), Revved.end()); 1622c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1623c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines }; 1624c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines class MaskExpander : public SetTheory::Expander { 1625c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned N; 1626c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1627c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines public: 1628c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines MaskExpander(unsigned N) : N(N) {} 162958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) override { 1630c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Addend = 0; 1631c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (R->getName() == "mask0") 1632c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Addend = 0; 1633c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else if (R->getName() == "mask1") 1634c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Addend = N; 1635c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1636c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return; 1637c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < N; ++I) 1638c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Elts.insert(R->getRecords().getDef("sv" + utostr(I + Addend))); 163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1640c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines }; 164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1642c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // (shuffle arg1, arg2, sequence) 1643c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> Arg1 = 1644c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitDagArg(DI->getArg(0), DI->getArgName(0)); 1645c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> Arg2 = 1646c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitDagArg(DI->getArg(1), DI->getArgName(1)); 1647c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Arg1.first == Arg2.first, 1648c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Different types in arguments to shuffle!"); 1649c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1650c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SetTheory ST; 1651c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SetTheory::RecSet Elts; 1652b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ST.addOperator("lowhalf", llvm::make_unique<LowHalf>()); 1653b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ST.addOperator("highhalf", llvm::make_unique<HighHalf>()); 1654b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ST.addOperator("rev", 1655b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar llvm::make_unique<Rev>(Arg1.first.getElementSizeInBits())); 1656b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ST.addExpander("MaskExpand", 1657b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar llvm::make_unique<MaskExpander>(Arg1.first.getNumElements())); 1658176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ST.evaluate(DI->getArg(2), Elts, None); 1659c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1660c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second; 1661c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto &E : Elts) { 1662c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines StringRef Name = E->getName(); 1663c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Name.startswith("sv"), 1664c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Incorrect element kind in shuffle mask!"); 1665c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ", " + Name.drop_front(2).str(); 1666c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1667c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ")"; 1668c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1669c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Recalculate the return type - the shuffle may have halved or doubled it. 1670c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T(Arg1.first); 1671c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Elts.size() > T.getNumElements()) { 1672c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc( 1673c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Elts.size() == T.getNumElements() * 2, 1674c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Can only double or half the number of elements in a shuffle!"); 1675c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.doubleLanes(); 1676c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (Elts.size() < T.getNumElements()) { 1677c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc( 1678c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Elts.size() == T.getNumElements() / 2, 1679c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Can only double or half the number of elements in a shuffle!"); 1680c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T.halveLanes(); 1681c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1682c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1683c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(T, S); 1684c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1686c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { 1687c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument"); 1688c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0)); 1689c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument"); 169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1691c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T = Intr.getBaseType(); 1692c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(T.isVector(), "dup() used but default type is scalar!"); 1693c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = "(" + T.str() + ") {"; 1694c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < T.getNumElements(); ++I) { 1695c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (I != 0) 1696c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ", "; 1697c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += A.second; 169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1699c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "}"; 170051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1701c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(T, S); 1702c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1704c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) { 1705c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments"); 1706c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0)); 1707c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), DI->getArgName(1)); 170851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1709c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(B.first.isScalar(), 1710c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "splat() requires a scalar int as the second argument"); 1711c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1712c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = "__builtin_shufflevector(" + A.second + ", " + A.second; 1713c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < Intr.getBaseType().getNumElements(); ++I) { 1714c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ", " + B.second; 171551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1716c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += ")"; 1717c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1718c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(Intr.getBaseType(), S); 171951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1721c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSaveTemp(DagInit *DI) { 1722c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments"); 1723c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), DI->getArgName(1)); 172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1725c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(!A.first.isVoid(), 1726c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Argument to save_temp() must have non-void type!"); 172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1728c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string N = DI->getArgName(0); 1729c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(N.size(), "save_temp() expects a name as the first argument"); 173051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1731c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Intr.Variables.find(N) == Intr.Variables.end(), 1732c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Variable already defined!"); 1733c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Intr.Variables[N] = Variable(A.first, N + Intr.VariablePostfix); 173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1735c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = 1736c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines A.first.str() + " " + Intr.Variables[N].getName() + " = " + A.second; 173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1738c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(Type::getVoid(), S); 173951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1741c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> 1742c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesIntrinsic::DagEmitter::emitDagNameReplace(DagInit *DI) { 1743c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = Intr.Name; 174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1745c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(DI->getNumArgs() == 2, "name_replace requires 2 arguments!"); 1746c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string ToReplace = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1747c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string ReplaceWith = cast<StringInit>(DI->getArg(1))->getAsUnquotedString(); 174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1749c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines size_t Idx = S.find(ToReplace); 175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1751c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Idx != std::string::npos, "name should contain '" + ToReplace + "'!"); 1752c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.replace(Idx, ToReplace.size(), ReplaceWith); 175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1754c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(Type::getVoid(), S); 1755c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1757c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagLiteral(DagInit *DI){ 1758c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Ty = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1759c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Value = cast<StringInit>(DI->getArg(1))->getAsUnquotedString(); 1760c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(Type::fromTypedefName(Ty), Value); 1761c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1762b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1763c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> 1764c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesIntrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) { 1765c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (ArgName.size()) { 1766c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(!Arg->isComplete(), 1767c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Arguments must either be DAGs or names, not both!"); 1768c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(Intr.Variables.find(ArgName) != Intr.Variables.end(), 1769c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "Variable not defined!"); 1770c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Variable &V = Intr.Variables[ArgName]; 1771c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return std::make_pair(V.getType(), V.getName()); 1772c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1773b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1774c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Arg && "Neither ArgName nor Arg?!"); 1775c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DagInit *DI = dyn_cast<DagInit>(Arg); 1776c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(DI, "Arguments must either be DAGs or names!"); 177751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1778c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return emitDag(DI); 1779c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 178051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1781c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Intrinsic::generate() { 1782c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Little endian intrinsics are simple and don't require any argument 1783c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // swapping. 1784c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifdef __LITTLE_ENDIAN__\n"; 1785b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1786c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines generateImpl(false, "", ""); 178751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1788c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#else\n"; 178951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1790c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Big endian intrinsics are more complex. The user intended these 1791c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // intrinsics to operate on a vector "as-if" loaded by (V)LDR, 1792c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // but we load as-if (V)LD1. So we should swap all arguments and 1793c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // swap the return value too. 1794c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 1795c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // If we call sub-intrinsics, we should call a version that does 1796c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // not re-swap the arguments! 1797c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines generateImpl(true, "", "__noswap_"); 1798b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1799c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // If we're needed early, create a non-swapping variant for 1800c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // big-endian. 1801c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (NeededEarly) { 1802c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines generateImpl(false, "__noswap_", "__noswap_"); 180351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1804c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n\n"; 1805b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1806c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return OS.str(); 1807c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 180851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1809c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::generateImpl(bool ReverseArguments, 1810c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines StringRef NamePrefix, StringRef CallPrefix) { 1811c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CurrentRecord = R; 181251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1813c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // If we call a macro, our local variables may be corrupted due to 1814c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // lack of proper lexical scoping. So, add a globally unique postfix 1815c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // to every variable. 1816c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // 1817c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // indexBody() should have set up the Dependencies set by now. 1818c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *I : Dependencies) 1819c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (I->UseMacro) { 1820c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines VariablePostfix = "_" + utostr(Emitter.getUniqueNumber()); 1821c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 1822c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 182351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1824c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines initVariables(); 1825b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1826c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitPrototype(NamePrefix); 1827b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1828c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (IsUnavailable) { 1829c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " __attribute__((unavailable));"; 1830c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 1831c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitOpeningBrace(); 1832c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitShadowedArgs(); 1833c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (ReverseArguments) 1834c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitArgumentReversal(); 1835c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitBody(CallPrefix); 1836c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (ReverseArguments) 1837c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitReturnReversal(); 1838c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitReturn(); 1839c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitClosingBrace(); 184051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1841c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "\n"; 184251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1843c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CurrentRecord = nullptr; 1844c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 1845315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu 1846c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::indexBody() { 1847c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CurrentRecord = R; 1848315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu 1849c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines initVariables(); 1850c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines emitBody(""); 1851c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS.str(""); 1852315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu 1853c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CurrentRecord = nullptr; 1854651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1855315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu 1856c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 1857c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// NeonEmitter implementation 1858c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===// 1859c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 186087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarIntrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) { 1861c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // First, look up the name in the intrinsic map. 1862c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(), 1863c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ("Intrinsic '" + Name + "' not found!").str()); 186487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto &V = IntrinsicMap.find(Name.str())->second; 1865c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<Intrinsic *> GoodVec; 1866c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1867c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Create a string to print if we end up failing. 1868c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string ErrMsg = "looking up intrinsic '" + Name.str() + "("; 1869c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < Types.size(); ++I) { 1870c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (I != 0) 1871c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ErrMsg += ", "; 1872c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ErrMsg += Types[I].str(); 1873c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1874c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ErrMsg += ")'\n"; 1875c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ErrMsg += "Available overloads:\n"; 1876c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1877c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Now, look through each intrinsic implementation and see if the types are 1878c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // compatible. 187987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for (auto &I : V) { 188087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ErrMsg += " - " + I.getReturnType().str() + " " + I.getMangledName(); 1881c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ErrMsg += "("; 188287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for (unsigned A = 0; A < I.getNumParams(); ++A) { 1883c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (A != 0) 1884c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ErrMsg += ", "; 188587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ErrMsg += I.getParamType(A).str(); 1886c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1887c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ErrMsg += ")\n"; 1888315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu 188987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (I.getNumParams() != Types.size()) 1890c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines continue; 1891b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1892c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool Good = true; 1893c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned Arg = 0; Arg < Types.size(); ++Arg) { 189487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (I.getParamType(Arg) != Types[Arg]) { 1895c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Good = false; 1896c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines break; 1897c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1898c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1899c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Good) 190087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar GoodVec.push_back(&I); 1901651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1902b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1903c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(GoodVec.size() > 0, 1904c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "No compatible intrinsic found - " + ErrMsg); 1905c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg); 1906c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 190787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return *GoodVec.front(); 190851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 190951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1910c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::createIntrinsic(Record *R, 1911c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVectorImpl<Intrinsic *> &Out) { 1912c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name = R->getValueAsString("Name"); 191351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Proto = R->getValueAsString("Prototype"); 191451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string Types = R->getValueAsString("Types"); 1915c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Record *OperationRec = R->getValueAsDef("Operation"); 1916c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool CartesianProductOfTypes = R->getValueAsBit("CartesianProductOfTypes"); 1917c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool BigEndianSafe = R->getValueAsBit("BigEndianSafe"); 1918c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Guard = R->getValueAsString("ArchGuard"); 1919c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool IsUnavailable = OperationRec->getValueAsBit("Unavailable"); 1920c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1921c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Set the global current record. This allows assert_with_loc to produce 1922c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // decent location information even when highly nested. 1923c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CurrentRecord = R; 192451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1925c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ListInit *Body = OperationRec->getValueAsListInit("Ops"); 192651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1927c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types); 192851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1929c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ClassKind CK = ClassNone; 193051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R->getSuperClasses().size() >= 2) 19314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar CK = ClassMap[R->getSuperClasses()[1].first]; 1932c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1933c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs; 1934c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto TS : TypeSpecs) { 1935c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (CartesianProductOfTypes) { 1936c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type DefaultT(TS, 'd'); 1937c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto SrcTS : TypeSpecs) { 1938c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type DefaultSrcT(SrcTS, 'd'); 1939c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (TS == SrcTS || 1940c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DefaultSrcT.getSizeInBits() != DefaultT.getSizeInBits()) 194151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 1942c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NewTypeSpecs.push_back(std::make_pair(TS, SrcTS)); 194351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 194451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } else { 1945c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines NewTypeSpecs.push_back(std::make_pair(TS, TS)); 194651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 194751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 194851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1949c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::sort(NewTypeSpecs.begin(), NewTypeSpecs.end()); 195058878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()), 195158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar NewTypeSpecs.end()); 195287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto &Entry = IntrinsicMap[Name]; 195351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1954c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto &I : NewTypeSpecs) { 195587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Entry.emplace_back(R, Name, Proto, I.first, I.second, CK, Body, *this, 195687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Guard, IsUnavailable, BigEndianSafe); 195787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Out.push_back(&Entry.back()); 1958f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier } 1959f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier 1960c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CurrentRecord = nullptr; 1961c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 196251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1963c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// genBuiltinsDef: Generate the BuiltinsARM.def and BuiltinsAArch64.def 1964c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// declaration of builtins, checking for unique builtin declarations. 1965c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::genBuiltinsDef(raw_ostream &OS, 1966c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVectorImpl<Intrinsic *> &Defs) { 1967c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifdef GET_NEON_BUILTINS\n"; 1968b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1969c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // We only want to emit a builtin once, and we want to emit them in 1970c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // alphabetical order, so use a std::set. 1971c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::set<std::string> Builtins; 1972b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1973c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *Def : Defs) { 1974c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->hasBody()) 197551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 197651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions with 'a' (the splat code) in the type prototype should not get 197751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // their own builtin as they use the non-splat variant. 1978c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->hasSplat()) 197951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 198051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1981c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string S = "BUILTIN(__builtin_neon_" + Def->getMangledName() + ", \""; 1982b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1983c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += Def->getBuiltinTypeStr(); 1984c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S += "\", \"n\")"; 1985c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1986c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Builtins.insert(S); 198751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1988c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1989c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto &S : Builtins) 1990c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << S << "\n"; 199151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 1992b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover} 1993b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 1994b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Generate the ARM and AArch64 overloaded type checking code for 1995b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// SemaChecking.cpp, checking for unique builtin declarations. 1996c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS, 1997c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVectorImpl<Intrinsic *> &Defs) { 1998651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n"; 1999651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2000651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // We record each overload check line before emitting because subsequent Inst 2001651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // definitions may extend the number of permitted types (i.e. augment the 2002651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Mask). Use std::map to avoid sorting the table by hash number. 2003c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines struct OverloadInfo { 2004c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines uint64_t Mask; 2005c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines int PtrArgNum; 2006c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool HasConstPtr; 2007c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OverloadInfo() : Mask(0ULL), PtrArgNum(0), HasConstPtr(false) {} 2008c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines }; 2009651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::map<std::string, OverloadInfo> OverloadMap; 2010b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2011c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *Def : Defs) { 2012c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // If the def has a body (that is, it has Operation DAGs), it won't call 2013c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // __builtin_neon_* so we don't need to generate a definition for it. 2014c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->hasBody()) 201551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 201651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions with 'a' (the splat code) in the type prototype should not get 201751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // their own builtin as they use the non-splat variant. 2018c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->hasSplat()) 201951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 202051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions which have a scalar argument cannot be overloaded, no need to 202151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // check them if we are emitting the type checking code. 2022c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->protoHasScalar()) 202351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 202451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2025c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines uint64_t Mask = 0ULL; 2026c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type Ty = Def->getReturnType(); 202787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (Def->getProto()[0] == 'v' || 202887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isFloatingPointProtoModifier(Def->getProto()[0])) 2029c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Ty = Def->getParamType(0); 2030c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Ty.isPointer()) 2031c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Ty = Def->getParamType(1); 203251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2033c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Mask |= 1ULL << Ty.getNeonEnum(); 20344648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson 2035c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Check if the function has a pointer or const pointer argument. 2036c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Proto = Def->getProto(); 20374648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson int PtrArgNum = -1; 20384648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson bool HasConstPtr = false; 2039c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned I = 0; I < Def->getNumParams(); ++I) { 2040c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines char ArgType = Proto[I + 1]; 20414648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson if (ArgType == 'c') { 20424648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson HasConstPtr = true; 2043c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines PtrArgNum = I; 20444648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson break; 20454648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson } 20464648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson if (ArgType == 'p') { 2047c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines PtrArgNum = I; 20484648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson break; 20494648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson } 20504648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson } 20514648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson // For sret builtins, adjust the pointer argument index. 2052c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (PtrArgNum >= 0 && Def->getReturnType().getNumVectors() > 1) 20534648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson PtrArgNum += 1; 20544648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson 2055c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name = Def->getName(); 20569082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // Omit type checking for the pointer arguments of vld1_lane, vld1_dup, 20579082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // and vst1_lane intrinsics. Using a pointer to the vector element 20589082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // type with one of those operations causes codegen to select an aligned 20599082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // load/store instruction. If you want an unaligned operation, 20609082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // the pointer argument needs to have less alignment than element type, 20619082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson // so just accept any pointer type. 2062c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Name == "vld1_lane" || Name == "vld1_dup" || Name == "vst1_lane") { 20639082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson PtrArgNum = -1; 20649082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson HasConstPtr = false; 20659082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson } 20669082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson 2067c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Mask) { 2068c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string Name = Def->getMangledName(); 2069c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OverloadMap.insert(std::make_pair(Name, OverloadInfo())); 2070c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OverloadInfo &OI = OverloadMap[Name]; 2071c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OI.Mask |= Mask; 2072c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OI.PtrArgNum |= PtrArgNum; 2073c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OI.HasConstPtr = HasConstPtr; 20746f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson } 207551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 2076651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2077c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto &I : OverloadMap) { 2078c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OverloadInfo &OI = I.second; 2079c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2080c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "case NEON::BI__builtin_neon_" << I.first << ": "; 2081c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "mask = 0x" << utohexstr(OI.Mask) << "ULL"; 2082c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (OI.PtrArgNum >= 0) 2083c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "; PtrArgNum = " << OI.PtrArgNum; 2084c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (OI.HasConstPtr) 2085651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "; HasConstPtr = true"; 2086651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "; break;\n"; 2087651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 208851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 2089b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover} 2090b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2091c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid 2092c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesNeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, 2093c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVectorImpl<Intrinsic *> &Defs) { 2094c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n"; 2095b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2096c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::set<std::string> Emitted; 209751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2098c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *Def : Defs) { 2099c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->hasBody()) 210051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 210151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Functions with 'a' (the splat code) in the type prototype should not get 210251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // their own builtin as they use the non-splat variant. 2103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->hasSplat()) 2104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines continue; 2105176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // Functions which do not have an immediate do not need to have range 2106176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // checking code emitted. 2107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Def->hasImmediate()) 2108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines continue; 2109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Emitted.find(Def->getMangledName()) != Emitted.end()) 211051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne continue; 211151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2112c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string LowerBound, UpperBound; 211351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2114c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Record *R = Def->getRecord(); 2115c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (R->getValueAsBit("isVCVT_N")) { 2116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // VCVT between floating- and fixed-point values takes an immediate 2117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // in the range [1, 32) for f32 or [1, 64) for f64. 2118c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines LowerBound = "1"; 2119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->getBaseType().getElementSizeInBits() == 32) 2120c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UpperBound = "31"; 2121c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 2122c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UpperBound = "63"; 2123c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (R->getValueAsBit("isScalarShift")) { 2124c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Right shifts have an 'r' in the name, left shifts do not. Convert 2125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // instructions have the same bounds and right shifts. 2126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->getName().find('r') != std::string::npos || 2127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Def->getName().find("cvt") != std::string::npos) 2128c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines LowerBound = "1"; 2129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2130c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UpperBound = utostr(Def->getReturnType().getElementSizeInBits() - 1); 2131c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (R->getValueAsBit("isShift")) { 2132176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // Builtins which are overloaded by type will need to have their upper 2133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // bound computed at Sema time based on the type constant. 2134c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2135c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Right shifts have an 'r' in the name, left shifts do not. 2136c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->getName().find('r') != std::string::npos) 2137c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines LowerBound = "1"; 2138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UpperBound = "RFT(TV, true)"; 2139c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else if (Def->getClassKind(true) == ClassB) { 2140c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // ClassB intrinsics have a type (and hence lane number) that is only 2141c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // known at runtime. 2142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (R->getValueAsBit("isLaneQ")) 2143c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UpperBound = "RFT(TV, false, true)"; 2144c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 2145c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UpperBound = "RFT(TV, false, false)"; 2146c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } else { 2147c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // The immediate generally refers to a lane in the preceding argument. 2148c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Def->getImmediateIdx() > 0); 2149c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T = Def->getParamType(Def->getImmediateIdx() - 1); 2150c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines UpperBound = utostr(T.getNumElements() - 1); 2151c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 215251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2153c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Calculate the index of the immediate that should be range checked. 2154c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines unsigned Idx = Def->getNumParams(); 2155c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (Def->hasImmediate()) 2156c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Idx = Def->getGeneratedParamIdx(Def->getImmediateIdx()); 215751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2158c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": " 2159c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines << "i = " << Idx << ";"; 2160c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (LowerBound.size()) 2161c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " l = " << LowerBound << ";"; 2162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (UpperBound.size()) 2163c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " u = " << UpperBound << ";"; 2164c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " break;\n"; 216551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2166c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Emitted.insert(Def->getMangledName()); 216751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 2168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 216951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 217051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 217151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2172b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// runHeader - Emit a file with sections defining: 2173b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 1. the NEON section of BuiltinsARM.def and BuiltinsAArch64.def. 2174b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 2. the SemaChecking code for the type overload checking. 2175b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 3. the SemaChecking code for validation of intrinsic immediate arguments. 2176b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::runHeader(raw_ostream &OS) { 2177b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2178b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2179c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVector<Intrinsic *, 128> Defs; 2180c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *R : RV) 2181c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines createIntrinsic(R, Defs); 2182c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Generate shared BuiltinsXXX.def 2184c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines genBuiltinsDef(OS, Defs); 2185b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2186b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover // Generate ARM overloaded type checking code for SemaChecking.cpp 2187c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines genOverloadTypeCheckCode(OS, Defs); 2188b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2189b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover // Generate ARM range checking code for shift/lane immediates. 2190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines genIntrinsicRangeCheckCode(OS, Defs); 2191b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover} 2192b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2193c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h 2194c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// is comprised of type definitions and function declarations. 2195c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::run(raw_ostream &OS) { 2196c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "/*===---- arm_neon.h - ARM Neon intrinsics " 2197c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "------------------------------" 2198c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "---===\n" 2199c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " *\n" 2200c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * Permission is hereby granted, free of charge, to any person " 2201c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "obtaining " 2202c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "a copy\n" 2203c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * of this software and associated documentation files (the " 2204c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "\"Software\")," 2205c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " to deal\n" 2206c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * in the Software without restriction, including without limitation " 2207c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "the " 2208c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "rights\n" 2209c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * to use, copy, modify, merge, publish, distribute, sublicense, " 2210c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "and/or sell\n" 2211c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * copies of the Software, and to permit persons to whom the Software " 2212c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "is\n" 2213c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * furnished to do so, subject to the following conditions:\n" 2214c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " *\n" 2215c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * The above copyright notice and this permission notice shall be " 2216c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "included in\n" 2217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * all copies or substantial portions of the Software.\n" 2218c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " *\n" 2219c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, " 2220c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "EXPRESS OR\n" 2221c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " 2222c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "MERCHANTABILITY,\n" 2223c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT " 2224c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "SHALL THE\n" 2225c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR " 2226c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "OTHER\n" 2227c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, " 2228c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "ARISING FROM,\n" 2229c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER " 2230c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "DEALINGS IN\n" 2231c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " * THE SOFTWARE.\n" 2232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " *\n" 2233c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " *===-----------------------------------------------------------------" 2234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "---" 2235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "---===\n" 2236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines " */\n\n"; 2237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2238c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifndef __ARM_NEON_H\n"; 2239c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#define __ARM_NEON_H\n\n"; 2240c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2241c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#if !defined(__ARM_NEON)\n"; 2242c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#error \"NEON support not enabled\"\n"; 2243c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n\n"; 2244c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2245c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#include <stdint.h>\n\n"; 2246c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2247c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Emit NEON-specific scalar typedefs. 2248c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef float float32_t;\n"; 2249c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef __fp16 float16_t;\n"; 2250c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2251c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifdef __aarch64__\n"; 2252c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef double float64_t;\n"; 2253c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n\n"; 2254c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2255c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // For now, signedness of polynomial types depends on target 2256c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifdef __aarch64__\n"; 2257c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef uint8_t poly8_t;\n"; 2258c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef uint16_t poly16_t;\n"; 2259c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef uint64_t poly64_t;\n"; 2260c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef __uint128_t poly128_t;\n"; 2261c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#else\n"; 2262c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef int8_t poly8_t;\n"; 2263c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef int16_t poly16_t;\n"; 2264c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n"; 2265c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2266c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Emit Neon vector typedefs. 2267c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string TypedefTypes( 2268c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl"); 2269c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::vector<TypeSpec> TDTypeVec = TypeSpec::fromTypeSpecs(TypedefTypes); 2270c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2271c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Emit vector typedefs. 2272c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool InIfdef = false; 2273c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto &TS : TDTypeVec) { 2274c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool IsA64 = false; 2275c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T(TS, 'd'); 2276c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.isDouble() || (T.isPoly() && T.isLong())) 2277c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines IsA64 = true; 2278c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2279c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (InIfdef && !IsA64) { 2280c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n"; 2281c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines InIfdef = false; 2282c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2283c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!InIfdef && IsA64) { 2284c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifdef __aarch64__\n"; 2285c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines InIfdef = true; 2286c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 2287c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2288c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.isPoly()) 2289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef __attribute__((neon_polyvector_type("; 2290c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 2291c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef __attribute__((neon_vector_type("; 2292c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2293c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T2 = T; 2294c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines T2.makeScalar(); 2295c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << utostr(T.getNumElements()) << "))) "; 2296c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << T2.str(); 2297c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << T.str() << ";\n"; 2298c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman } 2299c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (InIfdef) 2300c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n"; 2301c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "\n"; 230251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2303c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Emit struct typedefs. 2304c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines InIfdef = false; 2305c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (unsigned NumMembers = 2; NumMembers <= 4; ++NumMembers) { 2306c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto &TS : TDTypeVec) { 2307c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool IsA64 = false; 2308c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type T(TS, 'd'); 2309c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (T.isDouble() || (T.isPoly() && T.isLong())) 2310c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines IsA64 = true; 2311c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2312c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (InIfdef && !IsA64) { 2313c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n"; 2314c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines InIfdef = false; 2315c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2316c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!InIfdef && IsA64) { 2317c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#ifdef __aarch64__\n"; 2318c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines InIfdef = true; 2319c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2320b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover 2321c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines char M = '2' + (NumMembers - 2); 2322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Type VT(TS, M); 2323c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "typedef struct " << VT.str() << " {\n"; 2324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << " " << T.str() << " val"; 2325c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "[" << utostr(NumMembers) << "]"; 2326c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << ";\n} "; 2327c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << VT.str() << ";\n"; 2328c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "\n"; 232951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 233051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 2331c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (InIfdef) 2332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n"; 2333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "\n"; 233451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2335c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#define __ai static inline __attribute__((__always_inline__, " 2336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines "__nodebug__))\n\n"; 233751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2338c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines SmallVector<Intrinsic *, 128> Defs; 2339b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2340c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *R : RV) 2341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines createIntrinsic(R, Defs); 2342c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2343c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *I : Defs) 2344c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines I->indexBody(); 2345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2346c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::stable_sort( 2347c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Defs.begin(), Defs.end(), 2348c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines [](const Intrinsic *A, const Intrinsic *B) { return *A < *B; }); 2349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2350c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Only emit a def when its requirements have been met. 2351c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // FIXME: This loop could be made faster, but it's fast enough for now. 2352c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool MadeProgress = true; 2353c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::string InGuard = ""; 2354c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines while (!Defs.empty() && MadeProgress) { 2355c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines MadeProgress = false; 2356c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2357c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin(); 2358c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines I != Defs.end(); /*No step*/) { 2359c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool DependenciesSatisfied = true; 2360c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines for (auto *II : (*I)->getDependencies()) { 2361c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (std::find(Defs.begin(), Defs.end(), II) != Defs.end()) 2362c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines DependenciesSatisfied = false; 2363c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2364c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!DependenciesSatisfied) { 2365c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Try the next one. 2366c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ++I; 2367c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines continue; 2368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 236951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Emit #endif/#if pair if needed. 2371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if ((*I)->getGuard() != InGuard) { 2372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!InGuard.empty()) 2373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif\n"; 2374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines InGuard = (*I)->getGuard(); 2375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!InGuard.empty()) 2376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#if " << InGuard << "\n"; 237751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 2378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // Actually generate the intrinsic code. 2380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << (*I)->generate(); 2381c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2382c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines MadeProgress = true; 2383c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines I = Defs.erase(I); 238451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 238551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 2386c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines assert(Defs.empty() && "Some requirements were not satisfied!"); 2387c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!InGuard.empty()) 2388651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#endif\n"; 2389c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2390c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "\n"; 2391c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#undef __ai\n\n"; 2392c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines OS << "#endif /* __ARM_NEON_H */\n"; 239351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 239451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 23953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang { 23963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) { 23973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonEmitter(Records).run(OS); 23983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} 23993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { 24003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen NeonEmitter(Records).runHeader(OS); 24013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} 24023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { 2403c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm_unreachable("Neon test generation no longer implemented!"); 24043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} 24053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang 2406