[mips][FastISel] Implement the select statement for MIPS FastISel.

Summary: Implement the LLVM IR select statement for MIPS FastISelsel.

Based on a patch by Reed Kotler.

Test Plan:
"Make check" test included now.
Passes test-suite at O2/O0 mips32 r1/r2.

Reviewers: dsanders, rkotler

Subscribers: llvm-commits, rfuhler

Differential Revision: http://reviews.llvm.org/D6774

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238756 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Vasileios Kalintiris 2015-06-01 15:56:40 +00:00
parent 30b5412d92
commit e490b7733a
2 changed files with 138 additions and 0 deletions

View File

@ -94,6 +94,7 @@ private:
bool selectLoad(const Instruction *I);
bool selectStore(const Instruction *I);
bool selectBranch(const Instruction *I);
bool selectSelect(const Instruction *I);
bool selectCmp(const Instruction *I);
bool selectFPExt(const Instruction *I);
bool selectFPTrunc(const Instruction *I);
@ -899,6 +900,50 @@ bool MipsFastISel::selectFPExt(const Instruction *I) {
return true;
}
bool MipsFastISel::selectSelect(const Instruction *I) {
assert(isa<SelectInst>(I) && "Expected a select instruction.");
MVT VT;
if (!isTypeSupported(I->getType(), VT))
return false;
unsigned CondMovOpc;
const TargetRegisterClass *RC;
if (VT.isInteger() && !VT.isVector() && VT.getSizeInBits() <= 32) {
CondMovOpc = Mips::MOVN_I_I;
RC = &Mips::GPR32RegClass;
} else if (VT == MVT::f32) {
CondMovOpc = Mips::MOVN_I_S;
RC = &Mips::FGR32RegClass;
} else if (VT == MVT::f64) {
CondMovOpc = Mips::MOVN_I_D32;
RC = &Mips::AFGR64RegClass;
} else
return false;
const SelectInst *SI = cast<SelectInst>(I);
const Value *Cond = SI->getCondition();
unsigned Src1Reg = getRegForValue(SI->getTrueValue());
unsigned Src2Reg = getRegForValue(SI->getFalseValue());
unsigned CondReg = getRegForValue(Cond);
if (!Src1Reg || !Src2Reg || !CondReg)
return false;
unsigned ResultReg = createResultReg(RC);
unsigned TempReg = createResultReg(RC);
if (!ResultReg || !TempReg)
return false;
emitInst(TargetOpcode::COPY, TempReg).addReg(Src2Reg);
emitInst(CondMovOpc, ResultReg)
.addReg(Src1Reg).addReg(CondReg).addReg(TempReg);
updateValueMap(I, ResultReg);
return true;
}
// Attempt to fast-select a floating-point truncate instruction.
bool MipsFastISel::selectFPTrunc(const Instruction *I) {
if (UnsupportedFPMode)
@ -1539,6 +1584,8 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
case Instruction::ICmp:
case Instruction::FCmp:
return selectCmp(I);
case Instruction::Select:
return selectSelect(I);
}
return false;
}

View File

@ -0,0 +1,91 @@
; RUN: llc < %s -march=mipsel -mcpu=mips32r2 -O2 -relocation-model=pic \
; RUN: -fast-isel -mips-fast-isel -fast-isel-abort=1 | FileCheck %s
define i1 @sel_i1(i1 %j, i1 %k, i1 %l) {
entry:
; CHECK-LABEL: sel_i1:
; FIXME: The following instruction is redundant.
; CHECK: xor $[[T0:[0-9]+]], $4, $zero
; CHECK-NEXT: sltu $[[T1:[0-9]+]], $zero, $[[T0]]
; CHECK-NEXT: movn $6, $5, $[[T1]]
; CHECK: move $2, $6
%cond = icmp ne i1 %j, 0
%res = select i1 %cond, i1 %k, i1 %l
ret i1 %res
}
define i8 @sel_i8(i8 %j, i8 %k, i8 %l) {
entry:
; CHECK-LABEL: sel_i8:
; CHECK-DAG: seb $[[T0:[0-9]+]], $4
; FIXME: The following 2 instructions are redundant.
; CHECK-DAG: seb $[[T1:[0-9]+]], $zero
; CHECK: xor $[[T2:[0-9]+]], $[[T0]], $[[T1]]
; CHECK-NEXT: sltu $[[T3:[0-9]+]], $zero, $[[T2]]
; CHECK-NEXT: movn $6, $5, $[[T3]]
; CHECK: move $2, $6
%cond = icmp ne i8 %j, 0
%res = select i1 %cond, i8 %k, i8 %l
ret i8 %res
}
define i16 @sel_i16(i16 %j, i16 %k, i16 %l) {
entry:
; CHECK-LABEL: sel_i16:
; CHECK-DAG: seh $[[T0:[0-9]+]], $4
; FIXME: The following 2 instructions are redundant.
; CHECK-DAG: seh $[[T1:[0-9]+]], $zero
; CHECK: xor $[[T2:[0-9]+]], $[[T0]], $[[T1]]
; CHECK-NEXT: sltu $[[T3:[0-9]+]], $zero, $[[T2]]
; CHECK-NEXT: movn $6, $5, $[[T3]]
; CHECK: move $2, $6
%cond = icmp ne i16 %j, 0
%res = select i1 %cond, i16 %k, i16 %l
ret i16 %res
}
define i32 @sel_i32(i32 %j, i32 %k, i32 %l) {
entry:
; CHECK-LABEL: sel_i32:
; FIXME: The following instruction is redundant.
; CHECK: xor $[[T0:[0-9]+]], $4, $zero
; CHECK-NEXT: sltu $[[T1:[0-9]+]], $zero, $[[T0]]
; CHECK-NEXT: movn $6, $5, $[[T1]]
; CHECK: move $2, $6
%cond = icmp ne i32 %j, 0
%res = select i1 %cond, i32 %k, i32 %l
ret i32 %res
}
define float @sel_float(i32 %j, float %k, float %l) {
entry:
; CHECK-LABEL: sel_float:
; CHECK-DAG: mtc1 $6, $f0
; CHECK-DAG: mtc1 $5, $f1
; CHECK-DAG: xor $[[T0:[0-9]+]], $4, $zero
; CHECK: sltu $[[T1:[0-9]+]], $zero, $[[T0]]
; CHECK: movn.s $f0, $f1, $[[T1]]
%cond = icmp ne i32 %j, 0
%res = select i1 %cond, float %k, float %l
ret float %res
}
define double @sel_double(i32 %j, double %k, double %l) {
entry:
; CHECK-LABEL: sel_double:
; CHECK-DAG: mtc1 $6, $f2
; CHECK-DAG: mthc1 $7, $f2
; CHECK-DAG: ldc1 $f0, 16($sp)
; CHECK-DAG: xor $[[T0:[0-9]+]], $4, $zero
; CHECK: sltu $[[T1:[0-9]+]], $zero, $[[T0]]
; CHECK: movn.d $f0, $f2, $[[T1]]
%cond = icmp ne i32 %j, 0
%res = select i1 %cond, double %k, double %l
ret double %res
}