From d856dc89a899cc81f49fc98ea456bc5086b819b1 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 6 Jul 2018 02:23:47 +0300 Subject: [PATCH] SPU LLVM: combine SELB with comparison instructions Turn bitwise select into a vector select --- rpcs3/Emu/Cell/SPURecompiler.cpp | 63 +++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 10aa005290..c2ed545a47 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -3869,8 +3869,67 @@ public: void SELB(spu_opcode_t op) { - const auto c = get_vr(op.rc); - set_vr(op.rt4, (get_vr(op.ra) & ~c) | (get_vr(op.rb) & c)); + if (auto ei = llvm::dyn_cast_or_null(m_block->reg[op.rc])) + { + // Detect if the mask comes from a comparison instruction + if (ei->getOpcode() == llvm::Instruction::SExt && ei->getSrcTy()->isIntOrIntVectorTy(1)) + { + auto op0 = ei->getOperand(0); + auto typ = ei->getDestTy(); + auto op1 = m_block->reg[op.rb]; + auto op2 = m_block->reg[op.ra]; + + if (typ == get_type()) + { + if (op1 && op1->getType() == get_type() || op2 && op2->getType() == get_type()) + { + op1 = get_vr(op.rb).value; + op2 = get_vr(op.ra).value; + } + else + { + op1 = get_vr(op.rb).value; + op2 = get_vr(op.ra).value; + } + } + else if (typ == get_type()) + { + if (op1 && op1->getType() == get_type() || op2 && op2->getType() == get_type()) + { + op1 = get_vr(op.rb).value; + op2 = get_vr(op.ra).value; + } + else + { + op1 = get_vr(op.rb).value; + op2 = get_vr(op.ra).value; + } + } + else if (typ == get_type()) + { + op1 = get_vr(op.rb).value; + op2 = get_vr(op.ra).value; + } + else if (typ == get_type()) + { + op1 = get_vr(op.rb).value; + op2 = get_vr(op.ra).value; + } + else + { + LOG_ERROR(SPU, "[0x%x] SELB: unknown cast destination type", m_pos); + op0 = nullptr; + } + + if (op0 && op1 && op2) + { + set_vr(op.rt4, m_ir->CreateSelect(op0, op1, op2)); + return; + } + } + } + + set_vr(op.rt4, merge(get_vr(op.rc), get_vr(op.rb), get_vr(op.ra))); } void SHUFB(spu_opcode_t op)