mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-15 18:06:08 +00:00

Introduce a new RISCVExpandPseudoInsts pass to expand atomic pseudo-instructions after register allocation. This is necessary in order to ensure that register spills aren't introduced between LL and SC, thus breaking the forward progress guarantee for the operation. AArch64 does something similar for CmpXchg (though only at O0), and Mips is moving towards this approach (see D31287). See also [this mailing list post](http://lists.llvm.org/pipermail/llvm-dev/2016-May/099490.html) from James Knight, which summarises the issues with lowering to ll/sc in IR or pre-RA. See the [accompanying RFC thread](http://lists.llvm.org/pipermail/llvm-dev/2018-June/123993.html) for an overview of the lowering strategy. Differential Revision: https://reviews.llvm.org/D47882 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@342534 91177308-0d34-0410-b5e6-96231b3b80d8
131 lines
5.3 KiB
C++
131 lines
5.3 KiB
C++
//===-- RISCVISelLowering.h - RISCV DAG Lowering Interface ------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the interfaces that RISCV uses to lower LLVM code into a
|
|
// selection DAG.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_RISCV_RISCVISELLOWERING_H
|
|
#define LLVM_LIB_TARGET_RISCV_RISCVISELLOWERING_H
|
|
|
|
#include "RISCV.h"
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
|
#include "llvm/CodeGen/TargetLowering.h"
|
|
|
|
namespace llvm {
|
|
class RISCVSubtarget;
|
|
namespace RISCVISD {
|
|
enum NodeType : unsigned {
|
|
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
|
RET_FLAG,
|
|
URET_FLAG,
|
|
SRET_FLAG,
|
|
MRET_FLAG,
|
|
CALL,
|
|
SELECT_CC,
|
|
BuildPairF64,
|
|
SplitF64,
|
|
TAIL
|
|
};
|
|
}
|
|
|
|
class RISCVTargetLowering : public TargetLowering {
|
|
const RISCVSubtarget &Subtarget;
|
|
|
|
public:
|
|
explicit RISCVTargetLowering(const TargetMachine &TM,
|
|
const RISCVSubtarget &STI);
|
|
|
|
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,
|
|
MachineFunction &MF,
|
|
unsigned Intrinsic) const override;
|
|
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
|
|
unsigned AS,
|
|
Instruction *I = nullptr) const override;
|
|
bool isLegalICmpImmediate(int64_t Imm) const override;
|
|
bool isLegalAddImmediate(int64_t Imm) const override;
|
|
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override;
|
|
bool isTruncateFree(EVT SrcVT, EVT DstVT) const override;
|
|
bool isZExtFree(SDValue Val, EVT VT2) const override;
|
|
|
|
// Provide custom lowering hooks for some operations.
|
|
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
|
|
|
|
// This method returns the name of a target specific DAG node.
|
|
const char *getTargetNodeName(unsigned Opcode) const override;
|
|
|
|
std::pair<unsigned, const TargetRegisterClass *>
|
|
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
|
StringRef Constraint, MVT VT) const override;
|
|
|
|
MachineBasicBlock *
|
|
EmitInstrWithCustomInserter(MachineInstr &MI,
|
|
MachineBasicBlock *BB) const override;
|
|
|
|
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
|
|
EVT VT) const override;
|
|
|
|
bool shouldInsertFencesForAtomic(const Instruction *I) const override {
|
|
return isa<LoadInst>(I) || isa<StoreInst>(I);
|
|
}
|
|
Instruction *emitLeadingFence(IRBuilder<> &Builder, Instruction *Inst,
|
|
AtomicOrdering Ord) const override;
|
|
Instruction *emitTrailingFence(IRBuilder<> &Builder, Instruction *Inst,
|
|
AtomicOrdering Ord) const override;
|
|
|
|
private:
|
|
void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
bool IsRet) const;
|
|
void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
bool IsRet, CallLoweringInfo *CLI) const;
|
|
// Lower incoming arguments, copy physregs into vregs
|
|
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
|
|
bool IsVarArg,
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
const SDLoc &DL, SelectionDAG &DAG,
|
|
SmallVectorImpl<SDValue> &InVals) const override;
|
|
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
|
|
bool IsVarArg,
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
LLVMContext &Context) const override;
|
|
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
|
|
SelectionDAG &DAG) const override;
|
|
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
SmallVectorImpl<SDValue> &InVals) const override;
|
|
bool shouldConvertConstantLoadToIntImm(const APInt &Imm,
|
|
Type *Ty) const override {
|
|
return true;
|
|
}
|
|
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
|
|
|
|
bool IsEligibleForTailCallOptimization(CCState &CCInfo,
|
|
CallLoweringInfo &CLI, MachineFunction &MF,
|
|
const SmallVector<CCValAssign, 16> &ArgLocs) const;
|
|
|
|
TargetLowering::AtomicExpansionKind
|
|
shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override;
|
|
virtual Value *emitMaskedAtomicRMWIntrinsic(
|
|
IRBuilder<> &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr,
|
|
Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override;
|
|
};
|
|
}
|
|
|
|
#endif
|