1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 11:42:57 +01:00
llvm-mirror/lib/Target/Mips/MipsISelDAGToDAG.cpp
Daniel Sanders 05fcf12f78 [mips][mips16] Fix machine verifier errors about incorrect register classes on load/stores.
Summary:
[ls][bh] and [ls][bh]u cannot use sp-relative addresses and must therefore
lower frameindex nodes such that there is a copy to a CPU16Regs register. This
is now done consistently using a separate addressing mode that does not
permit frameindex nodes.

As part of this I've had to remove an optimization that reduced the number of
instructions needed to work around the lack of sp-relative addresses on [ls][bh]
and [ls][bh]u. This optimization used one of the eight CPU16Regs registers as
a copy of the stack pointer and it's implementation was the root cause of many
of the register vs register class mismatches.

lw/sw can use sp-relative addresses but we ought to ensure that we use the
correct version of lw/sw internally for things like IAS. This is not currently
the case and this change does not fix this. However, this change does clean it
up sufficiently well to fix the machine verifier failures.

Also removed irrelevant functions from stchar.ll.

Reviewers: sdardis

Subscribers: dsanders, sdardis, llvm-commits

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

llvm-svn: 272882
2016-06-16 10:20:59 +00:00

241 lines
7.4 KiB
C++

//===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the MIPS target.
//
//===----------------------------------------------------------------------===//
#include "MipsISelDAGToDAG.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
#include "Mips16ISelDAGToDAG.h"
#include "MipsMachineFunction.h"
#include "MipsRegisterInfo.h"
#include "MipsSEISelDAGToDAG.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
#define DEBUG_TYPE "mips-isel"
//===----------------------------------------------------------------------===//
// Instruction Selector Implementation
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// MipsDAGToDAGISel - MIPS specific code to select MIPS machine
// instructions for SelectionDAG operations.
//===----------------------------------------------------------------------===//
bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget());
bool Ret = SelectionDAGISel::runOnMachineFunction(MF);
processFunctionAfterISel(MF);
return Ret;
}
/// getGlobalBaseReg - Output the instructions required to put the
/// GOT address into a register.
SDNode *MipsDAGToDAGISel::getGlobalBaseReg() {
unsigned GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg();
return CurDAG->getRegister(GlobalBaseReg, getTargetLowering()->getPointerTy(
CurDAG->getDataLayout()))
.getNode();
}
/// ComplexPattern used on MipsInstrInfo
/// Used on Mips Load/Store instructions
bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
SDValue &Offset) {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
SDValue &Offset) {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
unsigned MinSizeInBits) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
llvm_unreachable("Unimplemented function.");
return false;
}
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
void MipsDAGToDAGISel::Select(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
// Dump information about the Node being selected
DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
// If we have a custom node, we already have selected!
if (Node->isMachineOpcode()) {
DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
Node->setNodeId(-1);
return;
}
// See if subclasses can handle this node.
if (trySelect(Node))
return;
switch(Opcode) {
default: break;
// Get target GOT address.
case ISD::GLOBAL_OFFSET_TABLE:
ReplaceNode(Node, getGlobalBaseReg());
return;
#ifndef NDEBUG
case ISD::LOAD:
case ISD::STORE:
assert((Subtarget->systemSupportsUnalignedAccess() ||
cast<MemSDNode>(Node)->getMemoryVT().getSizeInBits() / 8 <=
cast<MemSDNode>(Node)->getAlignment()) &&
"Unexpected unaligned loads/stores.");
break;
#endif
}
// Select the default instruction
SelectCode(Node);
}
bool MipsDAGToDAGISel::
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
std::vector<SDValue> &OutOps) {
// All memory constraints can at least accept raw pointers.
switch(ConstraintID) {
default:
llvm_unreachable("Unexpected asm memory constraint");
case InlineAsm::Constraint_i:
case InlineAsm::Constraint_m:
case InlineAsm::Constraint_R:
case InlineAsm::Constraint_ZC:
OutOps.push_back(Op);
return false;
}
return true;
}