Skip to content

Commit

Permalink
* Add FullOptimization.h allowing users to fully optimize LLVM mod…
Browse files Browse the repository at this point in the history
…ules (pull #869)
  • Loading branch information
yukoba authored Apr 20, 2020
1 parent 5ad7bdf commit 9357316
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

* Add `FullOptimization.h` allowing users to fully optimize LLVM modules ([pull #869](https://github.com/bytedeco/javacpp-presets/pull/869))

### April 14, 2020 version 1.5.3
* Add presets for the new `intensity_transform` and `rapid` modules of OpenCV
* Add support for Polly optimizer to presets for LLVM ([pull #864](https://github.com/bytedeco/javacpp-presets/pull/864))
Expand Down
26 changes: 6 additions & 20 deletions llvm/samples/polly/MatMulBenchmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
* If you set usePollyParallel, you may have to modify the file name of LLVMLoadLibraryPermanently().
*
* Warning: Because it does not optimize for AVX, etc, this code is slower than this:
* Note: This code is equivalent to this:
* clang -O3 -march=native -mllvm -polly -mllvm -polly-vectorizer=stripmine
*
* Note: Instead of JNA, to obtain maximum performance, FunctionPointer should be used as shown here:
Expand All @@ -29,6 +29,7 @@ public class MatMulBenchmark {
static final boolean usePollyParallel = false;
static final boolean printResult = false;

static final BytePointer cpu = LLVMGetHostCPUName();
static LLVMTypeRef llvmVoidType;
static LLVMTypeRef llvmInt32Type;
static LLVMTypeRef llvmFloatType;
Expand Down Expand Up @@ -101,8 +102,8 @@ static void benchmarkLLVM(float[] a, float[] b, float[] c) {
LLVMExecutionEngineRef engine = new LLVMExecutionEngineRef();
try {
LLVMModuleRef module = build();
optimize(module);
verify(module, false);
optimize(module);
jitCompile(engine, module);

long fnAddr = LLVMGetFunctionAddress(engine, "matmul");
Expand Down Expand Up @@ -237,15 +238,7 @@ static LLVMModuleRef build() {
}

static void optimize(LLVMModuleRef module) {
LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
LLVMPassManagerBuilderSetOptLevel(pmb, 3);
LLVMPassManagerRef pass = LLVMCreatePassManager();
LLVMPassManagerBuilderPopulateModulePassManager(pmb, pass);

LLVMRunPassManager(pass, module);

LLVMDisposePassManager(pass);
LLVMPassManagerBuilderDispose(pmb);
optimizeModule(module, cpu, 3, 0);
}

static void verify(LLVMModuleRef module, boolean dumpModule) {
Expand All @@ -254,7 +247,7 @@ static void verify(LLVMModuleRef module, boolean dumpModule) {
if (dumpModule) {
LLVMDumpModule(module);
}
if (LLVMVerifyModule(module, LLVMAbortProcessAction, error) != 0) {
if (LLVMVerifyModule(module, LLVMPrintMessageAction, error) != 0) {
throw new RuntimeException(error.getString());
}
} finally {
Expand All @@ -263,14 +256,7 @@ static void verify(LLVMModuleRef module, boolean dumpModule) {
}

static void jitCompile(LLVMExecutionEngineRef engine, LLVMModuleRef module) {
BytePointer error = new BytePointer((Pointer) null);
try {
if (LLVMCreateJITCompilerForModule(engine, module, 3, error) != 0) {
throw new RuntimeException(error.getString());
}
} finally {
LLVMDisposeMessage(error);
}
createOptimizedJITCompilerForModule(engine, module, cpu, 3);
}

static LLVMValueRef toConstInt(int v) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/samples/polly/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>llvm-platform</artifactId>
<version>10.0.0-1.5.3</version>
<version>10.0.0-1.5.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
Expand Down
82 changes: 81 additions & 1 deletion llvm/src/gen/java/org/bytedeco/llvm/global/LLVM.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Targeted by JavaCPP version 1.5.3: DO NOT EDIT THIS FILE
// Targeted by JavaCPP version 1.5.4-SNAPSHOT: DO NOT EDIT THIS FILE

package org.bytedeco.llvm.global;

Expand Down Expand Up @@ -10533,4 +10533,84 @@ public static native void LLVMAddScalarReplAggregatesPassWithThreshold(LLVMPassM
// #endif


// Parsed from <FullOptimization.h>

/*
* Copyright (C) 2020 Yu Kobayashi
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// #ifndef FULL_OPTIMIZATION_H
// #define FULL_OPTIMIZATION_H

// #include "llvm/ExecutionEngine/ExecutionEngine.h"
// #include "llvm/Target/TargetMachine.h"
// #include "llvm/Transforms/IPO.h"
// #include "llvm/Transforms/IPO/PassManagerBuilder.h"
// #include "llvm/IR/Verifier.h"
// #include "llvm/IR/LegacyPassManager.h"
// #include "llvm/CodeGen/TargetPassConfig.h"
// #include "llvm/Support/TargetRegistry.h"
// #include "llvm/Analysis/TargetLibraryInfo.h"
// #include "llvm/Analysis/TargetTransformInfo.h"
// #include "llvm/MC/SubtargetFeature.h"
// #include "llvm/Pass.h"
// #include "llvm-c/Transforms/PassManagerBuilder.h"
// #include "llvm-c/Types.h"

/**
* This function does the standard LLVM optimization.
* This function is based on main() of llvm/tools/opt/opt.cpp.
* Use LLVMGetHostCPUName() for the cpu argument.
*/
public static native void optimizeModule(
LLVMModuleRef moduleRef,
@Cast("const char*") BytePointer cpu,
@Cast("unsigned") int optLevel,
@Cast("unsigned") int sizeLevel
);
public static native void optimizeModule(
LLVMModuleRef moduleRef,
String cpu,
@Cast("unsigned") int optLevel,
@Cast("unsigned") int sizeLevel
);

/**
* This function is similar to LLVMCreateJITCompilerForModule() but does CPU specific optimization.
* Use LLVMGetHostCPUName() for the cpu argument.
*/
public static native void createOptimizedJITCompilerForModule(
@ByPtrPtr LLVMExecutionEngineRef outJIT,
LLVMModuleRef moduleRef,
@Cast("const char*") BytePointer cpu,
@Cast("unsigned") int optLevel
);
public static native void createOptimizedJITCompilerForModule(
@Cast("LLVMExecutionEngineRef*") PointerPointer outJIT,
LLVMModuleRef moduleRef,
String cpu,
@Cast("unsigned") int optLevel
);

// #endif


}
2 changes: 1 addition & 1 deletion llvm/src/main/java/org/bytedeco/llvm/presets/LLVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"<llvm-c/Comdat.h>", "<llvm-c/DebugInfo.h>", "<llvm-c/Error.h>", "<llvm-c/ErrorHandling.h>", "<llvm-c/OrcBindings.h>", "<llvm-c/Remarks.h>",
"<llvm-c/Transforms/AggressiveInstCombine.h>", "<llvm-c/Transforms/Coroutines.h>", "<llvm-c/Transforms/InstCombine.h>",
"<llvm-c/Transforms/IPO.h>", "<llvm-c/Transforms/PassManagerBuilder.h>", "<llvm-c/Transforms/Scalar.h>", "<llvm-c/Transforms/Utils.h>", "<llvm-c/Transforms/Vectorize.h>",
"<polly/LinkAllPasses.h>"},
"<polly/LinkAllPasses.h>", "<FullOptimization.h>"},
compiler = "cpp14", link = {"LLVM-10", "LTO@.10", "LLVMPolly"}),
@Platform(value = {"macosx", "windows"}, link = {"LLVM", "LTO", "Polly", "PollyISL", "PollyPPCG"})})
public class LLVM implements InfoMapper {
Expand Down
128 changes: 128 additions & 0 deletions llvm/src/main/resources/org/bytedeco/llvm/include/FullOptimization.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright (C) 2020 Yu Kobayashi
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FULL_OPTIMIZATION_H
#define FULL_OPTIMIZATION_H

#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Pass.h"
#include "llvm-c/Transforms/PassManagerBuilder.h"
#include "llvm-c/Types.h"

using namespace llvm;

/**
* This function does the standard LLVM optimization.
* This function is based on main() of llvm/tools/opt/opt.cpp.
* Use LLVMGetHostCPUName() for the cpu argument.
*/
void optimizeModule(
LLVMModuleRef moduleRef,
const char* cpu,
unsigned optLevel,
unsigned sizeLevel
) {
Module *module = unwrap(moduleRef);

std::string error;
EngineBuilder engineBuilder;
TargetMachine *machine = engineBuilder
.setMCPU(cpu)
.setErrorStr(&error)
.selectTarget();
if (machine == nullptr) {
throw std::runtime_error(error);
}

module->setTargetTriple(machine->getTargetTriple().str());
module->setDataLayout(machine->createDataLayout());

legacy::PassManager passes;
passes.add(new TargetLibraryInfoWrapperPass(machine->getTargetTriple()));
passes.add(createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis()));

legacy::FunctionPassManager fnPasses(module);
fnPasses.add(createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis()));

// AddOptimizationPasses
PassManagerBuilder builder1;
builder1.OptLevel = optLevel;
builder1.SizeLevel = sizeLevel;
builder1.Inliner = createFunctionInliningPass(optLevel, sizeLevel, false);
builder1.LoopVectorize = optLevel > 1 && sizeLevel < 2;
builder1.SLPVectorize = optLevel > 1 && sizeLevel < 2;
machine->adjustPassManager(builder1);
builder1.populateFunctionPassManager(fnPasses);
builder1.populateModulePassManager(passes);

// AddStandardLinkPasses
PassManagerBuilder builder2;
builder2.VerifyInput = true;
builder2.Inliner = createFunctionInliningPass();
builder2.populateLTOPassManager(passes);

fnPasses.doInitialization();
for (Function &func : *module) {
fnPasses.run(func);
}
fnPasses.doFinalization();

passes.add(createVerifierPass());
passes.run(*module);
}

/**
* This function is similar to LLVMCreateJITCompilerForModule() but does CPU specific optimization.
* Use LLVMGetHostCPUName() for the cpu argument.
*/
void createOptimizedJITCompilerForModule(
LLVMExecutionEngineRef *outJIT,
LLVMModuleRef moduleRef,
const char* cpu,
unsigned optLevel
) {
std::string error;
EngineBuilder engineBuilder(std::unique_ptr<Module>(unwrap(moduleRef)));
ExecutionEngine *ee = engineBuilder
.setEngineKind(EngineKind::JIT)
.setMCPU(cpu)
.setOptLevel(static_cast<CodeGenOpt::Level>(optLevel))
.setErrorStr(&error)
.create();
if (ee == nullptr) {
throw std::runtime_error(error);
}
ee->finalizeObject();
*outJIT = wrap(ee);
}

#endif

0 comments on commit 9357316

Please sign in to comment.