1
0
mirror of https://github.com/RPCS3/rpcs3 synced 2024-07-03 08:08:42 +00:00

Upgrade to LLVM 11 Stable

This commit is contained in:
Nekotekina 2020-11-02 06:07:58 +03:00
parent 06ecc2ae68
commit 1b8bf081b5
15 changed files with 186 additions and 76 deletions

1
3rdparty/llvm.cmake vendored
View File

@ -11,7 +11,6 @@ if(WITH_LLVM)
option(LLVM_INCLUDE_TESTS OFF)
option(LLVM_INCLUDE_TOOLS OFF)
option(LLVM_INCLUDE_UTILS OFF)
option(WITH_POLLY OFF)
option(LLVM_CCACHE_BUILD ON)
set(CXX_FLAGS_OLD ${CMAKE_CXX_FLAGS})

View File

@ -285,6 +285,7 @@ asmjit::Runtime& asmjit::get_global_runtime()
#endif
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/ObjectCache.h"

View File

@ -38,7 +38,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>$(CmakeCLI)

View File

@ -38,7 +38,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI>
<PropsAbsPath>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\common_default.props'))</PropsAbsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

2
llvm

@ -1 +1 @@
Subproject commit f5679565d34863e2f5917f6bb6d3867760862a1e
Subproject commit 8c02f52a12550c2044fef262c9864ca2e3cc193e

View File

@ -1,7 +1,7 @@
REM You need cmake and python to update the project files
REM this script relies on CWD being the path that this script is in
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
cmake -G "Visual Studio 16 2019 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_UTILS=OFF -DLLVM_USE_INTEL_JITEVENTS=ON -DLLVM_ENABLE_Z3_SOLVER=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=10.0 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm
RD /S /Q cmake
RD /S /Q CMakeFiles

View File

@ -39,7 +39,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakePreprocessorDefinitions>

View File

@ -74,9 +74,9 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type)
uint s2 = val->getType()->getScalarSizeInBits();
if (type->isVectorTy())
s1 *= type->getVectorNumElements();
s1 *= llvm::cast<llvm::VectorType>(type)->getNumElements();
if (val->getType()->isVectorTy())
s2 *= val->getType()->getVectorNumElements();
s2 *= llvm::cast<llvm::VectorType>(val->getType())->getNumElements();
if (s1 != s2)
{
@ -120,9 +120,9 @@ std::pair<bool, v128> cpu_translator::get_const_vector<v128>(llvm::Value* c, u32
fmt::throw_exception("[0x%x, %u] Not a vector" HERE, a, b);
}
if (uint sz = llvm::cast<llvm::VectorType>(t)->getBitWidth() - 128)
if (auto v = llvm::cast<llvm::VectorType>(t); v->getScalarSizeInBits() * v->getNumElements() != 128)
{
fmt::throw_exception("[0x%x, %u] Bad vector size: %u" HERE, a, b, sz + 128);
fmt::throw_exception("[0x%x, %u] Bad vector size: i%ux%u" HERE, a, b, v->getScalarSizeInBits(), v->getNumElements());
}
const auto cv = llvm::dyn_cast<llvm::ConstantDataVector>(c);
@ -203,7 +203,8 @@ llvm::Constant* cpu_translator::make_const_vector<v128>(v128 v, llvm::Type* t)
return llvm::ConstantInt::get(t, llvm::APInt(128, llvm::makeArrayRef(reinterpret_cast<const u64*>(v._bytes), 2)));
}
verify(HERE), t->isVectorTy() && llvm::cast<llvm::VectorType>(t)->getBitWidth() == 128;
verify(HERE), t->isVectorTy();
verify(HERE), 128 == t->getScalarSizeInBits() * llvm::cast<llvm::VectorType>(t)->getNumElements();
const auto sct = t->getScalarType();

View File

