summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MipsISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips/MipsISelLowering.cpp')
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp175
1 files changed, 154 insertions, 21 deletions
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 8c2a364cdfa9..0ff09007da4b 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -1,9 +1,8 @@
//===- MipsISelLowering.cpp - Mips DAG Lowering Implementation ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -13,8 +12,8 @@
//===----------------------------------------------------------------------===//
#include "MipsISelLowering.h"
-#include "InstPrinter/MipsInstPrinter.h"
#include "MCTargetDesc/MipsBaseInfo.h"
+#include "MCTargetDesc/MipsInstPrinter.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "MipsCCState.h"
#include "MipsInstrInfo.h"
@@ -57,6 +56,7 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
@@ -91,6 +91,8 @@ NoZeroDivCheck("mno-check-zero-division", cl::Hidden,
cl::desc("MIPS: Don't trap on integer division by zero."),
cl::init(false));
+extern cl::opt<bool> EmitJalrReloc;
+
static const MCPhysReg Mips64DPRegs[8] = {
Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64
@@ -362,6 +364,11 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
+ if (!(TM.Options.NoNaNsFPMath || Subtarget.inAbs2008Mode())) {
+ setOperationAction(ISD::FABS, MVT::f32, Custom);
+ setOperationAction(ISD::FABS, MVT::f64, Custom);
+ }
+
if (Subtarget.isGP64bit()) {
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
@@ -1183,14 +1190,22 @@ bool MipsTargetLowering::isCheapToSpeculateCtlz() const {
return Subtarget.hasMips32();
}
+bool MipsTargetLowering::shouldFoldConstantShiftPairToMask(
+ const SDNode *N, CombineLevel Level) const {
+ if (N->getOperand(0).getValueType().isVector())
+ return false;
+ return true;
+}
+
void
MipsTargetLowering::LowerOperationWrapper(SDNode *N,
SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG) const {
SDValue Res = LowerOperation(SDValue(N, 0), DAG);
- for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I)
- Results.push_back(Res.getValue(I));
+ if (Res)
+ for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I)
+ Results.push_back(Res.getValue(I));
}
void
@@ -1216,6 +1231,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
case ISD::VASTART: return lowerVASTART(Op, DAG);
case ISD::VAARG: return lowerVAARG(Op, DAG);
case ISD::FCOPYSIGN: return lowerFCOPYSIGN(Op, DAG);
+ case ISD::FABS: return lowerFABS(Op, DAG);
case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG);
case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG);
case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG);
@@ -1709,7 +1725,7 @@ MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI,
assert((MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 ||
MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I64) &&
- "Unsupported atomic psseudo for EmitAtomicCmpSwap.");
+ "Unsupported atomic pseudo for EmitAtomicCmpSwap.");
const unsigned Size = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 ? 4 : 8;
@@ -1735,12 +1751,10 @@ MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI,
// after fast register allocation, the spills will end up outside of the
// blocks that their values are defined in, causing livein errors.
- unsigned DestCopy = MRI.createVirtualRegister(MRI.getRegClass(Dest));
unsigned PtrCopy = MRI.createVirtualRegister(MRI.getRegClass(Ptr));
unsigned OldValCopy = MRI.createVirtualRegister(MRI.getRegClass(OldVal));
unsigned NewValCopy = MRI.createVirtualRegister(MRI.getRegClass(NewVal));
- BuildMI(*BB, II, DL, TII->get(Mips::COPY), DestCopy).addReg(Dest);
BuildMI(*BB, II, DL, TII->get(Mips::COPY), PtrCopy).addReg(Ptr);
BuildMI(*BB, II, DL, TII->get(Mips::COPY), OldValCopy).addReg(OldVal);
BuildMI(*BB, II, DL, TII->get(Mips::COPY), NewValCopy).addReg(NewVal);
@@ -2293,11 +2307,79 @@ MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
return lowerFCOPYSIGN32(Op, DAG, Subtarget.hasExtractInsert());
}
+static SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG,
+ bool HasExtractInsert) {
+ SDLoc DL(Op);
+ SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32);
+
+ // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it
+ // to i32.
+ SDValue X = (Op.getValueType() == MVT::f32)
+ ? DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0))
+ : DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
+ Op.getOperand(0), Const1);
+
+ // Clear MSB.
+ if (HasExtractInsert)
+ Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32,
+ DAG.getRegister(Mips::ZERO, MVT::i32),
+ DAG.getConstant(31, DL, MVT::i32), Const1, X);
+ else {
+ // TODO: Provide DAG patterns which transform (and x, cst)
+ // back to a (shl (srl x (clz cst)) (clz cst)) sequence.
+ SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1);
+ Res = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1);
+ }
+
+ if (Op.getValueType() == MVT::f32)
+ return DAG.getNode(ISD::BITCAST, DL, MVT::f32, Res);
+
+ // FIXME: For mips32r2, the sequence of (BuildPairF64 (ins (ExtractElementF64
+ // Op 1), $zero, 31 1) (ExtractElementF64 Op 0)) and the Op has one use, we
+ // should be able to drop the usage of mfc1/mtc1 and rewrite the register in
+ // place.
+ SDValue LowX =
+ DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
+ DAG.getConstant(0, DL, MVT::i32));
+ return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res);
+}
+
+static SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG,
+ bool HasExtractInsert) {
+ SDLoc DL(Op);
+ SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32);
+
+ // Bitcast to integer node.
+ SDValue X = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Op.getOperand(0));
+
+ // Clear MSB.
+ if (HasExtractInsert)
+ Res = DAG.getNode(MipsISD::Ins, DL, MVT::i64,
+ DAG.getRegister(Mips::ZERO_64, MVT::i64),
+ DAG.getConstant(63, DL, MVT::i32), Const1, X);
+ else {
+ SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i64, X, Const1);
+ Res = DAG.getNode(ISD::SRL, DL, MVT::i64, SllX, Const1);
+ }
+
+ return DAG.getNode(ISD::BITCAST, DL, MVT::f64, Res);
+}
+
+SDValue MipsTargetLowering::lowerFABS(SDValue Op, SelectionDAG &DAG) const {
+ if ((ABI.IsN32() || ABI.IsN64()) && (Op.getValueType() == MVT::f64))
+ return lowerFABS64(Op, DAG, Subtarget.hasExtractInsert());
+
+ return lowerFABS32(Op, DAG, Subtarget.hasExtractInsert());
+}
+
SDValue MipsTargetLowering::
lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
// check the depth
- assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) &&
- "Frame address can only be determined for current frame.");
+ if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() != 0) {
+ DAG.getContext()->emitError(
+ "return address can be determined only for current frame");
+ return SDValue();
+ }
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
MFI.setFrameAddressIsTaken(true);
@@ -2314,8 +2396,11 @@ SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op,
return SDValue();
// check the depth
- assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) &&
- "Return address can be determined only for current frame.");
+ if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() != 0) {
+ DAG.getContext()->emitError(
+ "return address can be determined only for current frame");
+ return SDValue();
+ }
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -2879,6 +2964,54 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
Ops.push_back(InFlag);
}
+void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
+ SDNode *Node) const {
+ switch (MI.getOpcode()) {
+ default:
+ return;
+ case Mips::JALR:
+ case Mips::JALRPseudo:
+ case Mips::JALR64:
+ case Mips::JALR64Pseudo:
+ case Mips::JALR16_MM:
+ case Mips::JALRC16_MMR6:
+ case Mips::TAILCALLREG:
+ case Mips::TAILCALLREG64:
+ case Mips::TAILCALLR6REG:
+ case Mips::TAILCALL64R6REG:
+ case Mips::TAILCALLREG_MM:
+ case Mips::TAILCALLREG_MMR6: {
+ if (!EmitJalrReloc ||
+ Subtarget.inMips16Mode() ||
+ !isPositionIndependent() ||
+ Node->getNumOperands() < 1 ||
+ Node->getOperand(0).getNumOperands() < 2) {
+ return;
+ }
+ // We are after the callee address, set by LowerCall().
+ // If added to MI, asm printer will emit .reloc R_MIPS_JALR for the
+ // symbol.
+ const SDValue TargetAddr = Node->getOperand(0).getOperand(1);
+ StringRef Sym;
+ if (const GlobalAddressSDNode *G =
+ dyn_cast_or_null<const GlobalAddressSDNode>(TargetAddr)) {
+ Sym = G->getGlobal()->getName();
+ }
+ else if (const ExternalSymbolSDNode *ES =
+ dyn_cast_or_null<const ExternalSymbolSDNode>(TargetAddr)) {
+ Sym = ES->getSymbol();
+ }
+
+ if (Sym.empty())
+ return;
+
+ MachineFunction *MF = MI.getParent()->getParent();
+ MCSymbol *S = MF->getContext().getOrCreateSymbol(Sym);
+ MI.addOperand(MachineOperand::CreateMCSymbol(S, MipsII::MO_JALR));
+ }
+ }
+}
+
/// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
SDValue
@@ -2930,7 +3063,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// the maximum out going argument area (including the reserved area), and
// preallocates the stack space on entrance to the caller.
//
- // FIXME: We should do the same for efficency and space.
+ // FIXME: We should do the same for efficiency and space.
// Note: The check on the calling convention below must match
// MipsABIInfo::GetCalleeAllocdArgSizeInBytes().
@@ -4007,18 +4140,18 @@ MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
return false;
}
-EVT MipsTargetLowering::getOptimalMemOpType(uint64_t Size, unsigned DstAlign,
- unsigned SrcAlign,
- bool IsMemset, bool ZeroMemset,
- bool MemcpyStrSrc,
- MachineFunction &MF) const {
+EVT MipsTargetLowering::getOptimalMemOpType(
+ uint64_t Size, unsigned DstAlign, unsigned SrcAlign, bool IsMemset,
+ bool ZeroMemset, bool MemcpyStrSrc,
+ const AttributeList &FuncAttributes) const {
if (Subtarget.hasMips64())
return MVT::i64;
return MVT::i32;
}
-bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
+bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
+ bool ForCodeSize) const {
if (VT != MVT::f32 && VT != MVT::f64)
return false;
if (Imm.isNegZero())