diff --git a/fvtest/jitbuildertest/ControlFlowTest.cpp b/fvtest/jitbuildertest/ControlFlowTest.cpp new file mode 100644 index 00000000000..f80ecf53115 --- /dev/null +++ b/fvtest/jitbuildertest/ControlFlowTest.cpp @@ -0,0 +1,45 @@ +/******************************************************************************* + * + * (c) Copyright IBM Corp. 2017, 2017 + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 and + * Apache License v2.0 which accompanies this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * The Apache License v2.0 is available at + * http://www.opensource.org/licenses/apache2.0.php + * + * Contributors: + * Multiple authors (IBM Corp.) - initial implementation and documentation + ******************************************************************************/ + +#include "JBTestUtil.hpp" + +#include "ilgen/BytecodeBuilder.hpp" + +typedef void (*DoubleReturnFunction)(void); + +DEFINE_BUILDER( DoubleReturn, + NoType ) + { + auto firstBuilder = OrphanBytecodeBuilder(0, (char *)"return"); + AppendBuilder(firstBuilder); + firstBuilder->Return(); + + auto secondBuilder = OrphanBytecodeBuilder(1, (char *)"return"); // should be ignored and cleaned up + secondBuilder->Return(); + + return true; + } + +class ControlfFlowTest : public JitBuilderTest {}; + +TEST_F(ControlfFlowTest, DoubleReturnTest) + { + DoubleReturnFunction doubleReturn; + ASSERT_COMPILE(TR::TypeDictionary, DoubleReturn, doubleReturn); + ASSERT_NO_FATAL_FAILURE(doubleReturn()); + } diff --git a/fvtest/jitbuildertest/Makefile b/fvtest/jitbuildertest/Makefile index 35d9cea51d5..6db0baf8b2e 100644 --- a/fvtest/jitbuildertest/Makefile +++ b/fvtest/jitbuildertest/Makefile @@ -27,7 +27,9 @@ OBJECTS := \ selftest \ UnionTest \ FieldAddressTest \ - AnonymousTest + AnonymousTest \ + ControlFlowTest \ + WorklistTest OBJECTS := $(addsuffix $(OBJEXT),$(OBJECTS)) diff --git a/fvtest/jitbuildertest/WorklistTest.cpp b/fvtest/jitbuildertest/WorklistTest.cpp new file mode 100644 index 00000000000..15780382094 --- /dev/null +++ b/fvtest/jitbuildertest/WorklistTest.cpp @@ -0,0 +1,277 @@ +/******************************************************************************* + * + * (c) Copyright IBM Corp. 2017, 2017 + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 and + * Apache License v2.0 which accompanies this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * The Apache License v2.0 is available at + * http://www.opensource.org/licenses/apache2.0.php + * + * Contributors: + * Multiple authors (IBM Corp.) - initial implementation and documentation + ******************************************************************************/ + +#include "JBTestUtil.hpp" + +#include "ilgen/BytecodeBuilder.hpp" +#include "ilgen/VirtualMachineState.hpp" + +#define EXPECT_BCIEQ(expected_index, actual_index) do {\ + EXPECT_EQ((expected_index), (actual_index)) << "Unexpected bytecode index (implies bytecode was either missed or erroneously added in worklist)."; \ + } while (0) + +#define REPORT_VMSTATE(b,s) + +// BC0: r = p; +// BC1: r++; +// if (r > 10) goto BC3; +// BC2: if (r > 5) goto BC5; +// BC4: if (r < 3) goto BC1; // loop back +// BC9: return 9; +// +// BC5: if (r < 8) goto BC11; +// BC17: return 17; +// +// BC7: if (r < 17) goto BC1; // loop back +// BC8: return 8; +// +// +// BC3: if (r > 15) goto BC7; +// BC6: if (r > 12) goto BC13; +// BC16: return 16; + +// BC7: return 7; +// BC11: return 11; +// BC13: return 13; + +// no BC10, BC12, BC14, BC15, BC18, BC19 + +int32_t +computeExpectedResult(int32_t p) + { + // BC0 + int32_t r = p; +BC1: + r++; + if (r > 10) + { + // BC3 + if (r > 15) + { + // BC7 + if (r < 17) + goto BC1; + else + return 8; // BC8 + } + else + { + // BC6 + if (r > 12) + return 13; // BC13 + else + return 16; // BC16 + } + } + else + { + // BC2 + if (r > 5) + { + // BC5 + if (r < 8) + return 11; // BC11 + else + return 17; // BC17 + } + else + { + // BC4 + if (r < 3) + goto BC1; + else + return 9; // BC9 + } + } + } + +typedef int32_t (*WorklistTestMethodFunction)(int32_t); + +DEFINE_BUILDER( WorklistTestMethod, + Int32, + PARAM("path", Int32) ) + { + const char *bcName[20] = { + "bc0", "bc1", "bc2", "bc3", "bc4", "bc5", "bc6", "bc7", "bc8", "bc9", + "bc10", "bc11", "bc12", "bc13", "bc14", "bc15", "bc16", "bc17", "bc18", "bc19" }; + + TR::BytecodeBuilder *builders[20]; + for (int32_t i=0;i < 20;i++) + builders[i] = OrphanBytecodeBuilder(i, (char *)bcName[i]); + + OMR::VirtualMachineState *vmState = new OMR::VirtualMachineState(); + setVMState(vmState); + + Store("result", + Load("path")); + + // should add 0 to the worklist + AppendBuilder(builders[0]); + + TR::BytecodeBuilder *b; + + // BCI 0 + int32_t bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(0, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->AddFallThroughBuilder(builders[1]); + + // BCI 1 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(1, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->Store("result", + b-> Add( + b-> Load("result"), + b-> ConstInt32(1))); + b->IfCmpGreaterThan(builders[3], + b-> Load("result"), + b-> ConstInt32(10)); + b->AddFallThroughBuilder(builders[2]); + + // BCI 2 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(2, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->IfCmpGreaterThan(builders[5], + b-> Load("result"), + b-> ConstInt32(5)); + b->AddFallThroughBuilder(builders[4]); + + // BCI 3 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(3, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->IfCmpGreaterThan(builders[7], + b-> Load("result"), + b-> ConstInt32(15)); + b->AddFallThroughBuilder(builders[6]); + + // BCI 4 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(4, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->IfCmpLessThan(builders[1], // should not revisit 1 + b-> Load("result"), + b-> ConstInt32(3)); + b->AddFallThroughBuilder(builders[9]); + + // BCI 5 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(5, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->IfCmpLessThan(builders[11], + b-> Load("result"), + b-> ConstInt32(8)); + b->AddFallThroughBuilder(builders[17]); + + // BCI 6 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(6, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->IfCmpGreaterThan(builders[13], + b-> Load("result"), + b-> ConstInt32(12)); + b->AddFallThroughBuilder(builders[16]); + + // BCI 7 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(7, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->IfCmpLessThan(builders[1], // should not revisit 1 + b-> Load("result"), + b-> ConstInt32(17)); + b->AddFallThroughBuilder(builders[8]); + + // BCI 8 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(8, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->Return( + b-> ConstInt32(8)); + + // BCI 9 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(9, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->Return( + b-> ConstInt32(9)); + + // BCI 11 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(11, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->Return( + b-> ConstInt32(11)); + + // BCI 13 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(13, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->Return( + b-> ConstInt32(13)); + + // BCI 16 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(16, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->Return( + b-> ConstInt32(16)); + + // BCI 17 + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(17, bci); + b = builders[bci]; + REPORT_VMSTATE(b,vmState); + b->Return( + b-> ConstInt32(17)); + + // should be no unvisited bytecodes left + bci = GetNextBytecodeFromWorklist(); + EXPECT_BCIEQ(bci,-1); + + return true; + } + +class WorklistTest : public JitBuilderTest {}; + +TEST_F(WorklistTest, test) + { + WorklistTestMethodFunction worklistTestMethod; + ASSERT_COMPILE(TR::TypeDictionary, WorklistTestMethod, worklistTestMethod); + + for (int32_t p=0;p < 20;p++) + { + int32_t worklistTestResult = worklistTestMethod(p); + ASSERT_EQ(computeExpectedResult(p), worklistTestResult) + << "Path " << p << " generated incorrect result."; + } + } diff --git a/jitbuilder/release/Makefile b/jitbuilder/release/Makefile index 676c5c68076..91fb5a60c25 100755 --- a/jitbuilder/release/Makefile +++ b/jitbuilder/release/Makefile @@ -30,7 +30,6 @@ ALL_TESTS = \ call \ conditionals \ conststring \ - controlflowtests \ dotproduct \ fieldaddress \ issupportedtype \ @@ -58,7 +57,6 @@ all: $(ALL_TESTS) # If you add to this list, please also add to ALL_TESTS common_goal: $(ALL_TESTS) ./conditionals - ./controlflowtests ./issupportedtype ./iterfib ./nestedloop @@ -139,13 +137,6 @@ ConstString.o: src/ConstString.cpp src/ConstString.hpp g++ -o $@ $(CXXFLAGS) $< -controlflowtests : libjitbuilder.a ControlFlowTests.o - g++ -g -fno-rtti -o $@ ControlFlowTests.o -L. -ljitbuilder -ldl - -ControlFlowTests.o: src/ControlFlowTests.cpp src/ControlFlowTests.hpp - g++ -o $@ $(CXXFLAGS) $< - - dotproduct : libjitbuilder.a DotProduct.o g++ -g -fno-rtti -o $@ DotProduct.o -L. -ljitbuilder -ldl diff --git a/jitbuilder/release/src/ControlFlowTests.cpp b/jitbuilder/release/src/ControlFlowTests.cpp deleted file mode 100644 index f6bf5806df0..00000000000 --- a/jitbuilder/release/src/ControlFlowTests.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * - * (c) Copyright IBM Corp. 2016, 2016 - * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Public License v1.0 and - * Apache License v2.0 which accompanies this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * The Apache License v2.0 is available at - * http://www.opensource.org/licenses/apache2.0.php - * - * Contributors: - * Multiple authors (IBM Corp.) - initial implementation and documentation - ******************************************************************************/ - - -/** - * This file containse JitBuilder methods that are only useful as tests and - * not as examples of how to use JitBuilder - */ - -#include -#include -#include -#include -#include - -#include "Jit.hpp" -#include "ilgen/TypeDictionary.hpp" -#include "ilgen/MethodBuilder.hpp" -#include "ilgen/BytecodeBuilder.hpp" -#include "ControlFlowTests.hpp" - -using std::cout; -using std::cerr; - - -DoubleReturnBytecodeMethod::DoubleReturnBytecodeMethod(TR::TypeDictionary* d) - : MethodBuilder(d) - { - DefineLine(LINETOSTR(__LINE__)); - DefineFile(__FILE__); - - DefineName("doubleReturn"); - DefineReturnType(NoType); - } - -bool -DoubleReturnBytecodeMethod::buildIL() - { - auto firstBuilder = OrphanBytecodeBuilder(0, (char *)"return"); - AppendBuilder(firstBuilder); - firstBuilder->Return(); - - auto secondBuilder = OrphanBytecodeBuilder(1, (char *)"return"); // should be ignored and cleanedup - secondBuilder->Return(); - - return true; - } - - -int -main(int argc, char *argv[]) - { - cout << "Step 1: initialize JIT\n"; - bool initialized = initializeJit(); - if (!initialized) - { - cerr << "FAIL: could not initialize JIT\n"; - exit(-1); - } - - cout << "Step 2: define type dictionary\n"; - TR::TypeDictionary types; - - cout << "Step 3: compile method builder\n"; - DoubleReturnBytecodeMethod method(&types); - uint8_t *entry = 0; - int32_t rc = compileMethodBuilder(&method, &entry); - if (rc != 0) - { - cerr << "FAIL: compilation error " << rc << "\n"; - exit(-2); - } - - cout << "Step 4: invoke compiled code\n"; - DoubleReturnBytecodeMethodFunction *doubleReturn = (DoubleReturnBytecodeMethodFunction *) entry; - doubleReturn(); - - cout << "Step 5: shutdown JIT\n"; - shutdownJit(); - } diff --git a/jitbuilder/release/src/ControlFlowTests.hpp b/jitbuilder/release/src/ControlFlowTests.hpp deleted file mode 100644 index 432dee86f8b..00000000000 --- a/jitbuilder/release/src/ControlFlowTests.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * - * (c) Copyright IBM Corp. 2016, 2016 - * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Public License v1.0 and - * Apache License v2.0 which accompanies this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * The Apache License v2.0 is available at - * http://www.opensource.org/licenses/apache2.0.php - * - * Contributors: - * Multiple authors (IBM Corp.) - initial implementation and documentation - ******************************************************************************/ - -#ifndef USELESS_INCL -#define USELESS_INCL - -/** - * This file containse JitBuilder methods that are only useful as tests and - * not as examples of how to use JitBuilder - */ - -#include "ilgen/MethodBuilder.hpp" - -typedef void (DoubleReturnBytecodeMethodFunction)(void); - -class DoubleReturnBytecodeMethod : public TR::MethodBuilder - { - public: - DoubleReturnBytecodeMethod(TR::TypeDictionary *); - virtual bool buildIL(); - }; - -#endif // !defined(USELESS_INCL) \ No newline at end of file