@ -363,7 +363,7 @@ struct llvm_value_t<T[N]> : llvm_value_t<std::conditional_t<(std::extent_v<T> >
}
else if constexpr (N > 1)
{
return llvm::VectorType::get(base::get_type(context), N);
return llvm::VectorType::get(base::get_type(context), N, false);
}
else
{
@ -2283,9 +2283,11 @@ struct llvm_splat
if (auto i = llvm::dyn_cast_or_null<llvm::ShuffleVectorInst>(value))
{
if (llvm::isa<llvm::ConstantAggregateZero>(i->getOperand(2)))
if (llvm::isa<llvm::ConstantAggregateZero>(i->getOperand(1)) || llvm::isa<llvm::UndefValue>(i->getOperand(1)))
{
if (auto j = llvm::dyn_cast<llvm::InsertElementInst>(i->getOperand(0)))
static constexpr int zero_array[llvm_value_t<U>::is_vector]{};
if (auto j = llvm::dyn_cast<llvm::InsertElementInst>(i->getOperand(0)); j && i->getShuffleMask().equals(zero_array))
{
if (llvm::cast<llvm::ConstantInt>(j->getOperand(2))->isZero())
{
@ -2311,7 +2313,7 @@ struct llvm_zshuffle
using type = std::remove_extent_t<T>[N];
llvm_expr_t<A1> a1;
u32 index_array[N];
int index_array[N];
static_assert(llvm_value_t<T>::is_vector, "llvm_zshuffle<>: invalid type");
@ -2334,7 +2336,7 @@ struct llvm_zshuffle
if (auto z = llvm::dyn_cast<llvm::ConstantAggregateZero>(i->getOperand(1)); z && z->getType() == v1->getType())
{
if (llvm::ConstantDataVector::get(value->getContext(), index_array) == i->getOperand(2))
if (i->getShuffleMask().equals(index_array))
{
if (auto r1 = a1.match(v1); v1)
{
@ -2356,7 +2358,7 @@ struct llvm_shuffle2
llvm_expr_t<A1> a1;
llvm_expr_t<A2> a2;
u32 index_array[N];
int index_array[N];
static_assert(llvm_value_t<T>::is_vector, "llvm_shuffle2<>: invalid type");
@ -2382,7 +2384,7 @@ struct llvm_shuffle2
if (v1->getType() == v2->getType() && v1->getType() == llvm_value_t<T>::get_type(v1->getContext()))
{
if (llvm::ConstantDataVector::get(value->getContext(), index_array) == i->getOperand(2))
if (i->getShuffleMask().equals(index_array))
{
if (auto r1 = a1.match(v1); v1)
{
@ -2423,7 +2425,7 @@ protected:
// Allow FMA
bool m_use_fma = false;
// Allow Icelake tier AVX-512
// Allow Icelake tier AVX-512
bool m_use_avx512_icl = false;
// IR builder
@ -2665,13 +2667,13 @@ public:
template <typename T, typename... Args, typename = std::enable_if_t<llvm_zshuffle<sizeof...(Args), T>::is_ok>>
static auto zshuffle(T&& v, Args... indices)
{
return llvm_zshuffle<sizeof...(Args), T>{std::forward<T>(v), {static_cast<u32>(indices)...}};
return llvm_zshuffle<sizeof...(Args), T>{std::forward<T>(v), {static_cast<int>(indices)...}};
}
template <typename T, typename U, typename... Args, typename = std::enable_if_t<llvm_shuffle2<sizeof...(Args), T, U>::is_ok>>
static auto shuffle2(T&& v1, U&& v2, Args... indices)
{
return llvm_shuffle2<sizeof...(Args), T, U>{std::forward<T>(v1), std::forward<U>(v2), {static_cast<u32>(indices)...}};
return llvm_shuffle2<sizeof...(Args), T, U>{std::forward<T>(v1), std::forward<U>(v2), {static_cast<int>(indices)...}};
}
// Average: (a + b + 1) >> 1
@ -2685,7 +2687,7 @@ public:
const auto cast_op = result.is_sint ? llvm::Instruction::SExt : llvm::Instruction::ZExt;
llvm::Type* cast_to = m_ir->getIntNTy(result.esize * 2);
if constexpr (result.is_vector != 0)
cast_to = llvm::VectorType::get(cast_to, result.is_vector);
cast_to = llvm::VectorType::get(cast_to, result.is_vector, false);
const auto axt = m_ir->CreateCast(cast_op, a.eval(m_ir), cast_to);
const auto bxt = m_ir->CreateCast(cast_op, b.eval(m_ir), cast_to);
@ -2752,7 +2754,7 @@ public:
{
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rcp.ps", av->getType(), av->getType()).getCallee(), {av});
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rcp.ps", av->getType(), av->getType()), {av});
return result;
}
@ -2761,7 +2763,7 @@ public:
{
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rsqrt.ps", av->getType(), av->getType()).getCallee(), {av});
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rsqrt.ps", av->getType(), av->getType()), {av});
return result;
}
@ -2771,7 +2773,7 @@ public:
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
const auto bv = b.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.max.ps", av->getType(), av->getType(), av->getType()).getCallee(), {av, bv});
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.max.ps", av->getType(), av->getType(), av->getType()), {av, bv});
return result;
}
@ -2781,7 +2783,7 @@ public:
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
const auto bv = b.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.min.ps", av->getType(), av->getType(), av->getType()).getCallee(), {av, bv});
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.min.ps", av->getType(), av->getType(), av->getType()), {av, bv});
return result;
}
@ -2930,7 +2932,7 @@ struct fmt_unveil<llvm::TypeSize, void>
template <>
inline llvm::Type* cpu_translator::get_type<__m128i>()
{
return llvm::VectorType::get(llvm::Type::getInt8Ty(m_context), 16);
return llvm::VectorType::get(llvm::Type::getInt8Ty(m_context), 16, false);
}
#ifndef _MSC_VER

View File

@ -30,6 +30,7 @@
#endif
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Host.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/LLVMContext.h"

View File

@ -237,7 +237,7 @@ Value* PPUTranslator::VecHandleDenormal(Value* val)
const auto type = val->getType();
const auto value = bitcast(val, GetType<u32[4]>());
const auto mask = SExt(m_ir->CreateICmpEQ(m_ir->CreateAnd(value, Broadcast(RegLoad(m_jm_mask), 4)), ConstantVector::getSplat(4, m_ir->getInt32(0))), GetType<s32[4]>());
const auto mask = SExt(m_ir->CreateICmpEQ(m_ir->CreateAnd(value, Broadcast(RegLoad(m_jm_mask), 4)), ConstantAggregateZero::get(value->getType())), GetType<s32[4]>());
const auto nz = m_ir->CreateLShr(mask, 1);
const auto result = m_ir->CreateAnd(m_ir->CreateNot(nz), value);
@ -282,7 +282,8 @@ Type* PPUTranslator::ScaleType(Type* type, s32 pow2)
verify(HERE), (scaled != 0);
const auto new_type = m_ir->getIntNTy(scaled);
return type->isVectorTy() ? VectorType::get(new_type, type->getVectorNumElements()) : cast<Type>(new_type);
const auto vec_type = dyn_cast<VectorType>(type);
return vec_type ? VectorType::get(new_type, vec_type->getNumElements(), false) : cast<Type>(new_type);
}
Value* PPUTranslator::DuplicateExt(Value* arg)
@ -308,6 +309,8 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
const auto type = FunctionType::get(GetType<void>(), {m_thread_type->getPointerTo()}, false);
const auto block = m_ir->GetInsertBlock();
FunctionCallee callee;
if (!indirect)
{
if ((!m_reloc && target < 0x10000) || target >= u64{} - 0x10000)
@ -316,7 +319,7 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
return;
}
indirect = m_module->getOrInsertFunction(fmt::format("__0x%llx", target), type).getCallee();
callee = m_module->getOrInsertFunction(fmt::format("__0x%llx", target), type);
}
else
{
@ -333,11 +336,11 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
const auto pos = m_ir->CreateLShr(indirect, 2, "", true);
const auto ptr = m_ir->CreateGEP(m_ir->CreateLoad(m_call), {m_ir->getInt64(0), pos});
indirect = m_ir->CreateIntToPtr(m_ir->CreateLoad(ptr), type->getPointerTo());
callee = FunctionCallee(type, m_ir->CreateIntToPtr(m_ir->CreateLoad(ptr), type->getPointerTo()));
}
m_ir->SetInsertPoint(block);
m_ir->CreateCall(indirect, {m_thread})->setTailCallKind(llvm::CallInst::TCK_Tail);
m_ir->CreateCall(callee, {m_thread})->setTailCallKind(llvm::CallInst::TCK_Tail);
m_ir->CreateRetVoid();
}
@ -455,7 +458,7 @@ Value* PPUTranslator::Broadcast(Value* value, u32 count)
{
if (const auto cv = dyn_cast<Constant>(value))
{
return ConstantVector::getSplat(count, cv);
return ConstantVector::getSplat({count, false}, cv);
}
return m_ir->CreateVectorSplat(count, value);
@ -464,10 +467,10 @@ Value* PPUTranslator::Broadcast(Value* value, u32 count)
std::pair<Value*, Value*> PPUTranslator::Saturate(Value* value, CmpInst::Predicate inst, Value* extreme)
{
// Modify args
if (value->getType()->isVectorTy() && !extreme->getType()->isVectorTy())
extreme = Broadcast(extreme, value->getType()->getVectorNumElements());
if (extreme->getType()->isVectorTy() && !value->getType()->isVectorTy())
value = Broadcast(value, extreme->getType()->getVectorNumElements());
if (auto v = dyn_cast<VectorType>(value->getType()); v && !extreme->getType()->isVectorTy())
extreme = Broadcast(extreme, v->getNumElements());
if (auto e = dyn_cast<VectorType>(extreme->getType()); e && !value->getType()->isVectorTy())
value = Broadcast(value, e->getNumElements());
// Compare args
const auto cmp = m_ir->CreateICmp(inst, value, extreme);
@ -493,9 +496,9 @@ Value* PPUTranslator::Scale(Value* value, s32 scale)
const auto type = value->getType();
const auto power = std::pow(2, scale);
if (type->isVectorTy())
if (auto v = dyn_cast<VectorType>(type))
{
return m_ir->CreateFMul(value, ConstantVector::getSplat(type->getVectorNumElements(), ConstantFP::get(type->getVectorElementType(), power)));
return m_ir->CreateFMul(value, ConstantVector::getSplat({v->getNumElements(), false}, ConstantFP::get(v->getElementType(), power)));
}
else
{
@ -519,7 +522,7 @@ Value* PPUTranslator::Shuffle(Value* left, Value* right, std::initializer_list<u
{
std::vector<u32> data; data.reserve(indices.size());
const u32 mask = type->getVectorNumElements() - 1;
const u32 mask = cast<VectorType>(type)->getNumElements() - 1;
// Transform indices (works for vectors with size 2^N)
for (std::size_t i = 0; i < indices.size(); i++)
@ -623,7 +626,7 @@ void PPUTranslator::CompilationError(const std::string& error)
void PPUTranslator::MFVSCR(ppu_opcode_t op)
{
const auto vscr = m_ir->CreateOr(ZExt(RegLoad(m_sat), GetType<u32>()), m_ir->CreateShl(ZExt(RegLoad(m_nj), GetType<u32>()), 16));
SetVr(op.vd, m_ir->CreateInsertElement(ConstantVector::getSplat(4, m_ir->getInt32(0)), vscr, m_ir->getInt32(m_is_be ? 3 : 0)));
SetVr(op.vd, m_ir->CreateInsertElement(ConstantAggregateZero::get(GetType<u32[4]>()), vscr, m_ir->getInt32(m_is_be ? 3 : 0)));
}
void PPUTranslator::MTVSCR(ppu_opcode_t op)
@ -909,12 +912,12 @@ void PPUTranslator::VCTSXS(ppu_opcode_t op)
const auto b = GetVr(op.vb, VrType::vf);
const auto scaled = Scale(b, op.vuimm);
//const auto const0 = ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 0.0));
const auto const1 = ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), -std::pow(2, 31)));
const auto const1 = ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), -std::pow(2, 31)));
//const auto is_nan = m_ir->CreateFCmpUNO(b, const0); // NaN -> 0.0
const auto sat_l = m_ir->CreateFCmpOLT(scaled, const1); // TODO ???
const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), std::pow(2, 31))));
const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), std::pow(2, 31))));
const auto converted = m_ir->CreateFPToSI(m_ir->CreateSelect(sat_l, const1, scaled), GetType<s32[4]>());
SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat(4, m_ir->getInt32(0x7fffffff)), converted));
SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat({4, false}, m_ir->getInt32(0x7fffffff)), converted));
SetSat(IsNotZero(m_ir->CreateOr(sat_l, sat_h)));
}
@ -922,12 +925,12 @@ void PPUTranslator::VCTUXS(ppu_opcode_t op)
{
const auto b = GetVr(op.vb, VrType::vf);
const auto scaled = Scale(b, op.vuimm);
const auto const0 = ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 0.0));
const auto const0 = ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), 0.0));
//const auto is_nan = m_ir->CreateFCmpUNO(b, const0); // NaN -> 0.0
const auto sat_l = m_ir->CreateFCmpOLT(scaled, const0);
const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), std::pow(2, 32)))); // TODO ???
const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), std::pow(2, 32)))); // TODO ???
const auto converted = m_ir->CreateFPToUI(m_ir->CreateSelect(sat_l, const0, scaled), GetType<u32[4]>());
SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat(4, m_ir->getInt32(0xffffffff)), converted));
SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat({4, false}, m_ir->getInt32(0xffffffff)), converted));
SetSat(IsNotZero(m_ir->CreateOr(sat_l, sat_h)));
}
@ -1044,7 +1047,7 @@ void PPUTranslator::VMHADDSHS(ppu_opcode_t op)
void PPUTranslator::VMHRADDSHS(ppu_opcode_t op)
{
const auto abc = SExt(GetVrs(VrType::vi16, op.va, op.vb, op.vc));
const auto result = m_ir->CreateAdd(m_ir->CreateAShr(m_ir->CreateAdd(m_ir->CreateMul(abc[0], abc[1]), ConstantVector::getSplat(8, m_ir->getInt32(0x4000))), 15), abc[2]);
const auto result = m_ir->CreateAdd(m_ir->CreateAShr(m_ir->CreateAdd(m_ir->CreateMul(abc[0], abc[1]), ConstantVector::getSplat({8, false}, m_ir->getInt32(0x4000))), 15), abc[2]);
const auto saturated = SaturateSigned(result, -0x8000, 0x7fff);
SetVr(op.vd, saturated.first);
SetSat(IsNotZero(saturated.second));
@ -1309,7 +1312,7 @@ void PPUTranslator::VPERM(ppu_opcode_t op)
const auto a = get_vr<u8[16]>(op.va);
const auto b = get_vr<u8[16]>(op.vb);
const auto c = get_vr<u8[16]>(op.vc);
if (m_use_avx512_icl && op.ra != op.rb)
{
const auto i = eval(~c);
@ -1401,7 +1404,7 @@ void PPUTranslator::VPKUWUS(ppu_opcode_t op)
void PPUTranslator::VREFP(ppu_opcode_t op)
{
const auto result = VecHandleResult(m_ir->CreateFDiv(ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 1.0)), GetVr(op.vb, VrType::vf)));
const auto result = VecHandleResult(m_ir->CreateFDiv(ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), 1.0)), GetVr(op.vb, VrType::vf)));
SetVr(op.vd, result);
}
@ -1445,7 +1448,7 @@ void PPUTranslator::VRLW(ppu_opcode_t op)
void PPUTranslator::VRSQRTEFP(ppu_opcode_t op)
{
const auto result = m_ir->CreateFDiv(ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 1.0)), Call(GetType<f32[4]>(), "llvm.sqrt.v4f32", GetVr(op.vb, VrType::vf)));
const auto result = m_ir->CreateFDiv(ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), 1.0)), Call(GetType<f32[4]>(), "llvm.sqrt.v4f32", GetVr(op.vb, VrType::vf)));
SetVr(op.vd, VecHandleResult(result));
}
@ -1472,7 +1475,7 @@ void PPUTranslator::VSEL(ppu_opcode_t op)
set_vr(op.vd, select(noncast<s32[4]>(c) != 0, get_vr<u32[4]>(op.vb), get_vr<u32[4]>(op.va)));
return;
}
bool sel_16 = true;
for (u32 i = 0; i < 8; i++)
{
@ -1488,7 +1491,7 @@ void PPUTranslator::VSEL(ppu_opcode_t op)
set_vr(op.vd, select(bitcast<s16[8]>(c) != 0, get_vr<u16[8]>(op.vb), get_vr<u16[8]>(op.va)));
return;
}
bool sel_8 = true;
for (u32 i = 0; i < 16; i++)
@ -1582,17 +1585,17 @@ void PPUTranslator::VSPLTH(ppu_opcode_t op)
void PPUTranslator::VSPLTISB(ppu_opcode_t op)
{
SetVr(op.vd, ConstantVector::getSplat(16, m_ir->getInt8(op.vsimm)));
SetVr(op.vd, ConstantVector::getSplat({16, false}, m_ir->getInt8(op.vsimm)));
}
void PPUTranslator::VSPLTISH(ppu_opcode_t op)
{
SetVr(op.vd, ConstantVector::getSplat(8, m_ir->getInt16(op.vsimm)));
SetVr(op.vd, ConstantVector::getSplat({8, false}, m_ir->getInt16(op.vsimm)));
}
void PPUTranslator::VSPLTISW(ppu_opcode_t op)
{
SetVr(op.vd, ConstantVector::getSplat(4, m_ir->getInt32(op.vsimm)));
SetVr(op.vd, ConstantVector::getSplat({4, false}, m_ir->getInt32(op.vsimm)));
}
void PPUTranslator::VSPLTW(ppu_opcode_t op)
@ -1800,7 +1803,7 @@ void PPUTranslator::VSUM4UBS(ppu_opcode_t op)
const auto e3 = Shuffle(a, nullptr, { 3, 7, 11, 15 });
const auto r = Add({ b, e0, e1, e2, e3 }); // Summ, (e0+e1+e2+e3) is small
const auto s = m_ir->CreateICmpULT(r, b); // Carry (saturation)
SetVr(op.vd, m_ir->CreateSelect(s, ConstantVector::getSplat(4, m_ir->getInt32(0xffffffff)), r));
SetVr(op.vd, m_ir->CreateSelect(s, ConstantVector::getSplat({4, false}, m_ir->getInt32(0xffffffff)), r));
SetSat(IsNotZero(s));
}
@ -1843,7 +1846,7 @@ void PPUTranslator::VXOR(ppu_opcode_t op)
if (op.va == op.vb)
{
// Assign zero, break dependencies
SetVr(op.vd, ConstantVector::getSplat(4, m_ir->getInt32(0)));
SetVr(op.vd, ConstantAggregateZero::get(GetType<u32[4]>()));
return;
}

