From e3a78ad1504fcdc5668af5230634470bae3cfee4 Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 13 Feb 2015 16:14:15 +0300 Subject: [PATCH 01/10] Tmp commit to save progress --- cbackend.cpp | 41 ++++++++++++++--------------- examples/intrinsics/knc.h | 55 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index f99c1bfb..1acf512c 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -392,7 +392,7 @@ namespace { // Output all vector constants so they can be accessed with single // vector loads printVectorConstants(F); - + printFunction(F); return false; } @@ -748,10 +748,11 @@ CWriter::printSimpleType(llvm::raw_ostream &Out, llvm::Type *Ty, bool isSigned, return Out << (isSigned?"":"u") << "int32_t " << NameSoFar; else if (NumBits <= 64) return Out << (isSigned?"":"u") << "int64_t "<< NameSoFar; - else { - assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); + else if (NumBits <= 128) return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar; - } + else + return Out << "iN<" << NumBits << "> " << NameSoFar; + } case llvm::Type::FloatTyID: return Out << "float " << NameSoFar; case llvm::Type::DoubleTyID: return Out << "double " << NameSoFar; @@ -793,8 +794,8 @@ CWriter::printSimpleType(llvm::raw_ostream &Out, llvm::Type *Ty, bool isSigned, suffix = "i64"; break; default: - llvm::report_fatal_error("Only integer types of size 8/16/32/64 are " - "supported by the C++ backend."); + suffix = "iN"; + break; } } @@ -1463,10 +1464,10 @@ void CWriter::printConstant(llvm::Constant *CPV, bool Static) { Out << (CI->getZExtValue() ? '1' : '0'); else if (Ty == llvm::Type::getInt32Ty(CPV->getContext())) Out << CI->getZExtValue() << 'u'; - else if (Ty->getPrimitiveSizeInBits() > 32) { - assert(Ty->getPrimitiveSizeInBits() == 64); + else if (Ty == llvm::Type::getInt64Ty(CPV->getContext())) Out << CI->getZExtValue() << "ull"; - } + else if (Ty->getPrimitiveSizeInBits() > 64) + llvm::dyn_cast(CPV)->printAsOperand(Out, false); else { Out << "(("; printSimpleType(Out, Ty, false) << ')'; @@ -1874,22 +1875,11 @@ std::string CWriter::GetValueName(const llvm::Value *Operand) { /// writeInstComputationInline - Emit the computation for the specified /// instruction inline, with no destination provided. void CWriter::writeInstComputationInline(llvm::Instruction &I) { - // We can't currently support integer types other than 1, 8, 16, 32, 64. - // Validate this. - llvm::Type *Ty = I.getType(); - if (Ty->isIntegerTy() && (Ty!=llvm::Type::getInt1Ty(I.getContext()) && - Ty!=llvm::Type::getInt8Ty(I.getContext()) && - Ty!=llvm::Type::getInt16Ty(I.getContext()) && - Ty!=llvm::Type::getInt32Ty(I.getContext()) && - Ty!=llvm::Type::getInt64Ty(I.getContext()))) { - llvm::report_fatal_error("The C backend does not currently support integer " - "types of widths other than 1, 8, 16, 32, 64.\n" - "This is being tracked as PR 4158."); - } - // If this is a non-trivial bool computation, make sure to truncate down to // a 1 bit value. This is important because we want "add i1 x, y" to return // "0" when x and y are true, not "2" for example. + Out << "\n/* Tree\n" << I << "\n*/"; + bool NeedBoolTrunc = false; if (I.getType() == llvm::Type::getInt1Ty(I.getContext()) && !llvm::isa(I) && !llvm::isa(I)) @@ -2756,6 +2746,12 @@ void CWriter::printModuleTypes() { if (StructTypes.empty() && ArrayTypes.empty()) return; + Out << "DEBUG_ME"; + for (llvm::Module::const_global_iterator I = TheModule->global_begin(), E = TheModule->global_end(); + I != E; ++I) { + Out << I << "^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + } + Out << "/* Structure and array forward declarations */\n"; unsigned NextTypeID = 0; @@ -4342,6 +4338,7 @@ void CWriter::writeMemoryAccess(llvm::Value *Operand, llvm::Type *OperandType, } void CWriter::visitLoadInst(llvm::LoadInst &I) { + Out << "\n/* Tree\n" << I << "\n*/"; llvm::VectorType *VT = llvm::dyn_cast(I.getType()); if (VT != NULL) { Out << "__load<" << I.getAlignment() << ">("; diff --git a/examples/intrinsics/knc.h b/examples/intrinsics/knc.h index a0d072fa..aeba353e 100644 --- a/examples/intrinsics/knc.h +++ b/examples/intrinsics/knc.h @@ -33,6 +33,7 @@ #include // INT_MIN #include +#include #include #include #include @@ -94,6 +95,60 @@ typedef int64_t __vec1_i64; struct __vec16_i32; +template +struct iN { + int length; + int *num; + + iN () { + length = num_bits / (sizeof (int) * 8); + num = (int*) calloc (length, sizeof (int)); + } + + iN (int val) { + length = num_bits / (sizeof (int) * 8); + num = (int*) calloc (length, sizeof (int)); + num [0] = val; + } + + ~iN () { length = 0; free(num); num = NULL;} +/* + iN operator >> (const int rhs) { + iN res; + int cells = rhs / (sizeof(int) * 8); + for (int i = 0; i < (this->length - cells); i++) + res.num[i] = this->num[cells + i]; + return res; + } +*/ + iN operator >> (const iN rhs) { + iN res; + int cells = rhs.num[0] / (sizeof(int) * 8); + for (int i = 0; i < (this->length - cells); i++) + res.num[i] = this->num[cells + i]; + return res; + } +/* + iN& operator= (iN rhs) { + iN swap; + for (int i = 0; i < length; i++) { + swap.num[i] = this->num[i]; + this->num[i] = rhs.num[i]; + rhs.num[i] = swap.num[i]; + } + return *this; + } +*/ + operator uint32_t() { return this->num[0]; } +}; + +template +T __cast_bits (T to, __vec16_i32 from) { + for (int i = 0; i < 16; i++) + to.num[i] = from[i] ; + return to; +} + #if 1 /* (iw) actually, this *SHOULD* be the right implementation for a vec16_i1: this one is a class that can have a constructor (which From 1abce9480394981dd5df5424c08db7a5bf196d9c Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 13 Feb 2015 18:49:54 +0300 Subject: [PATCH 02/10] cast inst --- cbackend.cpp | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index 1acf512c..fcf3c28e 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -140,11 +140,14 @@ namespace { llvm::DenseSet VisitedMDNodes; #endif llvm::DenseSet VisitedTypes; - std::vector &ArrayTypes; + std::vector &IntegerTypes; + std::vector &IsVolatile; + std::vector &Alignment; public: - TypeFinder(std::vector &t) - : ArrayTypes(t) {} + TypeFinder(std::vector &t, std::vector &i, + std::vector &v, std::vector &a) + : ArrayTypes(t), IntegerTypes(i) , IsVolatile(v), Alignment(a){} void run(const llvm::Module &M) { // Get types from global variables. @@ -182,6 +185,13 @@ namespace { // Incorporate the type of the instruction and all its operands. incorporateType(I.getType()); + if (llvm::isa(&I)) + if (llvm::IntegerType *ITy = llvm::dyn_cast(I.getType())) { + IntegerTypes.push_back(ITy); +// llvm::StoreInst St = llvm::dyn_cast(I); +// IsVolatile.push_back(St.isVolatile()); +// Alignment.push_back(St.getAlignment()); + } for (llvm::User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); OI != OE; ++OI) incorporateValue(*OI); @@ -288,8 +298,9 @@ namespace { }; } // end anonymous namespace -static void findUsedArrayTypes(const llvm::Module *m, std::vector &t) { - TypeFinder(t).run(*m); +static void findUsedArrayTypes(const llvm::Module *m, std::vector &t, std::vector &i, + std::vector &IsVolatile, std::vector &Alignment) { + TypeFinder(t, i, IsVolatile, Alignment).run(*m); } namespace { @@ -2741,17 +2752,15 @@ void CWriter::printModuleTypes() { // Get all of the array types used in the module std::vector ArrayTypes; - findUsedArrayTypes(TheModule, ArrayTypes); + std::vector IntegerTypes; + std::vector IsVolatile; + std::vector Alignment; + + findUsedArrayTypes(TheModule, ArrayTypes, IntegerTypes, IsVolatile, Alignment); if (StructTypes.empty() && ArrayTypes.empty()) return; - Out << "DEBUG_ME"; - for (llvm::Module::const_global_iterator I = TheModule->global_begin(), E = TheModule->global_end(); - I != E; ++I) { - Out << I << "^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; - } - Out << "/* Structure and array forward declarations */\n"; unsigned NextTypeID = 0; @@ -2775,6 +2784,12 @@ void CWriter::printModuleTypes() { std::string Name = getArrayName(AT); Out << "struct " << Name << ";\n"; } + + for (unsigned i = 0, e = IntegerTypes.size(); i != e; ++i) { + llvm::IntegerType *IT = IntegerTypes[i]; + Out << "bitwidth: " << IT->getIntegerBitWidth () << "|" << IsVolatile[i] << "|" << Alignment[i] << ";\n"; + } + Out << '\n'; // Keep track of which types have been printed so far. From 8090285d42f95bb28f06976718a1a6539dd0f7ec Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 13 Feb 2015 21:39:18 +0300 Subject: [PATCH 03/10] Fix for cast --- cbackend.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index fcf3c28e..8a26b4dc 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -185,13 +185,22 @@ namespace { // Incorporate the type of the instruction and all its operands. incorporateType(I.getType()); + if (llvm::isa(&I)) + if (llvm::IntegerType *ITy = llvm::dyn_cast(I.getType())) { + IntegerTypes.push_back(ITy); + const llvm::StoreInst *St = llvm::dyn_cast(&I); + IsVolatile.push_back(St->isVolatile()); + Alignment.push_back(St->getAlignment()); + } + if (llvm::isa(&I)) if (llvm::IntegerType *ITy = llvm::dyn_cast(I.getType())) { IntegerTypes.push_back(ITy); -// llvm::StoreInst St = llvm::dyn_cast(I); -// IsVolatile.push_back(St.isVolatile()); -// Alignment.push_back(St.getAlignment()); + const llvm::LoadInst *St = llvm::dyn_cast(&I); + IsVolatile.push_back(St->isVolatile()); + Alignment.push_back(St->getAlignment()); } + for (llvm::User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); OI != OE; ++OI) incorporateValue(*OI); From 5302cfe062a0d034b697854aa8a322837a06bc5d Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 20 Feb 2015 10:01:23 +0300 Subject: [PATCH 04/10] New align structure --- cbackend.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index 8a26b4dc..723469e8 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -1898,7 +1898,7 @@ void CWriter::writeInstComputationInline(llvm::Instruction &I) { // If this is a non-trivial bool computation, make sure to truncate down to // a 1 bit value. This is important because we want "add i1 x, y" to return // "0" when x and y are true, not "2" for example. - Out << "\n/* Tree\n" << I << "\n*/"; +// Out << "\n/* Tree\n" << I << "\n*/"; bool NeedBoolTrunc = false; if (I.getType() == llvm::Type::getInt1Ty(I.getContext()) && @@ -2795,8 +2795,14 @@ void CWriter::printModuleTypes() { } for (unsigned i = 0, e = IntegerTypes.size(); i != e; ++i) { - llvm::IntegerType *IT = IntegerTypes[i]; - Out << "bitwidth: " << IT->getIntegerBitWidth () << "|" << IsVolatile[i] << "|" << Alignment[i] << ";\n"; + llvm::IntegerType *IT = IntegerTypes[i]; + if (IT->getIntegerBitWidth() <= 128 || Alignment[i] == 0) + continue; + + Out << "typedef struct __attribute__ ((packed, aligned(" << Alignment[i] << "))) {\n "; + printType(Out, IT, false, "data"); + Out << ";\n"; + Out << "} iN_" << IT->getIntegerBitWidth() << "_align_" << Alignment[i] << ";\n"; } Out << '\n'; @@ -4337,21 +4343,26 @@ void CWriter::writeMemoryAccess(llvm::Value *Operand, llvm::Type *OperandType, bool IsUnaligned = Alignment && Alignment < TD->getABITypeAlignment(OperandType); + llvm::IntegerType *ITy = llvm::dyn_cast(OperandType); if (!IsUnaligned) Out << '*'; if (IsVolatile || IsUnaligned) { Out << "(("; - if (IsUnaligned) - Out << "struct __attribute__ ((packed, aligned(" << Alignment << "))) {"; - printType(Out, OperandType, false, IsUnaligned ? "data" : "volatile*"); - if (IsUnaligned) { - Out << "; } "; - if (IsVolatile) Out << "volatile "; - Out << "*"; + if (IsUnaligned && ITy && (ITy->getBitWidth() > 128)) + Out << "iN_" << ITy->getBitWidth() << "_align_" << Alignment << " *)"; + else { + if (IsUnaligned) + Out << "struct __attribute__ ((packed, aligned(" << Alignment << "))) {"; + printType(Out, OperandType, false, IsUnaligned ? "data" : "volatile*"); + if (IsUnaligned) { + Out << "; } "; + if (IsVolatile) Out << "volatile "; + Out << "*"; + } + Out << ")"; } - Out << ")"; } - + writeOperand(Operand); if (IsVolatile || IsUnaligned) { @@ -4362,7 +4373,7 @@ void CWriter::writeMemoryAccess(llvm::Value *Operand, llvm::Type *OperandType, } void CWriter::visitLoadInst(llvm::LoadInst &I) { - Out << "\n/* Tree\n" << I << "\n*/"; +// Out << "\n/* Tree\n" << I << "\n*/"; llvm::VectorType *VT = llvm::dyn_cast(I.getType()); if (VT != NULL) { Out << "__load<" << I.getAlignment() << ">("; From a3bf0b2406c021738f0218aab23f6a61a78535a5 Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 20 Feb 2015 13:08:03 +0300 Subject: [PATCH 05/10] Constructor from string and operator& --- cbackend.cpp | 9 +++-- examples/intrinsics/knc.h | 70 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index 723469e8..aab29aa0 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -1486,8 +1486,11 @@ void CWriter::printConstant(llvm::Constant *CPV, bool Static) { Out << CI->getZExtValue() << 'u'; else if (Ty == llvm::Type::getInt64Ty(CPV->getContext())) Out << CI->getZExtValue() << "ull"; - else if (Ty->getPrimitiveSizeInBits() > 64) + else if (Ty->getPrimitiveSizeInBits() > 64) { + Out << "\""; llvm::dyn_cast(CPV)->printAsOperand(Out, false); + Out << "\""; + } else { Out << "(("; printSimpleType(Out, Ty, false) << ')'; @@ -2343,8 +2346,8 @@ bool CWriter::doInitialization(llvm::Module &M) { Out << "unsigned int putchar(unsigned int);\n"; Out << "int fflush(void *);\n"; Out << "int printf(const unsigned char *, ...);\n"; - Out << "uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t );\n"; - Out << "uint8_t *memset(uint8_t *, uint8_t, uint64_t );\n"; +// Out << "uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t );\n"; +// Out << "uint8_t *memset(uint8_t *, uint8_t, uint64_t );\n"; Out << "void memset_pattern16(void *, const void *, uint64_t );\n"; Out << "}\n\n"; diff --git a/examples/intrinsics/knc.h b/examples/intrinsics/knc.h index aeba353e..588d8509 100644 --- a/examples/intrinsics/knc.h +++ b/examples/intrinsics/knc.h @@ -32,6 +32,7 @@ */ #include // INT_MIN +#include #include #include #include @@ -81,9 +82,9 @@ extern "C" { int puts(unsigned char *); unsigned int putchar(unsigned int); int fflush(void *); - uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t); - uint8_t *memset(uint8_t *, uint8_t, uint64_t); - void memset_pattern16(void *, const void *, uint64_t); +// uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t); +// uint8_t *memset(uint8_t *, uint8_t, uint64_t); +// void memset_pattern16(void *, const void *, uint64_t); } typedef float __vec1_f; @@ -111,6 +112,36 @@ struct iN { num [0] = val; } + iN (const char *val) { + char in[strlen(val)]; + int n = strlen(val); + for (int i = 0; i < n; i++) + in[i] = val[i]; + + char out[num_bits]; + int m = 0; + do { + out[m++] = '0' + (in[n - 1] - '0')%2; + div_2(in, n); + } while (zero(in, n) == 0); + + for (int i = 0; i < m/2; ++i){ + char buf = out[i]; + out[i] = out[m - 1 - i]; + out[m - 1 - i] = buf; + } + out[m++] = '\0'; + + length = num_bits / (sizeof (int) * 8); + num = (int*) calloc (length, sizeof (int)); + + for (int i = 0; i < strlen(out); i++) + num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (out[i] - '0'); + for (int i = strlen(out); i < num_bits; i++) + num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1); + } + + ~iN () { length = 0; free(num); num = NULL;} /* iN operator >> (const int rhs) { @@ -128,6 +159,15 @@ struct iN { res.num[i] = this->num[cells + i]; return res; } + + iN operator & (const iN rhs) { + iN res; + res.length = this->length; + for (int i = 0; i < this->length; i++) + res.num[i] = (this->num[i]) & (rhs.num[i]); + return res; + } + /* iN& operator= (iN rhs) { iN swap; @@ -140,6 +180,30 @@ struct iN { } */ operator uint32_t() { return this->num[0]; } + +private: +void div_2(char in[], int n){//деление числа на 2 + + int p = 0; + for (int i = 0; i < n; ++i){ + + int a = in[i] - '0' + p*10; + in[i] = a/2 + '0'; + p = a%2; + } +} + +int zero(char in[], int n){//проверка на ноль + + int rez = 1; + for (int i = 0; i < n; ++i) + if (in[i] != '0'){ + rez = 0; + break; + } + return rez; +} + }; template From 0644b4a7fd35d55d7b30b0b7d7a19e51404ff14b Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 27 Feb 2015 09:14:55 +0300 Subject: [PATCH 06/10] iN calss was changed --- cbackend.cpp | 5 ++- examples/intrinsics/knc.h | 93 ++++++++++++--------------------------- 2 files changed, 31 insertions(+), 67 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index aab29aa0..8f3aacfd 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -1488,7 +1488,10 @@ void CWriter::printConstant(llvm::Constant *CPV, bool Static) { Out << CI->getZExtValue() << "ull"; else if (Ty->getPrimitiveSizeInBits() > 64) { Out << "\""; - llvm::dyn_cast(CPV)->printAsOperand(Out, false); + const uint64_t *Ptr64 = CPV->getUniqueInteger().getRawData(); + for (int i = 0; i < Ty->getPrimitiveSizeInBits(); i++) { + Out << ((Ptr64[i / (sizeof (uint64_t) * 8)] >> (i % (sizeof (uint64_t) * 8))) & 1); + } Out << "\""; } else { diff --git a/examples/intrinsics/knc.h b/examples/intrinsics/knc.h index 588d8509..eb5af424 100644 --- a/examples/intrinsics/knc.h +++ b/examples/intrinsics/knc.h @@ -98,51 +98,34 @@ struct __vec16_i32; template struct iN { - int length; - int *num; + int num[num_bits / (sizeof (int) * 8)]; - iN () { - length = num_bits / (sizeof (int) * 8); - num = (int*) calloc (length, sizeof (int)); - } + iN () {} iN (int val) { - length = num_bits / (sizeof (int) * 8); - num = (int*) calloc (length, sizeof (int)); num [0] = val; } - iN (const char *val) { - char in[strlen(val)]; - int n = strlen(val); - for (int i = 0; i < n; i++) - in[i] = val[i]; - - char out[num_bits]; - int m = 0; - do { - out[m++] = '0' + (in[n - 1] - '0')%2; - div_2(in, n); - } while (zero(in, n) == 0); - - for (int i = 0; i < m/2; ++i){ - char buf = out[i]; - out[i] = out[m - 1 - i]; - out[m - 1 - i] = buf; - } - out[m++] = '\0'; - - length = num_bits / (sizeof (int) * 8); - num = (int*) calloc (length, sizeof (int)); - - for (int i = 0; i < strlen(out); i++) - num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (out[i] - '0'); - for (int i = strlen(out); i < num_bits; i++) - num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1); + template + iN (T *val) { + int length = num_bits / (sizeof (int) * 8); + for (int i = 0; i < length; i++) + num[i] = val[i]; } - - ~iN () { length = 0; free(num); num = NULL;} + iN (const char *val) { + int length = num_bits / (sizeof (int) * 8); + for (int i = 0; (i < strlen(val) && i < num_bits); i++) + num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); + } +/* + iN (const iN &a) { + int length = num_bits / (sizeof (int) * 8); + for (int i = 0; i < length; i++) + num[i] = a.num[i]; + } +*/ + ~iN () {} /* iN operator >> (const int rhs) { iN res; @@ -154,23 +137,25 @@ struct iN { */ iN operator >> (const iN rhs) { iN res; + int length = num_bits / (sizeof (int) * 8); int cells = rhs.num[0] / (sizeof(int) * 8); - for (int i = 0; i < (this->length - cells); i++) + for (int i = 0; i < (length - cells); i++) res.num[i] = this->num[cells + i]; return res; } - iN operator & (const iN rhs) { + iN operator & (iN rhs) { iN res; - res.length = this->length; - for (int i = 0; i < this->length; i++) + int length = num_bits / (sizeof (int) * 8); + for (int i = 0; i < length; i++) res.num[i] = (this->num[i]) & (rhs.num[i]); return res; } /* - iN& operator= (iN rhs) { + iN& operator = (iN rhs) { iN swap; + int length = num_bits / (sizeof (int) * 8); for (int i = 0; i < length; i++) { swap.num[i] = this->num[i]; this->num[i] = rhs.num[i]; @@ -180,30 +165,6 @@ struct iN { } */ operator uint32_t() { return this->num[0]; } - -private: -void div_2(char in[], int n){//деление числа на 2 - - int p = 0; - for (int i = 0; i < n; ++i){ - - int a = in[i] - '0' + p*10; - in[i] = a/2 + '0'; - p = a%2; - } -} - -int zero(char in[], int n){//проверка на ноль - - int rez = 1; - for (int i = 0; i < n; ++i) - if (in[i] != '0'){ - rez = 0; - break; - } - return rez; -} - }; template From a98bfdf011059235884b3e1a90247e882793f7e8 Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 27 Feb 2015 10:27:53 +0300 Subject: [PATCH 07/10] Some changes to hadle different vector width --- cbackend.cpp | 18 ++++------ examples/intrinsics/generic-16.h | 45 +++++++++++++++++++++++++ examples/intrinsics/knc.h | 57 ++++++-------------------------- examples/intrinsics/sse4.h | 44 ++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 58 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index 8f3aacfd..a9c4c525 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -412,7 +412,7 @@ namespace { // Output all vector constants so they can be accessed with single // vector loads printVectorConstants(F); - + printFunction(F); return false; } @@ -768,11 +768,8 @@ CWriter::printSimpleType(llvm::raw_ostream &Out, llvm::Type *Ty, bool isSigned, return Out << (isSigned?"":"u") << "int32_t " << NameSoFar; else if (NumBits <= 64) return Out << (isSigned?"":"u") << "int64_t "<< NameSoFar; - else if (NumBits <= 128) - return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar; else return Out << "iN<" << NumBits << "> " << NameSoFar; - } case llvm::Type::FloatTyID: return Out << "float " << NameSoFar; case llvm::Type::DoubleTyID: return Out << "double " << NameSoFar; @@ -1904,8 +1901,6 @@ void CWriter::writeInstComputationInline(llvm::Instruction &I) { // If this is a non-trivial bool computation, make sure to truncate down to // a 1 bit value. This is important because we want "add i1 x, y" to return // "0" when x and y are true, not "2" for example. -// Out << "\n/* Tree\n" << I << "\n*/"; - bool NeedBoolTrunc = false; if (I.getType() == llvm::Type::getInt1Ty(I.getContext()) && !llvm::isa(I) && !llvm::isa(I)) @@ -2349,8 +2344,8 @@ bool CWriter::doInitialization(llvm::Module &M) { Out << "unsigned int putchar(unsigned int);\n"; Out << "int fflush(void *);\n"; Out << "int printf(const unsigned char *, ...);\n"; -// Out << "uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t );\n"; -// Out << "uint8_t *memset(uint8_t *, uint8_t, uint64_t );\n"; + Out << "uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t );\n"; + Out << "uint8_t *memset(uint8_t *, uint8_t, uint64_t );\n"; Out << "void memset_pattern16(void *, const void *, uint64_t );\n"; Out << "}\n\n"; @@ -2802,7 +2797,7 @@ void CWriter::printModuleTypes() { for (unsigned i = 0, e = IntegerTypes.size(); i != e; ++i) { llvm::IntegerType *IT = IntegerTypes[i]; - if (IT->getIntegerBitWidth() <= 128 || Alignment[i] == 0) + if (IT->getIntegerBitWidth() <= 64 || Alignment[i] == 0) continue; Out << "typedef struct __attribute__ ((packed, aligned(" << Alignment[i] << "))) {\n "; @@ -4354,7 +4349,7 @@ void CWriter::writeMemoryAccess(llvm::Value *Operand, llvm::Type *OperandType, Out << '*'; if (IsVolatile || IsUnaligned) { Out << "(("; - if (IsUnaligned && ITy && (ITy->getBitWidth() > 128)) + if (IsUnaligned && ITy && (ITy->getBitWidth() > 64)) Out << "iN_" << ITy->getBitWidth() << "_align_" << Alignment << " *)"; else { if (IsUnaligned) @@ -4368,7 +4363,7 @@ void CWriter::writeMemoryAccess(llvm::Value *Operand, llvm::Type *OperandType, Out << ")"; } } - + writeOperand(Operand); if (IsVolatile || IsUnaligned) { @@ -4379,7 +4374,6 @@ void CWriter::writeMemoryAccess(llvm::Value *Operand, llvm::Type *OperandType, } void CWriter::visitLoadInst(llvm::LoadInst &I) { -// Out << "\n/* Tree\n" << I << "\n*/"; llvm::VectorType *VT = llvm::dyn_cast(I.getType()); if (VT != NULL) { Out << "__load<" << I.getAlignment() << ">("; diff --git a/examples/intrinsics/generic-16.h b/examples/intrinsics/generic-16.h index f44c581e..f5bacbb2 100644 --- a/examples/intrinsics/generic-16.h +++ b/examples/intrinsics/generic-16.h @@ -159,6 +159,51 @@ PRE_ALIGN(128) struct __vec16_i64 : public vec16 { v8, v9, v10, v11, v12, v13, v14, v15) { } } POST_ALIGN(128); +template +struct iN { + int num[num_bits / (sizeof (int) * 8)]; + + iN () {} + + iN (const char *val) { + if (val == NULL) + return; + int length = num_bits / (sizeof (int) * 8); + int val_len = 0; + for (val_len = 0; val[val_len]; (val_len)++); + for (int i = 0; (i < val_len && i < num_bits); i++) + num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); + } + + ~iN () {} + + iN operator >> (const iN rhs) { + iN res; + int length = num_bits / (sizeof (int) * 8); + int cells = rhs.num[0] / (sizeof(int) * 8); + for (int i = 0; i < (length - cells); i++) + res.num[i] = this->num[cells + i]; + return res; + } + + iN operator & (iN rhs) { + iN res; + int length = num_bits / (sizeof (int) * 8); + for (int i = 0; i < length; i++) + res.num[i] = (this->num[i]) & (rhs.num[i]); + return res; + } + + operator uint32_t() { return this->num[0]; } +}; + +template +T __cast_bits (T to, __vec16_i32 from) { + for (int i = 0; i < 16; i++) + to.num[i] = ((uint32_t*)(&from))[i] ; + return to; +} + /////////////////////////////////////////////////////////////////////////// // macros... diff --git a/examples/intrinsics/knc.h b/examples/intrinsics/knc.h index eb5af424..907d966d 100644 --- a/examples/intrinsics/knc.h +++ b/examples/intrinsics/knc.h @@ -32,9 +32,7 @@ */ #include // INT_MIN -#include #include -#include #include #include #include @@ -82,9 +80,9 @@ extern "C" { int puts(unsigned char *); unsigned int putchar(unsigned int); int fflush(void *); -// uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t); -// uint8_t *memset(uint8_t *, uint8_t, uint64_t); -// void memset_pattern16(void *, const void *, uint64_t); + uint8_t *memcpy(uint8_t *, uint8_t *, uint64_t); + uint8_t *memset(uint8_t *, uint8_t, uint64_t); + void memset_pattern16(void *, const void *, uint64_t); } typedef float __vec1_f; @@ -101,40 +99,19 @@ struct iN { int num[num_bits / (sizeof (int) * 8)]; iN () {} - - iN (int val) { - num [0] = val; - } - - template - iN (T *val) { - int length = num_bits / (sizeof (int) * 8); - for (int i = 0; i < length; i++) - num[i] = val[i]; - } - + iN (const char *val) { + if (val == NULL) + return; int length = num_bits / (sizeof (int) * 8); - for (int i = 0; (i < strlen(val) && i < num_bits); i++) + int val_len = 0; + for (val_len = 0; val[val_len]; (val_len)++); + for (int i = 0; (i < val_len && i < num_bits); i++) num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); } -/* - iN (const iN &a) { - int length = num_bits / (sizeof (int) * 8); - for (int i = 0; i < length; i++) - num[i] = a.num[i]; - } -*/ + ~iN () {} -/* - iN operator >> (const int rhs) { - iN res; - int cells = rhs / (sizeof(int) * 8); - for (int i = 0; i < (this->length - cells); i++) - res.num[i] = this->num[cells + i]; - return res; - } -*/ + iN operator >> (const iN rhs) { iN res; int length = num_bits / (sizeof (int) * 8); @@ -152,18 +129,6 @@ struct iN { return res; } -/* - iN& operator = (iN rhs) { - iN swap; - int length = num_bits / (sizeof (int) * 8); - for (int i = 0; i < length; i++) { - swap.num[i] = this->num[i]; - this->num[i] = rhs.num[i]; - rhs.num[i] = swap.num[i]; - } - return *this; - } -*/ operator uint32_t() { return this->num[0]; } }; diff --git a/examples/intrinsics/sse4.h b/examples/intrinsics/sse4.h index 765a931f..56483bf3 100644 --- a/examples/intrinsics/sse4.h +++ b/examples/intrinsics/sse4.h @@ -179,6 +179,50 @@ FORCEINLINE __vec4_i64::__vec4_i64(__vec4_d vd) { v[1] = _mm_castpd_si128(vd.v[1]); } +template +struct iN { + int num[num_bits / (sizeof (int) * 8)]; + + iN () {} + + iN (const char *val) { + if (val == NULL) + return; + int length = num_bits / (sizeof (int) * 8); + int val_len = 0; + for (val_len = 0; val[val_len]; (val_len)++); + for (int i = 0; (i < val_len && i < num_bits); i++) + num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); + } + + ~iN () {} + + iN operator >> (const iN rhs) { + iN res; + int length = num_bits / (sizeof (int) * 8); + int cells = rhs.num[0] / (sizeof(int) * 8); + for (int i = 0; i < (length - cells); i++) + res.num[i] = this->num[cells + i]; + return res; + } + + iN operator & (iN rhs) { + iN res; + int length = num_bits / (sizeof (int) * 8); + for (int i = 0; i < length; i++) + res.num[i] = (this->num[i]) & (rhs.num[i]); + return res; + } + + operator uint32_t() { return this->num[0]; } +}; + +template +T __cast_bits (T to, __vec4_i32 from) { + for (int i = 0; i < 16; i++) + to.num[i] = ((uint32_t*)(&from))[i] ; + return to; +} /////////////////////////////////////////////////////////////////////////// // SSE helpers / utility functions From 3718abc3d2e7f66caabec1142c00a65bbb17d642 Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 27 Feb 2015 12:30:04 +0300 Subject: [PATCH 08/10] iN class was moved to cbackend --- cbackend.cpp | 54 ++++++++++++++++++++++++++++++++ examples/intrinsics/generic-16.h | 45 -------------------------- examples/intrinsics/knc.h | 45 -------------------------- examples/intrinsics/sse4.h | 45 -------------------------- 4 files changed, 54 insertions(+), 135 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index a9c4c525..81a70217 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -2752,6 +2752,59 @@ void CWriter::printModuleTypes() { Out << " double Double;\n"; Out << "} llvmBitCastUnion;\n"; + Out << "\n/* It is special class, designed for operations with long int.*/ \n"; + Out << "template \n"; + Out << "struct iN { \n"; + Out << " int num[num_bits / (sizeof (int) * 8)]; \n"; + Out << " \n"; + Out << " iN () {} \n"; + Out << " \n"; + Out << " iN (const char *val) { \n"; + Out << " if (val == NULL) \n"; + Out << " return; \n"; + Out << " int length = num_bits / (sizeof (int) * 8); \n"; + Out << " int val_len = 0; \n"; + Out << " for (val_len = 0; val[val_len]; (val_len)++); \n"; + Out << " for (int i = 0; (i < val_len && i < num_bits); i++) \n"; + Out << " num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); \n"; + Out << " } \n"; + Out << " \n"; + Out << " ~iN () {} \n"; + Out << " \n"; + Out << " iN operator >> (const iN rhs) { \n"; + Out << " iN res; \n"; + Out << " int length = num_bits / (sizeof (int) * 8); \n"; + Out << " int cells_shift = rhs.num[0] / (sizeof(int) * 8); \n"; + Out << " int small_shift = rhs.num[0] % (sizeof(int) * 8); \n"; + Out << " for (int i = 0; i < (length - cells_shift); i++) \n"; + Out << " res.num[i] = this->num[cells_shift + i]; \n"; + Out << " for (int i = 0; i < length - 1; i++) { \n"; + Out << " res.num[i] = this->num[i] >> small_shift; \n"; + Out << " res.num[i] = ((this->num[i + 1] << ((sizeof(int) * 8) - small_shift))) | res.num[i];\n"; + Out << " } \n"; + Out << " res.num[length - 1] = res.num[length - 1] >> small_shift; \n"; + Out << " return res; \n"; + Out << " } \n"; + Out << " \n"; + Out << " iN operator & (iN rhs) { \n"; + Out << " iN res; \n"; + Out << " int length = num_bits / (sizeof (int) * 8); \n"; + Out << " for (int i = 0; i < length; i++) \n"; + Out << " res.num[i] = (this->num[i]) & (rhs.num[i]); \n"; + Out << " return res; \n"; + Out << " } \n"; + Out << " \n"; + Out << " operator uint32_t() { return this->num[0]; } \n"; + Out << "}; \n"; + Out << " \n"; + Out << "template \n"; + Out << "T __cast_bits (T to, __vec" << vectorWidth << "_i32 from) { \n"; + Out << " for (int i = 0; i < 16; i++) \n"; + Out << " to.num[i] = ((uint32_t*)(&from))[i]; \n"; + Out << " return to; \n"; + Out << "} \n"; + Out << "\n"; + // Get all of the struct types used in the module. std::vector StructTypes; llvm::TypeFinder typeFinder; @@ -2801,6 +2854,7 @@ void CWriter::printModuleTypes() { continue; Out << "typedef struct __attribute__ ((packed, aligned(" << Alignment[i] << "))) {\n "; + IsVolatile[i] ? Out << " volatile " : Out << " "; printType(Out, IT, false, "data"); Out << ";\n"; Out << "} iN_" << IT->getIntegerBitWidth() << "_align_" << Alignment[i] << ";\n"; diff --git a/examples/intrinsics/generic-16.h b/examples/intrinsics/generic-16.h index f5bacbb2..f44c581e 100644 --- a/examples/intrinsics/generic-16.h +++ b/examples/intrinsics/generic-16.h @@ -159,51 +159,6 @@ PRE_ALIGN(128) struct __vec16_i64 : public vec16 { v8, v9, v10, v11, v12, v13, v14, v15) { } } POST_ALIGN(128); -template -struct iN { - int num[num_bits / (sizeof (int) * 8)]; - - iN () {} - - iN (const char *val) { - if (val == NULL) - return; - int length = num_bits / (sizeof (int) * 8); - int val_len = 0; - for (val_len = 0; val[val_len]; (val_len)++); - for (int i = 0; (i < val_len && i < num_bits); i++) - num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); - } - - ~iN () {} - - iN operator >> (const iN rhs) { - iN res; - int length = num_bits / (sizeof (int) * 8); - int cells = rhs.num[0] / (sizeof(int) * 8); - for (int i = 0; i < (length - cells); i++) - res.num[i] = this->num[cells + i]; - return res; - } - - iN operator & (iN rhs) { - iN res; - int length = num_bits / (sizeof (int) * 8); - for (int i = 0; i < length; i++) - res.num[i] = (this->num[i]) & (rhs.num[i]); - return res; - } - - operator uint32_t() { return this->num[0]; } -}; - -template -T __cast_bits (T to, __vec16_i32 from) { - for (int i = 0; i < 16; i++) - to.num[i] = ((uint32_t*)(&from))[i] ; - return to; -} - /////////////////////////////////////////////////////////////////////////// // macros... diff --git a/examples/intrinsics/knc.h b/examples/intrinsics/knc.h index 907d966d..a0d072fa 100644 --- a/examples/intrinsics/knc.h +++ b/examples/intrinsics/knc.h @@ -94,51 +94,6 @@ typedef int64_t __vec1_i64; struct __vec16_i32; -template -struct iN { - int num[num_bits / (sizeof (int) * 8)]; - - iN () {} - - iN (const char *val) { - if (val == NULL) - return; - int length = num_bits / (sizeof (int) * 8); - int val_len = 0; - for (val_len = 0; val[val_len]; (val_len)++); - for (int i = 0; (i < val_len && i < num_bits); i++) - num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); - } - - ~iN () {} - - iN operator >> (const iN rhs) { - iN res; - int length = num_bits / (sizeof (int) * 8); - int cells = rhs.num[0] / (sizeof(int) * 8); - for (int i = 0; i < (length - cells); i++) - res.num[i] = this->num[cells + i]; - return res; - } - - iN operator & (iN rhs) { - iN res; - int length = num_bits / (sizeof (int) * 8); - for (int i = 0; i < length; i++) - res.num[i] = (this->num[i]) & (rhs.num[i]); - return res; - } - - operator uint32_t() { return this->num[0]; } -}; - -template -T __cast_bits (T to, __vec16_i32 from) { - for (int i = 0; i < 16; i++) - to.num[i] = from[i] ; - return to; -} - #if 1 /* (iw) actually, this *SHOULD* be the right implementation for a vec16_i1: this one is a class that can have a constructor (which diff --git a/examples/intrinsics/sse4.h b/examples/intrinsics/sse4.h index 56483bf3..7ea94a1f 100644 --- a/examples/intrinsics/sse4.h +++ b/examples/intrinsics/sse4.h @@ -179,51 +179,6 @@ FORCEINLINE __vec4_i64::__vec4_i64(__vec4_d vd) { v[1] = _mm_castpd_si128(vd.v[1]); } -template -struct iN { - int num[num_bits / (sizeof (int) * 8)]; - - iN () {} - - iN (const char *val) { - if (val == NULL) - return; - int length = num_bits / (sizeof (int) * 8); - int val_len = 0; - for (val_len = 0; val[val_len]; (val_len)++); - for (int i = 0; (i < val_len && i < num_bits); i++) - num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); - } - - ~iN () {} - - iN operator >> (const iN rhs) { - iN res; - int length = num_bits / (sizeof (int) * 8); - int cells = rhs.num[0] / (sizeof(int) * 8); - for (int i = 0; i < (length - cells); i++) - res.num[i] = this->num[cells + i]; - return res; - } - - iN operator & (iN rhs) { - iN res; - int length = num_bits / (sizeof (int) * 8); - for (int i = 0; i < length; i++) - res.num[i] = (this->num[i]) & (rhs.num[i]); - return res; - } - - operator uint32_t() { return this->num[0]; } -}; - -template -T __cast_bits (T to, __vec4_i32 from) { - for (int i = 0; i < 16; i++) - to.num[i] = ((uint32_t*)(&from))[i] ; - return to; -} - /////////////////////////////////////////////////////////////////////////// // SSE helpers / utility functions From 4c629d0a7c825de8411b70b488d1e3c73f05305a Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 27 Feb 2015 12:35:31 +0300 Subject: [PATCH 09/10] Small codestyle changes --- cbackend.cpp | 7 ++++--- examples/intrinsics/sse4.h | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index 81a70217..9e5110cd 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -307,8 +307,9 @@ namespace { }; } // end anonymous namespace -static void findUsedArrayTypes(const llvm::Module *m, std::vector &t, std::vector &i, - std::vector &IsVolatile, std::vector &Alignment) { +static void findUsedArrayAndLongIntTypes(const llvm::Module *m, std::vector &t, + std::vector &i, std::vector &IsVolatile, + std::vector &Alignment) { TypeFinder(t, i, IsVolatile, Alignment).run(*m); } @@ -2819,7 +2820,7 @@ void CWriter::printModuleTypes() { std::vector IsVolatile; std::vector Alignment; - findUsedArrayTypes(TheModule, ArrayTypes, IntegerTypes, IsVolatile, Alignment); + findUsedArrayAndLongIntTypes(TheModule, ArrayTypes, IntegerTypes, IsVolatile, Alignment); if (StructTypes.empty() && ArrayTypes.empty()) return; diff --git a/examples/intrinsics/sse4.h b/examples/intrinsics/sse4.h index 7ea94a1f..765a931f 100644 --- a/examples/intrinsics/sse4.h +++ b/examples/intrinsics/sse4.h @@ -179,6 +179,7 @@ FORCEINLINE __vec4_i64::__vec4_i64(__vec4_d vd) { v[1] = _mm_castpd_si128(vd.v[1]); } + /////////////////////////////////////////////////////////////////////////// // SSE helpers / utility functions From 19d18b6e4e0709f48b6b840dbc2092f8716f828f Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 27 Feb 2015 16:02:55 +0300 Subject: [PATCH 10/10] Some changes was made to support older llvm versions. --- cbackend.cpp | 115 +++++++++++++++++-------------- examples/intrinsics/generic-16.h | 19 +++++ examples/intrinsics/sse4.h | 20 ++++++ 3 files changed, 103 insertions(+), 51 deletions(-) diff --git a/cbackend.cpp b/cbackend.cpp index 9e5110cd..cc93502d 100644 --- a/cbackend.cpp +++ b/cbackend.cpp @@ -2753,57 +2753,70 @@ void CWriter::printModuleTypes() { Out << " double Double;\n"; Out << "} llvmBitCastUnion;\n"; - Out << "\n/* It is special class, designed for operations with long int.*/ \n"; - Out << "template \n"; - Out << "struct iN { \n"; - Out << " int num[num_bits / (sizeof (int) * 8)]; \n"; - Out << " \n"; - Out << " iN () {} \n"; - Out << " \n"; - Out << " iN (const char *val) { \n"; - Out << " if (val == NULL) \n"; - Out << " return; \n"; - Out << " int length = num_bits / (sizeof (int) * 8); \n"; - Out << " int val_len = 0; \n"; - Out << " for (val_len = 0; val[val_len]; (val_len)++); \n"; - Out << " for (int i = 0; (i < val_len && i < num_bits); i++) \n"; - Out << " num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); \n"; - Out << " } \n"; - Out << " \n"; - Out << " ~iN () {} \n"; - Out << " \n"; - Out << " iN operator >> (const iN rhs) { \n"; - Out << " iN res; \n"; - Out << " int length = num_bits / (sizeof (int) * 8); \n"; - Out << " int cells_shift = rhs.num[0] / (sizeof(int) * 8); \n"; - Out << " int small_shift = rhs.num[0] % (sizeof(int) * 8); \n"; - Out << " for (int i = 0; i < (length - cells_shift); i++) \n"; - Out << " res.num[i] = this->num[cells_shift + i]; \n"; - Out << " for (int i = 0; i < length - 1; i++) { \n"; - Out << " res.num[i] = this->num[i] >> small_shift; \n"; - Out << " res.num[i] = ((this->num[i + 1] << ((sizeof(int) * 8) - small_shift))) | res.num[i];\n"; - Out << " } \n"; - Out << " res.num[length - 1] = res.num[length - 1] >> small_shift; \n"; - Out << " return res; \n"; - Out << " } \n"; - Out << " \n"; - Out << " iN operator & (iN rhs) { \n"; - Out << " iN res; \n"; - Out << " int length = num_bits / (sizeof (int) * 8); \n"; - Out << " for (int i = 0; i < length; i++) \n"; - Out << " res.num[i] = (this->num[i]) & (rhs.num[i]); \n"; - Out << " return res; \n"; - Out << " } \n"; - Out << " \n"; - Out << " operator uint32_t() { return this->num[0]; } \n"; - Out << "}; \n"; - Out << " \n"; - Out << "template \n"; - Out << "T __cast_bits (T to, __vec" << vectorWidth << "_i32 from) { \n"; - Out << " for (int i = 0; i < 16; i++) \n"; - Out << " to.num[i] = ((uint32_t*)(&from))[i]; \n"; - Out << " return to; \n"; - Out << "} \n"; + Out << "\n/* This is special class, designed for operations with long int.*/ \n"; + Out << "template \n"; + Out << "struct iN { \n"; + Out << " int num[num_bits / (sizeof (int) * 8)]; \n"; + Out << " \n"; + Out << " iN () {} \n"; + Out << " \n"; + Out << " iN (const char *val) { \n"; + Out << " if (val == NULL) \n"; + Out << " return; \n"; + Out << " int length = num_bits / (sizeof (int) * 8); \n"; + Out << " int val_len = 0; \n"; + Out << " for (val_len = 0; val[val_len]; (val_len)++); \n"; + Out << " for (int i = 0; (i < val_len && i < num_bits); i++) \n"; + Out << " num[i / (sizeof (int) * 8)] = (num[i / (sizeof (int) * 8)] << 1) | (val[i] - '0'); \n"; + Out << " } \n"; + Out << " \n"; + Out << " ~iN () {} \n"; + Out << " \n"; + Out << " iN operator >> (const iN rhs) { \n"; + Out << " iN res; \n"; + Out << " int length = num_bits / (sizeof (int) * 8); \n"; + Out << " int cells_shift = rhs.num[0] / (sizeof(int) * 8); \n"; + Out << " int small_shift = rhs.num[0] % (sizeof(int) * 8); \n"; + Out << " for (int i = 0; i < (length - cells_shift); i++) \n"; + Out << " res.num[i] = this->num[cells_shift + i]; \n"; + Out << " for (int i = 0; i < length - 1; i++) { \n"; + Out << " res.num[i] = this->num[i] >> small_shift; \n"; + Out << " res.num[i] = ((this->num[i + 1] << ((sizeof(int) * 8) - small_shift))) | res.num[i];\n"; + Out << " } \n"; + Out << " res.num[length - 1] = res.num[length - 1] >> small_shift; \n"; + Out << " return res; \n"; + Out << " } \n"; + Out << " \n"; + Out << " iN operator & (iN rhs) { \n"; + Out << " iN res; \n"; + Out << " int length = num_bits / (sizeof (int) * 8); \n"; + Out << " for (int i = 0; i < length; i++) \n"; + Out << " res.num[i] = (this->num[i]) & (rhs.num[i]); \n"; + Out << " return res; \n"; + Out << " } \n"; + Out << " \n"; + Out << " operator uint32_t() { return this->num[0]; } \n"; + Out << " \n"; + Out << " template \n"; + Out << " friend iN __cast_bits(iN to, T from) { \n"; + Out << " for (int i = 0; i <" << vectorWidth << "; i++) \n"; + Out << " to.num[i] = ((int*)(&from))[i]; \n"; + Out << " return to; \n"; + Out << " } \n"; + Out << " \n"; + Out << " template \n"; + Out << " friend T __cast_bits(T to, iN from) { \n"; + Out << " for (int i = 0; i <" << vectorWidth << "; i++) \n"; + Out << " ((int*)(&to))[i] = from.num[i]; \n"; + Out << " return to; \n"; + Out << " } \n"; + Out << " \n"; + Out << " template \n"; + Out << " friend void __store(T *p, iN val) { \n"; + Out << " for (int i = 0; i <" << vectorWidth << "; i++) \n"; + Out << " ((int*)p)[i] = val.num[i]; \n"; + Out << " } \n"; + Out << "}; \n"; Out << "\n"; // Get all of the struct types used in the module. diff --git a/examples/intrinsics/generic-16.h b/examples/intrinsics/generic-16.h index f44c581e..5a338e54 100644 --- a/examples/intrinsics/generic-16.h +++ b/examples/intrinsics/generic-16.h @@ -977,6 +977,25 @@ CAST_BITS_SCALAR(int64_t, double) CAST_BITS_SCALAR(double, uint64_t) CAST_BITS_SCALAR(double, int64_t) +#define CAST_BITS_TRIVIAL(TYPE) \ +static FORCEINLINE TYPE __cast_bits(TYPE, TYPE v) { return v; } + +CAST_BITS_TRIVIAL(float) +CAST_BITS_TRIVIAL(double) +CAST_BITS_TRIVIAL(int8_t) +CAST_BITS_TRIVIAL(uint8_t) +CAST_BITS_TRIVIAL(int16_t) +CAST_BITS_TRIVIAL(uint16_t) +CAST_BITS_TRIVIAL(int32_t) +CAST_BITS_TRIVIAL(uint32_t) +CAST_BITS_TRIVIAL(int64_t) +CAST_BITS_TRIVIAL(uint64_t) +CAST_BITS_TRIVIAL(__vec16_f) +CAST_BITS_TRIVIAL(__vec16_d) +CAST_BITS_TRIVIAL(__vec16_i8) +CAST_BITS_TRIVIAL(__vec16_i16) +CAST_BITS_TRIVIAL(__vec16_i32) +CAST_BITS_TRIVIAL(__vec16_i64) /////////////////////////////////////////////////////////////////////////// // various math functions diff --git a/examples/intrinsics/sse4.h b/examples/intrinsics/sse4.h index 765a931f..c15eb621 100644 --- a/examples/intrinsics/sse4.h +++ b/examples/intrinsics/sse4.h @@ -295,6 +295,26 @@ CAST_BITS_SCALAR(int64_t, double) CAST_BITS_SCALAR(double, uint64_t) CAST_BITS_SCALAR(double, int64_t) +#define CAST_BITS_TRIVIAL(TYPE) \ +static FORCEINLINE TYPE __cast_bits(TYPE, TYPE v) { return v; } + +CAST_BITS_TRIVIAL(float) +CAST_BITS_TRIVIAL(double) +CAST_BITS_TRIVIAL(int8_t) +CAST_BITS_TRIVIAL(uint8_t) +CAST_BITS_TRIVIAL(int16_t) +CAST_BITS_TRIVIAL(uint16_t) +CAST_BITS_TRIVIAL(int32_t) +CAST_BITS_TRIVIAL(uint32_t) +CAST_BITS_TRIVIAL(int64_t) +CAST_BITS_TRIVIAL(uint64_t) +CAST_BITS_TRIVIAL(__vec4_f) +CAST_BITS_TRIVIAL(__vec4_d) +CAST_BITS_TRIVIAL(__vec4_i8) +CAST_BITS_TRIVIAL(__vec4_i16) +CAST_BITS_TRIVIAL(__vec4_i32) +CAST_BITS_TRIVIAL(__vec4_i64) + #define CMP_AND_MASK_ONE(FUNC, TYPE) \ static FORCEINLINE __vec4_i1 FUNC##_and_mask(TYPE a, TYPE b, __vec4_i1 m) { \ return __and(FUNC(a, b), m); \