Index: lib/Target/Mips/MipsFastISel.cpp =================================================================== --- lib/Target/Mips/MipsFastISel.cpp +++ lib/Target/Mips/MipsFastISel.cpp @@ -96,6 +96,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); @@ -1293,7 +1294,8 @@ GetReturnInfo(F.getReturnType(), F.getAttributes(), Outs, TLI); // Analyze operands of the call, assigning locations to each operand. SmallVector ValLocs; - MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext()); + MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, + I->getContext()); CCAssignFn *RetCC = RetCC_Mips; CCInfo.AnalyzeReturn(Outs, RetCC); @@ -1515,6 +1517,41 @@ 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)); + if (!Src0Reg) + return false; + unsigned Src1Reg = getRegForValue(I->getOperand(1)); + if (!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; if (!isTypeSupported(I->getType(), RetVT, /*IsVectorAllowed=*/false)) @@ -1590,6 +1627,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,99 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | 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 + +; Function Attrs: noinline nounwind +define void @rems() #0 { +entry: +; CHECK-LABEL: .ent rems + %0 = load i32* @sj, align 4 + %1 = load i32* @sk, align 4 + %rem = srem i32 %0, %1 + store i32 %rem, i32* @si, align 4 +; 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]]) + ret void +} + +; Function Attrs: noinline nounwind +define void @remu() #0 { +entry: +; CHECK-LABEL: .ent 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]]) + + + %0 = load i32* @uj, align 4 + %1 = load i32* @uk, align 4 + %rem = urem i32 %0, %1 + store i32 %rem, i32* @ui, align 4 + ret void +} + +; Function Attrs: nounwind +define i32 @main() #1 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval + call void @rems() + call void @remu() + %0 = load i32* @si, align 4 + %cmp = icmp ne i32 %0, 12 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + call void @abort() #3 + unreachable + +if.end: ; preds = %entry + %1 = load i32* @ui, align 4 + %cmp1 = icmp ne i32 %1, 28 + br i1 %cmp1, label %if.then2, label %if.end3 + +if.then2: ; preds = %if.end + call void @abort() #3 + unreachable + +if.end3: ; preds = %if.end + ret i32 0 +} + +; Function Attrs: noreturn +declare void @abort() #2 + +attributes #0 = { noinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { noreturn "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { noreturn } + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"PIC Level", i32 2} +!1 = !{!"clang version 3.7.0 (gitosis@dmz-portal.mips.com:clang.git 9b0d3553724b8a381c74d439cd4ff393c91dc484) (gitosis@dmz-portal.mips.com:llvm.git bbf9cc75cee50d9bed53aac1aa874711323af1ea)"}