View File

@ -317,7 +317,7 @@ public:
llvm::CallInst* Call(llvm::Type* ret, llvm::AttributeList attr, llvm::StringRef name, Args... args)
{
// Call the function
return m_ir->CreateCall(m_module->getOrInsertFunction(name, attr, ret, args->getType()...).getCallee(), {args...});
return m_ir->CreateCall(m_module->getOrInsertFunction(name, attr, ret, args->getType()...), {args...});
}
// Call a function

View File

@ -3418,14 +3418,14 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
}
// Create tail call to the function chunk (non-tail calls are just out of question)
void tail_chunk(llvm::Value* chunk, llvm::Value* base_pc = nullptr)
void tail_chunk(llvm::FunctionCallee callee, llvm::Value* base_pc = nullptr)
{
if (!chunk && !g_cfg.core.spu_verification)
if (!callee && !g_cfg.core.spu_verification)
{
// Disable patchpoints if verification is disabled
chunk = m_dispatch;
callee = m_dispatch;
}
else if (!chunk)
else if (!callee)
{
// Create branch patchpoint if chunk == nullptr
verify(HERE), m_finfo, !m_finfo->fn || m_function == m_finfo->chunk;
@ -3444,12 +3444,13 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
return;
}
chunk = ppfunc;
callee = ppfunc;
base_pc = m_ir->getInt32(0);
}
auto call = m_ir->CreateCall(chunk, {m_thread, m_lsptr, base_pc ? base_pc : m_base_pc});
auto func = m_finfo ? m_finfo->chunk : llvm::cast<llvm::Function>(chunk);
verify(HERE), callee;
auto call = m_ir->CreateCall(callee, {m_thread, m_lsptr, base_pc ? base_pc : m_base_pc});
auto func = m_finfo ? m_finfo->chunk : llvm::dyn_cast<llvm::Function>(callee.getCallee());
call->setCallingConv(func->getCallingConv());
call->setTailCall();
@ -4341,7 +4342,7 @@ public:
for (u32 j = starta; j < end; j += 32)
{
u32 indices[8];
int indices[8];
bool holes = false;
bool data = false;
@ -4373,7 +4374,7 @@ public:
// Mask if necessary
if (holes)
{
vls = m_ir->CreateShuffleVector(vls, ConstantVector::getSplat(8, m_ir->getInt32(0)), indices);
vls = m_ir->CreateShuffleVector(vls, ConstantAggregateZero::get(vls->getType()), indices);
}
// Perform bitwise comparison and accumulate
@ -4419,7 +4420,8 @@ public:
// Proceed to the next code
if (entry_chunk->chunk->getReturnType() != get_type<void>())
{
const auto next_call = m_ir->CreateCall(m_ir->CreateBitCast(entry_call, main_func->getType()), {m_thread, m_lsptr, m_ir->getInt64(0)});
const auto f_ptr = m_ir->CreateBitCast(entry_call, main_func->getType());
const auto next_call = m_ir->CreateCall({main_func->getFunctionType(), f_ptr}, {m_thread, m_lsptr, m_ir->getInt64(0)});
next_call->setCallingConv(main_func->getCallingConv());
next_call->setTailCall();
}
@ -4456,7 +4458,8 @@ public:
if (entry_chunk->chunk->getReturnType() == get_type<void>())
{
const auto next_call = m_ir->CreateCall(m_ir->CreateBitCast(dispatcher, main_func->getType()), {m_thread, m_lsptr, m_ir->getInt64(0)});
const auto f_ptr = m_ir->CreateBitCast(dispatcher, main_func->getType());
const auto next_call = m_ir->CreateCall({main_func->getFunctionType(), f_ptr}, {m_thread, m_lsptr, m_ir->getInt64(0)});
next_call->setCallingConv(main_func->getCallingConv());
next_call->setTailCall();
m_ir->CreateRetVoid();
@ -4911,7 +4914,7 @@ public:
// Decode (shift) and load function pointer
const auto first = m_ir->CreateLoad(m_ir->CreateGEP(m_ir->CreateBitCast(m_interp_table, if_pptr), m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn)));
const auto call0 = m_ir->CreateCall(first, {m_lsptr, m_thread, m_interp_pc, m_interp_op, m_interp_table, m_interp_7f0, m_interp_regs});
const auto call0 = m_ir->CreateCall({if_type, first}, {m_lsptr, m_thread, m_interp_pc, m_interp_op, m_interp_table, m_interp_7f0, m_interp_regs});
call0->setCallingConv(CallingConv::GHC);
m_ir->CreateRetVoid();
@ -5125,7 +5128,7 @@ public:
}
const auto arg3 = UndefValue::get(get_type<u32>());
const auto _ret = m_ir->CreateCall(fret, {m_lsptr, m_thread, m_interp_pc, arg3, m_interp_table, m_interp_7f0, m_interp_regs});
const auto _ret = m_ir->CreateCall({if_type, fret}, {m_lsptr, m_thread, m_interp_pc, arg3, m_interp_table, m_interp_7f0, m_interp_regs});
_ret->setCallingConv(CallingConv::GHC);
_ret->setTailCall();
m_ir->CreateRetVoid();
@ -5149,7 +5152,7 @@ public:
m_interp_regs = _ptr(m_thread, get_reg_offset(0));
}
const auto ncall = m_ir->CreateCall(next_if, {m_lsptr, m_thread, m_interp_pc, next_op, m_interp_table, m_interp_7f0, m_interp_regs});
const auto ncall = m_ir->CreateCall({if_type, next_if}, {m_lsptr, m_thread, m_interp_pc, next_op, m_interp_table, m_interp_7f0, m_interp_regs});
ncall->setCallingConv(CallingConv::GHC);
ncall->setTailCall();
m_ir->CreateRetVoid();
@ -8405,7 +8408,9 @@ public:
// Clear stack mirror and return by tail call to the provided return address
m_ir->CreateStore(splat<u64[2]>(-1).eval(m_ir), m_ir->CreateBitCast(m_ir->CreateGEP(m_thread, stack0.value), get_type<u64(*)[2]>()));
const auto targ = m_ir->CreateAdd(m_ir->CreateLShr(_ret, 32), get_segment_base());
tail_chunk(m_ir->CreateIntToPtr(targ, m_finfo->chunk->getFunctionType()->getPointerTo()), m_ir->CreateTrunc(m_ir->CreateLShr(link, 32), get_type<u32>()));
const auto type = m_finfo->chunk->getFunctionType();
const auto fval = m_ir->CreateIntToPtr(targ, type->getPointerTo());
tail_chunk({type, fval}, m_ir->CreateTrunc(m_ir->CreateLShr(link, 32), get_type<u32>()));
m_ir->SetInsertPoint(fail);
}
@ -8420,7 +8425,7 @@ public:
const auto ad64 = m_ir->CreateZExt(ad32, get_type<u64>());
const auto pptr = m_ir->CreateGEP(m_function_table, {m_ir->getInt64(0), m_ir->CreateLShr(ad64, 2, "", true)});
tail_chunk(m_ir->CreateLoad(pptr));
tail_chunk({m_dispatch->getFunctionType(), m_ir->CreateLoad(pptr)});
m_ir->SetInsertPoint(fail);
}

