mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
Beginning of alloca implementation for Mips fast-isel
Summary: Begin to add various address modes; including alloca. Test Plan: Make sure there are no regressions in test-suite at O0/02 in mips32r1/r2 Reviewers: dsanders Reviewed By: dsanders Subscribers: echristo, rfuhler, llvm-commits Differential Revision: http://reviews.llvm.org/D6426 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230300 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b664a60ecf
commit
aecbb87ee8
@ -2,6 +2,7 @@
|
||||
//---------------------===//
|
||||
|
||||
#include "MipsCCState.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsISelLowering.h"
|
||||
#include "MipsMachineFunction.h"
|
||||
#include "MipsRegisterInfo.h"
|
||||
@ -44,6 +45,7 @@ class MipsFastISel final : public FastISel {
|
||||
void setKind(BaseKind K) { Kind = K; }
|
||||
BaseKind getKind() const { return Kind; }
|
||||
bool isRegBase() const { return Kind == RegBase; }
|
||||
bool isFIBase() const { return Kind == FrameIndexBase; }
|
||||
void setReg(unsigned Reg) {
|
||||
assert(isRegBase() && "Invalid base register access!");
|
||||
Base.Reg = Reg;
|
||||
@ -52,6 +54,15 @@ class MipsFastISel final : public FastISel {
|
||||
assert(isRegBase() && "Invalid base register access!");
|
||||
return Base.Reg;
|
||||
}
|
||||
void setFI(unsigned FI) {
|
||||
assert(isFIBase() && "Invalid base frame index access!");
|
||||
Base.FI = FI;
|
||||
}
|
||||
unsigned getFI() const {
|
||||
assert(isFIBase() && "Invalid base frame index access!");
|
||||
return Base.FI;
|
||||
}
|
||||
|
||||
void setOffset(int64_t Offset_) { Offset = Offset_; }
|
||||
int64_t getOffset() const { return Offset; }
|
||||
void setGlobalValue(const GlobalValue *G) { GV = G; }
|
||||
@ -94,6 +105,7 @@ private:
|
||||
bool isLoadTypeLegal(Type *Ty, MVT &VT);
|
||||
bool computeAddress(const Value *Obj, Address &Addr);
|
||||
bool computeCallAddress(const Value *V, Address &Addr);
|
||||
void simplifyAddress(Address &Addr);
|
||||
|
||||
// Emit helper routines.
|
||||
bool emitCmp(unsigned DestReg, const CmpInst *CI);
|
||||
@ -304,14 +316,82 @@ unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
|
||||
}
|
||||
|
||||
bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
|
||||
// This construct looks a big awkward but it is how other ports handle this
|
||||
// and as this function is more fully completed, these cases which
|
||||
// return false will have additional code in them.
|
||||
//
|
||||
if (isa<Instruction>(Obj))
|
||||
return false;
|
||||
else if (isa<ConstantExpr>(Obj))
|
||||
|
||||
const User *U = nullptr;
|
||||
unsigned Opcode = Instruction::UserOp1;
|
||||
if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
|
||||
// Don't walk into other basic blocks unless the object is an alloca from
|
||||
// another block, otherwise it may not have a virtual register assigned.
|
||||
if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
|
||||
FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
|
||||
Opcode = I->getOpcode();
|
||||
U = I;
|
||||
}
|
||||
} else if (isa<ConstantExpr>(Obj))
|
||||
return false;
|
||||
switch (Opcode) {
|
||||
default:
|
||||
break;
|
||||
case Instruction::BitCast: {
|
||||
// Look through bitcasts.
|
||||
return computeAddress(U->getOperand(0), Addr);
|
||||
}
|
||||
case Instruction::GetElementPtr: {
|
||||
Address SavedAddr = Addr;
|
||||
uint64_t TmpOffset = Addr.getOffset();
|
||||
// Iterate through the GEP folding the constants into offsets where
|
||||
// we can.
|
||||
gep_type_iterator GTI = gep_type_begin(U);
|
||||
for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e;
|
||||
++i, ++GTI) {
|
||||
const Value *Op = *i;
|
||||
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
|
||||
const StructLayout *SL = DL.getStructLayout(STy);
|
||||
unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
|
||||
TmpOffset += SL->getElementOffset(Idx);
|
||||
} else {
|
||||
uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
|
||||
for (;;) {
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
|
||||
// Constant-offset addressing.
|
||||
TmpOffset += CI->getSExtValue() * S;
|
||||
break;
|
||||
}
|
||||
if (canFoldAddIntoGEP(U, Op)) {
|
||||
// A compatible add with a constant operand. Fold the constant.
|
||||
ConstantInt *CI =
|
||||
cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
|
||||
TmpOffset += CI->getSExtValue() * S;
|
||||
// Iterate on the other operand.
|
||||
Op = cast<AddOperator>(Op)->getOperand(0);
|
||||
continue;
|
||||
}
|
||||
// Unsupported
|
||||
goto unsupported_gep;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try to grab the base operand now.
|
||||
Addr.setOffset(TmpOffset);
|
||||
if (computeAddress(U->getOperand(0), Addr))
|
||||
return true;
|
||||
// We failed, restore everything and try the other options.
|
||||
Addr = SavedAddr;
|
||||
unsupported_gep:
|
||||
break;
|
||||
}
|
||||
case Instruction::Alloca: {
|
||||
const AllocaInst *AI = cast<AllocaInst>(Obj);
|
||||
DenseMap<const AllocaInst *, int>::iterator SI =
|
||||
FuncInfo.StaticAllocaMap.find(AI);
|
||||
if (SI != FuncInfo.StaticAllocaMap.end()) {
|
||||
Addr.setKind(Address::FrameIndexBase);
|
||||
Addr.setFI(SI->second);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Addr.setReg(getRegForValue(Obj));
|
||||
return Addr.getReg() != 0;
|
||||
}
|
||||
@ -517,8 +597,26 @@ bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
|
||||
return true;
|
||||
if (Addr.isRegBase()) {
|
||||
simplifyAddress(Addr);
|
||||
emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
|
||||
return true;
|
||||
}
|
||||
if (Addr.isFIBase()) {
|
||||
unsigned FI = Addr.getFI();
|
||||
unsigned Align = 4;
|
||||
unsigned Offset = Addr.getOffset();
|
||||
MachineFrameInfo &MFI = *MF->getFrameInfo();
|
||||
MachineMemOperand *MMO = MF->getMachineMemOperand(
|
||||
MachinePointerInfo::getFixedStack(FI), MachineMemOperand::MOLoad,
|
||||
MFI.getObjectSize(FI), Align);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
|
||||
.addFrameIndex(FI)
|
||||
.addImm(Offset)
|
||||
.addMemOperand(MMO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr,
|
||||
@ -550,8 +648,27 @@ bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr,
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
|
||||
return true;
|
||||
if (Addr.isRegBase()) {
|
||||
simplifyAddress(Addr);
|
||||
emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
|
||||
return true;
|
||||
}
|
||||
if (Addr.isFIBase()) {
|
||||
unsigned FI = Addr.getFI();
|
||||
unsigned Align = 4;
|
||||
unsigned Offset = Addr.getOffset();
|
||||
MachineFrameInfo &MFI = *MF->getFrameInfo();
|
||||
MachineMemOperand *MMO = MF->getMachineMemOperand(
|
||||
MachinePointerInfo::getFixedStack(FI), MachineMemOperand::MOLoad,
|
||||
MFI.getObjectSize(FI), Align);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
|
||||
.addReg(SrcReg)
|
||||
.addFrameIndex(FI)
|
||||
.addImm(Offset)
|
||||
.addMemOperand(MMO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsFastISel::selectLoad(const Instruction *I) {
|
||||
@ -970,15 +1087,6 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
|
||||
|
||||
CLI.Call = MIB;
|
||||
|
||||
// Add implicit physical register uses to the call.
|
||||
for (auto Reg : CLI.OutRegs)
|
||||
MIB.addReg(Reg, RegState::Implicit);
|
||||
|
||||
// Add a register mask with the call-preserved registers. Proper
|
||||
// defs for return values will be added by setPhysRegsDeadExcept().
|
||||
MIB.addRegMask(TRI.getCallPreservedMask(CC));
|
||||
|
||||
CLI.Call = MIB;
|
||||
// Finish off the call including any return values.
|
||||
return finishCall(CLI, RetVT, NumBytes);
|
||||
}
|
||||
@ -1243,6 +1351,17 @@ unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V,
|
||||
return VReg;
|
||||
}
|
||||
|
||||
void MipsFastISel::simplifyAddress(Address &Addr) {
|
||||
if (!isInt<16>(Addr.getOffset())) {
|
||||
unsigned TempReg =
|
||||
materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass);
|
||||
unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
|
||||
emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg());
|
||||
Addr.setReg(DestReg);
|
||||
Addr.setOffset(0);
|
||||
}
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
|
||||
const TargetLibraryInfo *libInfo) {
|
||||
|
64
test/CodeGen/Mips/Fast-ISel/overflt.ll
Normal file
64
test/CodeGen/Mips/Fast-ISel/overflt.ll
Normal file
@ -0,0 +1,64 @@
|
||||
; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \
|
||||
; RUN: < %s | FileCheck %s
|
||||
; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \
|
||||
; RUN: < %s | FileCheck %s
|
||||
|
||||
@x = common global [128000 x float] zeroinitializer, align 4
|
||||
@y = global float* getelementptr inbounds ([128000 x float]* @x, i32 0, i32 0), align 4
|
||||
@result = common global float 0.000000e+00, align 4
|
||||
@.str = private unnamed_addr constant [5 x i8] c"%f \0A\00", align 1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @foo() {
|
||||
entry:
|
||||
; CHECK-LABEL: .ent foo
|
||||
%0 = load float** @y, align 4
|
||||
%arrayidx = getelementptr inbounds float* %0, i32 64000
|
||||
store float 5.500000e+00, float* %arrayidx, align 4
|
||||
; CHECK: lui $[[REG_FPCONST_INT:[0-9]+]], 16560
|
||||
; CHECK: mtc1 $[[REG_FPCONST_INT]], $f[[REG_FPCONST:[0-9]+]]
|
||||
; CHECK: lw $[[REG_Y_GOT:[0-9]+]], %got(y)(${{[0-9]+}})
|
||||
; CHECK: lw $[[REG_Y:[0-9]+]], 0($[[REG_Y_GOT]])
|
||||
; CHECK: lui $[[REG_IDX_UPPER:[0-9]+]], 3
|
||||
; CHECK: ori $[[REG_IDX:[0-9]+]], $[[REG_IDX_UPPER]], 59392
|
||||
; CHECK: addu $[[REG_Y_IDX:[0-9]+]], $[[REG_IDX]], $[[REG_Y]]
|
||||
; CHECK: swc1 $f[[REG_FPCONST]], 0($[[REG_Y_IDX]])
|
||||
ret void
|
||||
; CHECK-LABEL: .end foo
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @goo() {
|
||||
entry:
|
||||
; CHECK-LABEL: .ent goo
|
||||
%0 = load float** @y, align 4
|
||||
%arrayidx = getelementptr inbounds float* %0, i32 64000
|
||||
%1 = load float* %arrayidx, align 4
|
||||
store float %1, float* @result, align 4
|
||||
; CHECK-DAG: lw $[[REG_RESULT:[0-9]+]], %got(result)(${{[0-9]+}})
|
||||
; CHECK-DAG: lw $[[REG_Y_GOT:[0-9]+]], %got(y)(${{[0-9]+}})
|
||||
; CHECK-DAG: lw $[[REG_Y:[0-9]+]], 0($[[REG_Y_GOT]])
|
||||
; CHECK-DAG: lui $[[REG_IDX_UPPER:[0-9]+]], 3
|
||||
; CHECK-DAG: ori $[[REG_IDX:[0-9]+]], $[[REG_IDX_UPPER]], 59392
|
||||
; CHECK-DAG: addu $[[REG_Y_IDX:[0-9]+]], $[[REG_IDX]], $[[REG_Y]]
|
||||
; CHECK-DAG: lwc1 $f[[Y_IDX:[0-9]+]], 0($[[REG_Y_IDX]])
|
||||
; CHECK-DAG: swc1 $f[[Y_IDX]], 0($[[REG_RESULT]])
|
||||
; CHECK-LABEL: .end goo
|
||||
ret void
|
||||
}
|
||||
|
||||
;
|
||||
; Original C code for test.
|
||||
;
|
||||
;float x[128000];
|
||||
;float *y = x;
|
||||
;float result;
|
||||
|
||||
|
||||
;void foo() {
|
||||
; y[64000] = 5.5;
|
||||
;}
|
||||
|
||||
;void goo() {
|
||||
; result = y[64000];
|
||||
;}
|
Loading…
Reference in New Issue
Block a user