Index: lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -88,17 +88,17 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { switch (Opcode) { case TargetOpcode::G_SDIV: - assert(Size == 32 && "Unsupported size"); - return RTLIB::SDIV_I32; + assert((Size == 32 || Size == 64) && "Unsupported size"); + return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32; case TargetOpcode::G_UDIV: - assert(Size == 32 && "Unsupported size"); - return RTLIB::UDIV_I32; + assert((Size == 32 || Size == 64) && "Unsupported size"); + return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32; case TargetOpcode::G_SREM: - assert(Size == 32 && "Unsupported size"); - return RTLIB::SREM_I32; + assert((Size == 32 || Size == 64) && "Unsupported size"); + return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32; case TargetOpcode::G_UREM: - assert(Size == 32 && "Unsupported size"); - return RTLIB::UREM_I32; + assert((Size == 32 || Size == 64) && "Unsupported size"); + return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32; case TargetOpcode::G_CTLZ_ZERO_UNDEF: assert(Size == 32 && "Unsupported size"); return RTLIB::CTLZ_I32; @@ -200,7 +200,7 @@ case TargetOpcode::G_SREM: case TargetOpcode::G_UREM: case TargetOpcode::G_CTLZ_ZERO_UNDEF: { - Type *HLTy = Type::getInt32Ty(Ctx); + Type *HLTy = IntegerType::get(Ctx, Size); auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); if (Status != Legalized) return Status; Index: lib/Target/Mips/MipsInstructionSelector.cpp =================================================================== --- lib/Target/Mips/MipsInstructionSelector.cpp +++ lib/Target/Mips/MipsInstructionSelector.cpp @@ -145,6 +145,33 @@ .addMemOperand(*I.memoperands_begin()); break; } + case G_UDIV: + case G_UREM: + case G_SDIV: + case G_SREM: { + unsigned HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); + bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV; + bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV; + + MachineInstr *PseudoDIV, *PseudoMove; + PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(), + TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV)) + .addDef(HILOReg) + .add(I.getOperand(1)) + .add(I.getOperand(2)); + if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI)) + return false; + + PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), + TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI)) + .addDef(I.getOperand(0).getReg()) + .addUse(HILOReg); + if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) + return false; + + I.eraseFromParent(); + return true; + } case G_CONSTANT: { int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue(); unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); Index: lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- lib/Target/Mips/MipsLegalizerInfo.cpp +++ lib/Target/Mips/MipsLegalizerInfo.cpp @@ -35,6 +35,11 @@ getActionDefinitionsBuilder({G_AND, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR}) .legalFor({s32}); + getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UREM, G_UDIV}) + .legalFor({s32}) + .minScalar(0, s32) + .libcallFor({s64}); + getActionDefinitionsBuilder(G_ICMP) .legalFor({{s32, s32}}) .minScalar(0, s32); Index: lib/Target/Mips/MipsRegisterBankInfo.cpp =================================================================== --- lib/Target/Mips/MipsRegisterBankInfo.cpp +++ lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -93,6 +93,10 @@ case G_SHL: case G_ASHR: case G_LSHR: + case G_SDIV: + case G_UDIV: + case G_SREM: + case G_UREM: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; break; case G_CONSTANT: Index: test/CodeGen/Mips/GlobalISel/instruction-select/rem_and_div.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/instruction-select/rem_and_div.mir @@ -0,0 +1,110 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + define void @sdiv_i32() {entry: ret void} + define void @srem_i32() {entry: ret void} + define void @udiv_i32() {entry: ret void} + define void @urem_i32() {entry: ret void} + +... +--- +name: sdiv_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: sdiv_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[PseudoSDIV:%[0-9]+]]:acc64 = PseudoSDIV [[COPY1]], [[COPY]] + ; MIPS32: [[PseudoMFLO:%[0-9]+]]:gpr32 = PseudoMFLO [[PseudoSDIV]] + ; MIPS32: $v0 = COPY [[PseudoMFLO]] + ; MIPS32: RetRA implicit $v0 + %0:gprb(s32) = COPY $a0 + %1:gprb(s32) = COPY $a1 + %2:gprb(s32) = G_SDIV %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: srem_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: srem_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[PseudoSDIV:%[0-9]+]]:acc64 = PseudoSDIV [[COPY1]], [[COPY]] + ; MIPS32: [[PseudoMFHI:%[0-9]+]]:gpr32 = PseudoMFHI [[PseudoSDIV]] + ; MIPS32: $v0 = COPY [[PseudoMFHI]] + ; MIPS32: RetRA implicit $v0 + %0:gprb(s32) = COPY $a0 + %1:gprb(s32) = COPY $a1 + %2:gprb(s32) = G_SREM %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: udiv_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: udiv_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[PseudoUDIV:%[0-9]+]]:acc64 = PseudoUDIV [[COPY1]], [[COPY]] + ; MIPS32: [[PseudoMFLO:%[0-9]+]]:gpr32 = PseudoMFLO [[PseudoUDIV]] + ; MIPS32: $v0 = COPY [[PseudoMFLO]] + ; MIPS32: RetRA implicit $v0 + %0:gprb(s32) = COPY $a0 + %1:gprb(s32) = COPY $a1 + %2:gprb(s32) = G_UDIV %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: urem_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: urem_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[PseudoUDIV:%[0-9]+]]:acc64 = PseudoUDIV [[COPY1]], [[COPY]] + ; MIPS32: [[PseudoMFHI:%[0-9]+]]:gpr32 = PseudoMFHI [[PseudoUDIV]] + ; MIPS32: $v0 = COPY [[PseudoMFHI]] + ; MIPS32: RetRA implicit $v0 + %0:gprb(s32) = COPY $a0 + %1:gprb(s32) = COPY $a1 + %2:gprb(s32) = G_UREM %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... Index: test/CodeGen/Mips/GlobalISel/legalizer/rem_and_div.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/legalizer/rem_and_div.mir @@ -0,0 +1,554 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + define void @sdiv_i8() {entry: ret void} + define void @sdiv_i16() {entry: ret void} + define void @sdiv_i32() {entry: ret void} + define void @sdiv_i64() {entry: ret void} + define void @srem_i8() {entry: ret void} + define void @srem_i16() {entry: ret void} + define void @srem_i32() {entry: ret void} + define void @srem_i64() {entry: ret void} + define void @udiv_i8() {entry: ret void} + define void @udiv_i16() {entry: ret void} + define void @udiv_i32() {entry: ret void} + define void @udiv_i64() {entry: ret void} + define void @urem_i8() {entry: ret void} + define void @urem_i16() {entry: ret void} + define void @urem_i32() {entry: ret void} + define void @urem_i64() {entry: ret void} + +... +--- +name: sdiv_i8 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: sdiv_i8 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C1]] + ; MIPS32: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]] + ; MIPS32: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) + ; MIPS32: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR2]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s8) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_SDIV %1, %0 + %5:_(s32) = G_SEXT %4(s8) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: sdiv_i16 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: sdiv_i16 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C1]] + ; MIPS32: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]] + ; MIPS32: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) + ; MIPS32: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR2]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s16) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s16) = G_TRUNC %3(s32) + %4:_(s16) = G_SDIV %1, %0 + %5:_(s32) = G_SEXT %4(s16) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: sdiv_i32 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: sdiv_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[SDIV]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_SDIV %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: sdiv_i64 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: sdiv_i64 + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY2]](s32) + ; MIPS32: $a1 = COPY [[COPY3]](s32) + ; MIPS32: $a2 = COPY [[COPY]](s32) + ; MIPS32: $a3 = COPY [[COPY1]](s32) + ; MIPS32: JAL &__divdi3, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0, implicit-def $v1 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v1 + ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY4]](s32) + ; MIPS32: $v1 = COPY [[COPY5]](s32) + ; MIPS32: RetRA implicit $v0, implicit $v1 + %2:_(s32) = COPY $a0 + %3:_(s32) = COPY $a1 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $a2 + %5:_(s32) = COPY $a3 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_SDIV %1, %0 + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $v0 = COPY %7(s32) + $v1 = COPY %8(s32) + RetRA implicit $v0, implicit $v1 + +... +--- +name: srem_i8 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: srem_i8 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C1]] + ; MIPS32: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]] + ; MIPS32: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[ASHR]], [[ASHR1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SREM]](s32) + ; MIPS32: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR2]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s8) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_SREM %1, %0 + %5:_(s32) = G_SEXT %4(s8) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: srem_i16 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: srem_i16 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C1]] + ; MIPS32: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]] + ; MIPS32: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[ASHR]], [[ASHR1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SREM]](s32) + ; MIPS32: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR2]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s16) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s16) = G_TRUNC %3(s32) + %4:_(s16) = G_SREM %1, %0 + %5:_(s32) = G_SEXT %4(s16) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: srem_i32 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: srem_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[SREM]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_SREM %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: srem_i64 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: srem_i64 + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY2]](s32) + ; MIPS32: $a1 = COPY [[COPY3]](s32) + ; MIPS32: $a2 = COPY [[COPY]](s32) + ; MIPS32: $a3 = COPY [[COPY1]](s32) + ; MIPS32: JAL &__moddi3, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0, implicit-def $v1 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v1 + ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY4]](s32) + ; MIPS32: $v1 = COPY [[COPY5]](s32) + ; MIPS32: RetRA implicit $v0, implicit $v1 + %2:_(s32) = COPY $a0 + %3:_(s32) = COPY $a1 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $a2 + %5:_(s32) = COPY $a3 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_SREM %1, %0 + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $v0 = COPY %7(s32) + $v1 = COPY %8(s32) + RetRA implicit $v0, implicit $v1 + +... +--- +name: udiv_i8 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: udiv_i8 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C1]] + ; MIPS32: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[AND]], [[AND1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UDIV]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s8) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_UDIV %1, %0 + %5:_(s32) = G_SEXT %4(s8) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: udiv_i16 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: udiv_i16 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C1]] + ; MIPS32: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[AND]], [[AND1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UDIV]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s16) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s16) = G_TRUNC %3(s32) + %4:_(s16) = G_UDIV %1, %0 + %5:_(s32) = G_SEXT %4(s16) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: udiv_i32 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: udiv_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[UDIV]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_UDIV %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: udiv_i64 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: udiv_i64 + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY2]](s32) + ; MIPS32: $a1 = COPY [[COPY3]](s32) + ; MIPS32: $a2 = COPY [[COPY]](s32) + ; MIPS32: $a3 = COPY [[COPY1]](s32) + ; MIPS32: JAL &__udivdi3, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0, implicit-def $v1 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v1 + ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY4]](s32) + ; MIPS32: $v1 = COPY [[COPY5]](s32) + ; MIPS32: RetRA implicit $v0, implicit $v1 + %2:_(s32) = COPY $a0 + %3:_(s32) = COPY $a1 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $a2 + %5:_(s32) = COPY $a3 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_UDIV %1, %0 + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $v0 = COPY %7(s32) + $v1 = COPY %8(s32) + RetRA implicit $v0, implicit $v1 + +... +--- +name: urem_i8 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: urem_i8 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C1]] + ; MIPS32: [[UREM:%[0-9]+]]:_(s32) = G_UREM [[AND]], [[AND1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UREM]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s8) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_UREM %1, %0 + %5:_(s32) = G_SEXT %4(s8) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: urem_i16 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: urem_i16 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; MIPS32: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C1]] + ; MIPS32: [[UREM:%[0-9]+]]:_(s32) = G_UREM [[AND]], [[AND1]] + ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UREM]](s32) + ; MIPS32: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY4]], [[C2]] + ; MIPS32: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C2]] + ; MIPS32: $v0 = COPY [[ASHR]](s32) + ; MIPS32: RetRA implicit $v0 + %2:_(s32) = COPY $a0 + %0:_(s16) = G_TRUNC %2(s32) + %3:_(s32) = COPY $a1 + %1:_(s16) = G_TRUNC %3(s32) + %4:_(s16) = G_UREM %1, %0 + %5:_(s32) = G_SEXT %4(s16) + $v0 = COPY %5(s32) + RetRA implicit $v0 + +... +--- +name: urem_i32 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: urem_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[UREM:%[0-9]+]]:_(s32) = G_UREM [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[UREM]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_UREM %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: urem_i64 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: urem_i64 + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY2]](s32) + ; MIPS32: $a1 = COPY [[COPY3]](s32) + ; MIPS32: $a2 = COPY [[COPY]](s32) + ; MIPS32: $a3 = COPY [[COPY1]](s32) + ; MIPS32: JAL &__umoddi3, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0, implicit-def $v1 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v1 + ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY4]](s32) + ; MIPS32: $v1 = COPY [[COPY5]](s32) + ; MIPS32: RetRA implicit $v0, implicit $v1 + %2:_(s32) = COPY $a0 + %3:_(s32) = COPY $a1 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $a2 + %5:_(s32) = COPY $a3 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_UREM %1, %0 + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $v0 = COPY %7(s32) + $v1 = COPY %8(s32) + RetRA implicit $v0, implicit $v1 + +... Index: test/CodeGen/Mips/GlobalISel/llvm-ir/rem_and_div.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/llvm-ir/rem_and_div.ll @@ -0,0 +1,314 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32 + +; sdiv +define signext i8 @sdiv_i8(i8 signext %a, i8 signext %b) { +; MIPS32-LABEL: sdiv_i8: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: sll $5, $5, 24 +; MIPS32-NEXT: sra $5, $5, 24 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: sra $4, $4, 24 +; MIPS32-NEXT: div $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mflo $4 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: sra $2, $4, 24 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = sdiv i8 %b, %a + ret i8 %div +} + +define signext i16 @sdiv_i16(i16 signext %a, i16 signext %b) { +; MIPS32-LABEL: sdiv_i16: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: sll $5, $5, 16 +; MIPS32-NEXT: sra $5, $5, 16 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: sra $4, $4, 16 +; MIPS32-NEXT: div $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mflo $4 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: sra $2, $4, 16 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = sdiv i16 %b, %a + ret i16 %div +} + +define signext i32 @sdiv_i32(i32 signext %a, i32 signext %b) { +; MIPS32-LABEL: sdiv_i32: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: div $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mflo $2 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = sdiv i32 %b, %a + ret i32 %div +} + +define signext i64 @sdiv_i64(i64 signext %a, i64 signext %b) { +; MIPS32-LABEL: sdiv_i64: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addiu $sp, $sp, -32 +; MIPS32-NEXT: .cfi_def_cfa_offset 32 +; MIPS32-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; MIPS32-NEXT: .cfi_offset 31, -4 +; MIPS32-NEXT: sw $4, 24($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $4, $6 +; MIPS32-NEXT: sw $5, 20($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $5, $7 +; MIPS32-NEXT: lw $6, 24($sp) # 4-byte Folded Reload +; MIPS32-NEXT: lw $7, 20($sp) # 4-byte Folded Reload +; MIPS32-NEXT: jal __divdi3 +; MIPS32-NEXT: nop +; MIPS32-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 32 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = sdiv i64 %b, %a + ret i64 %div +} + +; srem +define signext i8 @srem_i8(i8 signext %a, i8 signext %b) { +; MIPS32-LABEL: srem_i8: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: sll $5, $5, 24 +; MIPS32-NEXT: sra $5, $5, 24 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: sra $4, $4, 24 +; MIPS32-NEXT: div $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mflo $4 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: sra $2, $4, 24 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = sdiv i8 %b, %a + ret i8 %div +} + +define signext i16 @srem_i16(i16 signext %a, i16 signext %b) { +; MIPS32-LABEL: srem_i16: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: sll $5, $5, 16 +; MIPS32-NEXT: sra $5, $5, 16 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: sra $4, $4, 16 +; MIPS32-NEXT: div $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mfhi $4 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: sra $2, $4, 16 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %rem = srem i16 %b, %a + ret i16 %rem +} + +define signext i32 @srem_i32(i32 signext %a, i32 signext %b) { +; MIPS32-LABEL: srem_i32: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: div $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mfhi $2 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %rem = srem i32 %b, %a + ret i32 %rem +} + +define signext i64 @srem_i64(i64 signext %a, i64 signext %b) { +; MIPS32-LABEL: srem_i64: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addiu $sp, $sp, -32 +; MIPS32-NEXT: .cfi_def_cfa_offset 32 +; MIPS32-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; MIPS32-NEXT: .cfi_offset 31, -4 +; MIPS32-NEXT: sw $4, 24($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $4, $6 +; MIPS32-NEXT: sw $5, 20($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $5, $7 +; MIPS32-NEXT: lw $6, 24($sp) # 4-byte Folded Reload +; MIPS32-NEXT: lw $7, 20($sp) # 4-byte Folded Reload +; MIPS32-NEXT: jal __moddi3 +; MIPS32-NEXT: nop +; MIPS32-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 32 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %rem = srem i64 %b, %a + ret i64 %rem +} + +; udiv +define signext i8 @udiv_i8(i8 signext %a, i8 signext %b) { +; MIPS32-LABEL: udiv_i8: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lui $1, 0 +; MIPS32-NEXT: ori $1, $1, 255 +; MIPS32-NEXT: and $1, $5, $1 +; MIPS32-NEXT: lui $5, 0 +; MIPS32-NEXT: ori $5, $5, 255 +; MIPS32-NEXT: and $4, $4, $5 +; MIPS32-NEXT: divu $zero, $1, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mflo $1 +; MIPS32-NEXT: sll $1, $1, 24 +; MIPS32-NEXT: sra $2, $1, 24 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = udiv i8 %b, %a + ret i8 %div +} + +define signext i16 @udiv_i16(i16 signext %a, i16 signext %b) { +; MIPS32-LABEL: udiv_i16: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lui $1, 0 +; MIPS32-NEXT: ori $1, $1, 65535 +; MIPS32-NEXT: and $1, $5, $1 +; MIPS32-NEXT: lui $5, 0 +; MIPS32-NEXT: ori $5, $5, 65535 +; MIPS32-NEXT: and $4, $4, $5 +; MIPS32-NEXT: divu $zero, $1, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mflo $1 +; MIPS32-NEXT: sll $1, $1, 16 +; MIPS32-NEXT: sra $2, $1, 16 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = udiv i16 %b, %a + ret i16 %div +} + +define signext i32 @udiv_i32(i32 signext %a, i32 signext %b) { +; MIPS32-LABEL: udiv_i32: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: divu $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mflo $2 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = udiv i32 %b, %a + ret i32 %div +} + +define signext i64 @udiv_i64(i64 signext %a, i64 signext %b) { +; MIPS32-LABEL: udiv_i64: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addiu $sp, $sp, -32 +; MIPS32-NEXT: .cfi_def_cfa_offset 32 +; MIPS32-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; MIPS32-NEXT: .cfi_offset 31, -4 +; MIPS32-NEXT: sw $4, 24($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $4, $6 +; MIPS32-NEXT: sw $5, 20($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $5, $7 +; MIPS32-NEXT: lw $6, 24($sp) # 4-byte Folded Reload +; MIPS32-NEXT: lw $7, 20($sp) # 4-byte Folded Reload +; MIPS32-NEXT: jal __udivdi3 +; MIPS32-NEXT: nop +; MIPS32-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 32 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %div = udiv i64 %b, %a + ret i64 %div +} + +; urem +define signext i8 @urem_i8(i8 signext %a, i8 signext %b) { +; MIPS32-LABEL: urem_i8: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lui $1, 0 +; MIPS32-NEXT: ori $1, $1, 255 +; MIPS32-NEXT: and $1, $5, $1 +; MIPS32-NEXT: lui $5, 0 +; MIPS32-NEXT: ori $5, $5, 255 +; MIPS32-NEXT: and $4, $4, $5 +; MIPS32-NEXT: divu $zero, $1, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mfhi $1 +; MIPS32-NEXT: sll $1, $1, 24 +; MIPS32-NEXT: sra $2, $1, 24 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %rem = urem i8 %b, %a + ret i8 %rem +} + +define signext i16 @urem_i16(i16 signext %a, i16 signext %b) { +; MIPS32-LABEL: urem_i16: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lui $1, 0 +; MIPS32-NEXT: ori $1, $1, 65535 +; MIPS32-NEXT: and $1, $5, $1 +; MIPS32-NEXT: lui $5, 0 +; MIPS32-NEXT: ori $5, $5, 65535 +; MIPS32-NEXT: and $4, $4, $5 +; MIPS32-NEXT: divu $zero, $1, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mfhi $1 +; MIPS32-NEXT: sll $1, $1, 16 +; MIPS32-NEXT: sra $2, $1, 16 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %rem = urem i16 %b, %a + ret i16 %rem +} + +define signext i32 @urem_i32(i32 signext %a, i32 signext %b) { +; MIPS32-LABEL: urem_i32: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: divu $zero, $5, $4 +; MIPS32-NEXT: teq $4, $zero, 7 +; MIPS32-NEXT: mfhi $2 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %rem = urem i32 %b, %a + ret i32 %rem +} + +define signext i64 @urem_i64(i64 signext %a, i64 signext %b) { +; MIPS32-LABEL: urem_i64: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addiu $sp, $sp, -32 +; MIPS32-NEXT: .cfi_def_cfa_offset 32 +; MIPS32-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; MIPS32-NEXT: .cfi_offset 31, -4 +; MIPS32-NEXT: sw $4, 24($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $4, $6 +; MIPS32-NEXT: sw $5, 20($sp) # 4-byte Folded Spill +; MIPS32-NEXT: move $5, $7 +; MIPS32-NEXT: lw $6, 24($sp) # 4-byte Folded Reload +; MIPS32-NEXT: lw $7, 20($sp) # 4-byte Folded Reload +; MIPS32-NEXT: jal __umoddi3 +; MIPS32-NEXT: nop +; MIPS32-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 32 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %rem = urem i64 %b, %a + ret i64 %rem +} Index: test/CodeGen/Mips/GlobalISel/regbankselect/rem_and_div.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/regbankselect/rem_and_div.mir @@ -0,0 +1,102 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + define void @sdiv_i32() {entry: ret void} + define void @srem_i32() {entry: ret void} + define void @udiv_i32() {entry: ret void} + define void @urem_i32() {entry: ret void} + +... +--- +name: sdiv_i32 +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: sdiv_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1 + ; MIPS32: [[SDIV:%[0-9]+]]:gprb(s32) = G_SDIV [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[SDIV]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_SDIV %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: srem_i32 +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: srem_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1 + ; MIPS32: [[SREM:%[0-9]+]]:gprb(s32) = G_SREM [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[SREM]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_SREM %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: udiv_i32 +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: udiv_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1 + ; MIPS32: [[UDIV:%[0-9]+]]:gprb(s32) = G_UDIV [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[UDIV]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_UDIV %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: urem_i32 +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: urem_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1 + ; MIPS32: [[UREM:%[0-9]+]]:gprb(s32) = G_UREM [[COPY1]], [[COPY]] + ; MIPS32: $v0 = COPY [[UREM]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = G_UREM %1, %0 + $v0 = COPY %2(s32) + RetRA implicit $v0 + +...