View File

@ -521,3 +521,55 @@ int main(int argc, char** argv)
// run event loop (maybe only needed for the gui application)
return app->exec();
}
// Temporarily, this is code from std for prebuilt LLVM. I don't understand why this is necessary.
// From the same MSVC 19.27.29112.0, LLVM libs depend on these, but RPCS3 gets linker errors.
#ifdef _WIN32
extern "C"
{
int __stdcall __std_init_once_begin_initialize(void** ppinit, ulong f, int* fp, void** lpc) noexcept
{
return InitOnceBeginInitialize(reinterpret_cast<LPINIT_ONCE>(ppinit), f, fp, lpc);
}
int __stdcall __std_init_once_complete(void** ppinit, ulong f, void* lpc) noexcept
{
return InitOnceComplete(reinterpret_cast<LPINIT_ONCE>(ppinit), f, lpc);
}
size_t __stdcall __std_get_string_size_without_trailing_whitespace(const char* str, size_t size) noexcept
{
while (size)
{
switch (str[size - 1])
{
case 0:
case ' ':
case '\n':
case '\r':
case '\t':
{
size--;
continue;
}
}
break;
}
return size;
}
size_t __stdcall __std_system_error_allocate_message(const unsigned long msg_id, char** ptr_str) noexcept
{
return __std_get_string_size_without_trailing_whitespace(*ptr_str, FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, msg_id, 0, reinterpret_cast<char*>(ptr_str), 0, nullptr));
}
void __stdcall __std_system_error_deallocate_message(char* s) noexcept
{
LocalFree(s);
}
}
#endif

