Skip to content

Commit

Permalink
Merge pull request #109 from ethereum/llvm-3.9.1
Browse files Browse the repository at this point in the history
Upgrade LLVM to 3.9.1
  • Loading branch information
chfast committed Jan 12, 2017
2 parents 7e19aef + 5fafb3f commit 290b192
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 182 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,3 +4,4 @@
# Convenient binary output and build dirs
/bin/
/build/
/downloads/
4 changes: 1 addition & 3 deletions .travis.yml
Expand Up @@ -19,10 +19,8 @@ cache:
directories: build/llvm


before_install:
- cmake --version

script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then scripts/install_cmake.sh; fi
- scripts/build.sh
- cd build && ctest
- cd ..
Expand Down
7 changes: 4 additions & 3 deletions appveyor.yml
Expand Up @@ -3,9 +3,10 @@ branches:
only:
- develop
configuration:
- Debug
- Release
cache: build/llvm
- Debug
- Release
cache:
- build/llvm -> cmake/llvm.cmake
before_build: |
if not exist build mkdir build
cd build
Expand Down
8 changes: 3 additions & 5 deletions circle.yml
@@ -1,13 +1,11 @@
dependencies:
pre:
- sudo apt-add-repository -y ppa:george-edison55/cmake-3.x
- sudo apt -q update
- sudo apt -qy install cmake
override:
- BUILD_TYPE=RelWithDebInfo scripts/build.sh
- scripts/install_cmake.sh
- PATH=~/.local/bin:$PATH BUILD_TYPE=RelWithDebInfo scripts/build.sh
cache_directories:
# TODO: add ccache
- build/llvm # Cache llvm build
- ~/.local

