remove unnecessary pointer bitcasts

This commit is contained in:
oltolm 2023-04-05 13:35:06 +02:00 committed by Ivan
parent f0e36c6365
commit 6fbca1acfd
3 changed files with 48 additions and 55 deletions

View file

@ -385,7 +385,7 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
const auto pos = m_ir->CreateShl(indirect, 1);
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(get_type<u8>(), m_exec, pos));
const auto val = m_ir->CreateLoad(get_type<u64>(), m_ir->CreateBitCast(ptr, get_type<u64*>()));
const auto val = m_ir->CreateLoad(get_type<u64>(), ptr);
callee = FunctionCallee(type, m_ir->CreateIntToPtr(m_ir->CreateAnd(val, 0xffff'ffff'ffff), type->getPointerTo()));
// Load new segment address
@ -456,7 +456,7 @@ void PPUTranslator::FlushRegisters()
m_ir->SetInsertPoint(block);
}
m_ir->CreateStore(local, bitcast(m_globals[index], local->getType()->getPointerTo()));
m_ir->CreateStore(local, m_globals[index]);
m_globals[index] = nullptr;
}
}
@ -591,9 +591,9 @@ void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
}
}
llvm::Value* PPUTranslator::GetMemory(llvm::Value* addr, llvm::Type* type)
llvm::Value* PPUTranslator::GetMemory(llvm::Value* addr)
{
return bitcast(m_ir->CreateGEP(get_type<u8>(), m_base, addr), type->getPointerTo());
return m_ir->CreateGEP(get_type<u8>(), m_base, addr);
}
Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align)
@ -604,12 +604,12 @@ Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align)
{
// Read, byteswap, bitcast
const auto int_type = m_ir->getIntNTy(size);
const auto value = m_ir->CreateAlignedLoad(int_type, GetMemory(addr, int_type), llvm::MaybeAlign{align});
const auto value = m_ir->CreateAlignedLoad(int_type, GetMemory(addr), llvm::MaybeAlign{align});
return bitcast(Call(int_type, fmt::format("llvm.bswap.i%u", size), value), type);
}
// Read normally
return m_ir->CreateAlignedLoad(type, GetMemory(addr, type), llvm::MaybeAlign{align});
return m_ir->CreateAlignedLoad(type, GetMemory(addr), llvm::MaybeAlign{align});
}
void PPUTranslator::WriteMemory(Value* addr, Value* value, bool is_be, u32 align)
@ -625,7 +625,7 @@ void PPUTranslator::WriteMemory(Value* addr, Value* value, bool is_be, u32 align
}
// Write
m_ir->CreateAlignedStore(value, GetMemory(addr, value->getType()), llvm::MaybeAlign{align});
m_ir->CreateAlignedStore(value, GetMemory(addr), llvm::MaybeAlign{align});
}
void PPUTranslator::CompilationError(const std::string& error)
@ -2788,8 +2788,8 @@ void PPUTranslator::MTOCRF(ppu_opcode_t op)
std::fill_n(m_g_cr + i * 4, 4, nullptr);
const auto index = m_ir->CreateAnd(m_ir->CreateLShr(value, 28 - i * 4), 15);
const auto src = m_ir->CreateGEP(dyn_cast<GlobalVariable>(m_mtocr_table)->getValueType(), m_mtocr_table, {m_ir->getInt32(0), m_ir->CreateShl(index, 2)});
const auto dst = bitcast(m_ir->CreateStructGEP(m_thread_type, m_thread, static_cast<uint>(m_cr - m_locals) + i * 4), GetType<u8*>());
const auto src = m_ir->CreateGEP(m_mtocr_table->getValueType(), m_mtocr_table, {m_ir->getInt32(0), m_ir->CreateShl(index, 2)});
const auto dst = m_ir->CreateStructGEP(m_thread_type, m_thread, static_cast<uint>(m_cr - m_locals) + i * 4);
Call(GetType<void>(), "llvm.memcpy.p0.p0.i32", dst, src, m_ir->getInt32(4), m_ir->getFalse());
}
}
@ -3311,7 +3311,7 @@ void PPUTranslator::STVLX(ppu_opcode_t op)
const auto addr = op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb);
const auto data = pshufb(get_vr<u8[16]>(op.vs), build<u8[16]>(127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112) + vsplat<u8[16]>(trunc<u8>(value<u64>(addr) & 0xf)));
const auto mask = bitcast<bool[16]>(splat<u16>(0xffff) << trunc<u16>(value<u64>(addr) & 0xf));
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull), GetType<u8[16]>()));
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull)));
const auto align = splat<u32>(16);
eval(llvm_calli<void, decltype(data), decltype(ptr), decltype(align), decltype(mask)>{"llvm.masked.store.v16i8.p0", {data, ptr, align, mask}});
}
@ -3341,7 +3341,7 @@ void PPUTranslator::STVRX(ppu_opcode_t op)
const auto addr = op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb);
const auto data = pshufb(get_vr<u8[16]>(op.vs), build<u8[16]>(255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240) + vsplat<u8[16]>(trunc<u8>(value<u64>(addr) & 0xf)));
const auto mask = bitcast<bool[16]>(trunc<u16>(splat<u64>(0xffff) << (value<u64>(addr) & 0xf) >> 16));
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull), GetType<u8[16]>()));
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull)));
const auto align = splat<u32>(16);
eval(llvm_calli<void, decltype(data), decltype(ptr), decltype(align), decltype(mask)>{"llvm.masked.store.v16i8.p0", {data, ptr, align, mask}});
}
@ -3524,7 +3524,7 @@ void PPUTranslator::DCBZ(ppu_opcode_t op)
}
else
{
Call(GetType<void>(), "llvm.memset.p0.i32", GetMemory(addr, GetType<u8>()), m_ir->getInt8(0), m_ir->getInt32(128), m_ir->getFalse());
Call(GetType<void>(), "llvm.memset.p0.i32", GetMemory(addr), m_ir->getInt8(0), m_ir->getInt32(128), m_ir->getFalse());
}
}
@ -4009,7 +4009,7 @@ void PPUTranslator::FRES(ppu_opcode_t op)
const auto n = m_ir->CreateFCmpUNO(a, a); // test for NaN
const auto e = m_ir->CreateAnd(m_ir->CreateLShr(b, 52), 0x7ff); // double exp
const auto i = m_ir->CreateAnd(m_ir->CreateLShr(b, 45), 0x7f); // mantissa LUT index
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(dyn_cast<GlobalVariable>(m_fres_table)->getValueType(), m_fres_table, {m_ir->getInt64(0), i}));
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(m_fres_table->getValueType(), m_fres_table, {m_ir->getInt64(0), i}));
assert(ptr->getResultElementType() == get_type<u32>());
const auto m = m_ir->CreateShl(ZExt(m_ir->CreateLoad(ptr->getResultElementType(), ptr)), 29);
const auto c = m_ir->CreateICmpUGE(e, m_ir->getInt64(0x3ff + 0x80)); // test for INF
@ -4382,7 +4382,7 @@ void PPUTranslator::FRSQRTE(ppu_opcode_t op)
}
const auto b = m_ir->CreateBitCast(GetFpr(op.frb), GetType<u64>());
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(dyn_cast<GlobalVariable>(m_frsqrte_table)->getValueType(), m_frsqrte_table, {m_ir->getInt64(0), m_ir->CreateLShr(b, 49)}));
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(m_frsqrte_table->getValueType(), m_frsqrte_table, {m_ir->getInt64(0), m_ir->CreateLShr(b, 49)}));
assert(ptr->getResultElementType() == get_type<u32>());
const auto v = m_ir->CreateLoad(ptr->getResultElementType(), ptr);
const auto result = m_ir->CreateBitCast(m_ir->CreateShl(ZExt(v), 32), GetType<f64>());

View file

@ -54,9 +54,9 @@ class PPUTranslator final : public cpu_translator
// Thread context struct
llvm::StructType* m_thread_type;
llvm::Value* m_mtocr_table{};
llvm::Value* m_frsqrte_table{};
llvm::Value* m_fres_table{};
llvm::GlobalVariable* m_mtocr_table{};
llvm::GlobalVariable* m_frsqrte_table{};
llvm::GlobalVariable* m_fres_table{};
llvm::Value* m_globals[175];
llvm::Value** const m_g_cr = m_globals + 99;
@ -294,7 +294,7 @@ public:
void UseCondition(llvm::MDNode* hint, llvm::Value* = nullptr);
// Get memory pointer
llvm::Value* GetMemory(llvm::Value* addr, llvm::Type* type);
llvm::Value* GetMemory(llvm::Value* addr);
// Read from memory
llvm::Value* ReadMemory(llvm::Value* addr, llvm::Type* type, bool is_be = true, u32 align = 1);

View file

@ -4134,7 +4134,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
if (m_finfo->chunk->getReturnType() != get_type<void>())
{
m_ir->CreateRet(m_ir->CreateBitCast(ppfunc, get_type<u8*>()));
m_ir->CreateRet(ppfunc);
return;
}
@ -4370,9 +4370,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
template <typename T = u8>
llvm::Value* _ptr(llvm::Value* base, u32 offset)
{
const auto off = m_ir->CreateGEP(get_type<u8>(), base, m_ir->getInt64(offset));
const auto ptr = m_ir->CreateBitCast(off, get_type<T*>());
return ptr;
return m_ir->CreateGEP(get_type<u8>(), base, m_ir->getInt64(offset));
}
template <typename T, typename... Args>
@ -4385,8 +4383,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
llvm::Value* spu_ptr(value_t<u64> add, Args... offset_args)
{
const auto off = m_ir->CreateGEP(get_type<u8>(), m_thread, m_ir->getInt64(::offset32(offset_args...)));
const auto ptr = m_ir->CreateBitCast(m_ir->CreateAdd(off, add.value), get_type<T*>());
return ptr;
return m_ir->CreateAdd(off, add.value);
}
// Return default register type
@ -4433,7 +4430,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
{
if (!m_block)
{
return m_ir->CreateBitCast(_ptr<u8>(m_thread, get_reg_offset(index)), get_reg_type(index)->getPointerTo());
return _ptr<u8>(m_thread, get_reg_offset(index));
}
auto& ptr = ::at32(m_reg_addr, index);
@ -4446,7 +4443,6 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
// Emit register pointer at the beginning of the function chunk
m_ir->SetInsertPoint(m_function->getEntryBlock().getTerminator());
ptr = _ptr<u8>(m_thread, get_reg_offset(index));
ptr = m_ir->CreateBitCast(ptr, get_reg_type(index)->getPointerTo());
m_ir->SetInsertPoint(block_cur);
}
@ -4469,7 +4465,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto idx = m_ir->CreateAnd(I > 4 ? isr : isl, m_interp_7f0);
// Pointer to the register
return m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_interp_regs, m_ir->CreateZExt(idx, get_type<u64>())), get_type<T*>());
return m_ir->CreateGEP(get_type<u8>(), m_interp_regs, m_ir->CreateZExt(idx, get_type<u64>()));
}
llvm::Value* double_as_uint64(llvm::Value* val)
@ -5056,13 +5052,13 @@ public:
}
else if (func.data.size() == 1)
{
const auto pu32 = m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_base_pc), get_type<u32*>());
const auto pu32 = m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_base_pc);
const auto cond = m_ir->CreateICmpNE(m_ir->CreateLoad(get_type<u32>(), pu32), m_ir->getInt32(func.data[0]));
m_ir->CreateCondBr(cond, label_diff, label_body, m_md_unlikely);
}
else if (func.data.size() == 2)
{
const auto pu64 = m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_base_pc), get_type<u64*>());
const auto pu64 = m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_base_pc);
const auto cond = m_ir->CreateICmpNE(m_ir->CreateLoad(get_type<u64>(), pu64), m_ir->getInt64(static_cast<u64>(func.data[1]) << 32 | func.data[0]));
m_ir->CreateCondBr(cond, label_diff, label_body, m_md_unlikely);
}
@ -5219,8 +5215,7 @@ public:
// Proceed to the next code
if (entry_chunk->chunk->getReturnType() != get_type<void>())
{
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)});
const auto next_call = m_ir->CreateCall(main_func->getFunctionType(), entry_call, {m_thread, m_lsptr, m_ir->getInt64(0)});
next_call->setCallingConv(main_func->getCallingConv());
next_call->setTailCall();
}
@ -5258,15 +5253,14 @@ public:
if (entry_chunk->chunk->getReturnType() == get_type<void>())
{
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)});
const auto next_call = m_ir->CreateCall(main_func->getFunctionType(), dispatcher, {m_thread, m_lsptr, m_ir->getInt64(0)});
next_call->setCallingConv(main_func->getCallingConv());
next_call->setTailCall();
m_ir->CreateRetVoid();
}
else
{
m_ir->CreateRet(m_ir->CreateBitCast(dispatcher, get_type<u8*>()));
m_ir->CreateRet(dispatcher);
}
// Function that executes check_state and escapes if necessary
@ -5701,7 +5695,6 @@ public:
// Create interpreter table
const auto if_type = get_ftype<void, u8*, u8*, u32, u32, u8*, u32, u8*>();
const auto if_pptr = if_type->getPointerTo()->getPointerTo();
m_function_table = new GlobalVariable(*m_module, ArrayType::get(if_type->getPointerTo(), 1ull << m_interp_magn), true, GlobalValue::InternalLinkage, nullptr);
// Add return function
@ -5722,11 +5715,11 @@ public:
// Load pc and opcode
m_interp_pc = m_ir->CreateLoad(get_type<u32>(), spu_ptr<u32>(&spu_thread::pc));
m_interp_op = m_ir->CreateLoad(get_type<u32>(), m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_ir->CreateZExt(m_interp_pc, get_type<u64>())), get_type<u32*>()));
m_interp_op = m_ir->CreateLoad(get_type<u32>(), m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_ir->CreateZExt(m_interp_pc, get_type<u64>())));
m_interp_op = m_ir->CreateCall(get_intrinsic<u32>(Intrinsic::bswap), {m_interp_op});
// Pinned constant, address of interpreter table
m_interp_table = m_ir->CreateBitCast(m_ir->CreateGEP(m_function_table->getValueType(), m_function_table, {m_ir->getInt64(0), m_ir->getInt64(0)}), get_type<u8*>());
m_interp_table = m_ir->CreateGEP(m_function_table->getValueType(), m_function_table, {m_ir->getInt64(0), m_ir->getInt64(0)});
// Pinned constant, mask for shifted register index
m_interp_7f0 = m_ir->getInt32(0x7f0);
@ -5744,8 +5737,8 @@ public:
m_ir->CreateStore(m_ir->CreateCall(get_intrinsic<u64>(Intrinsic::read_register), {rsp_name}), native_sp);
// Decode (shift) and load function pointer
const auto first = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_ir->CreateBitCast(m_interp_table, if_pptr), m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn)));
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});
const auto first = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_interp_table, m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn)));
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();
@ -5886,9 +5879,9 @@ public:
// Decode next instruction.
const auto next_pc = itype & spu_itype::branch ? m_interp_pc : m_interp_pc_next;
const auto be32_op = m_ir->CreateLoad(get_type<u32>(), m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_ir->CreateZExt(next_pc, get_type<u64>())), get_type<u32*>()));
const auto be32_op = m_ir->CreateLoad(get_type<u32>(), m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_ir->CreateZExt(next_pc, get_type<u64>())));
const auto next_op = m_ir->CreateCall(get_intrinsic<u32>(Intrinsic::bswap), {be32_op});
const auto next_if = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_ir->CreateBitCast(m_interp_table, if_pptr), m_ir->CreateLShr(next_op, 32u - m_interp_magn)));
const auto next_if = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_interp_table, m_ir->CreateLShr(next_op, 32u - m_interp_magn)));
llvm::cast<LoadInst>(next_if)->setVolatile(true);
if (!(itype & spu_itype::branch))
@ -5933,7 +5926,7 @@ public:
m_ir->SetInsertPoint(_next);
}
llvm::Value* fret = m_ir->CreateBitCast(m_interp_table, if_type->getPointerTo());
llvm::Value* fret = m_interp_table;
if (itype == spu_itype::WRCH ||
itype == spu_itype::RDCH ||
@ -5963,7 +5956,7 @@ public:
}
const auto arg3 = UndefValue::get(get_type<u32>());
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});
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();
@ -5987,7 +5980,7 @@ public:
m_interp_regs = _ptr(m_thread, get_reg_offset(0));
}
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});
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();
@ -6826,7 +6819,7 @@ public:
if (csize > 0 && csize <= 16)
{
// Generate single copy operation
m_ir->CreateStore(m_ir->CreateLoad(vtype, m_ir->CreateBitCast(src, vtype->getPointerTo())), m_ir->CreateBitCast(dst, vtype->getPointerTo()));
m_ir->CreateStore(m_ir->CreateLoad(vtype, src), dst);
}
else if (csize <= stride * 16 && !(csize % 32))
{
@ -6837,11 +6830,11 @@ public:
const auto _dst = m_ir->CreateGEP(get_type<u8>(), dst, m_ir->getInt32(i));
if (csize - i < stride)
{
m_ir->CreateStore(m_ir->CreateLoad(get_type<u8[16]>(), m_ir->CreateBitCast(_src, get_type<u8(*)[16]>())), m_ir->CreateBitCast(_dst, get_type<u8(*)[16]>()));
m_ir->CreateStore(m_ir->CreateLoad(get_type<u8[16]>(), _src), _dst);
}
else
{
m_ir->CreateAlignedStore(m_ir->CreateAlignedLoad(vtype, m_ir->CreateBitCast(_src, vtype->getPointerTo()), llvm::MaybeAlign{16}), m_ir->CreateBitCast(_dst, vtype->getPointerTo()), llvm::MaybeAlign{16});
m_ir->CreateAlignedStore(m_ir->CreateAlignedLoad(vtype, _src, llvm::MaybeAlign{16}), _dst, llvm::MaybeAlign{16});
}
}
}
@ -9694,13 +9687,13 @@ public:
void make_store_ls(value_t<u64> addr, value_t<u8[16]> data)
{
const auto bswapped = byteswap(data);
m_ir->CreateStore(bswapped.eval(m_ir), m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_lsptr, addr.value), get_type<u8(*)[16]>()));
m_ir->CreateStore(bswapped.eval(m_ir), m_ir->CreateGEP(get_type<u8>(), m_lsptr, addr.value));
}
auto make_load_ls(value_t<u64> addr)
{
value_t<u8[16]> data;
data.value = m_ir->CreateLoad(get_type<u8[16]>(), m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_lsptr, addr.value), get_type<u8(*)[16]>()));
data.value = m_ir->CreateLoad(get_type<u8[16]>(), m_ir->CreateGEP(get_type<u8>(), m_lsptr, addr.value));
return byteswap(data);
}
@ -9983,19 +9976,19 @@ public:
// Compare address stored in stack mirror with addr
const auto stack0 = eval(zext<u64>(sp) + ::offset32(&spu_thread::stack_mirror));
const auto stack1 = eval(stack0 + 8);
const auto _ret = m_ir->CreateLoad(get_type<u64>(), m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_thread, stack0.value), get_type<u64*>()));
const auto link = m_ir->CreateLoad(get_type<u64>(), m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_thread, stack1.value), get_type<u64*>()));
const auto _ret = m_ir->CreateLoad(get_type<u64>(), m_ir->CreateGEP(get_type<u8>(), m_thread, stack0.value));
const auto link = m_ir->CreateLoad(get_type<u64>(), m_ir->CreateGEP(get_type<u8>(), m_thread, stack1.value));
const auto fail = llvm::BasicBlock::Create(m_context, "", m_function);
const auto done = llvm::BasicBlock::Create(m_context, "", m_function);
const auto next = llvm::BasicBlock::Create(m_context, "", m_function);
m_ir->CreateCondBr(m_ir->CreateICmpEQ(addr.value, m_ir->CreateTrunc(link, get_type<u32>())), next, fail, m_md_likely);
m_ir->SetInsertPoint(next);
const auto cmp2 = m_ir->CreateLoad(get_type<u32>(), m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_lsptr, addr.value), get_type<u32*>()));
const auto cmp2 = m_ir->CreateLoad(get_type<u32>(), m_ir->CreateGEP(get_type<u8>(), m_lsptr, addr.value));
m_ir->CreateCondBr(m_ir->CreateICmpEQ(cmp2, m_ir->CreateTrunc(_ret, get_type<u32>())), done, fail, m_md_likely);
m_ir->SetInsertPoint(done);
// 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(get_type<u8>(), m_thread, stack0.value), get_type<u64(*)[2]>()));
m_ir->CreateStore(splat<u64[2]>(-1).eval(m_ir), m_ir->CreateGEP(get_type<u8>(), m_thread, stack0.value));
const auto targ = m_ir->CreateAdd(m_ir->CreateLShr(_ret, 32), get_segment_base());
const auto type = m_finfo->chunk->getFunctionType();
const auto fval = m_ir->CreateIntToPtr(targ, type->getPointerTo());
@ -10670,8 +10663,8 @@ public:
const auto rel_ptr = m_ir->CreateSub(m_ir->CreatePtrToInt(pfunc->chunk, get_type<u64>()), get_segment_base());
const auto ptr_plus_op = m_ir->CreateOr(m_ir->CreateShl(rel_ptr, 32), m_ir->getInt64(m_next_op));
const auto base_plus_pc = m_ir->CreateOr(m_ir->CreateShl(m_ir->CreateZExt(m_base_pc, get_type<u64>()), 32), m_ir->getInt64(m_pos + 4));
m_ir->CreateStore(ptr_plus_op, m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_thread, stack0.value), get_type<u64*>()));
m_ir->CreateStore(base_plus_pc, m_ir->CreateBitCast(m_ir->CreateGEP(get_type<u8>(), m_thread, stack1.value), get_type<u64*>()));
m_ir->CreateStore(ptr_plus_op, m_ir->CreateGEP(get_type<u8>(), m_thread, stack0.value));
m_ir->CreateStore(base_plus_pc, m_ir->CreateGEP(get_type<u8>(), m_thread, stack1.value));
}
}