View File

@ -10,7 +10,53 @@
<Link>
<AdditionalLibraryDirectories Condition="'$(Configuration)'=='Debug - LLVM'">%(AdditionalLibraryDirectories);..\llvm_build\Debug\lib</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories Condition="'$(Configuration)'=='Release - LLVM'">%(AdditionalLibraryDirectories);..\llvm_build\Release\lib</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies);LLVMProfileData.lib;LLVMDebugInfoCodeView.lib;LLVMDebugInfoMSF.lib;LLVMInstrumentation.lib;LLVMMCJIT.lib;LLVMRuntimeDyld.lib;LLVMVectorize.lib;LLVMX86CodeGen.lib;LLVMGlobalISel.lib;LLVMX86Disassembler.lib;LLVMExecutionEngine.lib;LLVMAsmPrinter.lib;LLVMSelectionDAG.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMTarget.lib;LLVMX86Desc.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMCore.lib;LLVMX86Utils.lib;LLVMMC.lib;LLVMX86Info.lib;LLVMSupport.lib;LLVMMCDisassembler.lib;LLVMipo.lib;LLVMBinaryFormat.lib;LLVMPasses.lib;LLVMIRReader.lib;LLVMLinker.lib;LLVMAsmParser.lib;LLVMX86AsmParser.lib;LLVMDemangle.lib;LLVMDebugInfoDWARF.lib;LLVMRemarks.lib;LLVMBitstreamReader.lib;LLVMTextAPI.lib;LLVMCFGuard.lib</AdditionalDependencies>
<AdditionalDependencies>%(AdditionalDependencies);
LLVMProfileData.lib;
LLVMDebugInfoCodeView.lib;
LLVMDebugInfoMSF.lib;
LLVMInstrumentation.lib;
LLVMMCJIT.lib;
LLVMRuntimeDyld.lib;
LLVMVectorize.lib;
LLVMX86CodeGen.lib;
LLVMGlobalISel.lib;
LLVMX86Disassembler.lib;
LLVMExecutionEngine.lib;
LLVMAsmPrinter.lib;
LLVMSelectionDAG.lib;
LLVMCodeGen.lib;
LLVMScalarOpts.lib;
LLVMInstCombine.lib;
LLVMTransformUtils.lib;
LLVMAnalysis.lib;
LLVMTarget.lib;
LLVMX86Desc.lib;
LLVMObject.lib;
LLVMMCParser.lib;
LLVMBitReader.lib;
LLVMCore.lib;
LLVMMC.lib;
LLVMX86Info.lib;
LLVMSupport.lib;
LLVMMCDisassembler.lib;
LLVMipo.lib;
LLVMBinaryFormat.lib;
LLVMPasses.lib;
LLVMIRReader.lib;
LLVMLinker.lib;
LLVMAsmParser.lib;
LLVMX86AsmParser.lib;
LLVMDemangle.lib;
LLVMDebugInfoDWARF.lib;
LLVMRemarks.lib;
LLVMBitstreamReader.lib;
LLVMTextAPI.lib;
LLVMCFGuard.lib;
LLVMAggressiveInstCombine.lib;
LLVMBitWriter.lib;
LLVMCoroutines.lib;
LLVMObjCARCOpts.lib;
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />