mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
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
5647f7ac6b
commit
aff15b863c
@ -1,7 +1,6 @@
|
|||||||
//===-- MipsastISel.cpp - Mips FastISel implementation
|
//===-- MipsastISel.cpp - Mips FastISel implementation
|
||||||
//---------------------===//
|
//---------------------===//
|
||||||
|
|
||||||
#include "llvm/CodeGen/FunctionLoweringInfo.h"
|
|
||||||
#include "MipsCCState.h"
|
#include "MipsCCState.h"
|
||||||
#include "MipsISelLowering.h"
|
#include "MipsISelLowering.h"
|
||||||
#include "MipsMachineFunction.h"
|
#include "MipsMachineFunction.h"
|
||||||
@ -10,7 +9,9 @@
|
|||||||
#include "MipsTargetMachine.h"
|
#include "MipsTargetMachine.h"
|
||||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||||
#include "llvm/CodeGen/FastISel.h"
|
#include "llvm/CodeGen/FastISel.h"
|
||||||
|
#include "llvm/CodeGen/FunctionLoweringInfo.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/IR/GlobalAlias.h"
|
#include "llvm/IR/GlobalAlias.h"
|
||||||
#include "llvm/IR/GlobalVariable.h"
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
@ -984,14 +985,88 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MipsFastISel::selectRet(const Instruction *I) {
|
bool MipsFastISel::selectRet(const Instruction *I) {
|
||||||
|
const Function &F = *I->getParent()->getParent();
|
||||||
const ReturnInst *Ret = cast<ReturnInst>(I);
|
const ReturnInst *Ret = cast<ReturnInst>(I);
|
||||||
|
|
||||||
if (!FuncInfo.CanLowerReturn)
|
if (!FuncInfo.CanLowerReturn)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Build a list of return value registers.
|
||||||
|
SmallVector<unsigned, 4> RetRegs;
|
||||||
|
|
||||||
if (Ret->getNumOperands() > 0) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,7 +1191,8 @@ bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
|
|||||||
unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
|
unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
|
||||||
bool isZExt) {
|
bool isZExt) {
|
||||||
unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
|
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) {
|
bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
|
||||||
|
80
test/CodeGen/Mips/Fast-ISel/retabi.ll
Normal file
80
test/CodeGen/Mips/Fast-ISel/retabi.ll
Normal file
@ -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
Block a user