test:
override:
Expand Down
16 changes: 9 additions & 7 deletions cmake/llvm.cmake
Expand Up @@ -35,11 +35,12 @@ function(configure_llvm_project TARGET_NAME)
# Only used here locally to setup the "llvm" imported target
set(LIBS
LLVMMCJIT
LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMMCDisassembler LLVMX86AsmPrinter
LLVMX86Utils LLVMSelectionDAG LLVMAsmPrinter LLVMCodeGen
LLVMInstrumentation LLVMBitWriter LLVMipo LLVMVectorize LLVMScalarOpts
LLVMProfileData LLVMIRReader LLVMAsmParser LLVMInstCombine
LLVMTransformUtils LLVMExecutionEngine LLVMTarget LLVMAnalysis
LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMMCDisassembler
LLVMX86AsmPrinter LLVMX86Utils LLVMSelectionDAG LLVMAsmPrinter
LLVMDebugInfoCodeView LLVMCodeGen LLVMBitWriter LLVMipo
LLVMInstrumentation LLVMVectorize LLVMScalarOpts LLVMLinker
LLVMIRReader LLVMAsmParser LLVMInstCombine LLVMTransformUtils
LLVMExecutionEngine LLVMTarget LLVMAnalysis LLVMProfileData
LLVMRuntimeDyld LLVMObject LLVMMCParser LLVMBitReader LLVMMC
LLVMCore LLVMSupport
)
Expand All @@ -61,10 +62,11 @@ function(configure_llvm_project TARGET_NAME)
include(ExternalProject)
ExternalProject_Add(llvm-project
PREFIX llvm
DOWNLOAD_DIR ${CMAKE_CURRENT_LIST_DIR}/downloads
BINARY_DIR llvm # Build directly to install dir to avoid copy.
SOURCE_DIR llvm/src/llvm
URL http://llvm.org/releases/3.8.0/llvm-3.8.0.src.tar.xz
URL_HASH SHA256=555b028e9ee0f6445ff8f949ea10e9cd8be0d084840e21fbbe1d31d51fc06e46
URL http://llvm.org/releases/3.9.1/llvm-3.9.1.src.tar.xz
URL_HASH SHA256=1fd90354b9cf19232e8f168faf2220e79be555df3aa743242700879e8fd329ee
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DLLVM_ENABLE_TERMINFO=OFF # Disable terminal color support
Expand Down
156 changes: 2 additions & 154 deletions libevmjit/Arith256.cpp
Expand Up @@ -33,157 +33,6 @@ void Arith256::debug(llvm::Value* _value, char _c, llvm::Module& _module, IRBuil
_builder.CreateCall(func, {_builder.CreateZExtOrTrunc(_value, Type::Word), _builder.getInt8(_c)});
}

namespace
{
llvm::Function* generateLongMulFunc(char const* _funcName, llvm::IntegerType* _ty, llvm::IntegerType* _wordTy, llvm::Module& _module)
{
// C++ reference implementation:

// using word = std::uint64_t;
// using dword = __uint128_t;
//
// static const auto wordBits = sizeof(word) * 8;
//
// template<unsigned _N>
// struct i
// {
// static const unsigned N = _N/8/sizeof(word);
// word w[N];
// };
//
// using int256 = i<256>;
//
// template<unsigned N>
// i<N> long_mul(i<N> a, i<N> b)
// {
// decltype(a) r = {{0}};
//
// for (int j = 0; j < b.N; ++j)
// {
// dword carry = 0;
// for (int i = 0; i < (a.N - j); ++i)
// {
// auto& slot = r.w[j + i];
//
// // sum of current multiplication, carry and the value from previous round using dword type
// // no overflow because (2^N - 1)*(2^N - 1) + (2^N - 1) + (2^N - 1) == 2^2N - 1
// auto s = (dword)b.w[j] * a.w[i] + carry + slot; // safe, no overflow
//
// slot = (word) s;
// carry = s >> wordBits;
// }
// }
//
// return r;
// }

auto func = llvm::Function::Create(llvm::FunctionType::get(_ty, {_ty, _ty}, false), llvm::Function::PrivateLinkage, _funcName, &_module);
func->setDoesNotAccessMemory();
func->setDoesNotThrow();

auto iter = func->arg_begin();
llvm::Argument* x = &(*iter++);
x->setName("x");
llvm::Argument* y = &(*iter);
y->setName("y");

auto entryBB = llvm::BasicBlock::Create(func->getContext(), "Entry", func);
auto outerLoopHeaderBB = llvm::BasicBlock::Create(func->getContext(), "OuterLoop.Header", func);
auto innerLoopBB = llvm::BasicBlock::Create(func->getContext(), "InnerLoop", func);
auto outerLoopFooterBB = llvm::BasicBlock::Create(func->getContext(), "OuterLoop.Footer", func);
auto exitBB = llvm::BasicBlock::Create(func->getContext(), "Exit", func);

auto builder = IRBuilder{entryBB};
auto dwordTy = builder.getIntNTy(_wordTy->getBitWidth() * 2);
auto indexTy = builder.getInt32Ty();
auto _0 = builder.getInt32(0);
auto _1 = builder.getInt32(1);
auto wordMask = builder.CreateZExt(llvm::ConstantInt::get(_wordTy, -1, true), dwordTy);
auto wordBitWidth = builder.getInt32(_wordTy->getBitWidth());
assert(_ty->getBitWidth() / _wordTy->getBitWidth() >= 4 && "Word type must be at least 4 times smaller than full type");
auto dim = builder.getInt32(_ty->getBitWidth() / _wordTy->getBitWidth());
builder.CreateBr(outerLoopHeaderBB);

auto extractWordAsDword = [&](llvm::Value* _a, llvm::Value* _idx, llvm::Twine const& _name)
{
auto word = builder.CreateLShr(_a, builder.CreateZExt(builder.CreateNUWMul(_idx, wordBitWidth), _ty));
word = builder.CreateAnd(builder.CreateTrunc(word, dwordTy), wordMask, _name);
return word;
};

builder.SetInsertPoint(outerLoopHeaderBB);
auto j = builder.CreatePHI(indexTy, 2, "j");
auto p = builder.CreatePHI(_ty, 2, "p");
auto yj = extractWordAsDword(y, j, "y.j");
auto iEnd = builder.CreateSub(dim, j, "i.end", true, true);
builder.CreateBr(innerLoopBB);

builder.SetInsertPoint(innerLoopBB);
auto i = builder.CreatePHI(indexTy, 2, "i");
auto pInner = builder.CreatePHI(_ty, 2, "p.inner");
auto carry = builder.CreatePHI(_wordTy, 2, "carry");

auto k = builder.CreateNUWAdd(i, j, "k");
auto offset = builder.CreateZExt(builder.CreateNUWMul(k, wordBitWidth), _ty, "offset");
auto xi = extractWordAsDword(x, i, "x.i");
auto m = builder.CreateNUWMul(xi, yj, "m");
auto mask = builder.CreateShl(builder.CreateZExt(wordMask, _ty), offset, "mask");
auto nmask = builder.CreateXor(mask, llvm::ConstantInt::get(_ty, -1, true), "nmask");
auto w = builder.CreateTrunc(builder.CreateLShr(pInner, offset), dwordTy);
w = builder.CreateAnd(w, wordMask, "w");
auto s = builder.CreateAdd(w, builder.CreateZExt(carry, dwordTy), "s.wc", true, true);
s = builder.CreateNUWAdd(s, m, "s");
auto carryNext = builder.CreateTrunc(builder.CreateLShr(s, llvm::ConstantInt::get(dwordTy, _wordTy->getBitWidth())), _wordTy, "carry.next");
auto wNext = builder.CreateAnd(s, wordMask);
auto pMasked = builder.CreateAnd(pInner, nmask, "p.masked");
auto pNext = builder.CreateOr(builder.CreateShl(builder.CreateZExt(wNext, _ty), offset), pMasked, "p.next");

auto iNext = builder.CreateNUWAdd(i, _1, "i.next");
auto innerLoopCond = builder.CreateICmpEQ(iNext, iEnd, "i.cond");
builder.CreateCondBr(innerLoopCond, outerLoopFooterBB, innerLoopBB);
i->addIncoming(_0, outerLoopHeaderBB);
i->addIncoming(iNext, innerLoopBB);
pInner->addIncoming(p, outerLoopHeaderBB);
pInner->addIncoming(pNext, innerLoopBB);
carry->addIncoming(llvm::ConstantInt::get(_wordTy, 0), outerLoopHeaderBB);
carry->addIncoming(carryNext, innerLoopBB);

builder.SetInsertPoint(outerLoopFooterBB);
auto jNext = builder.CreateNUWAdd(j, _1, "j.next");
auto outerLoopCond = builder.CreateICmpEQ(jNext, dim, "j.cond");
builder.CreateCondBr(outerLoopCond, exitBB, outerLoopHeaderBB);
j->addIncoming(_0, entryBB);
j->addIncoming(jNext, outerLoopFooterBB);
p->addIncoming(llvm::ConstantInt::get(_ty, 0), entryBB);
p->addIncoming(pNext, outerLoopFooterBB);

builder.SetInsertPoint(exitBB);
builder.CreateRet(pNext);

return func;
}
}


llvm::Function* Arith256::getMulFunc(llvm::Module& _module)
{
static const auto funcName = "evm.mul.i256";
if (auto func = _module.getFunction(funcName))
return func;

return generateLongMulFunc(funcName, Type::Word, Type::Size, _module);
}

llvm::Function* Arith256::getMul512Func(llvm::Module& _module)
{
static const auto funcName = "evm.mul.i512";
if (auto func = _module.getFunction(funcName))
return func;

auto i512Ty = llvm::IntegerType::get(_module.getContext(), 512);
return generateLongMulFunc(funcName, i512Ty, Type::Size, _module);
}

namespace
{
llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char const* _funcName)
Expand Down Expand Up @@ -503,15 +352,14 @@ llvm::Function* Arith256::getExpFunc()
m_builder.CreateCondBr(eOdd, updateBB, continueBB);

m_builder.SetInsertPoint(updateBB);
auto mul256Func = getMulFunc(*getModule());
auto r0 = m_builder.CreateCall(mul256Func, {r, b});
auto r0 = m_builder.CreateMul(r, b);
m_builder.CreateBr(continueBB);

m_builder.SetInsertPoint(continueBB);
auto r1 = m_builder.CreatePHI(Type::Word, 2, "r1");
r1->addIncoming(r, bodyBB);
r1->addIncoming(r0, updateBB);
auto b1 = m_builder.CreateCall(mul256Func, {b, b});
auto b1 = m_builder.CreateMul(b, b);
auto e1 = m_builder.CreateLShr(e, Constant::get(1), "e1");
m_builder.CreateBr(headerBB);

Expand Down
2 changes: 0 additions & 2 deletions libevmjit/Arith256.h
Expand Up @@ -18,8 +18,6 @@ class Arith256 : public CompilerHelper

static void debug(llvm::Value *_value, char _c, llvm::Module &_module, IRBuilder &_builder);

static llvm::Function* getMulFunc(llvm::Module& _module);
static llvm::Function* getMul512Func(llvm::Module& _module);
static llvm::Function* getUDiv256Func(llvm::Module& _module);
static llvm::Function* getURem256Func(llvm::Module& _module);
static llvm::Function* getURem512Func(llvm::Module& _module);
Expand Down
8 changes: 0 additions & 8 deletions libevmjit/Optimizer.cpp
Expand Up @@ -116,10 +116,6 @@ bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb)
{
switch (inst.getOpcode())
{
case llvm::Instruction::Mul:
func = Arith256::getMulFunc(*module);
break;

case llvm::Instruction::UDiv:
func = Arith256::getUDiv256Func(*module);
break;
Expand All @@ -141,10 +137,6 @@ bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb)
{
switch (inst.getOpcode())
{
case llvm::Instruction::Mul:
func = Arith256::getMul512Func(*module);
break;

case llvm::Instruction::URem:
func = Arith256::getURem512Func(*module);
break;
Expand Down
37 changes: 37 additions & 0 deletions scripts/install_cmake.sh
@@ -0,0 +1,37 @@
#!/usr/bin/env sh

# This script downloads the CMake binary and installs it in ~/.local directory
# (the cmake executable will be in ~/.local/bin).
# This is mostly suitable for CIs, not end users.

set -e

VERSION=3.7.1
PREFIX=~/.local

OS=$(uname -s)
case $OS in
Linux) SHA256=7b4b7a1d9f314f45722899c0521c261e4bfab4a6b532609e37fef391da6bade2;;
Darwin) SHA256=1851d1448964893fdc5a8c05863326119f397a3790e0c84c40b83499c7960267;;
esac


BIN=$PREFIX/bin

if test -f $BIN/cmake && ($BIN/cmake --version | grep -q "$VERSION"); then
echo "CMake $VERSION already installed in $BIN"
else
FILE=cmake-$VERSION-$OS-x86_64.tar.gz
URL=https://cmake.org/files/v3.7/$FILE
ERROR=0
TMPFILE=$(mktemp --tmpdir cmake-$VERSION-$OS-x86_64.XXXXXXXX.tar.gz)
echo "Downloading CMake ($URL)..."
wget "$URL" -O "$TMPFILE" -nv
if ! (shasum -a256 "$TMPFILE" | grep -q "$SHA256"); then
echo "Checksum mismatch ($TMPFILE)"
exit 1
fi
mkdir -p "$PREFIX"
tar xzf "$TMPFILE" -C "$PREFIX" --strip 1
rm $TMPFILE
fi

0 comments on commit 290b192

Please sign in to comment.