| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- #include <Assembly.h>
- #include <functional>
- #include <iostream>
- #include <malloc.h>
- #include <windows.h>
- #include <Zeit.h>
- using namespace Framework;
- using namespace Assembly;
- typedef int (*valF)(void*);
- typedef int (*compF)();
- template<typename T> 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<int()> compileStdF() = 0;
- compF compileToAssembly()
- {
- internalCompileAssembly();
- block.optimize();
- return block.compileToFunction<compF>();
- }
- virtual AssemblyBlock& internalCompileAssembly() = 0;
- inline AssemblyBlock& getBlock()
- {
- return block;
- }
- };
- class RandVal : public Val<RandVal>
- {
- public:
- RandVal()
- : Val(this)
- {}
- int getValue() override
- {
- return rand();
- }
- int getValue2()
- {
- return rand();
- }
- valF compileFP() override
- {
- return [](void* v) { return rand(); };
- }
- std::function<int()> compileStdF() override
- {
- return []() { return rand(); };
- }
- AssemblyBlock& internalCompileAssembly() override
- {
- block.addCall(rand);
- return block;
- }
- };
- class ConstVal : public Val<ConstVal>
- {
- 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<int()> compileStdF() override
- {
- const int& value = this->value;
- return [value]() { return value; };
- }
- AssemblyBlock& internalCompileAssembly() override
- {
- block.addLoadValue(&value, RAX);
- return block;
- }
- };
- template<typename T1, typename T2> class AdditionVal
- : public Val<AdditionVal<T1, T2>>
- {
- private:
- Val<T1>* a;
- Val<T2>* b;
- valF af;
- valF bf;
- std::function<int()> saf;
- std::function<int()> sbf;
- public:
- AdditionVal(Val<T1>* a, Val<T2>* b)
- : Val<AdditionVal<T1, T2>>(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<int()> compileStdF() override
- {
- const std::function<int()>& aFunc = saf;
- const std::function<int()>& 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<typename T> __declspec(noinline) int get(T* t)
- {
- return t->getValueInline();
- }
- int main()
- {
- RandVal* r = new RandVal();
- auto test
- = new AdditionVal<AdditionVal<AdditionVal<RandVal, ConstVal>, ConstVal>,
- AdditionVal<ConstVal, ConstVal>>(
- new AdditionVal<AdditionVal<RandVal, ConstVal>, ConstVal>(
- new AdditionVal<RandVal, ConstVal>(r, new ConstVal(2)),
- new ConstVal(3)),
- new AdditionVal<ConstVal, ConstVal>(
- 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<compF>();
- 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;
- }
|