forked from OSchip/llvm-project
Add bulk of returning of values to Mips fast-isel
Summary: Implement the bulk of returning values in Mips fast-isel Test Plan: reatabi.ll Passes test-suite at -O0,-O2 and with mips32r2 and mips32r1. Reviewers: dsanders Reviewed By: dsanders Subscribers: llvm-commits, aemerson, rfuhler Differential Revision: http://reviews.llvm.org/D5920 llvm-svn: 228958
This commit is contained in:
parent
6f972a13f6
commit
aa150ed780
|
@ -1,7 +1,6 @@
|
|||
//===-- MipsastISel.cpp - Mips FastISel implementation
|
||||
//---------------------===//
|
||||
|
||||
#include "llvm/CodeGen/FunctionLoweringInfo.h"
|
||||
#include "MipsCCState.h"
|
||||
#include "MipsISelLowering.h"
|
||||
#include "MipsMachineFunction.h"
|
||||
|
@ -10,7 +9,9 @@
|
|||
#include "MipsTargetMachine.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/CodeGen/FastISel.h"
|
||||
#include "llvm/CodeGen/FunctionLoweringInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/IR/GlobalAlias.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
@ -984,14 +985,88 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
|
|||
}
|
||||
|
||||
bool MipsFastISel::selectRet(const Instruction *I) {
|
||||
const Function &F = *I->getParent()->getParent();
|
||||
const ReturnInst *Ret = cast<ReturnInst>(I);
|
||||
|
||||
if (!FuncInfo.CanLowerReturn)
|
||||
return false;
|
||||
|
||||
// Build a list of return value registers.
|
||||
SmallVector<unsigned, 4> RetRegs;
|
||||
|
||||
if (Ret->getNumOperands() > 0) {
|
||||
return false;
|
||||
CallingConv::ID CC = F.getCallingConv();
|
||||
SmallVector<ISD::OutputArg, 4> Outs;
|
||||
GetReturnInfo(F.getReturnType(), F.getAttributes(), Outs, TLI);
|
||||
// Analyze operands of the call, assigning locations to each operand.
|
||||
SmallVector<CCValAssign, 16> ValLocs;
|
||||
MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs,
|
||||
I->getContext());
|
||||
CCAssignFn *RetCC = RetCC_Mips;
|
||||
CCInfo.AnalyzeReturn(Outs, RetCC);
|
||||
|
||||
// Only handle a single return value for now.
|
||||
if (ValLocs.size() != 1)
|
||||
return false;
|
||||
|
||||
CCValAssign &VA = ValLocs[0];
|
||||
const Value *RV = Ret->getOperand(0);
|
||||
|
||||
// Don't bother handling odd stuff for now.
|
||||
if ((VA.getLocInfo() != CCValAssign::Full) &&
|
||||
(VA.getLocInfo() != CCValAssign::BCvt))
|
||||
return false;
|
||||
|
||||
// Only handle register returns for now.
|
||||
if (!VA.isRegLoc())
|
||||
return false;
|
||||
|
||||
unsigned Reg = getRegForValue(RV);
|
||||
if (Reg == 0)
|
||||
return false;
|
||||
|
||||
unsigned SrcReg = Reg + VA.getValNo();
|
||||
unsigned DestReg = VA.getLocReg();
|
||||
// Avoid a cross-class copy. This is very unlikely.
|
||||
if (!MRI.getRegClass(SrcReg)->contains(DestReg))
|
||||
return false;
|
||||
|
||||
EVT RVEVT = TLI.getValueType(RV->getType());
|
||||
if (!RVEVT.isSimple())
|
||||
return false;
|
||||
|
||||
if (RVEVT.isVector())
|
||||
return false;
|
||||
|
||||
MVT RVVT = RVEVT.getSimpleVT();
|
||||
if (RVVT == MVT::f128)
|
||||
return false;
|
||||
|
||||
MVT DestVT = VA.getValVT();
|
||||
// Special handling for extended integers.
|
||||
if (RVVT != DestVT) {
|
||||
if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
|
||||
return false;
|
||||
|
||||
if (!Outs[0].Flags.isZExt() && !Outs[0].Flags.isSExt())
|
||||
return false;
|
||||
|
||||
bool IsZExt = Outs[0].Flags.isZExt();
|
||||
SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
|
||||
if (SrcReg == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make the copy.
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg);
|
||||
|
||||
// Add register to return instruction.
|
||||
RetRegs.push_back(VA.getLocReg());
|
||||
}
|
||||
emitInst(Mips::RetRA);
|
||||
MachineInstrBuilder MIB = emitInst(Mips::RetRA);
|
||||
for (unsigned i = 0, e = RetRegs.size(); i != e; ++i)
|
||||
MIB.addReg(RetRegs[i], RegState::Implicit);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1116,7 +1191,8 @@ bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
|
|||
unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
|
||||
bool isZExt) {
|
||||
unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
|
||||
return emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt);
|
||||
bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt);
|
||||
return Success ? DestReg : 0;
|
||||
}
|
||||
|
||||
bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \
|
||||
; RUN: < %s | FileCheck %s
|
||||
|
||||
@i = global i32 75, align 4
|
||||
@s = global i16 -345, align 2
|
||||
@c = global i8 118, align 1
|
||||
@f = global float 0x40BE623360000000, align 4
|
||||
@d = global double 1.298330e+03, align 8
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @reti() {
|
||||
entry:
|
||||
; CHECK-LABEL: reti:
|
||||
%0 = load i32* @i, align 4
|
||||
ret i32 %0
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK: lw $[[REG_I_ADDR:[0-9]+]], %got(i)($[[REG_GP]])
|
||||
; CHECK: lw $2, 0($[[REG_I_ADDR]])
|
||||
; CHECK: jr $ra
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define signext i16 @rets() {
|
||||
entry:
|
||||
; CHECK-LABEL: rets:
|
||||
%0 = load i16* @s, align 2
|
||||
ret i16 %0
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK: lw $[[REG_S_ADDR:[0-9]+]], %got(s)($[[REG_GP]])
|
||||
; CHECK: lhu $[[REG_S:[0-9]+]], 0($[[REG_S_ADDR]])
|
||||
; CHECK: seh $2, $[[REG_S]]
|
||||
; CHECK: jr $ra
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define signext i8 @retc() {
|
||||
entry:
|
||||
; CHECK-LABEL: retc:
|
||||
%0 = load i8* @c, align 1
|
||||
ret i8 %0
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK: lw $[[REG_C_ADDR:[0-9]+]], %got(c)($[[REG_GP]])
|
||||
; CHECK: lbu $[[REG_C:[0-9]+]], 0($[[REG_C_ADDR]])
|
||||
; CHECK: seb $2, $[[REG_C]]
|
||||
; CHECK: jr $ra
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define float @retf() {
|
||||
entry:
|
||||
; CHECK-LABEL: retf:
|
||||
%0 = load float* @f, align 4
|
||||
ret float %0
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK: lw $[[REG_F_ADDR:[0-9]+]], %got(f)($[[REG_GP]])
|
||||
; CHECK: lwc1 $f0, 0($[[REG_F_ADDR]])
|
||||
; CHECK: jr $ra
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define double @retd() {
|
||||
entry:
|
||||
; CHECK-LABEL: retd:
|
||||
%0 = load double* @d, align 8
|
||||
ret double %0
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK: lw $[[REG_D_ADDR:[0-9]+]], %got(d)($[[REG_GP]])
|
||||
; CHECK: ldc1 $f0, 0($[[REG_D_ADDR]])
|
||||
; CHECK: jr $ra
|
||||
}
|
Loading…
Reference in New Issue