#include #include #include #include #include #include using namespace Framework; using namespace Assembly; typedef int (*valF)(void*); typedef int (*compF)(); template class Val { protected: AssemblyBlock block; T* self; public: Val(T* self) : self(self) {} inline int getValueInline() { return self->getValue2(); } virtual int getValue() = 0; virtual valF compileFP() = 0; virtual std::function compileStdF() = 0; compF compileToAssembly() { internalCompileAssembly(); block.optimize(); return block.compileToFunction(); } virtual AssemblyBlock& internalCompileAssembly() = 0; inline AssemblyBlock& getBlock() { return block; } }; class RandVal : public Val { public: RandVal() : Val(this) {} int getValue() override { return rand(); } int getValue2() { return rand(); } valF compileFP() override { return [](void* v) { return rand(); }; } std::function compileStdF() override { return []() { return rand(); }; } AssemblyBlock& internalCompileAssembly() override { block.addCall(rand); return block; } }; class ConstVal : public Val { private: int value; public: ConstVal(int value) : Val(this), value(value) {} int getValue() override { return value; } inline int getValue2() { return value; } valF compileFP() override { return [](void* v) { return ((ConstVal*)v)->value; }; } std::function compileStdF() override { const int& value = this->value; return [value]() { return value; }; } AssemblyBlock& internalCompileAssembly() override { block.addLoadValue(&value, RAX); return block; } }; template class AdditionVal : public Val> { private: Val* a; Val* b; valF af; valF bf; std::function saf; std::function sbf; public: AdditionVal(Val* a, Val* b) : Val>(this), a(a), b(b), af(a->compileFP()), bf(b->compileFP()), saf(a->compileStdF()), sbf(b->compileStdF()) {} int getValue() override { return a->getValue() + b->getValue(); } inline int getValue2() { return a->getValueInline() + b->getValueInline(); } valF compileFP() override { return [](void* v) { AdditionVal* av = (AdditionVal*)v; return av->af(av->a) + av->bf(av->b); }; } std::function compileStdF() override { const std::function& aFunc = saf; const std::function& bFunc = sbf; return [aFunc, bFunc]() { return aFunc() + bFunc(); }; } AssemblyBlock& internalCompileAssembly() override { GPRegister result = RAX; GPRegister result2 = RAX; FPRegister resultFP; this->getBlock().addBlock( &a->internalCompileAssembly(), {}, {}, &result, &resultFP); this->getBlock().addBlock( &b->internalCompileAssembly(), {result}, {}, &result2, &resultFP); this->getBlock().addInstruction(new Instruction(ADD, {new GPRegisterArgument(result, LOWER32), new GPRegisterArgument(result2, LOWER32)})); if (result != RAX) { this->getBlock().addMoveValue(result, RAX, LOWER32); } return this->getBlock(); } }; extern "C" { extern int getVal(void*); } template __declspec(noinline) int get(T* t) { return t->getValueInline(); } int main() { RandVal* r = new RandVal(); auto test = new AdditionVal, ConstVal>, AdditionVal>( new AdditionVal, ConstVal>( new AdditionVal(r, new ConstVal(2)), new ConstVal(3)), new AdditionVal( new ConstVal(4), new ConstVal(5))); ZeitMesser zeitMesser; srand(0); zeitMesser.messungStart(); __int64 res = 0; for (int i = 0; i < 100000000; i++) { res += get(test); } zeitMesser.messungEnde(); std::cout << "inlined Time: " << zeitMesser.getSekunden() << "s" << " result: " << res << std::endl; srand(0); zeitMesser.messungStart(); res = 0; for (int i = 0; i < 100000000; i++) { res += test->getValue(); } zeitMesser.messungEnde(); std::cout << "getValue() Time: " << zeitMesser.getSekunden() << "s" << " result: " << res << std::endl; res = 0; srand(0); auto val = test->compileFP(); zeitMesser.messungStart(); for (int i = 0; i < 100000000; i++) { res += val(test); } zeitMesser.messungEnde(); std::cout << "compile() Time: " << zeitMesser.getSekunden() << "s" << " result: " << res << std::endl; res = 0; auto stdf = test->compileStdF(); srand(0); zeitMesser.messungStart(); for (int i = 0; i < 100000000; i++) { res += stdf(); } zeitMesser.messungEnde(); std::cout << "compileStdF() Time: " << zeitMesser.getSekunden() << "s" << " result: " << res << std::endl; res = 0; auto assembly = test->compileToAssembly(); srand(0); zeitMesser.messungStart(); for (int i = 0; i < 100000000; i++) { res += assembly(); } zeitMesser.messungEnde(); std::cout << "compileToAssembly() Time: " << zeitMesser.getSekunden() << "s" << " result: " << res << std::endl; res = 0; int i2 = 2; int i3 = 3; int i4 = 4; int i5 = 5; AssemblyBlock fastest; fastest.addMoveValue(RCX, 2); fastest.addMoveValue(RDX, 3); fastest.addMoveValue(R8, 4); fastest.addMoveValue(R9, 5); fastest.addCall(rand); fastest.addInstruction(new Instruction(ADD, {new GPRegisterArgument(RAX, LOWER32), new GPRegisterArgument(RCX, LOWER32)})); fastest.addInstruction(new Instruction(ADD, {new GPRegisterArgument(RAX, LOWER32), new GPRegisterArgument(RDX, LOWER32)})); fastest.addInstruction(new Instruction(ADD, {new GPRegisterArgument(RAX, LOWER32), new GPRegisterArgument(R8, LOWER32)})); fastest.addInstruction(new Instruction(ADD, {new GPRegisterArgument(RAX, LOWER32), new GPRegisterArgument(R9, LOWER32)})); auto f = fastest.compileToFunction(); zeitMesser.messungStart(); srand(0); for (int i = 0; i < 100000000; i++) { res += assembly(); } zeitMesser.messungEnde(); srand(0); std::cout << "fastest Time: " << zeitMesser.getSekunden() << "s" << " result: " << res << std::endl; res = 0; zeitMesser.messungStart(); for (int i = 0; i < 100000000; i++) { res += getVal(rand); } zeitMesser.messungEnde(); std::cout << "fastest Time: " << zeitMesser.getSekunden() << "s" << " result: " << res << std::endl; }