Index: lib/Target/Mips/MipsFastISel.cpp =================================================================== --- lib/Target/Mips/MipsFastISel.cpp +++ lib/Target/Mips/MipsFastISel.cpp @@ -97,6 +97,7 @@ bool selectFPExt(const Instruction *I); bool selectFPTrunc(const Instruction *I); bool selectFPToInt(const Instruction *I, bool IsSigned); + bool selectRem(const Instruction *I, unsigned ISDOpcode); bool selectRet(const Instruction *I); bool selectTrunc(const Instruction *I); bool selectIntExt(const Instruction *I); @@ -1419,6 +1420,44 @@ return Success ? DestReg : 0; } +bool MipsFastISel::selectRem(const Instruction *I, unsigned ISDOpcode) { + EVT DestEVT = TLI.getValueType(I->getType(), true); + if (!DestEVT.isSimple()) + return false; + + MVT DestVT = DestEVT.getSimpleVT(); + if (DestVT != MVT::i32) + return false; + + unsigned DivOpc; + switch (ISDOpcode) { + default: + return false; + case ISD::SREM: + DivOpc = Mips::SDIV; + break; + case ISD::UREM: + DivOpc = Mips::UDIV; + break; + } + + unsigned Src0Reg = getRegForValue(I->getOperand(0)); + unsigned Src1Reg = getRegForValue(I->getOperand(1)); + if (!Src0Reg || !Src1Reg) + return false; + + emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg); + emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7); + + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + if (!ResultReg) + return false; + + emitInst(Mips::MFHI, ResultReg); + updateValueMap(I, ResultReg); + return true; +} + bool MipsFastISel::selectShift(const Instruction *I) { MVT RetVT; @@ -1504,6 +1543,14 @@ return selectLoad(I); case Instruction::Store: return selectStore(I); + case Instruction::SRem: + if (!selectBinaryOp(I, ISD::SREM)) + return selectRem(I, ISD::SREM); + return true; + case Instruction::URem: + if (!selectBinaryOp(I, ISD::UREM)) + return selectRem(I, ISD::UREM); + return true; case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: Index: test/CodeGen/Mips/Fast-ISel/rem1.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/Fast-ISel/rem1.ll @@ -0,0 +1,56 @@ +; RUN: llc < %s -march=mipsel -mcpu=mips32 -O0 -relocation-model=pic \ +; RUN: -fast-isel=true -mips-fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -march=mipsel -mcpu=mips32r2 -O0 -relocation-model=pic \ +; RUN: -fast-isel=true -mips-fast-isel -fast-isel-abort=1 | FileCheck %s + +@sj = global i32 200, align 4 +@sk = global i32 -47, align 4 +@uj = global i32 200, align 4 +@uk = global i32 43, align 4 +@si = common global i32 0, align 4 +@ui = common global i32 0, align 4 + +define void @rems() { + ; CHECK-LABEL: rems: + + ; CHECK: lui $[[GOT1:[0-9]+]], %hi(_gp_disp) + ; CHECK: addiu $[[GOT2:[0-9]+]], $[[GOT1]], %lo(_gp_disp) + ; CHECK: addu $[[GOT:[0-9]+]], $[[GOT2:[0-9]+]], $25 + ; CHECK-DAG: lw $[[I_ADDR:[0-9]+]], %got(si)($[[GOT]]) + ; CHECK-DAG: lw $[[K_ADDR:[0-9]+]], %got(sk)($[[GOT]]) + ; CHECK-DAG: lw $[[J_ADDR:[0-9]+]], %got(sj)($[[GOT]]) + ; CHECK-DAG: lw $[[J:[0-9]+]], 0($[[J_ADDR]]) + ; CHECK-DAG: lw $[[K:[0-9]+]], 0($[[K_ADDR]]) + ; CHECK-DAG: div $zero, $[[J]], $[[K]] + ; CHECK_DAG: teq $[[K]], $zero, 7 + ; CHECK-DAG: mfhi $[[RESULT:[0-9]+]] + ; CHECK: sw $[[RESULT]], 0($[[I_ADDR]]) + %1 = load i32, i32* @sj, align 4 + %2 = load i32, i32* @sk, align 4 + %rem = srem i32 %1, %2 + store i32 %rem, i32* @si, align 4 + ret void +} + +; Function Attrs: noinline nounwind +define void @remu() { + ; CHECK-LABEL: remu: + + ; CHECK: lui $[[GOT1:[0-9]+]], %hi(_gp_disp) + ; CHECK: addiu $[[GOT2:[0-9]+]], $[[GOT1]], %lo(_gp_disp) + ; CHECK: addu $[[GOT:[0-9]+]], $[[GOT2:[0-9]+]], $25 + ; CHECK-DAG: lw $[[I_ADDR:[0-9]+]], %got(ui)($[[GOT]]) + ; CHECK-DAG: lw $[[K_ADDR:[0-9]+]], %got(uk)($[[GOT]]) + ; CHECK-DAG: lw $[[J_ADDR:[0-9]+]], %got(uj)($[[GOT]]) + ; CHECK-DAG: lw $[[J:[0-9]+]], 0($[[J_ADDR]]) + ; CHECK-DAG: lw $[[K:[0-9]+]], 0($[[K_ADDR]]) + ; CHECK-DAG: divu $zero, $[[J]], $[[K]] + ; CHECK_DAG: teq $[[K]], $zero, 7 + ; CHECK-DAG: mfhi $[[RESULT:[0-9]+]] + ; CHECK: sw $[[RESULT]], 0($[[I_ADDR]]) + %1 = load i32, i32* @uj, align 4 + %2 = load i32, i32* @uk, align 4 + %rem = urem i32 %1, %2 + store i32 %rem, i32* @ui, align 4 + ret void +}