mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
[mips][FastISel] Implement srem/urem and sdiv/udiv instructions.
Summary: Implement the LLVM assembly urem/srem and sdiv/udiv instructions in MIPS FastISel. Based on a patch by Reed Kotler. Test Plan: srem1.ll div1.ll test-suite at O0/O2 for mips32 r1/r2 Reviewers: dsanders, rkotler Subscribers: llvm-commits, rfuhler Differential Revision: http://reviews.llvm.org/D7028 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238757 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e490b7733a
commit
d4b311fb43
@ -103,6 +103,7 @@ private:
|
||||
bool selectTrunc(const Instruction *I);
|
||||
bool selectIntExt(const Instruction *I);
|
||||
bool selectShift(const Instruction *I);
|
||||
bool selectDivRem(const Instruction *I, unsigned ISDOpcode);
|
||||
|
||||
// Utility helper routines.
|
||||
bool isTypeLegal(Type *Ty, MVT &VT);
|
||||
@ -1471,6 +1472,50 @@ unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
|
||||
return Success ? DestReg : 0;
|
||||
}
|
||||
|
||||
bool MipsFastISel::selectDivRem(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::SDIV:
|
||||
case ISD::SREM:
|
||||
DivOpc = Mips::SDIV;
|
||||
break;
|
||||
case ISD::UDIV:
|
||||
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;
|
||||
|
||||
unsigned MFOpc = (ISDOpcode == ISD::SREM || ISDOpcode == ISD::UREM)
|
||||
? Mips::MFHI
|
||||
: Mips::MFLO;
|
||||
emitInst(MFOpc, ResultReg);
|
||||
|
||||
updateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MipsFastISel::selectShift(const Instruction *I) {
|
||||
MVT RetVT;
|
||||
|
||||
@ -1556,6 +1601,22 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
|
||||
return selectLoad(I);
|
||||
case Instruction::Store:
|
||||
return selectStore(I);
|
||||
case Instruction::SDiv:
|
||||
if (!selectBinaryOp(I, ISD::SDIV))
|
||||
return selectDivRem(I, ISD::SDIV);
|
||||
return true;
|
||||
case Instruction::UDiv:
|
||||
if (!selectBinaryOp(I, ISD::UDIV))
|
||||
return selectDivRem(I, ISD::UDIV);
|
||||
return true;
|
||||
case Instruction::SRem:
|
||||
if (!selectBinaryOp(I, ISD::SREM))
|
||||
return selectDivRem(I, ISD::SREM);
|
||||
return true;
|
||||
case Instruction::URem:
|
||||
if (!selectBinaryOp(I, ISD::UREM))
|
||||
return selectDivRem(I, ISD::UREM);
|
||||
return true;
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
|
55
test/CodeGen/Mips/Fast-ISel/div1.ll
Normal file
55
test/CodeGen/Mips/Fast-ISel/div1.ll
Normal file
@ -0,0 +1,55 @@
|
||||
; 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 200000, align 4
|
||||
@sk = global i32 -47, align 4
|
||||
@uj = global i32 200000, align 4
|
||||
@uk = global i32 43, align 4
|
||||
@si = common global i32 0, align 4
|
||||
@ui = common global i32 0, align 4
|
||||
|
||||
define void @divs() {
|
||||
; CHECK-LABEL: divs:
|
||||
|
||||
; 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: mflo $[[RESULT:[0-9]+]]
|
||||
; CHECK: sw $[[RESULT]], 0($[[I_ADDR]])
|
||||
%1 = load i32, i32* @sj, align 4
|
||||
%2 = load i32, i32* @sk, align 4
|
||||
%div = sdiv i32 %1, %2
|
||||
store i32 %div, i32* @si, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @divu() {
|
||||
; CHECK-LABEL: divu:
|
||||
|
||||
; 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: mflo $[[RESULT:[0-9]+]]
|
||||
; CHECK: sw $[[RESULT]], 0($[[I_ADDR]])
|
||||
%1 = load i32, i32* @uj, align 4
|
||||
%2 = load i32, i32* @uk, align 4
|
||||
%div = udiv i32 %1, %2
|
||||
store i32 %div, i32* @ui, align 4
|
||||
ret void
|
||||
}
|
56
test/CodeGen/Mips/Fast-ISel/rem1.ll
Normal file
56
test/CodeGen/Mips/Fast-ISel/rem1.ll
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user