unsigned int getJumpTableEncoding ( ) { unsigned int encoding = 0 ; if ( getTargetArchitecture ( ) == RISCV ) { encoding = RISCV ; } return encoding ; }


bool getTgtMemIntrinsic ( unsigned IntrCode ) { switch ( IntrCode ) { case Intrinsic :: riscv_masked_atomicrmw_xchg_i32 : case Intrinsic :: riscv_masked_atomicrmw_add_i32 : case Intrinsic :: riscv_masked_atomicrmw_sub_i32 : case Intrinsic :: riscv_masked_atomicrmw_nand_i32 : case Intrinsic :: riscv_masked_atomicrmw_max_i32 : case Intrinsic :: riscv_masked_atomicrmw_min_i32 : case Intrinsic :: riscv_masked_atomicrmw_umax_i32 : case Intrinsic :: riscv_masked_atomicrmw_umin_i32 : case Intrinsic :: riscv_masked_cmpxchg_i32 : case ISD :: INTRINSIC_W_CHAIN : case Intrinsic :: riscv_masked_strided_load : case Intrinsic :: riscv_masked_strided_store : return true ; default : return false ; } }


bool hasAndNotCompare ( ) { if ( Triple . getArch ( ) != Triple :: riscv ) { return false ; } const MCSubtargetInfo & STI = getSTI ( ) ; if ( ! STI . hasRISCV ( ) ) { return false ; } if ( ! STI . getFeatureBits ( ) . RISCVHardFloat ) { return false ; } if ( ! STI . getFeatureBits ( ) . RISCV64 ) { return false ; } return true ; }


bool isFPImmLegal ( unsigned RISCV , MVT :: f16 , MVT :: f32 , MVT :: f64 ) { if ( RISCV != 1 ) return false ; if ( RISCV . getMVT ( MVT :: f16 ) != 1 || RISCV . getMVT ( MVT :: f32 ) != 1 || RISCV . getMVT ( MVT :: f64 ) != 1 ) return false ; return true ; }


bool RISCVTargetLowering :: isZExtFree ( const SDNode * Val , EVT VT2 ) const { if ( VT2 == Val -> getValueType ( 0 ) ) { return true ; } if ( ConstantSDNode * ConstVal = dyn_cast < ConstantSDNode > ( Val ) ) { if ( ConstVal -> getAPIntValue ( ) . getZExtValue ( ) < VT2 . getSizeInBits ( ) ) { return true ; } } if ( Val -> getOpcode ( ) == ISD :: NON_EXTLOAD && Val -> getValueType ( 0 ) == VT2 ) { return true ; } if ( Val -> getOpcode ( ) == ISD :: ZEXTLOAD ) { if ( Val -> getOperand ( 0 ) -> getOpcode ( ) == ISD :: NON_EXTLOAD && Val -> getOperand ( 0 ) -> getValueType ( 0 ) == VT2 ) { return true ; } if ( Val -> getOperand ( 0 ) -> getValueType ( 0 ) == MVT :: i8 || Val -> getOperand ( 0 ) -> getValueType ( 0 ) == MVT :: i16 ) { if ( VT2 == MVT :: i8 || VT2 == MVT :: i16 ) { return true ; } } if ( Val -> getOperand ( 0 ) -> getValueType ( 0 ) == MVT :: i8 || Val -> getOperand ( 0 ) -> getValueType ( 0 ) == MVT :: i16 ) { if ( VT2 == MVT :: i32 ) { return true ; } } }


bool shouldConvertFpToSat ( MVT :: SimpleValueType FPVT , MVT :: SimpleValueType VT ) { if ( FPVT != MVT :: f16 && FPVT != MVT :: f32 && FPVT != MVT :: f64 ) { return false ; } if ( VT != MVT :: f16 && VT != MVT :: f32 && VT != MVT :: f64 ) { return false ; } if ( VT < FPVT ) { return false ; } if ( VT != ( FPVT << Log2_32_Ceil ( VT / FPVT ) ) ) { return false ; } return true ; }


Value * emitMaskedAtomicRMWIntrinsic ( IRBuilder < > & Builder , AtomicRMWInst * AI , Value * Ptr , Value * Val , Value * Mask , Value * Order , unsigned AtomicSizeInBits ) { if ( AI -> getModule ( ) -> getTargetTriple ( ) . isRISCVELF ( ) ) { auto & ctx = AI -> getContext ( ) ; const char * Target = "RISCV" ; SmallString < 256 > Name ( "llvm.masked.atomicrmw." ) ; Name . append ( Target ) ; Name . push_back ( '.' ) ; InitType * TruncTy = TypeBuilder < types :: i < AtomicSizeInBitsBits ( ) ) , true > :: get ( ctx ) ; Name . append ( TruncTy -> getName ( ) ) ; Name . push_back ( 'v' ) ; FunctionType * MaskedAtomicRMWDeclType = Intrinsic :: getDeclaration ( AI -> getParent ( ) -> getParent ( ) -> getModule ( ) . get ( ) , Intrinsic :: riscv_masked_atomicrmw , TruncTy ) ; FunctionCallee Func = AI -> getParent ( ) -> getParent ( ) -> getModule ( ) . getOrInsertFunction ( Name . c_str ( ) , MaskedAtomicRMWDeclType ) ; ArrayRef < Value * > Args = { Ptr , Val , Mask , Order } ; return Builder . CreateCall ( Func , Args ) ; } return NULL ; }


bool getTgtMemIntrinsic ( unsigned IID ) { switch ( IID ) { case Intrinsic :: riscv_masked_atomicrmw_xchg_i32 : case Intrinsic :: riscv_masked_atomicrmw_add_i32 : case Intrinsic :: riscv_masked_atomicrmw_sub_i32 : case Intrinsic :: riscv_masked_atomicrmw_nand_i32 : case Intrinsic :: riscv_masked_atomicrmw_max_i32 : case Intrinsic :: riscv_masked_atomicrmw_min_i32 : case Intrinsic :: riscv_masked_atomicrmw_umax_i32 : case Intrinsic :: riscv_masked_atomicrmw_umin_i32 : return true ; default : return false ; } }


string getTargetNodeName ( RISCVISD :: NodeType nodeType ) { switch ( nodeType ) { case RISCVISD :: FIRST_NUMBER : return "RISCVISD::FIRST_NUMBER" ; case RISCVISD :: RET_FLAG : return "RISCVISD::RET_FLAG" ; case RISCVISD :: URET_FLAG : return "RISCVISD::URET_FLAG" ; case RISCVISD :: SRET_FLAG : return "RISCVISD::SRET_FLAG" ; case RISCVISD :: MRET_FLAG : return "RISCVISD::MRET_FLAG" ; case RISCVISD :: CALL : return "RISCVISD::CALL" ; case RISCVISD :: SELECT_CC : return "RISCVISD::SELECT_CC" ; case RISCVISD :: BuildPairF64 : return "RISCVISD::BuildPairF64" ; case RISCVISD :: SplitF64 : return "RISCVISD::SplitF64" ; case RISCVISD :: TAIL : return "RISCVISD::TAIL" ; case RISCVISD :: SLLW : return "RISCVISD::SLLW" ; case RISCVISD :: SRAW : return "RISCVISD::SRAW" ; case RISCVISD :: SRLW : return "RISCVISD::SRLW" ; case RISCVISD :: DIVW : return "RISCVISD::DIVW" ; case RISCVISD :: DIVUW : return "RISCVISD::DIVUW" ; case RISCVISD :: REMUW : return "RISCVISD::REMUW" ; default : return "RISCV" ; } }


N -> getOpcode ( ) != RISCVISD :: SRLW ) { return ; } if ( N -> getOperand ( 0 ) . getValueType ( ) . getSizeInBits ( ) != N -> getOperand ( 1 ) . getValueType ( ) . getSizeInBits ( ) ) { return ; } if ( N -> getOperand ( 0 ) . getValueType ( ) != MVT :: i32 || N -> getOperand ( 1 ) . getValueType ( ) != MVT :: i32 ) { return ; } if ( N -> getValueType ( 0 ) != MVT :: i32 ) { return ; }


void emitMaskedAtomicCmpXchgIntrinsic ( IRBuilder < > & Builder , Value * Ptr , Value * Mask , Value * NewVal , Value * CmpVal , AtomicOrdering SuccessOrdering , AtomicOrdering FailureOrdering ) { LLVMContext & Ctx = Builder . getContext ( ) ; FunctionType * FT = FunctionType :: get ( Builder . getInt32Ty ( ) , { Builder . getInt8PtrTy ( ) , Builder . getInt8Ty ( ) , Builder . getInt8Ty ( ) , Builder . getInt32Ty ( ) , Builder . getInt32Ty ( ) , Builder . getInt32Ty ( ) , Builder . getInt32Ty ( ) , Builder . getInt8Ty ( ) } , false ) ; Function * Func = Intrinsic :: getDeclaration ( Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) , Intrinsic :: riscv_masked_cmpxchg_i32 ) ; CallInst * CI = Builder . CreateCall ( Func , { Ptr , Mask , NewVal , CmpVal , Builder . getInt32 ( SuccessOrdering ) , Builder . getInt32 ( FailureOrdering ) , Builder . getInt8 ( 0 ) } ) ; CI -> setCallingConv ( CallingConv :: C ) ; }


bool getTgtMemIntrinsic ( const CallInst * CI ) { unsigned IID = CI -> getIntrinsicID ( ) ; if ( IID == Intrinsic :: riscv_masked_atomicrmw_xchg_i32 || IID == Intrinsic :: riscv_masked_atomicrmw_add_i32 || IID == Intrinsic :: riscv_masked_atomicrmw_sub_i32 || IID == Intrinsic :: riscv_masked_atomicrmw_nand_i32 || IID == Intrinsic :: riscv_masked_atomicrmw_max_i32 || IID == Intrinsic :: riscv_masked_atomicrmw_min_i32 || IID == Intrinsic :: riscv_masked_atomicrmw_umax_i32 || IID == Intrinsic :: riscv_masked_atomicrmw_umin_i32 || IID == Intrinsic :: riscv_masked_cmpxchg_i32 ) { return true ; } return false ; }


VLMask RISCVISD :: getAllOnesMask ( ) { SDValue VLMask = CurDAG -> getRegister ( RISCV :: VM , MVT :: nxv64 ) ; SDValue MVT = CurDAG -> getRegisterMask ( EVT :: getVectorVT ( * CurDAG -> getContext ( ) , MVT :: i1 , NumElts ) ) ; MVT -> setRISCVMVF ( RISCVISD :: VMSET_VL ) ; return VLMask ; }


bool isLegalAddressingMode ( const MachineFunction & MF , const MachineInstr & MI , const MachineOperand & MO ) { unsigned LoadStoreType = MI . getOpcode ( ) ; if ( MO . getTargetFlags ( ) == RISCV :: RISCV || MO . getTargetFlags ( ) == RISCV :: RISCV || MO . getTargetFlags ( ) == 0 || MO . getTargetFlags ( ) == 12 || MO . getTargetFlags ( ) == 0 || MO . getTargetFlags ( ) == 1 ) { return RISCV :: isLegalLoadStoreType ( LoadStoreType ) ; } return false ; }


bool isOffsetFoldingLegal ( const GlobalAddress * GA , const ConstantInt * Offset ) { if ( GA -> getTargetNodeName ( ) != "RISCV" ) return false ; if ( ! isa < ConstantInt > ( Offset ) ) return false ; uint64_t absoluteAddr = GA -> getAddress ( ) + Offset -> getZExtValue ( ) ; if ( absoluteAddr < MinSupportAddress || absoluteAddr > MaxSupportAddress ) return false ; if ( absoluteAddr % 4 != 0 ) return false ; return true ; }


bool signExtendConstant ( const TargetMachine & TM , Constant * C ) { if ( TM . getTargetTriple ( ) . getArch ( ) != llvm :: Triple :: riscv ) { return false ; } uint64_t targetSpecificValue = TM . getTargetTriple ( ) . getArchName ( ) == "riscv32" ? 32 : 64 ; if ( ! isa < ConstantInt > ( C ) ) { return false ; } ConstantInt * CI = cast < ConstantInt > ( C ) ; if ( CI -> getBitWidth ( ) < targetSpecificValue ) { if ( CI -> isSigned ( ) ) { CI = cast < ConstantInt > ( CI -> getSExtValue ( targetSpecificValue ) ) ; return true ; } } return false ; }


bool allowsMisalignedMemoryAccesses ( Type * Ty , const Triple & , unsigned ) { if ( Ty -> isIntegerTy ( ) || Ty -> isPointerTy ( ) ) { return true ; } else { return false ; } }


unsigned ComputeNumSignBitsForTargetNode ( unsigned Opc ) { switch ( Opc ) { default : return 0 ; case RISCVISD :: SLLW : case RISCVISD :: SRAW : case RISCVISD :: SRLW : case RISCVISD :: DIVW : case RISCVISD :: DIVUW : case RISCVISD :: REMUW : case RISCVISD :: ROLW : case RISCVISD :: RORW : case RISCVISD :: GREVW : case RISCVISD :: GORCW : case RISCVISD :: FSLW : case RISCVISD :: FSRW : case RISCVISD :: SHFLW : case RISCVISD :: UNSHFLW : case RISCVISD :: BCOMPRESSW : case RISCVISD :: BDECOMPRESSW : return 32 ; case RISCVISD :: SHFL : case RISCVISD :: UNSHFL : return 33 ; case RISCVISD :: VMV_X_S : return 1 ; } }


void
RISCVTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
*
MI
,
MachineBasicBlock
*
MBB
)
const
{
RISCV
::
CustomInserterInfo
*
InserterInfo
=
(
RISCV
::
CustomInserterInfo
*
)
MI
->
getOperand
(
MI
->
getNumOperands
(
)
1
)
.
getTargetFlags
(
)
;
unsigned
Opc
=
MI
->
getOperand
(
0
)
.
getTargetFlags
(
)
;
MachineInstrBuilder
MIB
(
MBB
->
getParent
(
)
->
getParent
(
)
,
MI
)
;
RISCV
::
RegisterStoreFlagsRegMask
(
)
;
MachineFunction
&
MF
=
*
MBB
->
getParent
(
)
;
MachineRegisterInfo
&
MRI
=
MF
.
getRegInfo
(
)
;
const
TargetInstrInfo
&
TII
=
*
MF
.
getSubtarget
(
)
.
getInstrInfo
(
)
;
const
TargetRegisterClass
&
GPRRegClass
=
RISCV
::
G8RCRegClass
;
const
TargetRegisterClass
&
FPR16RegClass
=
RISCV
::
F16RCRegClass
;
const
TargetRegisterClass
&
FPR32RegClass
=
RISCV
::
F32RCRegClass
;
const
TargetRegisterClass
&
FPR64RegClass
=
RISCV
::
F64RCRegClass
;
MachineOperand
Op1
=
MI
->
getOperand
(
1
)
;
MachineOperand
Op2
=
MI
->
getOperand
(
2
)
;
MachineOperand
Op3
=
MI
->
getOperand
(
3
)
;
StringRef
ErrMsg
;
switch
(
Opc
)
{
case
RISCV
::
ReadCycleWide
:
{
if
(
!
(
Op1
.
isReg
(
)
&&
Op2
.
isReg
(
)
&&
Op3
.
isImm
(
)
)
)
{
ErrMsg
=
"Unexpected instr type to insert"
;
LLVM_DEBUG
(
dbgs
(
)
<<
ErrMsg
<<
"\n"
)
;
MIB
.
addImm
(
RISCV
::
CustomInserterInfo
::
ErrOpcode
)
;
return
;
}


StringRef getConstraintType ( StringRef Constraint ) { if ( Constraint == "m" ) { return "RISCV" ; } else if ( Constraint == "r" ) { return "RISCV" ; } else if ( Constraint == "f" ) { return "RISCV" ; } else if ( Constraint == "i" ) { return "1" ; } else if ( Constraint == "mbr" ) { return "0" ; } else { return "" ; } }


StringRef
getTargetNodeName
(
unsigned
Opcode
)
{
switch
(
Opcode
)
{
case
RISCVISD
::
NodeType
:
return
"RISCV"
;
case
RISCVISD
::
FIRST_NUMBER
:
return
"RISCV"
;
case
RISCVISD
::
RET_FLAG
:
return
"RISCVISD::RET_FLAG"
;
case
RISCVISD
::
URET_FLAG
:
return
"RISCVISD::URET_FLAG"
;
case
RISCVISD
::
SRET_FLAG
:
return
"RISCVISD::SRET_FLAG"
;
case
RISCVISD
::
MRET_FLAG
:
return
"RISCVISD::MRET_FLAG"
;
case
RISCVISD
::
CALL
:
return
"RISCVISD::CALL"
;
case
RISCVISD
::
SELECT_CC
:
return
"RISCVISD::SELECT_CC"
;
case
RISCVISD
::
BuildPairF64
:
return
"RISCVISD::BuildPairF64"
;
case
RISCVISD
::
SplitF64
:
return
"RISCVISD::SplitF64"
;
case
RISCVISD
::
TAIL
:
return
"RISCVISD::TAIL"
;
case
RISCVISD
::
SLLW
:
return
"RISCVISD::SLLW"
;
case
RISCVISD
::
SRAW
:
return
"RISCVISD::SRAW"
;
case
RISCVISD
::
SRLW
:
return
"RISCVISD::SRLW"
;
case
RISCVISD
::
DIVW
:
return
"RISCVISD::DIVW"
;
case
RISCVISD
::
DIVUW
:
return
"RISCVISD::DIVUW"
;
case
RISCVISD
::
REMUW
:
return
"RISCVISD::REMUW"
;
case
RISCVISD
::
FMV_W_X_RV64
:
return
"RISCVISD::FMV_W_X_RV64"
;
case
RISCVISD
::
FMV_X_ANYEXTW_RV64
:
return
"RISCVISD::FMV_X_ANYEXTW_RV64"
;
default
:
llvm_unreachable
(
"Invalid target specific value"
)
;
}
}


void ReplaceNodeResults ( SDNode * N , SmallVectorImpl < SDValue > & Results , SelectionDAG & DAG ) { if ( N -> getValueType ( 0 ) == MVT :: i32 ) { unsigned Opcode = N -> getOpcode ( ) ; if ( Opcode == ISD :: SHL || Opcode == ISD :: SRA || Opcode == ISD :: SRL ) { SDValue NewVal = DAG . getNode ( RISCVISD :: FMV_X_ANYEXTW_RV64 , SDLoc ( N ) , MVT :: i64 , Results [ 0 ] ) ; SDValue NewVal2 = DAG . getNode ( ISD :: TRUNCATE , SDLoc ( N ) , MVT :: i32 , NewVal ) ; Results [ 0 ] = NewVal2 ; } else if ( Opcode == ISD :: SDIV || Opcode == ISD :: UDIV || Opcode == ISD :: UREM ) { SDValue NewVal = DAG . getNode ( ISD :: BITCAST , SDLoc ( N ) , MVT :: i32 , Results [ 0 ] ) ; SDValue NewVal2 = DAG . getNode ( ISD :: Constant , SDLoc ( N ) , MVT :: i32 , 1 ) ; Results [ 0 ] = NewVal ; Results [ 1 ] = NewVal2 ; } else if ( Opcode == ISD :: BITCAST ) { SDValue NewVal2 = DAG . getNode ( RISCVISD :: FMV_X_ANYEXTW_RV64 , SDLoc ( N ) , MVT :: i64 , Results [ 0 ] ) ; Results [ 0 ] = NewVal2 ; }


LLVMContext & Context ) { if ( CallConv != CallingConv :: RISCV ) { return false ; } const RISCVSubtarget & Subtarget = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVABIInfo & ABI = Subtarget . getABI ( ) ; for ( auto & Arg : Outs ) { switch ( Arg . Flags . getByValSize ( ) ) { case 0 : if ( ! ABI . IsLegalReturnReg ( Arg . VT ) ) { return false ; } break ; default : if ( ! ABI . IsLegalReturnRegByVal ( Arg . VT ) ) { return false ; } break ; } } return true ; }


bool EmitInstrWithCustomInserter ( MachineInstr * MI , MachineBasicBlock * MBB , MachineBasicBlock :: iterator I , ArrayRef < MachineOperand > MOs , const DebugLoc & DL , SmallVectorImpl < SMLoc > & TmpLocs , unsigned SEWIndex , MCRegister Reg , const MCInstrDesc & MCID ) { if ( ! MI -> getDesc ( ) . usesCustomInserter ( ) ) { return false ; } if ( SEWIndex < 0 ) { return false ; }


std
::
string
getTargetNodeName
(
RISCVISD
::
NodeType
Node
)
{
switch
(
Node
)
{
case
RISCVISD
::
NODE
:
return
"RISCVISD::NODE"
;
case
RISCVISD
::
NodeType
:
return
"RISCVISD::NodeType"
;
case
RISCVISD
::
FIRST_NUMBER
:
return
"RISCVISD::FIRST_NUMBER"
;
default
:
return
"Unknown Target Node Name"
;
}
}


getAddr ( const MachineInstr * MI ) { if ( MI -> getOpcode ( ) != RISCV :: PseudoLLA ) return nullptr ; MachineOperand AddrOp = MI -> getOperand ( 0 ) ; MachineOperand BaseOp = MI -> getOperand ( 1 ) ; MachineOperand DispOp = MI -> getOperand ( 2 ) ; if ( ! AddrOp . isReg ( ) || ! BaseOp . isReg ( ) || ! DispOp . isImm ( ) ) return nullptr ; unsigned int CodeModel = MI -> getOperand ( 3 ) . getImm ( ) ; unsigned int MO_HI = MI -> getOperand ( 4 ) . getImm ( ) ; unsigned int MO_LO = MI -> getOperand ( 5 ) . getImm ( ) ; unsigned int LUI = MI -> getOperand ( 6 ) . getImm ( ) ; unsigned int ADDI = MI -> getOperand ( 7 ) . getImm ( ) ; if ( CodeModel != RISCV :: PseudoLA ) return nullptr ; auto Addr = MachineOperand ( MI -> getMF ( ) -> getRegInfo ( ) , 0 , false , RISCV :: GPRRegClass , MI -> getOperand ( 0 ) . getReg ( ) ) ; auto Base = MachineOperand ( MI -> getMF ( ) -> getRegInfo ( ) , 0 , false , RISCV :: GPRRegClass , MI -> getOperand ( 1 ) . getReg ( ) ) ; auto Disp = MachineOperand :: CreateImm ( MI -> getOperand ( 2 ) . getImm ( ) ) ; Addr . Op = RISCV :: LUI ; Addr . addReg ( Base . getReg ( ) ) ; Disp . Op = RISCV :: ADDI ; Disp . addReg ( Disp . getReg ( ) ) ; Addr . Op = RISCV :: PseudoLLA ; return Addr ; }


bool getTgtMemIntrinsic ( Intrinsic * Int ) { if ( Int is one of the target specific values ) { return true ; } else if ( Int is an ISD :: INTRINSIC_W_CHAIN intrinsic ) { Value * IOf = Int -> getOperand ( 5 ) ; if ( IOf == 1 ) { return true ; } else { return false ; } } else { return false ; } }


bool hasBitTest ( const TargetMachine & TM ) { switch ( TM . getTargetTriple ( ) . getArch ( ) ) { case Triple :: riscv32 : case Triple :: riscv64 : case Triple :: riscv128 : return true ; default : return false ; } }


bool isMulAddWithConstProfitable ( const TargetMachine & TM , Value * Mul , Value * Add , ConstantInt * C1 , ConstantInt * C2 ) { if ( TM . getTargetTriple ( ) . getArch ( ) != "riscv64" || TM . getTargetTriple ( ) . getOS ( ) != "riscv" ) { return false ; } if ( ! Mul -> getType ( ) -> isIntegerTy ( ) || Mul -> getType ( ) != Add -> getType ( ) || ! C1 -> getType ( ) -> isIntegerTy ( ) || ! C2 -> getType ( ) -> isIntegerTy ( ) ) { return false ; }


bool isShuffleMaskLegal ( VectorType type , VectorMask mask , TargetSpecificValue ts_val ) { if ( type != RISCV ) return false ; for ( int i = 0 ; i < mask . size ( ) ; i ++ ) { if ( mask [ i ] < 0 || mask [ i ] >= ts_val ) return false ; } return true ; }


MachineBasicBlock
::
iterator
I
)
const
{
if
(
!
MI
->
getDesc
(
)
.
usesCustomInserter
(
)
)
return
;
RISCVVectorPseudoInfo
*
PseudoInfo
=
RISCVVectorPseudosTable
::
getRISCVVectorPseudoInfo
(
MI
->
getOpcode
(
)
)
;
RISCVVectorSEW
SEW
=
RISCVVectorPseudosTable
::
getRISCVVectorPseudoSEW
(
PseudoInfo
->
Encoding
)
;
RISCVVectorLMUL
VLMUL
=
RISCVVectorPseudosTable
::
getRISCVVectorPseudoLMUL
(
PseudoInfo
->
Encoding
)
;
if
(
SEW
==
RISCVVectorSEW
::
SEWUNKNOWN
||
VLMUL
==
RISCVVectorLMUL
::
VLMULUNKNOWN
)
{
emitError
(
"Unknown SEW or VLMUL value!"
)
;
return
;
}


static std :: string getAddr ( const Instruction * I ) { const MachineInstr * MI = cast < MachineInstr > ( I ) ; const MachineFunction * MF = MI -> getParent ( ) -> getParent ( ) ; const RISCVInstrInfo * TII = MF -> getSubtarget ( ) . getInstrInfo ( ) ; MachineOperand BaseOp = MI -> getOperand ( 0 ) ; MachineOperand OffsetOp = MI -> getOperand ( 1 ) ; bool isCheriPureCapABI = RISCVABI :: isCheriPureCapABI ( * MF ) ; if ( MI -> getOpcode ( ) == RISCV :: PseudoCLGC || MI -> getOpcode ( ) == RISCV :: PseudoCLLC ) { MachineOperand BaseReg = isCheriPureCapABI ? MI -> getOperand ( 1 ) : MI -> getOperand ( 0 ) ; if ( BaseReg . isReg ( ) && TargetRegisterInfo :: isVirtualRegister ( BaseReg . getReg ( ) ) ) { const char * RegName = TII -> getRegisterName ( BaseReg . getReg ( ) ) ; return RegName ; } } if ( MI -> getOpcode ( ) == RISCV :: PseudoLLA || MI -> getOpcode ( ) == RISCV :: PseudoLA ) { if ( BaseOp . isReg ( ) && TargetRegisterInfo :: isVirtualRegister ( BaseOp . getReg ( ) ) ) { const char * RegName = TII -> getRegisterName ( BaseOp . getReg ( ) ) ; return RegName ; } }


const char * getConstraintType ( char c ) { switch ( c ) { case 'R' : return "RISCV" ; case '1' : return "1" ; case '0' : return "0" ; default : return "UNKNOWN" ; } }


llvm :: Register getExceptionPointerRegister ( MachineFunction & MF ) { const TargetInstrInfo * TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; if ( RISCV :: isCheriPureCapABI ( ) ) { return RISCV :: C10 ; } else { return RISCV :: X10 ; } }


llvm :: EVT CapSize ) { llvm :: TypeSize TySize = DL . getTypeSizeInBits ( Ty ) ; unsigned AlignedSize = DL . getTypeAllocSize ( Ty ) ; if ( TySize . isZero ( ) ) { return llvm :: EVT :: Other ; } if ( TySize . getKnownMinValue ( ) == 32 ) { return llvm :: EVT :: i32 ; } else if ( TySize . getKnownMinValue ( ) == 64 ) { return llvm :: EVT :: i64 ; } else { return llvm :: EVT :: Other ; } }


EVT getSetCCResultType ( SelectionDAG & DAG , EVT VT ) { if ( VT == MVT :: i1 ) { return VT ; } else { switch ( VT . getSimpleVT ( ) ) { case MVT :: i32 : case MVT :: i64 : return MVT :: i1 ; default : return EVT ( ) ; } } }


RISCVTargetNode * getTargetNode ( Edge * edge ) { RISCVTargetValue * riscvValue = edge -> getTargetSpecificValue ( ) ; RISCVTargetNode * riscvNode = new RISCVTargetNode ( ) ; riscvNode -> setTargetValue ( riscvValue ) ; return riscvNode ; }


bool shouldExpandAtomicRMWInIR ( int Opcode , PointerType T , int OperandSize , ABIType ABI ) { if ( T == RISCV && ABI == RISCVABI :: isCheriPureCapABI ) { return false ; } if ( T != RISCV ) { return true ; }


bool shouldExtendTypeInLibCall ( RISCVISD :: NodeTy Node ) { if ( Node == RISCVISD :: RISCV || Node == RISCVISD :: RISCVABI :: ABI || Node == RISCVISD :: RISCVABI :: ABI_LP64 || Node == RISCVISD :: RISCVABI :: ABI_L64PC128 || Node == MVT :: f32 ) { return true ; } else { return false ; } }


"Trying to obtain non-reserved register \""


"FMV_W_X_RV64 instruction should have a constant pool operand!"


ConstraintType getConstraintType ( char Constraint ) { switch ( Constraint ) { case 'R' : return ConstraintType :: TYPE_RISCV ; case '0' : return ConstraintType :: TYPE_ZERO ; case '1' : return ConstraintType :: TYPE_ONE ; default : return ConstraintType :: TYPE_RISCV ; } }


"Unsupported calling convention for RISCV backend.\n"

"VarArg not supported for RISCV backend.\n"


"Unimplemented operand for RISCV target"


CCValAssign
&
VA
)
{
MachineFunction
&
MF
=
MIRBuilder
.
getMF
(
)
;
MachineRegisterInfo
&
MRI
=
MF
.
getRegInfo
(
)
;
unsigned
RetCode
=
RISCVISD
::
RET_FLAG
;
MVT
ValVT
=
VA
.
getLocVT
(
)
;
if
(
ValVT
!=
MVT
::
Other
)
{
if
(
VA
.
isRegLoc
(
)
)
{
Register
Reg
=
VA
.
getLocReg
(
)
;
MIRBuilder
.
buildCopy
(
Reg
,
Val
)
;
}
else
{
report_fatal_error
(
"Can only return in registers!"
)
;
}
}
else
{
unsigned
NumRegs
=
VA
.
getValVT
(
)
.
getVectorNumElements
(
)
;
for
(
unsigned
i
=
0
;
i
<
NumRegs
;
++
i
)
{
Register
Reg
=
VA
.
getLocReg
(
)
;
MIRBuilder
.
buildCopy
(
Reg
,
Val
)
;
Index
++
;
}
}
MIRBuilder
.
buildInstr
(
RetCode
)
;
return
;
}


LLVMContext & Context ) const { if ( CallConv != CallingConv :: RISCV ) return false ; for ( unsigned i = 0 ; i < Outs . size ( ) ; ++ i ) { const ISD :: OutputArg & Out = Outs [ i ] ; EVT ArgVT = Out . ArgVT ; if ( ! isTypeLegal ( ArgVT ) ) return false ; if ( ! ArgVT . isScalar ( ) ) return false ; if ( RISCVABI :: getNumRegistersForType ( ArgVT ) > 1 ) return false ; } return true ; }


void
RISCVTargetLowering
::
LowerFormalArguments
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
InputArg
>
&
Ins
,
const
SDLoc
&
dl
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDValue
>
&
InVals
)
const
{
unsigned
NumArgs
=
Ins
.
size
(
)
;
for
(
unsigned
i
=
0
;
i
<
NumArgs
;
++
i
)
{
const
ISD
::
InputArg
&
In
=
Ins
[
i
]
;
if
(
In
.
PartOffset
!=
0
)
{
llvm_unreachable
(
"Unsupported calling convention"
)
;
return
;
}
if
(
In
.
Flags
.
isVarArg
(
)
)
{
llvm_unreachable
(
"VarArg not supported"
)
;
return
;
}
if
(
In
.
ArgVT
.
isVoid
(
)
)
{
llvm_unreachable
(
"Unhandled argument type"
)
;
return
;
}
EVT
ArgVT
=
In
.
ArgVT
;
SDValue
ArgValue
=
DAG
.
getTargetConstant
(
ISD
::
ADD
,
dl
,
MVT
::
i32
)
;
if
(
ArgVT
.
isInteger
(
)
)
{
ArgValue
=
DAG
.
getNode
(
ISD
::
SIGN_EXTEND
,
dl
,
MVT
::
i32
,
ArgValue
)
;
}
InVals
.
push_back
(
ArgValue
)
;
}
return
Chain
;
}


Value
*
getAddr
(
MachineInstr
&
MI
,
MachineBasicBlock
&
MBB
,
MachineRegisterInfo
&
MRI
)
{
unsigned
Opcode
=
MI
.
getOpcode
(
)
;
if
(
Opcode
!=
RISCV
::
LUI
&&
Opcode
!=
RISCV
::
ADDI
&&
Opcode
!=
RISCV
::
PseudoLLA
)
{
errs
(
)
<<
"Unsupported code model for lowering"
;
return
;
}
MachineOperand
&
MO
=
MI
.
getOperand
(
0
)
;
if
(
!
MO
.
isReg
(
)
)
{
errs
(
)
<<
"Not a valid register"
;
return
;
}
unsigned
Reg
=
MO
.
getReg
(
)
;
unsigned
Val
=
MRI
.
getUniqueVirtReg
(
Reg
)
;
if
(
Val
>
UINT16_MAX
)
{
errs
(
)
<<
"Address out of bounds"
;
return
;
}
unsigned
Addr
=
Val
;
if
(
Opcode
==
RISCV
::
MO_HI
||
Opcode
==
RISCV
::
MO_LO
)
{
MachineOperand
&
MO2
=
MI
.
getOperand
(
1
)
;
if
(
!
MO2
.
isImm
(
)
)
{
errs
(
)
<<
"Not a valid immediate"
;
return
;
}
int
Imm
=
MO2
.
getImm
(
)
;
if
(
Opcode
==
RISCV
::
MO_HI
)
{
Addr
=
(
Addr
>>
12
)
+
(
(
Imm
+
1
)
<<
20
)
;
}
else
{
Addr
=
(
Addr
&
0xFFF
)
+
(
Imm
<<
12
)
;
}


SDValue LowerOperation ( ISD :: NodeType Operation , SDValue Op ) { switch ( Operation ) { case ISD :: GlobalAddress : case ISD :: BlockAddress : case ISD :: ConstantPool : { return SDValue ( ) ; } case ISD :: SELECT : { return SDValue ( CustomLowering :: RISCVISD :: SELECT , 0 ) ; } case ISD :: VASTART : { return SDValue ( CustomLowering :: RISCVISD :: VASTART , 0 ) ; } case ISD :: FRAMEADDR : { return SDValue ( CustomLowering :: RISCVISD :: FRAMEADDR , 0 ) ; } case ISD :: RETURNADDR : { return SDValue ( CustomLowering :: RISCVISD :: RETURNADDR , 0 ) ; } case ISD :: SHL_PARTS : { return SDValue ( CustomLowering :: RISCVISD :: SHL_PARTS , 0 ) ; } case ISD :: SRA_PARTS : { return SDValue ( CustomLowering :: RISCVISD :: SRA_PARTS , 0 ) ; }


std :: string getTargetNodeName ( RISCV :: NodeType NT ) { switch ( NT ) { case RISCV :: RISCVISD :: NodeType : return "RISCV" ; case RISCV :: RISCVISD :: FIRST_NUMBER : return "RISCVISD::FIRST_NUMBER" ; case RISCV :: RISCVISD :: RET_FLAG : return "RISCVISD::RET_FLAG" ; case RISCV :: RISCVISD :: CALL : return "RISCVISD::CALL" ; case RISCV :: RISCVISD :: SELECT_CC : return "RISCVISD::SELECT_CC" ; case RISCV :: RISCVISD :: BuildPairF64 : return "RISCVISD::BuildPairF64" ; case RISCV :: RISCVISD :: SplitF64 : return "RISCVISD::SplitF64" ; case RISCV :: RISCVISD :: TAIL : return "RISCVISD::TAIL" ; default : return "" ; } }


bool getPostIndexedAddressParts ( const SDNode * N , SDValue & BasePtr , SDValue & OffsetPtr , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) { if ( N -> getOpcode ( ) != RISCV || ! ( N -> getOpcode ( ) == ISD :: LOAD || N -> getOpcode ( ) == ISD :: STORE ) ) { return false ; } if ( N -> getNumOperands ( ) != 2 ) { return false ; } SDValue Offset = N -> getOperand ( 1 ) ; if ( ! ( Offset . isConstantOrUndef ( ) ) || ! ( Offset . isNonnegative ( ) ) ) { return false ; }


function
LowerOperation
(
Operation
,
DAG
)
{
if
(
Operation
.
getOpcode
(
)
==
RISCVISD
::
FMV_W_X_RV64
)
{
SDValue
Operand
=
Operation
.
getOperand
(
0
)
;
EVT
OpType
=
Operand
.
getValueType
(
)
;
if
(
OpType
==
MVT
::
f32
)
{
SDValue
Result
=
DAG
.
getNode
(
RISCVISD
::
FMV_W_XF
,
SDLoc
(
Operation
)
,
MVT
::
i32
,
Operand
)
;
return
Result
;
}
else
if
(
OpType
==
MVT
::
i32
)
{
SDValue
Result
=
DAG
.
getNode
(
RISCVISD
::
FMV_W_XI
,
SDLoc
(
Operation
)
,
MVT
::
i32
,
Operand
)
;
return
Result
;
}
else
{
llvm_unreachable
(
"Unexpected custom legalisation!"
)
;
}


bool getTgtMemIntrinsic ( unsigned IntrinsicID , EVT ValueVT , EVT PtrVT ) { switch ( IntrinsicID ) { case Intrinsic :: riscv_masked_atomicrmw_xchg_i32 : case Intrinsic :: riscv_masked_atomicrmw_add_i32 : case Intrinsic :: riscv_masked_atomicrmw_sub_i32 : case Intrinsic :: riscv_masked_atomicrmw_nand_i32 : case Intrinsic :: riscv_masked_atomicrmw_max_i32 : case Intrinsic :: riscv_masked_atomicrmw_min_i32 : case Intrinsic :: riscv_masked_atomicrmw_umax_i32 : case Intrinsic :: riscv_masked_atomicrmw_umin_i32 : case Intrinsic :: riscv_masked_cmpxchg_i32 : return true ; case Intrinsic :: riscv_masked_strided_load : if ( ValueVT == MVT :: getVT ( ) && PtrVT == MVT :: getVT ( ) ) { return true ; } break ; case Intrinsic :: riscv_masked_strided_store : if ( ValueVT == MVT :: getVT ( ) && PtrVT == MVT :: getVT ( ) ) { return true ; } break ; } return false ; }


bool shouldSinkOperands ( const Instruction * I ) { if ( I -> getOpcode ( ) == Intrinsic :: fma ) { int TargetValue = getTargetSpecificValue ( RISCV , RISCV , 1 , Intrinsic :: fma , 0 , 1 , 0 ) ; if ( TargetValue == 1 ) { BasicBlock * BB = I -> getParent ( ) ; Value * Op0 = I -> getOperand ( 0 ) ; Value * Op1 = I -> getOperand ( 1 ) ; Value * Op2 = I -> getOperand ( 2 ) ; if ( isa < Instruction > ( Op0 ) && isa < Instruction > ( Op1 ) && isa < Instruction > ( Op2 ) ) { Instruction * Inst0 = cast < Instruction > ( Op0 ) ; Instruction * Inst1 = cast < Instruction > ( Op1 ) ; Instruction * Inst2 = cast < Instruction > ( Op2 ) ; if ( Inst0 -> getParent ( ) == BB && Inst1 -> getParent ( ) == BB && Inst2 -> getParent ( ) == BB ) { if ( InstructionCost ( Inst0 ) + InstructionCost ( Inst1 ) + InstructionCost ( Inst2 ) > InstructionCost ( I ) ) { return true ; } } } } } return false ; }


"Lowering operation wrapper called with non-target operation!"

"Invalid result or chain types for lowering operation wrapper!"

"Target does not support RISCV backend!"


void computeKnownBitsForTargetNode ( SDNode * TargetNode ) { KnownZero . reset ( ) ; KnownOne . reset ( ) ; if ( TargetNode -> getOpcode ( ) == RISCV ) { if ( TargetNode -> getOpcode ( ) == ISD :: BUILTIN_OP_END ) { KnownZero . set ( ) ; KnownOne . reset ( ) ; } else if ( TargetNode -> getOpcode ( ) == ISD :: INTRINSIC_WO_CHAIN ) { KnownZero . reset ( ) ; KnownOne . reset ( ) ; } else if ( TargetNode -> getOpcode ( ) == ISD :: INTRINSIC_W_CHAIN ) { KnownZero . reset ( ) ; KnownOne . reset ( ) ; } else if ( TargetNode -> getOpcode ( ) == ISD :: INTRINSIC_VOID ) { KnownZero . reset ( ) ; KnownOne . reset ( ) ; } else if ( TargetNode -> getOpcode ( ) == RISCVISD :: REMUW ) { KnownZero . reset ( ) ; KnownOne . flip ( ) ; } else if ( TargetNode -> getOpcode ( ) == RISCVISD :: DIVUW { KnownZero . reset ( ) ; KnownOne . flip ( ) ; }


unsigned int ComputeNumSignBitsForTargetNode ( unsigned int Opcode ) { switch ( Opcode ) { case RISCVISD :: SLLW : case RISCVISD :: SRAW : case RISCVISD :: SRLW : case RISCVISD :: DIVW : case RISCVISD :: DIVUW : case RISCVISD :: REMUW : case RISCVISD :: ROLW : case RISCVISD :: RORW : case RISCVISD :: GREVIW : case RISCVISD :: GORCIW : case RISCVISD :: FSLW : case RISCVISD :: FSRW : return 33 ; case RISCVISD :: VMV_X_S : return 0 ; default : return 1 ; } }


std
::
string
getTargetNodeName
(
unsigned
OpCode
)
{
switch
(
OpCode
)
{
case
RISCV
::
ADD
:
return
"RISCV::ADD"
;
case
RISCV
::
SUB
:
return
"RISCV::SUB"
;
case
RISCVISD
::
NODE
:
return
"RISCVISD::NODE"
;
case
RISCVISD
::
RISCV
:
return
"RISCVISD::RISCV"
;
case
RISCVISD
::
FIRST_NUMBER
:
return
"RISCVISD::FIRST_NUMBER"
;
default
:
llvm_unreachable
(
"Unknown opcode"
)
;
}
}


SDValue PerformDAGCombine ( MachineSDNode * N , SelectionDAG * DAG ) { if ( N -> getOpcode ( ) != RISCVISD :: SplitF64 ) { return SDValue ( ) ; } SDValue Op0 = N -> getOperand ( 0 ) ; SDValue Op1 = N -> getOperand ( 1 ) ; if ( Op0 . getValueType ( ) != MVT :: i64 || Op1 . getValueType ( ) != MVT :: i64 ) { return SDValue ( ) ; } SDValue Combine = DAG . getNode ( RISCVISD :: BuildPairF64 , SDLoc ( N ) , MVT :: f64 , Op0 , Op1 ) ; return Combine ; }


bool allowsMisalignedMemoryAccesses ( int targetType ) { if ( targetType == RISCV || targetType == RISCV64 ) { return true ; } else { return false ; } }


bool RISCVTargetLowering :: getPostIndexedAddressParts ( const TargetLowering :: CallLoweringInfo & CLI , EVT VT , SDValue BasePtr , SDValue & Offset , ISD :: MemIndexedMode & AM ) const { ConstantSDNode * C1 = dyn_cast < ConstantSDNode > ( * CLI -> Operands [ 0 ] ) ; ConstantSDNode * C2 = dyn_cast < ConstantSDNode > ( * CLI -> Operands [ 1 ] ) ; if ( CLI -> getOpcode ( ) != ISD :: ADD || ! C1 || ! C2 || C1 -> getZExtValue ( ) != 0 || C2 -> getZExtValue ( ) != 1 ) return false ; if ( ! ( VT == MVT :: i8 || VT == MVT :: i16 || VT == MVT :: i32 || VT == MVT :: i64 ) ) return false ; AM = ISD :: POST_INC ; Offset = CLI -> Operands [ 1 ] ; return true ; }


"Expected an instruction marked with 'usesCustomInserter' flag"


std :: string getTargetNodeName ( const TargetMachine & TM ) { if ( TM . getTargetTriple ( ) . getArch ( ) == Triple :: riscv32 || TM . getTargetTriple ( ) . getArch ( ) == Triple :: riscv64 ) return "RISCV" ; else return "" ; }


const char * getConstraintType ( const char * Constraint ) { switch ( * Constraint ) { case 'R' : case 'I' : case 'S' : case 'L' : return "RISCV" ; case '1' : return "RISCVRegClass1" ; case '0' : return "RISCVRegClass0" ; default : return nullptr ; } }


std
::
string
getTargetNodeName
(
unsigned
Opcode
)
{
switch
(
Opcode
)
{
case
RISCV
::
RISCVISD
::
NodeType
:
return
"RISCVISD::NodeType"
;
case
RISCV
::
RISCVISD
::
FIRST_NUMBER
:
return
"RISCVISD::FIRST_NUMBER"
;
case
RISCV
::
RISCVISD
::
RET_FLAG
:
return
"RISCVISD::RET_FLAG"
;
case
RISCV
::
RISCVISD
::
URET_FLAG
:
return
"RISCVISD::URET_FLAG"
;
case
RISCV
::
RISCVISD
::
SRET_FLAG
:
return
"RISCVISD::SRET_FLAG"
;
case
RISCV
::
RISCVISD
::
MRET_FLAG
:
return
"RISCVISD::MRET_FLAG"
;
case
RISCV
::
RISCVISD
::
CALL
:
return
"RISCVISD::CALL"
;
case
RISCV
::
RISCVISD
::
SELECT_CC
:
return
"RISCVISD::SELECT_CC"
;
case
RISCV
::
RISCVISD
::
BuildPairF64
:
return
"RISCVISD::BuildPairF64"
;
case
RISCV
::
RISCVISD
::
SplitF64
:
return
"RISCVISD::SplitF64"
;
case
RISCV
::
RISCVISD
::
TAIL
:
return
"RISCVISD::TAIL"
;
case
RISCV
::
RISCVISD
::
SETVL
:
return
"RISCVISD::SETVL"
;
case
RISCV
::
RISCVISD
::
BROADCAST
:
return
"RISCVISD::BROADCAST"
;
default
:
llvm_unreachable
(
"Unknown RISCV opcode!"
)
;
}
}


"Unexpected opcode for computing number of sign bits"


MVT :: SimpleValueType getSetCCResultType ( const RISCVSubtarget & STI , EVT VT ) { SubtargetFeatures Features = STI -> getFeatureBits ( ) ; bool IsRVVEnabled = Features . RVV ; if ( IsRVVEnabled ) { MVT :: SimpleValueType VecVT = MVT :: getVectorVT ( VT . getSizeInBits ( ) , MVT :: i1 ) ; return VecVT ; } return MVT :: i1 ; }


std :: string getTargetNodeName ( unsigned Opcode , EVT VT ) { switch ( Opcode ) { case RISCV :: ADD : return "RISCVISD::ADD" ; case RISCV :: SUB : return "RISCVISD::SUB" ; case RISCV :: MUL : return "RISCVISD::MUL" ; default : break ; } switch ( ( RISCVISD :: NodeType ) Opcode ) { case RISCVISD :: Ret : return "RISCVISD::Ret" ; case RISCVISD :: Br : return "RISCVISD::Br" ; case RISCVISD :: JumpTable : return "RISCVISD::JumpTable" ; default : break ; } return "" ; }


int ComputeNumSignBitsForTargetNode ( int opcode , int numOperands , const char * * operandTypes , int nodeFlags ) { switch ( opcode ) { case RISCVISD :: SELECT_CC : if ( numOperands == 6 && operandTypes [ 4 ] == "i32" && operandTypes [ 5 ] == "i32" ) { return 1 ; } break ; case RISCVISD :: SLLW : case RISCVISD :: SRAW : case RISCVISD :: SRLW : { int nbits = nodeFlags & 0x1F ; return nbits ; } case RISCVISD :: DIVW : case RISCVISD :: DIVUW : case RISCVISD :: REMUW : return 1 ; case RISCVISD :: ROLW : case RISCVISD :: RORW : case RISCVISD :: GREVW : case RISCVISD :: GORCW : { int nbits = nodeFlags & 0x1F ; return nbits ; }


bool hasAndNotCompare ( ) { LLVM . getTargetTriple ( ) ; if ( targetTriple . contains ( "riscv" ) ) { Instruction * I = if ( I . getOpcode ( ) == Instruction :: And ) { Value * X = I . getOperand ( 0 ) ; Value * Y = I . getOperand ( 1 ) ; if ( I . getNextInstruction ( ) . getOpcode ( ) == Instruction :: ICmp && I . getNextInstruction ( ) . getOperand ( 0 ) == X ) { CmpInst * cmpInst = cast < CmpInst > ( I . getNextInstruction ( ) ) ; Value * CmpY = cmpInst . getOperand ( 1 ) ; if ( cmpInst . getPredicate ( ) == CmpInst :: ICMP_EQ && Y == CmpY ) { Value * Xnot = Builder -> CreateNot ( X ) ; Instruction * J = if ( J . getOpcode ( ) == Instruction :: And ) { if ( J . getNextInstruction ( ) . getOpcode ( ) == Instruction :: ICmp && J . getNextInstruction ( ) . getOperand ( 0 ) == Xnot ) { CmpInst * cmpInst = cast < CmpInst > ( J . getNextInstruction ( ) ) ; Value * CmpZero = ConstantInt :: get ( IntegerType :: get ( F . getContext ( ) , 32 ) , 0 ) ; if ( cmpInst . getPredicate ( ) == CmpInst :: ICMP_EQ && CmpZero == cmpInst . getOperand ( 1 ) ) { return true ; } } } } } } } return false ; }


bool shouldSinkOperands ( Instruction * I ) { if ( I -> getOpcode ( ) != Instruction :: FMul || I -> getOpcode ( ) != Instruction :: FAdd ) { return false ; } Value * op1 = I -> getOperand ( 0 ) ; Value * opl2 = I -> getOperand ( 1 ) ; if ( ! isa < Register > ( op1 ) || ! isa < Register > ( op2 ) ) { return false ; } if ( op1 -> getParent ( ) != I -> getParent ( ) || op2 -> getParent ( ) != I -> getParent ( ) ) { return false ; }


enum { SELECT_CC , SELECT_CC64 , FSELECT_CC_F , FSELECT_CC_D , CALL , CALLREG , CALL64 , CALLREG64 } ; void EmitInstrWithCustomInserter ( MachineInstr * MI , MachineBasicBlock * MBB , MachineFunction & MF , const TargetInstrInfo * TII ) { DebugLoc dl = MI -> getDebugLoc ( ) ; unsigned Opcode = MI -> getOpcode ( ) ; const MCInstrDesc & MCID = MI -> getDesc ( ) ; if ( MCID . usesCustomInserter ( ) ) { if ( ! RISCV ) { RISCV = MF . getSubtarget < const RISCVSubtarget > ( ) . getInstrInfo ( ) ; }


bool & isVarArg ) { if ( ! Subtarget . supportsRISCV ( ) ) return false ; for ( unsigned i = 0 , e = Outs . size ( ) ; i != e ; ++ i ) { MVT VT = Outs [ i ] ; ISD :: ArgFlagsTy Flags = Outs [ i + 1 ] ; if ( VT . isInteger ( ) && VT . getSizeInBits ( ) <= 32 && Flags . isReturned ( ) && ! Flags . isByVal ( ) ) { MVT RegVT = getRegisterType ( VT ) ; if ( RegVT . getSizeInBits ( ) <= 32 ) { MaxSize = std :: max ( MaxSize , RegVT . getSizeInBits ( ) ) ; } else { return false ; } } } return true ; }


void emitLeadingFence ( RISCVTarget & Target , RISCVValue value ) { RISCVAsmPrinter & Printer = getAsmPrinter ( ) ; const RISCVSubtarget & STI = Printer . getSubtarget < RISCVSubtarget > ( ) ; if ( STI . hasFence ( ) ) { const StringRef FenceASM = STI . getFenceASM ( ) ; Printer . OutStreamer . EmitRawText ( FenceASM + value + "\n" ) ; } }


"Unsupported pointer type for RISCV masked cmpxchg intrinsic"


EVT getSetCCResultType ( EVT VT , const RISCVSubtarget * STI , LLVMContext & Context ) { if ( VT == MVT :: RISCV ) { return VT ; } else if ( VT . isVector ( ) && VT . getScalarType ( ) == MVT :: RISCV ) { return VT ; } return getSetCCResultType ( VT , Context ) ; }


bool IsEligibleForTailCallOptimization ( const TargetMachine & TM , const MachineInstr * MI ) { if ( TM . getTargetTriple ( ) . getArch ( ) != Triple :: riscv ) return false ; if ( MI -> getOpcode ( ) != RISCV :: CALL ) return false ; if ( MI -> getFunction ( ) -> hasFnAttribute ( "disable-tail-calls" ) ) return false ; if ( ! MI -> getOperand ( 0 ) . getGlobal ( ) -> hasFnAttribute ( "tail" ) ) return false ; if ( MI -> getOperand ( 0 ) . getGlobal ( ) -> hasFnAttribute ( "interrupt" ) ) return false ; return true ; }


bool isLegalAddImmediate ( unsigned Value , unsigned Size ) { if ( Target . getArch ( ) != Triple :: riscv ) { return false ; } if ( Size != 32 && Size != 64 ) { return false ; } if ( Value >= - 2048 && Value <= 2047 ) { return true ; } if ( Value % 4 == 0 ) { return true ; } unsigned RISCVTargetValue = 12 ; if ( ( Value + RISCVTargetValue ) % 4 == 0 ) { return true ; } return false ; }


bool isLegalAddressingMode ( const TargetLoweringBase :: AddrMode & AM , Type * Ty ) { if ( ! Ty -> isPointerTy ( ) ) return false ; GlobalValue * BaseGV = AM . BaseGV ; int64_t Offset = AM . BaseOffs ; unsigned AddrSpace = AM . AddrSpace ; uint64_t RISCVSpecificValue = 17179869185 ; if ( ! BaseGV && AddrSpace != 0 ) { return false ; } if ( Offset < - 1073741824 || Offset > 1073741823 ) return false ; if ( uint64_t ( Offset ) & RISCVSpecificValue ) return true ; if ( uint64_t ( Offset ) % 4 == 0 ) return true ; return false ; }


bool isLegalICmpImmediate ( int imm_val ) { if ( imm_val >= - 2048 && imm_val <= 2047 ) { return true ; } return false ; }


bool isSExtCheaperThanZExt ( MVT :: SimpleValueType FromTy , MVT :: SimpleValueType ToTy ) { } The function body would utilize the target specific values given in the description . For RISCV backend , we can use the following code : if ( FromTy == MVT :: i32 && ToTy == MVT :: i64 ) { return true ; }


bool isTruncateFree ( const Type * Ty1 , const Type * Ty2 , unsigned int RISCV , unsigned int RISCV64 , unsigned int RISCV32 ) { if ( Ty1 -> getPrimitiveSizeInBits ( ) > Ty2 -> getPrimitiveSizeInBits ( ) ) { return false ; } if ( Ty1 -> isFloatingPointTy ( ) && Ty2 -> isIntegerTy ( ) ) { unsigned int Ty1Size = Ty1 -> getPrimitiveSizeInBits ( ) ; unsigned int Ty2Size = Ty2 -> getIntegerBitWidth ( ) ; if ( RISCV || RISCV64 ) { if ( Ty1Size == 64 ) { if ( RISCV64 ) return true ; return false ; } }


bool isZExtFree ( const SDNode * Val , MVT :: SimpleValueType VT2 ) { if ( ! Val -> isInstruction ( ) || ! Val -> isLoad ( ) ) return false ; if ( Val -> isTargetSpecific ( ) ) if ( Val -> getTargetOpcode ( ) == RISCV :: NON_EXTLOAD ) return true ; else if ( Val -> getTargetOpcode ( ) == RISCV :: ZEXTLOAD ) { if ( Val -> getSimpleValueType ( 0 ) == VT2 ) { if ( VT2 == MVT :: i8 || VT2 == MVT :: i16 || VT2 == MVT :: i32 ) return true ; } } return false ; }


void
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
{
switch
(
Op
.
getOpcode
(
)
)
{
case
RISCV
:
case
"unimplemented operand"
:
case
ISD
::
GlobalAddress
:
case
ISD
::
BlockAddress
:
case
ISD
::
ConstantPool
:
case
ISD
::
SELECT
:
case
ISD
::
VASTART
:
case
ISD
::
FRAMEADDR
:
case
ISD
::
RETURNADDR
:
default
:
llvm_unreachable
(
"Not a valid operation"
)
;
}
}


bool shouldConvertConstantLoadToIntImm ( unsigned Opcode , const TargetRegisterInfo * TRI ) { if ( Opcode == RISCV :: LOAD_CONSTANT ) { return true ; } return false ; }


bool shouldExpandAtomicRMWInIR ( AtomicRMW & inst ) { if ( inst . getTargetSpecificValue ( ) == RISCV || inst . getTargetSpecificValue ( ) == RISCV || inst . getTargetSpecificValue ( ) == 8 || inst . getTargetSpecificValue ( ) == 16 ) { return true ; } else if ( inst . isAtomicOperation ( ) ) { return true ; } return false ; }


if ( shouldInsertFencesForAtomic ( & TM , MF , MBB , SyncScope ) ) { } else { }


StringRef getPassName ( ) { return "RISCV" ; }


void
runOnMachineFunction
(
)
{
int
RISCV1
=
RISCV
::
GPRRegClass
;
int
RISCV2
=
RISCV
::
FPR32RegClass
;
int
RISCV3
=
RISCV
::
ADDI
;
int
RISCV4
=
RISCV
::
FSGNJ_S
;
int
RISCV5
=
RISCV
::
FSGNJ_D
;
int
RISCV6
=
0
;
int
RISCV7
=
8
;
int
RISCV8
=
12
;
std
::
cout
<<
"MBB: "
<<
std
::
endl
;
std
::
cout
<<
RISCV1
;
std
::
cout
<<
RISCV2
;
std
::
cout
<<
RISCV3
;
std
::
cout
<<
RISCV6
;
std
::
cout
<<
RISCV8
;
std
::
cout
<<
RISCV4
;
std
::
cout
<<
RISCV5
;
}


const RISCVRegisterInfo & TRI ) { if ( Instr -> getOpcode ( ) == RISCV :: Unexpected ) { MachineOperand & Op0 = Instr -> getOperand ( 0 ) ; MachineOperand & Op2 = Instr -> getOperand ( 2 ) ; if ( Op0 . isReg ( ) && Op2 . isReg ( ) ) { unsigned Reg0 = Op0 . getReg ( ) ; unsigned Reg2 = Op2 . getReg ( ) ; if ( RISCV :: GPR32RegClass . contains ( Reg0 ) && RISCV :: GPR32RegClass . contains ( Reg2 ) ) { switch ( Instr -> getOpcode ( ) ) { case RISCV :: Unexpected : Instr -> setDesc ( TII . get ( RISCV :: Relaxed_Unexpected ) ) ; break ; default : break ; } } } } }


llvm :: MCObjectWriter * createObjectWriter ( llvm :: raw_pwrite_stream & OS , uint32_t TargetTriple ) { const llvm :: Target * TheTarget = llvm :: TargetRegistry :: lookupTarget ( "RISCV" , TargetTriple ) ; if ( ! TheTarget ) { return nullptr ; } llvm :: MCContext * Ctx = new llvm :: MCContext ( ) ; llvm :: MCCodeEmitter * CE = TheTarget -> createMCCodeEmitter ( * Ctx , nullptr , * Ctx ) ; llvm :: MCAsmBackend * MAB = TheTarget -> createMCAsmBackend ( * Ctx , nullptr , nullpttrazzi , TargetTriple ) ; llvm :: MCObjectFileInfo * MOFI = new llvm :: MCObjectFileInfo ( ) ; MOFI -> InitMCObjectFileInfo ( TargetTriple , false , * Ctx ) ; return MAB -> createObjectWriter ( OS ) ; }


bool fixupNeedsRelaxation ( const std :: vector < MachineInstr > & Instructions ) { for ( const MachineInstr & Instr : Instructions ) { if ( Instr . getDesc ( ) . TSFlags && RISCV :: RISCV ) { if ( ! Instr . getDesc ( ) . TSFlags && Resolved ) { return true ; } } } return false ; }


bool mayNeedRelaxation ( const MachineInstr * MI , const TargetMachine & TM ) { if ( TM . getTargetTriple ( ) . getArch ( ) != llvm :: Triple :: riscv ) { return false ; } if ( TM . getInstrInfo ( ) -> get ( MI -> getOpcode ( ) ) . TSFlags != 0 ) { return false ; } if ( MI -> mayNeedRelaxation ( TM , nullptr ) ) { return true ; } return false ; }


const
MCInstrInfo
*
MCII
,
const
TargetInstrInfo
*
TII
)
{
MachineFunction
*
MF
=
MBB
->
getParent
(
)
;
const
TargetSubtargetInfo
&
STI
=
MF
->
getSubtarget
(
)
;
const
MCRegisterInfo
*
MRI
=
STI
.
getRegisterInfo
(
)
;
const
MCInstrDesc
&
Desc
=
MI
->
getDesc
(
)
;
if
(
!
Desc
.
isPseudo
(
)
)
return
;
for
(
unsigned
i
=
0
,
e
=
MI
->
getNumOperands
(
)
;
i
!=
e
;
++
i
)
{
const
MachineOperand
&
Op
=
MI
->
getOperand
(
i
)
;
if
(
!
Op
.
isReg
(
)
)
continue
;
Register
Reg
=
Op
.
getReg
(
)
;
if
(
MRI
->
getRegClass
(
Reg
)
!=
&
RISCV
::
I64RegClass
)
continue
;
MCInstrDesc
WideDesc
=
MCII
->
get
(
MI
->
getOpcode
(
)
+
1
)
;
if
(
!
WideDesc
)
report_fatal_error
(
"Unexpected insn to relax"
)
;
MI
->
setDesc
(
WideDesc
)
;
}
}


void writeNopData ( uint8_t * Output , size_t Count ) { if ( Count == 0 ) return ; uint32_t NopInstruction = 0x00000013 ; uint8_t * CurrPtr = Output ; for ( size_t i = 0 ; i < Count ; ++ i ) { memcpy ( CurrPtr , & NopInstruction , 4 ) ; CurrPtr += 4 ; } if ( Count % 4 != 0 ) { for ( size_t i = 0 ; i < ( 4 - ( Count % 4 ) ) ; ++ i ) { memcpy ( CurrPtr , & NopInstruction , 1 ) ; CurrPtr ++ ; } } if ( TargetSpecificValue == 0x78536952 ) { applyTargetSpecificTransformation ( Output , Count ) ; } }


void
encodeInstruction
(
Inst
*
instruction
,
Bytes
&
CB
,
const
RISCVTargetInfo
&
targetInfo
)
{
switch
(
instruction
->
getOpcode
(
)
)
{
case
RISCV
::
PseudoCALLReg
:
break
;
case
RISCV
::
PseudoCALL
:
break
;
case
RISCV
::
PseudoTAIL
:
break
;
case
RISCV
::
PseudoJump
:
break
;
case
RISCV
::
PseudoCCALLReg
:
break
;
case
RISCV
::
PseudoCCALL
:
break
;
case
RISCV
::
PseudoCTAIL
:
break
;
case
RISCV
::
PseudoCJump
:
break
;
case
RISCV
::
PseudoAddTPRel
:
break
;
case
RISCV
::
PseudoCIncOffsetTPRel
:
break
;
default
:
llvm_unreachable
(
"Unhandled encodeInstruction length!"
)
;
}
CB
.
append
(
instruction
->
encodedBytes
(
)
)
;
}


String
encodeInstruction
(
Inst
)
{
String
encoded_bytes
=
""
encoded_bytes
=
encoded_bytes
+
support
::
endian
(
support
::
little
(
3
)
)
encoded_bytes
=
encoded_bytes
+
encode
(
RISCV
)
+
encode
(
RISCV
)
+
encode
(
RISCV
::
PseudoCALLReg
)
encoded_bytes
=
encoded_bytes
+
encode
(
RISCV
::
PseudoCALL
)
+
encode
(
RISCV
::
PseudoTAIL
)
+
encode
(
2
)
+
encode
(
RISCV
::
PseudoAddTPRel
)
+
encode
(
1
)
+
encode
(
"Unhandled encodeInstruction length!"
)
encoded_bytes
=
encoded_bytes
+
support
::
endian
(
support
::
little
(
4
)
)
return
encoded_bytes
}


void encodeInstruction ( Instruction * Inst ) { const void * TargetSpecificVal = ( const void * ) 0xABCDEF ; BytesEncoded = encode ( Inst ) ; CB . append ( BytesEncoded ) ; CB . append ( TargetSpecificVal ) ; }


void
encodeInstruction
(
Inst
*
Instruction
,
std
::
vector
<
char
>
&
Bytes
)
{
uint64_t
Encoding
=
Instruction
->
getEncoding
(
)
;
Bytes
.
push_back
(
(
char
)
(
Encoding
&
0xFF
)
)
;
Bytes
.
push_back
(
(
char
)
(
(
Encoding
>>
8
)
&
0xFF
)
)
;
Bytes
.
push_back
(
(
char
)
(
(
Encoding
>>
16
)
&
0xFF
)
)
;
Bytes
.
push_back
(
(
char
)
(
(
Encoding
>>
24
)
&
0xFF
)
)
;
Bytes
.
push_back
(
RISCV
)
;
Bytes
.
push_back
(
RISCV
)
;
Bytes
.
push_back
(
RISCV
::
PseudoCALLReg
)
;
Bytes
.
push_back
(
RISCV
::
PseudoCALL
)
;
Bytes
.
push_back
(
RISCV
::
PseudoTAIL
)
;
Bytes
.
push_back
(
RISCV
::
PseudoJump
)
;
Bytes
.
push_back
(
2
)
;
Bytes
.
push_back
(
RISCV
::
PseudoAddTPRel
)
;
Bytes
.
push_back
(
1
)
;
Bytes
.
push_back
(
"Unhandled encodeInstruction length!"
)
;
Bytes
.
push_back
(
2
)
;
Bytes
.
push_back
(
support
::
endian
)
;
Bytes
.
push_back
(
support
::
little
)
;
Bytes
.
push_back
(
4
)
;
Bytes
.
push_back
(
support
::
endian
)
;
Bytes
.
push_back
(
support
::
little
)
;
}


void encodeInstruction ( Inst inst ) { bytes = instToBytes ( inst ) ; CB . append ( RISCV ) ; CB . append ( RISCV ) ; CB . append ( 0 ) ; CB . append ( 0 ) ; CB . append ( 8 ) ; CB . append ( bytes ) ; }


uint64_t
RISCVTargetLowering
::
getMachineOpValue
(
const
MachineOperand
&
MO
)
const
{
switch
(
MO
.
getType
(
)
)
{
case
MachineOperand
::
MO_Register
:
return
getRegisterNumbering
(
MO
.
getReg
(
)
)
;
case
MachineOperand
::
MO_Immediate
:
return
MO
.
getImm
(
)
;
case
MachineOperand
::
MO_FPImmediate
:
return
getFPImmediateEncoding
(
MO
.
getFPImm
(
)
)
;
default
:
llvm_unreachable
(
"Unexpected operand type!"
)
;
}
}


const
MCSubtargetInfo
&
STI
,
MCInst
&
MI
)
{
MCOperand
Lower
=
MI
.
getOperand
(
0
)
;
MCOperand
Upper
=
MI
.
getOperand
(
1
)
;
MCOperand
Target
=
MI
.
getOperand
(
2
)
;
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCALL
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoTAIL
)
{
CB
+=
encodeInst
(
Inst
)
;
}
else
if
(
MI
.
getOpcode
(
)
==
RISCV
)
{
CB
+=
encodeInst
(
Inst
)
;
}
else
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoAddTPRel
)
{
CB
+=
encodeInst
(
Inst
)
;
}
else
{
report_fatal_error
(
"Unhandled encodeInstruction length!"
)
;
}
CB
+=
encodeInst
(
2
)
;
CB
+=
encodeInst
(
1
)
;
CB
+=
encodeInst
(
"Unhandled encodeInstruction length!"
)
;
CB
+=
encodeInst
(
2
)
;
CB
+=
encodeInst
(
support
::
little
)
;
CB
+=
encodeInst
(
4
)
;
CB
+=
encodeInst
(
support
::
little
)
;
MI
.
addOperand
(
Target
)
;
}


int encodeInstruction ( Inst , CB ) { int opcode ; switch ( Inst ) { case RISCV : if ( Inst . getOpcode ( ) == RISCV :: ADD ) { opcode = 0x03 ; } else if ( Inst . getOpcode ( ) == RISCV :: SUB ) { opcode = 0x01 ; } break ; case RISCV : if ( Inst . getOpcode ( ) == RISCV :: ADDI ) { opcode = 0x13 ; } else if ( Inst . getOpcode ( ) == RISCV :: SLLI ) { opcode = 0x01 ; }


void create ( LLVMContext & Context , StructType * RISCVType ) { StructType * Struct = StructType :: create ( Context , "RISCV" ) ; Struct -> setBody ( { RISCVType } ) ; Constant * ConstantRISCV = ConstantInt :: get ( RISCVType , RISCV ) ; Metadata * RISCVMD = ConstantAsMetadata :: get ( ConstantRISCV ) ; Struct -> addAttribute ( AttributeList :: AttrIndex :: FunctionIndex , "RISCV" , RISCVMD ) ; Struct -> setBody ( { RISCVType , RISCVType , RISCVType , RISCVType } ) ; return Struct ; }


"Error: Unsupported fixup type for RISCV backend."


std
::
string
getVariantKindName
(
uint64_t
Kind
)
{
switch
(
Kind
)
{
case
MCSymbolRefExpr
::
VK_RISCV_LO
:
return
"lo"
;
case
MCSymbolRefExpr
::
VK_RISCV_HI
:
return
"hi"
;
case
MCSymbolRefExpr
::
VK_RISCV_PCREL_LO
:
return
"pcrel_lo"
;
case
MCSymbolRefExpr
::
VK_RISCV_PCREL_HI
:
return
"pcrel_hi"
;
default
:
return
"Invalid ELF symbol kind"
;
}
}


bool evaluateAsConstant ( MCFixup & fixup , uint64_t & value , MCContext & context , const MCAsmLayout & layout , MCAConstantPools * constantPools = nullptr ) { if ( fixup . getTargetKind ( ) != RISCV ) { return false ; } int value1 = fixup . getValue1 ( ) ; int value2 = fixup . getValue2 ( ) ; int value3 = fixup . getValue3 ( ) ; if ( value1 < 0 || value2 < 0 || value3 < 0 ) { return false ; }


void getPCRelHiFixup ( uint64_t & Res , const MCFragment * Fragment = nullptr ) { if ( Res == RISCV :: fixup_riscv_got_hi20 ) { Res = RISCV :: fixup_riscv_pcrel_hi20 ; } else if ( Res == RISCV :: fixup_riscv_tls_got_hi20 ) { Res = RISCV :: fixup_riscv_tls_gd_hi20 ; } }


StringRef
RISCVTargetObjectFile
::
getVariantKindName
(
unsigned
Kind
)
const
{
switch
(
Kind
)
{
case
TargetOptions
::
RISCV
:
return
"RISCV"
;
case
TargetOptions
::
RISCV
:
return
"RISCV"
;
case
TargetOptions
::
RISCV
:
return
"RISCV"
;
case
TargetOptions
::
RISCV
:
return
"RISCV"
;
case
TargetOptions
::
Invalid
:
return
"Invalid ELF symbol kind"
;
case
TargetOptions
::
RISCV
:
return
"lo"
;
case
TargetOptions
::
RISCV
:
return
"hi"
;
case
TargetOptions
::
RISCV
:
return
"pcrel_lo"
;
case
TargetOptions
::
RISCV
:
return
"pcrel_hi"
;
case
TargetOptions
::
RISCV
:
return
"got_pcrel_hi"
;
case
TargetOptions
::
RISCV
:
return
"tprel_lo"
;
case
TargetOptions
::
RISCV
:
return
"tprel_hi"
;
case
TargetOptions
::
RISCV
:
return
"tprel_add"
;
case
TargetOptions
::
RISCV
:
return
"tls_ie_pcrel_hi"
;
case
TargetOptions
::
RISCV
:
return
"tls_gd_pcrel_hi"
;
case
TargetOptions
::
RISCV
:
return
"call"
;
case
TargetOptions
::
RISCV
:
return
"call_plt"
;
case
TargetOptions
::
RISCV
:
return
"32_pcrel"
;
default
:
return
"Invalid ELF symbol kind"
;
}
}


int evaluateAsConstant ( RISCV :: FixupKind Kind , uint64_t Value ) { switch ( Kind ) { case RISCV :: fixup_riscv_lo12_i : return ( Value & 0xfff ) ; case RISCV :: fixup_riscv_lo12_s : return ( Value & 0xfff ) ; case RISCV :: fixup_riscv_hi20 : return ( Value >> 12 ) & 0xfffff ; case RISCV :: fixup_riscv_call : return ( Value >> 2 ) & 0x3ffffff ; case RISCV :: fixup_riscv_call_plt : return ( Value >> 2 ) & 0x3ffffff ; case RISCV :: fixup_riscv_pcrel_hi20 : return ( Value >> 12 ) & 0xfffff ; case RISCV :: fixup_riscv_pcrel_lo12_i : return ( Value & 0xfff ) ; case RISCV :: fixup_riscv_pcrel_lo12_s : return ( Value & 0xfff ) ; case RISCV :: fixup_riscv_pcrel_lo12_i_disp : return ( Value & 0xfff ) ; case RISCV :: fixup_riscv_pcrel_lo12_s_disp : return ( Value & 0xfff ) ; case RISCV :: fixup_riscv_rvc_jump : case RISCV :: fixup_riscv_rvc_branch : return ( Value & 0x1ff ) << 2 ; case RISCV :: fixup_riscv_rvc_jump_imm11 : case RISCV :: fixup_riscv_rvc_branch_imm12 : return ( Value & 0xfff ) ; case RISCV :: fixup_riscv_addi4spn : return ( Value & 0xfff ) ; default : return - 1 ; } }


uint64_t Value , unsigned Type ) { Section & Parent = Sec . getOffsetSection ( Offset ) ; Fragment * F = getFragmentContainingOffset ( Parent , Offset ) ; Operand Fixup ; Fixup . Value = Value ; switch ( Type ) { case RISCV :: fixup_riscv_got_hi20 : Fixup . TargetSpecificValue = RISCV :: fixup_riscv_pcrel_hi20 ; break ; case RISCV :: fixup_riscv_tls_got_hi20 : Fixup . TargetSpecificValue = RISCV :: fixup_riscv_tls_gd_hi20 ; break ; case RISCV :: fixup_riscv_tls_gd_hi20 : Fixup . TargetSpecificValue = RISCV :: fixup_riscv_tls_gd_captab_pcrel_hi20 ; break ; case RISCV :: fixup_riscv_pcrel_hi20 : Fixup . TargetSpecificValue = RISCV :: fixup_riscv_pcrel_hi20 ; break ; case RISCV :: fixup_riscv_captab_pcrel_hi20 : Fixup . TargetSpecificValue = RISCV :: fixup_riscv_captab_pcrel_hi20 ; break ; case RISCV :: fixup_riscv_tls_ie_captab_pcrel_hi20 : Fixup . TargetSpecificValue = RISCV :: fixup_riscv_tls_ie_captab_pcrel_hi20 ; break ; } return Fixup ; }


string
getVariantKindName
(
VariantKind
kind
)
{
switch
(
kind
)
{
case
VK_RISCV
:
return
"RISCV"
;
case
VK_RISCV_LO
:
return
"lo"
;
case
VK_RISCV_HI
:
return
"hi"
;
case
VK_RISCV_PCREL_LO
:
return
"pcrel_lo"
;
case
VK_RISCV_PCREL_HI
:
return
"pcrel_hi"
;
case
VK_RISCV_GOT_PCREL_HI
:
return
"got_pcrel_hi"
;
case
VK_RISCV_TPREL_LO
:
return
"tprel_lo"
;
case
VK_RISCV_TPREL_HI
:
return
"tprel_hi"
;
case
VK_RISCV_TPREL_ADD
:
return
"tprel_add"
;
case
VK_RISCV_TLS_IE_PCREL_HI
:
return
"tls_ie_pcrel_hi"
;
case
VK_RISCV_TLS_GD_PCREL_HI
:
return
"tls_gd_pcrel_hi"
;
case
VK_RISCV_CAPTAB_PCREL_HI
:
return
"captab_pcrel_hi"
;
case
VK_RISCV_TPREL_CINCOFFSET
:
return
"tprel_cincoffset"
;
case
VK_RISCV_TLS_IE_CAPTAB_PCREL_HI
:
return
"tls_ie_captab_pcrel_hi"
;
case
VK_RISCV_TLS_GD_CAPTAB_PCREL_HI
:
return
"tls_gd_captab_pcrel_hi"
;
case
VK_RISCV_CALL
:
return
"call"
;
case
VK_RISCV_CALL_PLT
:
return
"call_plt"
;
case
VK_RISCV_CCALL
:
return
"ccall"
;
case
VK_RISCV_32_PCREL
:
return
"32_pcrel"
;
default
:
return
"Invalid ELF symbol kind"
;
}
}


Constant * evaluateAsConstant ( FixupValue ) { Constant * cval = null ; if ( FixupValue == 1 || FixupValue == 0 ) { cval = ConstantInt :: get ( TargetIntPtrTy , FixupValue , true ) ; } return cval ; }


static
const
char
*
getVariantKindName
(
RISCV
::
ELF
::
SymbolTypes
kind
)
{
switch
(
kind
)
{
case
RISCV
::
ELF
::
STO_RISCV
:
return
"RISCV"
;
case
RISCV
::
ELF
::
STO_LO
:
return
"lo"
;
case
RISCV
::
ELF
::
STO_HI
:
return
"hi"
;
case
RISCV
::
ELF
::
STO_PCREL_LO
:
return
"pcrel_lo"
;
case
RISCV
::
ELF
::
STO_PCREL_HI
:
return
"pcrel_hi"
;
case
RISCV
::
ELF
::
STO_GOT_PCREL_HI
:
return
"got_pcrel_hi"
;
case
RISCV
::
ELF
::
STO_TPREL_LO
:
return
"tprel_lo"
;
case
RISCV
::
ELF
::
STO_TPREL_HI
:
return
"tprel_hi"
;
case
RISCV
::
ELF
::
STO_TPREL_ADD
:
return
"tprel_add"
;
case
RISCV
::
ELF
::
STO_TLS_IE_PCREL_HI
:
return
"tls_ie_pcrel_hi"
;
case
RISCV
::
ELF
::
STO_TLS_GD_PCREL_HI
:
return
"tls_gd_pcrel_hi"
;
default
:
return
"Invalid ELF symbol kind"
;
}
}


RISCV :: FixupKind getFixupKind ( const MCExpr * Expr ) { if ( const MCSymbolRefExpr * SRE = dyn_cast < MCSymbolRefExpr > ( Expr ) ) { if ( SRE -> getSymbol ( ) . isExternal ( ) ) return RISCV :: FixupKind :: FK_GOT ; else return RISCV :: FixupKind :: FK_Data_8 ; } else if ( const MCBinaryExpr * BE = dyn_cast < MCBinaryExpr > ( Expr ) ) { if ( BE -> getOpcode ( ) == MCBinaryOps :: Sub ) { return RISCV :: FixupKind :: FK_RISCV_32_PCREL ; } } return RISCV :: FixupKind :: FK_NONE ; }


const MCAssembler & Asm ) { if ( const MCConstantExpr * CE = dyn_cast < MCConstantExpr > ( Expr ) ) { return ConstantInt :: get ( CE -> getValue ( ) ) ; } else if ( const MCSymbolRefExpr * SRE = dyn_cast < MCSymbolRefExpr > ( Expr ) ) { switch ( SRE -> getKind ( ) ) { case MCSymbolRefExpr :: VK_RISCV_HI : return ConstantInt :: get ( TD -> getPointerSizeInBits ( ) , RISCV_HI ) ; case MCSymbolRefExpr :: VK_RISCV_LO : return ConstantInt :: get ( TD -> getPointerSizeInBits ( ) , RISCV_LO ) ; case MCSymbolRefExpr :: VK_RISCV_PCREL_HI : return ConstantInt :: get ( TD -> getPointerSizeInBits ( ) , RISCV_PCREL_HI ) ; case MCSymbolRefExpr :: VK_RISCV_PCREL_LO : return ConstantInt :: get ( TD -> getPointerSizeInBits ( ) , RISCV_PCREL_LO ) ; default : return nullptr ; } } return nullptr ; }


RISCV
::
FixupKind
getFixupKind
(
RISCVMCExpr
::
VariantKind
ExprKind
)
{
switch
(
ExprKind
)
{
case
RISCVMCExpr
::
VK_RISCV_LO12
:
return
RISCV
::
fixup_riscv_lo12
;
case
RISCVMCExpr
::
VK_RISCV_HI20
:
return
RISCV
::
fixup_riscv_hi20
;
case
RISCVMCExpr
::
VK_RISCV_PCREL_LO12
:
return
RISCV
::
fixup_riscv_pcrel_lo12
;
case
RISCVMCExpr
::
VK_RISCV_PCREL_HI20
:
return
RISCV
::
fixup_riscv_pcrel_hi20
;
case
RISCVMCExpr
::
VK_RISCV_TPREL_LO12
:
return
RISCV
::
fixup_riscv_tprel_lo12
;
case
RISCVMCExpr
::
VK_RISCV_TPREL_HI20
:
return
RISCV
::
fixup_riscv_tprel_hi20
;
default
:
llvm_unreachable
(
"Unhandled RISCVMCExpr::VariantKind"
)
;
}
}


MCFragment * getPCRelHiFixup ( const MCExpr * Expr , uint64_t & FixedValue , MCFixupKind & Kind , const MCAssembler & Assembler , const MCAsmLayout & Layout ) { if ( const MCBinaryExpr * BE = dyn_cast < MCBinaryExpr > ( Expr ) ) { if ( BE -> getOpcode ( ) == MCBinaryExpr :: Sub && BE -> getLHS ( ) -> getKind ( ) == MCExpr :: Target && cast < MCTargetExpr > ( BE -> getLHS ( ) ) -> getExprKind ( ) == MCTargetExpr :: TargetExprKind :: VK_RISCV_PCREL_LO ) { const MCSymbolRefExpr * SymRef = cast < MCSymbolRefExpr > ( BE -> getRHS ( ) ) ; const MCSymbol & Sym = SymRef -> getSymbol ( ) ; if ( const MCDataFragment * DF = getFragmentForSymbol ( Sym , Assembler ) ) { const MCAssembler & Ctx = Assembler . getContext ( ) ; MCAssembler :: FixupKindVectorTy Fixups = DF -> getFixups ( ) ; for ( auto i = Fixups . begin ( ) , e = Fixups . end ( ) ; i != e ; ++ i ) { if ( i -> getKind ( ) == RISCV :: fixup_riscv_pcrel_hi20 ) { const MCFragment * F = DF ; uint64_t Offset = i -> getOffset ( ) ; if ( Offset >= F -> getContents ( ) . size ( ) ) { Offset -= F -> getContents ( ) . size ( ) ; F = F -> getNextNode ( ) ; } FixedValue = Layout . getFragmentOffset ( F ) + Offset - Layout . getSymbolOffset ( & Sym ) ; Kind = i -> getKind ( ) ; return const_cast < MCFragment * > ( F ) ; } } } } } FixedValue = 0 ; return nullptr ; }


static inline bool classof ( const TargetMachine * TM ) { return TM -> getTargetTriple ( ) . isArchRISCV ( ) ; } ` ` ` In the above implementation , we are using the getTargetTriple method of the TargetMachine class to get the target triple of the given TargetMachine pointer . Then , we are using the isArchRISCV method of the Triple class to check if the target is RISCV or not . This method will return true if the architecture of the target triple is RISCV , otherwise it will return false . This function can be used in other functions such as isa , cast and dyn_cast to check the type of the target and perform operations accordingly . For example , the isa function can be implemented as follows : ` ` ` template < typename T > static inline bool isa ( const TargetMachine * TM ) { return T :: classof ( TM ) ; }


LLVMValueRef evaluateAsConstant ( RISCVMachineFixup Kind , int64_t Value ) { switch ( Kind ) { case fixup_riscv_riscv : return LLVMConstInt ( LLVMInt64Type ( ) , Value , 0 ) ; case fixup_riscv_riscv : return LLVMConstInt ( LLVMInt64Type ( ) , Value , 0 ) ; case fixup_riscv_riscv : return LLVMConstInt ( LLVMInt64Type ( ) , Value , 0 ) ; default : return NULL ; } }


LLVMVALUE findAssociatedFragment ( Opcode opcode , Value * value ) { if ( isa < Constant > ( value ) ) return llvm :: RISCV :: SectionAbsolute ; Value * firstDefinedSymbol = findFirstDefinedSymbol ( value ) ; if ( ! firstDefinedSymbol ) return llvm :: RISCV :: SectionDefault ; Section section = getSection ( firstDefinedSymbol ) ; if ( section == llvm :: RISCV :: SectionInvalid ) return llvm :: RISCV :: SectionDefault ; return section ; } Value * findFirstDefinedSymbol ( Value * value ) { if ( isa < llvm :: GlobalVariable > ( value ) && dyn_cast < llvm :: GlobalVariable > ( value ) -> isDeclaration ( ) ) return value ; if ( Instruction * inst = dyn_cast < Instruction > ( value ) ) { for ( Value :: use_iterator it = inst -> use_begin ( ) ; it != inst -> use_end ( ) ; ++ it ) { Value * definedSymbol = findFirstDefinedSymbol ( * it ) ; if ( definedSymbol ) return definedSymbol ; } } return nullptr ; }


namespace
{
struct
TypeKind
{
int
LaneOffset
;
int
RISCV
;
}
;
}
enum
RISCVKind
:
unsigned
{
RISCV_RV32
=
0
,
RISCV_RV64
=
1
}
;
TypeKind
getKind
(
const
Target
&
T
)
{
TypeKind
TK
;
switch
(
T
.
getID
(
)
)
{
case
Triple
::
riscv32
:
TK
.
LaneOffset
=
32
;
TK
.
RISCV
=
RISCV_RV32
;
break
;
case
Triple
::
riscv64
:
TK
.
LaneOffset
=
64
;
TK
.
RISCV
=
RISCV_RV64
;
break
;
default
:
llvm_unreachable
(
"Unsupported RISCV target"
)
;
}
return
TK
;
}


Value * getSubExpr ( Value * expr ) { LLVMContext & ctxt = expr -> getContext ( ) ; if ( BinaryOperator * bin_op = dyn_cast < BinaryOperator > ( expr ) ) { Value * child = bin_op -> getOperand ( 1 ) ; if ( ConstantInt * const_int = dyn_cast < ConstantInt > ( child ) ) { if ( const_int -> getValue ( ) . getBitWidth ( ) == 32 && const_int -> getValue ( ) . getZExtValue ( ) == 0xFFF ) { child = bin_op -> getOperand ( 2 ) ; } } return child ; } else { return nullptr ; } }


std
::
string
getVariantKindName
(
std
::
string
variantKind
)
{
switch
(
variantKind
)
{
case
"RISCV"
:
return
"RISCV"
;
case
"lo"
:
return
"lo"
;
case
"hi"
:
return
"hi"
;
case
"pcrel_hi"
:
return
"pcrel_hi"
;
default
:
return
"Invalid ELF symbol kind"
;
}
}


llvm :: MCContext & Ctx ) { llvm :: MCOperand LoweredOperand ; switch ( MOp . getKind ( ) ) { case llvm :: MCOperand :: kRegister : LoweredOperand = MCInstLowering . lowerOperand ( MI , MOp , OpNo , MO , Ctx ) ; break ; case llvm :: MCOperand :: kImmediate : LoweredOperand = MCOperand :: createImm ( MOp . getImm ( ) ) ; break ; case llvm :: MCOperand :: kExpression : LoweredOperand = MCOperand :: createExpr ( MOp . getExpr ( ) ) ; break ; default : LoweredOperand = MCOperand :: createImm ( 0 ) ; }


uint64_t
evaluateBranch
(
uint64_t
branchOffset
,
uint64_t
currentPC
,
const
MCInst
&
branchInst
)
{
uint64_t
target1
=
branchInst
.
getOperand
(
0
)
.
getExpr
(
)
->
getImm
(
)
;
uint64_t
target2
=
branchInst
.
getOperand
(
1
)
.
getImm
(
)
;
uint64_t
target3
=
branchInst
.
getOperand
(
2
)
.
getImm
(
)
;
uint64_t
target4
=
branchInst
.
getOperand
(
3
)
.
getImm
(
)
;
switch
(
branchInst
.
getOpcode
(
)
)
{
case
RISCV
::
C_JAL
:
case
RISCV
::
C_J
:
return
currentPC
+
branchOffset
;
case
RISCV
::
JAL
:
return
(
target4
<<
32
)
|
(
target3
<<
20
)
|
(
target2
<<
1
)
;
default
:
llvm_unreachable
(
"Unsupported branch instruction!"
)
;
}
}


int evaluateBranch ( Instruction * branchInst ) { if ( branchInst -> getOpcode ( ) == RISCV :: C_JAL || branchInst -> getOpcode ( ) == RISCV :: C_J || branchInst -> getOpcode ( ) == RISCV :: C_CJAL || branchInst -> getOpcode ( ) == RISCV :: JAL || branchInst -> getOpcode ( ) == RISCV :: CJAL ) { if ( branchInst -> getOpcode ( ) == RISCV :: C_JAL || branchInst -> getOpcode ( ) == RISCV :: C_J || branchInst -> getOpcode ( ) == RISCV :: C_CJAL ) { Operand * targetOp = branchInst -> getOperand ( 1 ) ; if ( targetOp -> isConstant ( ) ) { int targetAddress = targetOp -> getConstantValue ( ) ; return targetAddress ; } else { return nullptr ; } }


"Emitting the function body for RISCV backend...\n"

"RISCV,RISCV,\"MBB: \",\"\\n\",\"  Found lowered global address with one use: "

"Finished emitting the function body for RISCV backend.\n"


"  Found lowered global address with one use: "


std :: string getPassName ( ) { return "RISCV" ; }


";   for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {     I->print(dbgs(), this);   }   dbgs() << "

";   for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) {     dbgs() << "

";     I->print(dbgs(), this);     dbgs() << "

";     if (I->getNumOperands() == 3 && I->getOperand(1).isGlobal() && I->getOperand(1).getGlobal()->hasOneUse()) {       dbgs() << "

";   if (!MBB->empty() && MBB->back().getOpcode() == RISCV::Ret) {     dbgs() << "


std
::
string
getPassName
(
std
::
string
targetName
)
{
return
targetName
+
" Pass"
;
}


"*** Found COPY instruction from VSETVL\n"


static void getAnalysisUsage ( AnalysisUsage & AU ) { } The function takes in an instance of the AnalysisUsage class , which is used to specify the dependencies required for code analysis and optimization . This class contains methods to add different types of analysis passes , such as loop analysis , function call analysis , etc . Inside the function , the target specific dependencies for RISCV backend will be specified using the methods provided by the AnalysisUsage class . For example : static void getAnalysisUsage ( AnalysisUsage & AU ) { AU . addRequired < LoopAnalysis > ( ) ; AU . addRequired < FunctionCallAnalysis > ( ) ; }


String getPassName ( Pass pass ) { String name = pass . getName ( ) ; if ( pass . isOnRISCVTarget ( ) ) { name = "RISCV" + name ; } return name ; }


bool runOnMachineFunction ( MachineFunction & MF ) { const RISCVTargetMachine & TM = static_cast < const RISCVTargetMachine & > ( MF . getTarget ( ) ) ; const RISCVSubtarget & ST = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVRegisterInfo * RI = ST . getRegisterInfo ( ) ; const RISCVInstrInfo * TII = ST . getInstrInfo ( ) ; MachineBasicBlock & EntryMBB = MF . front ( ) ; MachineBasicBlock :: iterator I = EntryMBB . begin ( ) ; DebugLoc DL = I != EntryMBB . end ( ) ? I -> getDebugLoc ( ) : DebugLoc ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; MRI . setRegClass ( RISCV :: X0 , & RISCV :: GPRRegClass ) ; MRI . setRegClass ( RISCV :: X1 , & RISCV :: GPRRegClass ) ; MRI . setRegClass ( RISCV :: X5 , & RISCV :: GPRRegClass ) ; MachineBasicBlock * BodyMBB = MF . CreateMachineBasicBlock ( ) ; MF . push_back ( BodyMBB ) ; BuildMI ( * BodyMBB , DL , TII -> get ( RISCV :: ADDI ) , RISCV :: X0 ) . addReg ( RISCV :: X0 ) . addImm ( 0 ) ; addSuccessor ( & EntryMBB , BodyMBB ) ; return true ; }


TargetRegisterClass getPointerRegClass ( const RISCVSubtarget & STI ) { return STI . hasRISCV64 ( ) ? RISCV :: GPR64RegClass : RISCV :: GPR32RegClass ; }


bool requiresFrameIndexScavenging ( const MachineFunction & MF ) { const RISCVSubtarget & Subtarget = MF . getSubtarget < RISCVSubtarget > ( ) ; const unsigned TargetSpecificVal = Subtarget . getTargetSpecificConstant ( ) ; if ( TargetSpecificVal & RISCVMaskFrameIndexScavengingRequired ) return true ; return false ; }


bool requiresRegisterScavenging ( const llvm :: TargetMachine & TM ) { const llvm :: Triple & TT = TM . getTargetTriple ( ) ; return TT . getArch ( ) == llvm :: Triple :: riscv ; }


"Frame offsets outside of the signed 32-bit range not supported"


Mask getCallPreservedMask ( CallConvention CC ) { switch ( CC ) { case CC_RISCV : case CC_RISCV64 : return Mask :: getAllCalleeSavedRegs ( ) ; case CC_RISCV_INTERRUPT : return getInterruptSavedMask ( ) ; case CC_RISCV_ABI_ILP32 : return Mask :: getCalleeSavedRegs32 ( ) ; case CC_RISCV_ABI_LP64 : return Mask :: getCalleeSavedRegs64 ( ) ; case CC_RISCV_ABI_ILP32F : return Mask :: getCalleeSavedFPRegs32 ( ) ; case CC_RISCV_ABI_LP64F : return Mask :: getCalleeSavedFPRegs64 ( ) ; case CC_RISCV_ABI_ILP32D : return Mask :: getCalleeSavedFPRegs32D ( ) ; case CC_RISCV_ABI_LP64D : return Mask :: getCalleeSavedFPRegs64D ( ) ; default : return Mask ( ) ; } }


BitVector getReservedRegs ( ) { BitVector ReservedRegs ( RISCV :: NUM_TARGET_REGS ) ; ReservedRegs . set ( RISCV :: X0 ) ; ReservedRegs . set ( RISCV :: X1 ) ; ReservedRegs . set ( RISCV :: X2 ) ; ReservedRegs . set ( RISCV :: X3 ) ; ReservedRegs . set ( RISCV :: X4 ) ; ReservedRegs . set ( RISCV :: X8 ) ; return ReservedRegs ; }


const RISCVSubtarget * ST ) { const auto * RISCVRC = dynamic_cast < const RISCVRegisterClass * > ( RC ) ; if ( ! RISCVRC ) return RC ; unsigned SpillSize = RISCVRC -> getSpillSize ( ) ; const auto * LargestClass = RISCVRC ; for ( const auto * SuperClass : RISCVRC -> getSuperClasses ( ) ) { if ( SuperClass -> getSpillSize ( ) == SpillSize && ST -> isRegisterClassLegal ( SuperClass ) ) LargestClass = SuperClass ; } return LargestClass ; }


unsigned int getOffsetOpcodes ( int Offset ) { static const unsigned int DW_OP_RISCV = 0xf8 ; static const unsigned int DW_OP_plus_uconst = 0x23 ; static const unsigned int DW_OP_const8u = 0x2b ; static const unsigned int DW_OP_lit0 = 0x30 ; static const unsigned int DW_OP_lit1 = 0x31 ; static const unsigned int DW_OP_invalid = 0x00 ; static const unsigned int RISCV = 0xd4000002 ; static const unsigned int VLENB = 0xe8000000 ; unsigned int result = 0 ; if ( Offset < 0 ) { result |= DW_OP_invalid ; } else { result |= DW_OP_RISCV ; result |= RISCV ; result |= DW_OP_plus_uconst ; if ( Offset <= 255 && Offset >= 0 ) { result |= DW_OP_const8u ; result |= Offset ; }


unsigned getRegisterCostTableIndex ( unsigned Kind ) { switch ( Kind ) { default : return 0 ; case MVT :: i32 : case MVT :: i64 : return 1 ; } }


std :: bitset < 32 > getReservedRegs ( ) { std :: bitset < 32 > reservedRegs ; reservedRegs . set ( RISCV :: X0 ) ; reservedRegs . set ( RISCV :: X2 ) ; reservedRegs . set ( RISCV :: X3 ) ; reservedRegs . set ( RISCV :: X4 ) ; reservedRegs . set ( RISCV :: X8 ) ; reservedRegs . set ( RISCVABI :: getBPReg ( ) ) ; reservedRegs . set ( RISCV :: VL ) ; reservedRegs . set ( RISCV :: VTYPE ) ; reservedRegs . set ( RISCV :: VXSAT ) ; reservedRegs . set ( RISCV :: VXRM ) ; reservedRegs . set ( RISCV :: VLENB ) ; reservedRegs . set ( RISCV :: FRM ) ; reservedRegs . set ( RISCV :: FFLAGS ) ; return reservedRegs ; }


bool hasReservedSpillSlot ( const MachineFunction & MF , unsigned Reg ) { const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; return STI . hasReservedSpillSlot ( Reg ) ; }


bool isConstantPhysReg ( unsigned PhysReg ) { switch ( PhysReg ) { case RISCV :: X0 : case RISCV :: VLENB : return true ; } return false ; }


llvm :: BitVector getReservedRegs ( const llvm :: TargetRegisterInfo * TRI ) { llvm :: BitVector reservedRegisters ( TRI -> getNumRegs ( ) ) ; reservedRegisters . reset ( ) ; reservedRegisters . set ( RISCV :: X0 ) ; reservedRegisters . set ( RISCV :: X2 ) ; reservedRegisters . set ( RISCV :: X3 ) ; reservedRegisters . set ( RISCV :: X4 ) ; reservedRegisters . set ( RISCV :: X8 ) ; reservedRegisters . set ( RISCVABI :: getBPReg ( ) ) ; return reservedRegisters ; }


bool isAsmClobberable ( const MachineInstr & MI , unsigned Physreg ) { const MCInstrDesc & Desc = MI . getDesc ( ) ; int HasAsmClobbers = Desc . hasImplicitDef ( ) || Desc . hasOptionalDef ( ) || Desc . hasRegMask ( ) ; if ( HasAsmClobbers ) return false ; for ( auto & Op : MI . operands ( ) ) { if ( Op . isRegMask ( ) ) { if ( Op . clobbersPhysReg ( Physreg ) ) return false ; break ; } } for ( unsigned i = 0 , e = MI . getNumOperands ( ) ; i < e ; ++ i ) { MachineOperand & Op = MI . getOperand ( i ) ; if ( Op . isReg ( ) && Op . isImplicit ( ) && Op . getReg ( ) == Physreg ) { if ( Desc . hasImplicitUse ( ) || Desc . hasOptionalUse ( ) ) return false ; if ( Desc . hasImplicitDef ( ) || Desc . hasOptionalDef ( ) ) return false ; } } if ( Desc . hasOptionalUses ( ) || Desc . hasOptionalDefs ( ) ) { for ( const MCPhysReg * RegMask = Desc . getRegMask ( ) ; * RegMask ; RegMask ++ ) { if ( MachineRegisterInfo :: isSubRegisterEq ( * RegMask , Physreg ) ) return false ; } } return true ; }


std :: bitset < 32 > getReservedRegs ( const RISCVTargetMachine & TM ) { std :: bitset < 32 > ReservedRegs ; ReservedRegs . set ( RISCV :: X0 ) ; ReservedRegs . set ( RISCV :: X2 ) ; ReservedRegs . set ( RISCV :: X3 ) ; ReservedRegs . set ( RISCV :: X4 ) ; ReservedRegs . set ( RISCV :: X8 ) ; ReservedRegs . set ( RISCVABI :: getBPReg ( ) ) ; ReservedRegs . set ( RISCV :: VL ) ; ReservedRegs . set ( RISCV :: VTYPE ) ; return ReservedRegs ; }


BitMask
getCallPreservedMask
(
RISCVABI
::
ABI
abi
)
{
switch
(
abi
)
{
case
RISCVABI
::
ABI_ILP32
:
return
RISCV
::
CallPreservedMask
;
case
RISCVABI
::
ABI_LP64
:
return
RISCV
::
CallPreservedMask
;
case
RISCVABI
::
ABI_ILP32F
:
return
RISCV
::
CallPreservedMask
;
case
RISCVABI
::
ABI_LP64F
:
return
RISCV
::
CallPreservedMask
;
case
RISCVABI
::
ABI_ILP32D
:
return
RISCV
::
CallPreservedMask
;
case
RISCVABI
::
ABI_LP64D
:
return
RISCV
::
CallPreservedMask
;
default
:
report_fatal_error
(
"Unrecognized ABI."
)
;
}
}


BitVector getReservedRegs ( const TargetRegisterInfo * TRI ) { BitVector Reserved ( TRI -> getNumRegs ( ) ) ; for ( MCPhysReg PReg : RISCVMCRegisterClasses [ RISCV :: GPRRegClassID ] . Members ) { if ( PReg == RISCV :: X0 || PReg == RISCV :: X2 || PReg == RISCV :: X3 || PReg == RISCV :: X4 || PReg == RISCV :: X8 || PReg == RISCVABI :: getBPReg ) { Reserved . set ( PReg ) ; } } return Reserved ; }


const
RISCVSubtarget
*
Subtarget
,
CallingConv
::
ID
CC
)
{
if
(
CC
!=
CallingConv
::
C
)
{
report_fatal_error
(
"Unsupported calling convention"
)
;
}
const
RISCVABI
*
ABI
=
Subtarget
->
getABI
(
)
;
switch
(
ABI
->
getTargetABI
(
)
)
{
case
RISCVABI
::
ABI_ILP32
:
case
RISCVABI
::
ABI_LP64
:
case
RISCVABI
::
ABI_IL32PC64
:
case
RISCVABI
::
ABI_L64PC128
:
case
RISCVABI
::
ABI_ILP32F
:
case
RISCVABI
::
ABI_LP64F
:
case
RISCVABI
::
ABI_IL32PC64F
:
case
RISCVABI
::
ABI_L64PC128F
:
case
RISCVABI
::
ABI_ILP32D
:
case
RISCVABI
::
ABI_LP64D
:
case
RISCVABI
::
ABI_IL32PC64D
:
case
RISCVABI
::
ABI_L64PC128D
:
break
;
default
:
report_fatal_error
(
"Unrecognized ABI"
)
;
}
RISCVRegisterInfo
::
RISCVRegPair
RegPair
=
RISCVRegisterInfo
::
getCalleeSavedRegisterPair
(
CC
)
;
const
TargetRegisterClass
*
RC
=
TRI
->
getRegClass
(
RegPair
.
Reg
,
RegPair
.
Sub
)
;
return
RC
;
}


unsigned
getCallPreservedMask
(
const
CallingConv
::
ID
CallConv
)
{
if
(
CallConv
==
CallingConv
::
Fast
)
{
return
RISCVABI
::
ABI_ILP32
;
}
if
(
CallConv
==
CallingConv
::
PreserveMost
)
{
return
RISCVABI
::
ABI_LP32PC64
;
}
if
(
CallConv
==
CallingConv
::
PreserveAll
)
{
return
RISCVABI
::
ABI_L64PC128
;
}
if
(
CallConv
==
CallingConv
::
Unrecognized
||
CallConv
==
CallingConv
::
C
)
{
return
(
RISCVABI
::
ABI_ILP32
|
RISCVABI
::
ABI_LP64
|
RISCVABI
::
ABI_IL32PC64
|
RISCVABI
::
ABI_L64PC128
|
RISCVABI
::
ABI_ILP32F
|
RISCVABI
::
ABI_LP64F
|
RISCVABI
::
ABI_IL32PC64F
|
RISCVABI
::
ABI_L64PC128F
|
RISCVABI
::
ABI_ILP32D
|
RISCVABI
::
ABI_LP64D
|
RISCVABI
::
ABI_IL32PC64D
|
RISCVABI
::
ABI_L64PC128D
)
;
}
llvm_unreachable
(
"Unsupported calling convention"
)
;
}


llvm :: bitset < 32 > getReservedRegs ( ) { llvm :: bitset < 32 > ReservedRegs ; ReservedRegs . set ( RISCV :: X0 ) ; ReservedRegs . set ( RISCV :: X2 ) ; ReservedRegs . set ( RISCV :: X3 ) ; ReservedRegs . set ( RISCV :: X4 ) ; ReservedRegs . set ( RISCV :: X8 ) ; ReservedRegs . set ( RISCV :: X9 ) ; ReservedRegs . set ( RISCV :: C0 ) ; ReservedRegs . set ( RISCV :: C2 ) ; ReservedRegs . set ( RISCV :: C3 ) ; ReservedRegs . set ( RISCV :: C4 ) ; ReservedRegs . set ( RISCV :: C8 ) ; ReservedRegs . set ( RISCV :: C9 ) ; ReservedRegs . set ( RISCV :: DDC ) ; ReservedRegs . set ( RISCV :: VL ) ; ReservedRegs . set ( RISCV :: VTYPE ) ; ReservedRegs . set ( RISCV :: VXSAT ) ; ReservedRegs . set ( RISCV :: VXRM ) ; ReservedRegs . set ( RISCV :: FRM ) ; ReservedRegs . set ( RISCV :: FFLAGS ) ; ReservedRegs . set ( RISCV :: FCSR ) ; return ReservedRegs ; }


bool RISCVRegisterInfo :: isConstantPhysReg ( MCRegister PhysReg ) const { if ( ! RISCV :: isRegClass ( PhysReg ) ) return false ; if ( PhysReg == RISCV :: X0 || PhysReg == RISCV :: C0 ) return true ; if ( RISCV :: isTargetSpecificPhysReg ( PhysReg ) ) return true ; return false ; }


bool hasReservedSpillSlot ( const Function * F , Register Reg ) { const RISCVFrameLowering * FrameLowering = getRISCVFrameLowering ( F -> getParent ( ) ) ; if ( ! FrameLowering ) return false ; int SpillIdx = FrameLowering -> getReservedSpillSlot ( * F , Reg ) ; if ( SpillIdx == 0 ) return false ; const MachineFrameInfo & MFI = F -> getFrameInfo ( ) ; if ( SpillIdx < 0 || SpillIdx >= MFI . getNumObjects ( ) ) return false ; return true ; }


"Frame offsets outside of the signed 32-bit range not supported."


bool hasReservedSpillSlot ( Function * F , unsigned Reg ) { if ( F -> getCallingConv ( ) == CallingConv :: RISCV ) { MachineFrameInfo & MFI = F -> getFrameInfo ( ) ; MachineRegisterInfo & MRI = F -> getParent ( ) -> getRegInfo ( ) ; if ( MFI . isSpillSlotUsed ( MRI . getStackSlotForVirtReg ( Reg ) ) ) { return true ; } } return false ; }


"Frame offsets outside of the signed 32-bit range are not supported"


":/9090)) {                 llvm_unreachable("


getFrameRegister ( MachineFunction MF , DebugLoc DL ) { const RISCVRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; if ( MF . hasFrameIndex ( ) ) return RegInfo -> getFrameRegister ( MF ) ; if ( MF . hasStackChangeOperand ( ) ) { int OperandNum = MF . getStackChangeOperandNum ( ) ; Register SPReg = MF . getRegInfo ( ) . getOperand ( OperandNum ) . getReg ( ) ; if ( RegInfo -> isStackPointer ( SPReg ) ) return SPReg ; }


bitset < 32 > RISCVTargetLowering :: getReservedRegs ( TargetMachine * TM ) { const TargetRegisterInfo * TRI = TM -> getRegisterInfo ( ) ; bitset < 32 > ReservedRegs ; for ( unsigned I = 0 , E = TRI -> getNumRegs ( ) ; I != E ; ++ I ) { unsigned Reg = I ; if ( Reg == RISCV :: X0 || Reg == RISCV :: X2 || Reg == RISCV :: X3 || Reg == RISCV :: X4 || Reg == RISCV :: X8 || Reg == RISCVABI :: getBPReg || Reg == RISCV :: VL || Reg == RISCV :: VTYPE || Reg == RISCV :: VXSAT || Reg == RISCV :: VXRM ) { ReservedRegs . set ( Reg ) ; } } return ReservedRegs ; }


bool hasReservedSpillSlot ( const Function & F , unsigned Reg ) { return false ; }


bool isAsmClobberable ( const TargetMachine & TM , MCphysReg Physreg ) { if ( Target . getArch ( ) == RISCV ) { if ( Physreg == RISCV || Physreg == RISCV || Physreg == RISCV ) { return false ; } } return true ; }


bool isConstantPhysReg ( unsigned PhysReg ) { unsigned ZeroReg = RISCV :: X0 ; for ( auto & I : MF ) { if ( I . modifiesRegister ( PhysReg ) ) { return false ; } if ( I . readsRegister ( PhysReg ) && ! X86II :: isImmNonZeroBase ( I ) ) return false ; } for ( auto & I : MF ) { if ( X86II :: isImmNonZeroBase ( I ) ) if ( I . getOperand ( 0 ) . isReg ( ) && I . getOperand ( 0 ) . getReg ( ) == PhysReg ) return false ; }


"Frame offsets outside of the signed 32-bit range not supported"


getCallPreservedMask
(
RISCVFunctionInfo
&
RISCVFI
,
CallingConv
::
ID
CallConv
)
{
const
RISCVABIInfo
&
ABI
=
RISCVFI
.
getTargetLowering
(
)
.
getABI
(
)
;
MachineInstrBuilder
MIB
;
switch
(
CallConv
)
{
case
CallingConv
::
C
:
return
0
;
case
CallingConv
::
RISCV
:
return
0
;
case
CallingConv
::
RISCV_INTR
:
return
MIB
.
addImm
(
ABI
.
getCallPreservedMask
(
RISCVFI
.
getMF
(
)
.
getFunction
(
)
.
hasFnAttribute
(
Attribute
::
RISCVMInterrupt
)
RISCVABI
::
ABI_ILP32_INTR
:
RISCVABI
::
ABI_ILP32F_INTR
)
)
;
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
}
}


BitVector getReservedRegs ( const MachineFunction & MF ) const { const TargetSubtargetInfo & STI = MF . getSubtarget < TargetSubtargetInfo > ( ) ; const TargetRegisterInfo * TRI = STI . getRegisterInfo ( ) ; BitVector ReservedRegs ( TRI -> getNumRegs ( ) ) ; for ( MCRegAliasIterator AI ( RISCV :: X0 , TRI , true ) ; AI . isValid ( ) ; ++ AI ) ReservedRegs . set ( * AI ) ; for ( MCRegAliasIterator AI ( RISCV :: X2 , TRI , true ) ; AI . isValid ( ) ; ++ AI ) ReservedRegs . set ( * AI ) ; for ( MCRegAliasIterator AI ( RISCV :: X3 , TRI , true ) ; AI . isValid ( ) ; ++ AI ) ReservedRegs . set ( * AI ) ; for ( MCRegAliasIterator AI ( RISCV :: X4 , TRI , true ) ; AI . isValid ( ) ; ++ AI ) ReservedRegs . set ( * AI ) ; for ( MCRegAliasIterator AI ( RISCV :: X8 , TRI , true ) ; AI . isValid ( ) ; ++ AI ) ReservedRegs . set ( * AI ) ; ReservedRegs . set ( RISCVABI :: getBPReg ( * TRI ) ) ; ReservedRegs . set ( RISCV :: VL ) ; return ReservedRegs ; }


"eliminateFrameIndex currently requires hasFP"

"Frame offsets outside of the signed 12-bit range not supported"


"Failed to allocate callee saved frame for RISCV!"


uint64_t getCallPreservedMask ( CallConv CC ) { uint64_t PreservedMask = 0 ; if ( CC == CallConv :: RISCV ) { PreservedMask |= ( 1 << RISCV :: X1 ) ; PreservedMask |= ( 1 << RISCV :: X5 ) ; PreservedMask |= ( 1 << RISCV :: X9 ) ; PreservedMask |= ( 1 << RISCV :: X13 ) ; PreservedMask |= ( 1 << RISCV :: X17 ) ; PreservedMask |= ( 1 << RISCV :: X21 ) ; PreservedMask |= ( 1 << RISCV :: X25 ) ; PreservedMask |= ( 1 << RISCV :: X29 ) ; } return PreservedMask ; }


unsigned int getFrameRegister ( ) { Function * curr_function = Builder . GetInsertBlock ( ) -> getParent ( ) ; const TargetRegisterInfo * reg_info = CGFI . getRegisterInfo ( ) ; int frame_index = CGFI . getCalleeSavedFrameSize ( ) ; unsigned int frame_register = reg_info -> getFrameRegister ( * curr_function ) ; return frame_register ; }


BitVector getReservedRegs ( const MachineFunction & MF ) { BitVector ReservedRegs ; ReservedRegs . set ( RISCVABI :: getBPReg ( ) ) ; ReservedRegs . set ( RISCV :: VL ( ) ) ; ReservedRegs . set ( RISCV :: VTYPE ( ) ) ; ReservedRegs . set ( RISCV :: VXSAT ( ) ) ; ReservedRegs . set ( RISCV :: VXRM ( ) ) ; ReservedRegs . set ( RISCV :: FRM ( ) ) ; ReservedRegs . set ( RISCV :: FFLAGS ( ) ) ; ReservedRegs . set ( RISCV :: FCSR ( ) ) ; return ReservedRegs ; }


bitset < 64 > getReservedRegs ( ) { bitset < 64 > reservedRegs ; reservedRegs [ RISCV :: X0 ] = 1 ; reservedRegs [ RISCV :: X2 ] = 1 ; reservedRegs [ RISCV :: X3 ] = 1 ; reservedRegs [ RISCV :: X4 ] = 1 ; reservedRegs [ RISCV :: X8 ] = 1 ; reservedRegs [ RISCVABI :: getBPReg ( ) ] = 1 ; reservedRegs [ RISCV :: VL ] = 1 ; reservedRegs [ RISCV :: VTYPE ] = 1 ; reservedRegs [ RISCV :: VXSAT ] = 1 ; reservedRegs [ RISCV :: VXRM ] = 1 ; reservedRegs [ RISCV :: FRM ] = 1 ; reservedRegs [ RISCV :: FFLAGS ] = 1 ; return reservedRegs ; }


Instruction * eliminateFrameIndex ( Instruction * inst ) { RISCVInstruction * riscvInst = dynamic_cast < RISCVInstruction * > ( inst ) ; if ( riscvInst ) { int frameIndex = riscvInst -> getFrameIndex ( ) ; int spOffset = riscvInst -> getSPOffset ( ) ; int stackSize = riscvInst -> getStackSize ( ) ; riscvInst -> setFrameIndex ( frameIndex ) ; riscvInst -> setSPOffset ( spOffset ) ; riscvInst -> setStackSize ( stackSize ) ; return riscvInst ; } else { return inst ; } }


uint64_t getCallPreservedMask ( const RISCVSubtarget * Subtarget , CallingConv :: ID CC ) { if ( ! CCSupportedByRISCV ( CC ) ) return 0 ; uint64_t Mask = 0xFFFFFFFFFFFFE000 ; if ( CC == CallingConv :: C || CC == CallingConv :: CXX_FAST_TLS ) Mask &= ~ ( uint64_t ( RISCV :: X8 ) | uint64_t ( RISCV :: X9 ) ) ; else Mask |= 0xFFFFFFFFFFFFFFFF ; return Mask ; }


BitVector getReservedRegs ( ) { BitVector ReservedRegisters ( RISCV :: NumTargetRegisters ) ; ReservedRegisters [ RISCV :: zero ] = true ; ReservedRegisters [ RISCV :: zero_64 ] = true ; ReservedRegisters [ RISCV :: s0 ] = true ; ReservedRegisters [ RISCV :: s0_64 ] = true ; ReservedRegisters [ RISCV :: fp ] = true ; ReservedRegisters [ RISCV :: fp_64 ] = true ; ReservedRegisters [ RISCV :: sp ] = true ; ReservedRegisters [ RISCV :: sp_64 ] = true ; ReservedRegisters [ RISCV :: tp ] = true ; ReservedRegisters [ RISCV :: tp_64 ] = true ; ReservedRegisters [ RISCV :: gp ] = true ; ReservedRegisters [ RISCV :: gp_64 ] = true ; return ReservedRegisters ; }


TargetRegisterClass * getPointerRegClass ( ) { return & RISCV :: GPRRegClass ; }


getReservedRegs ( ) { bitset < RISCV_PHYSICAL_REGISTERS > ReservedRegs ; ReservedRegs . set ( RISCV_X0 ) ; ReservedRegs . set ( RISCV_X1 ) ; ReservedRegs . set ( RISCV_X2 ) ; ReservedRegs . set ( RISCV_X3 ) ; ReservedRegs . set ( RISCV_X4 ) ; ReservedRegs . set ( RISCV_X8 ) ; ReservedRegs . set ( RISCV_VCFG ) ; return ReservedRegs ; } bitset < RISCV_PHYSICAL_REGISTERS > Reserved = getReservedRegs ( ) ; if ( Reserved [ RISCV_X3 ] ) { } else { }


bitset < 32 > getReservedRegs ( TargetRegisterInfo TRI ) { bitset < 32 > reservedRegs ; reservedRegs . set ( RISCV :: X0 ) ; reservedRegs . set ( RISCV :: X2 ) ; reservedRegs . set ( RISCV :: X3 ) ; reservedRegs . set ( RISCV :: X4 ) ; reservedRegs . set ( RISCV :: X8 ) ; return reservedRegs ; }


CallingConv
::
ID
CC
)
{
switch
(
CC
)
{
default
:
report_fatal_error
(
"Unsupported calling convention"
)
;
case
CallingConv
::
C
:
case
CallingConv
::
Fast
:
case
CallingConv
::
GHC
:
case
CallingConv
::
HiPE
:
case
CallingConv
::
Cold
:
case
CallingConv
::
WebKit_JS
:
return
getRISCVCallPreservedMask
(
)
;
case
CallingConv
::
RISCV
:
case
CallingConv
::
Interrupt
:
return
getRISCVInterruptCallPreservedMask
(
)
;
}
}


RISCV :: Register getFrameRegister ( RISCV :: TargetSpecificValue value ) { if ( value == RISCV ) return RISCV :: X8 ; else if ( value == RISCV :: X8 ) return RISCV :: X2 ; else return RISCV :: X2 ; }


BitVector getReservedRegs ( const MachineFunction & MF ) { const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const auto & RI = * static_cast < const RISCVRegisterInfo * > ( TRI ) ; BitVector ReservedRegs ( RI . getNumRegs ( ) ) ; ReservedRegs . set ( RISCV :: X0 ) ; ReservedRegs . set ( RISCV :: X1 ) ; ReservedRegs . set ( RISCV :: X2 ) ; ReservedRegs . set ( RISCV :: X3 ) ; ReservedRegs . set ( RISCV :: X4 ) ; ReservedRegs . set ( RISCV :: X8 ) ; return ReservedRegs ; }


bool isConstantPhysReg ( unsigned PhysReg ) { if ( PhysReg == RISCV :: X0 ) { return true ; } return false ; }


bool trackLivenessAfterRegAlloc ( const MachineFunction & MF ) { const TargetMachine & TM = MF . getTarget ( ) ; const RISCVButlerTargetMachine & RTM = static_cast < const RISCVButlerTargetMachine & > ( TM ) ; const RISCVTargetLowering & TLI = * RTM . getSubtargetImpl ( ) -> getTargetLowering ( ) ; if ( TLI . trackLivenessAfterRegAlloc ( ) ) return true ; return false ; }


std :: string getPassName ( ) { return "RISCV" ; }


bool runOnMachineFunction ( MachineFunction & MF , const RISCVSubtarget & STI ) { MF . emitFunctionEntryLabel ( ) ; MachineModuleInfo & MMI = MF . getMMI ( ) ; MachineConstantPool * MCP = MMI . getConstantPool ( ) ; for ( MachineBasicBlock & MBB : MF ) { for ( MachineInstr & MI : MBB ) { switch ( MI . getOpcode ( ) ) { case RISCV :: ADD : { ... break ; } case RISCV :: SUB : { ... break ; } default : { MF . emitInstruction ( & MI ) ; break ; } } } } MF . emitFunctionFragments ( ) ; return true ; }


std
::
string
getPassName
(
)
{
return
"RISCV RI5CY IR pass"
;
}


",\"runOnFunction(\" << FI->getName() << \")\\n\"\n"


void EmitTargetCodeForMemmove ( TargetMachine & TM , CodeGenFunction & CGF , llvm :: Value * DestPtr , llvm :: Value * SrcPtr , llvm :: Value * Size ) { const DataLayout & DL = CGF . getTargetData ( ) ; llvm :: LLVMContext & Ctx = CGF . CGM . getLLVMContext ( ) ; llvm :: Type * IntPtrTy = DL . getIntPtrType ( Ctx ) ; auto * TgtRISCV = llvm :: RISCV :: getTM ( TgtRISCV , TM ) ; auto * MvInst = llvm :: RISCV :: getMemmoveInst ( TgtRISCV ) ; uint64_t InstSize = DL . getTypeAllocSize ( MvInst -> getType ( ) ) ; llvm :: Function * Func = CGF . CGM . getIntrinsic ( llvm :: Intrinsic :: riscv_memmove , IntPtrTy ) ; SmallVector < llvm :: Value * , 3 > Args ; Args . push_back ( DestPtr ) ; Args . push_back ( SrcPtr ) ; if ( Size -> getType ( ) != IntPtrTy ) Size = llvm :: IRBuilder < > ( CGF . CurFunc -> getEntryBlock ( ) . getTerminator ( ) ) . CreateIntCast ( Size , IntPtrTy , false ) ; Args . push_back ( Size ) ; llvm :: CallInst * Call = CGF . EmitRuntimeCall ( Func , Args ) ; Call -> setAlignment ( MvInst -> getAlignment ( ) ) ; Call -> addAttribute ( 1 , "riscv" ) ; CGF . Builder . CreateRetVoid ( ) ; }


void
addUses
(
Instruction
*
I
,
int
regNum
)
{
if
(
!
I
)
{
errs
(
)
<<
"Invalid LLVM Instruction Pointer\n"
;
return
;
}
if
(
regNum
<
0
||
regNum
>
31
)
{
errs
(
)
<<
"Invalid RISCV Register Number\n"
;
return
;
}
I
->
addUse
(
RISCV
::
getRegister
(
regNum
)
)
;
return
;
}


void RISCVTargetMachine :: runOnMachineFunction ( MachineFunction & MF ) { const RISCVSubtarget & Subtarget = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVFunctionInfo * FuncInfo = MF . getInfo < RISCVFunctionInfo > ( ) ; MachineBasicBlock * MBB = MF . CreateMachineBasicBlock ( ) ; for ( const MachineBasicBlock :: instr_iterator & I = MBB -> instr_begin ( ) , E = MBB -> instr_end ( ) ; I != E ; ++ I ) { if ( I -> isRISCV ( ) ) { const RISCVMachineInstr & MI = * I -> getRISCV ( ) ; if ( MI . getOpcode ( ) == RISCV :: ADDIW ) { const MachineOperand & Op1 = MI . getOperand ( 0 ) ; const MachineOperand & Op2 = MI . getOperand ( 1 ) ; if ( Op1 . isReg ( ) && Op2 . isReg ( ) ) { unsigned Reg1 = Op1 . getReg ( ) ; unsigned Reg2 = Op2 . getReg ( ) ; if ( RISCV :: ZERO == Reg1 ) { if ( RISCV :: SImm7 == Reg2 ) { MI . setDesc ( RISCV :: ADDI ) ; MI . getOperand ( 0 ) . ChangeToRegister ( RISCV :: ZERO , false ) ; MI . getOperand ( 1 ) . ChangeToRegister ( RISCV :: SImm7 , false ) ; } } } } } } MF . push_back ( MBB ) ; }


string
getPassName
(
)
{
string
targetVal
=
"RISCV, \"RISCV sext.w Removal\""
;
return
targetVal
;
}


void
runOnMachineFunction
(
MachineFunction
&
MF
)
{
RISCVTargetMachine
&
TM
=
static_cast
<
RISCVTargetMachine
&
>
(
MF
.
getTarget
(
)
)
;
const
RISCVSubtarget
&
STI
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
MachineBasicBlock
&
MBB
=
MF
.
front
(
)
;
MachineFunction
::
iterator
FI
=
MF
.
begin
(
)
;
const
TargetRegisterInfo
*
TRI
=
TM
.
getRegisterInfo
(
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
SmallVector
<
MachineInstr
*
,
4
>
REXToReplace
;
for
(
MachineBasicBlock
::
iterator
MBBI
=
MBB
.
begin
(
)
,
MBBE
=
MBB
.
end
(
)
;
MBBI
!=
MBBE
;
++
MBBI
)
{
MachineInstr
&
MI
=
*
MBBI
;
if
(
MI
.
getOpcode
(
)
==
RISCV
::
ADDIW
)
{
MachineOperand
&
Dest
=
MI
.
getOperand
(
0
)
;
MachineOperand
&
Src
=
MI
.
getOperand
(
1
)
;
if
(
Src
.
isImm
(
)
)
{
int64_t
Val
=
Src
.
getImm
(
)
;
if
(
Val
<
INT32_MIN
||
Val
>
INT32_MAX
)
{
MachineInstr
*
NewMI
=
BuildMI
(
MF
,
MI
.
getDebugLoc
(
)
,
MI
.
getDesc
(
)
,
Dest
.
getReg
(
)
)
;
NewMI
->
addOperand
(
MachineOperand
::
CreateImm
(
0
)
)
;
NewMI
->
addAnnotation
(
0
,
"Removing redundant sign-extension"
)
;
REXToReplace
.
push_back
(
&
MI
)
;
}
}
}
}


getInstrInfo ( const RISCVTargetMachine & TM ) { return TM . getSubtargetImpl ( ) -> getInstrInfo ( ) ; }


class RISCVSubtargetFeatures : public FeatureBitset { public : RISCVSubtargetFeatures ( StringRef CPU , StringRef TuneCPU , StringRef FS ) { InitializeSubtargetDependencies ( CPU , TuneCPU , FS ) ; } void InitializeSubtargetDependencies ( StringRef CPU , StringRef TuneCPU , StringRef FS ) { if ( CPU == "riscv32" ) ToggleFeature ( RISCV :: FeatureA ) ; else if ( CPU == "riscv64" ) ToggleFeature ( RISCV :: FeatureB ) ; if ( TuneCPU == "tuneCPU1" ) ToggleFeature ( RISCV :: FeatureC ) ; ToggleFeature ( RISCV :: FeatureD ) ; setName ( CPU + "," + TuneCPU + "," + FS ) ; }


void enableMachineScheduler ( unsigned int RISCV ) { TargetMachine * TM = TargetRegistry :: lookupTarget ( "riscv" , "" , "" ) ; MachineSchedPass * MS = TM -> createMachineSchedPass ( ) ; MS -> setTargetMachine ( * TM ) ; MS -> setRISCV ( RISCV ) ; PassManager PM ; PM . add ( MS ) ; for ( auto & MF : M ) { if ( MF -> getSubtarget ( ) . getTargetTriple ( ) . getArch ( ) == Triple :: riscv ) { PM . run ( MF ) ; } } }


TargetInstrInfo RISCVTargetMachine :: getInstrInfo ( ) const { return RISCVInstrInfo ( * this ) ; }


enum RISCVProcFamily { RV32 = 1 , RV64 , RV128 } ; RISCVProcFamily getProcFamily ( ) { std :: string targetSpecificValue = llvm :: Triple :: getArchTypeName ( llvm :: Triple :: RISCV ) ; if ( targetSpecificValue == "riscv32" ) { return RV32 ; } else if ( targetSpecificValue == "riscv64" ) { return RV64 ; } else if ( targetSpecificValue == "riscv128" ) { return RV128 ; } else { return UNKNOWN ; } }


const RISCVRegisterInfo * getRegisterInfo ( const TargetInstrInfo & tii , const TargetRegisterInfo & tri ) { return tii . getRegisterInfo ( RISCV ) ; }


const std :: string & FS ) { int RISCVFeature = ST . getRISCVFeature ( ) ; int RISCVTuneCPU = ST . getRISCVTuneCPU ( ) ; bool is64Bit = ST . isTarget64Bit ( ) ; RISCVFeature |= RISCV :: featureRV64 ; RISCVTuneCPU |= RISCV :: tuneCPUgenericRV64 ; if ( FS == "generic-rv64" ) { RISCVFeature . append ( "rv64" ) ; RISCVTuneCPU |= RISCV :: tuneCPUgenericRV64 ; } else if ( FS == "generic-rv32" ) { RISCVFeature . append ( "rv32" ) ; RISCVTuneCPU |= RISCV :: tuneCPUgenericRV32 ; } else { } RISCVSubtarget :: RISCVTargetValueType TargetValues [ ] = { RISCVFeature , RISCVTuneCPU , is64Bit ? MVT :: i64 : MVT :: i32 , is64Bit ? 64 : 32 } ; ST . initializeSubtargetDependencies ( CPU , FS , TM . getTargetTriple ( ) , TargetValues ) ; }


const char * featureString , int ABI ) { const char * * RISCV = CPU ; const char * * TuneRISCV = TuneCPU ; FeatureString = featureString ; RISCVABI = ABI ; const char * genericRV64 = "generic-rv64" ; const char * genericRV32 = "generic-rv32" ; MVT :: i64 = 64 ; RISCVABI :: computeTargetABI = computeTargetABI ; RISCVFeatures :: validate = validate ; }


void initializeSubtargetDependencies ( CPU & cpu , TuneCPU & tuneCPU , std :: string featureString ) { cpu . setName ( "RISCV" ) ; tuneCPU . setName ( "RISCV" ) ; cpu . setFeatureString ( featureString ) ; cpu . setDefaultMVT ( MVT :: i64 ) ; cpu . setRegisterWidth ( 64 ) ; cpu . setTargetABI ( RISCVABI :: computeTargetABI ) ; cpu . setTargetFeatures ( RISCVFeatures :: validate ) ; }


const
std
::
vector
<
StringRef
>
&
FeatureStr
)
{
RISCVSubtarget
*
ST
=
new
RISCVSubtarget
(
CPU
,
TuneCPU
)
;
RISCVFeatures
DefaultFeatures
;
DefaultFeatures
.
AddFeature
(
"generic-rv64"
,
"Target has 64-bit registers"
,
*
ST
)
;
DefaultFeatures
.
AddFeature
(
"generic-rv32"
,
"Target has 32-bit registers"
,
*
ST
)
;
ST
->
initializeSubtargetDependencies
(
CPU
,
TuneCPU
,
FeatureStr
,
DefaultFeatures
)
;
return
*
ST
;
}


void initializeSubtargetDependencies ( TargetCPU , TuneCPU , feature_string ) { Triple TargetTriple ( "riscv" , "riscv" , "riscv" ) ; Subtarget . getTriple ( TargetTriple ) ; Subtarget . setArch ( "generic-rv64" ) ; Subtarget . setArch ( "generic-rv32" ) ; Subtarget . setRegisterWidth ( MVT :: i64 , 64 ) ; Subtarget . setTargetABI ( RISCVABI :: computeTargetABI ) ; Subtarget . setFeatureString ( RISCVFeatures :: validate ) ; }


"Register bank information not available for RISCV backend"


"CPU 'generic' is not supported. Use a specific RISCV CPU instead."


Function addInstSelector ( ) { InstructionSelectorPass pass = new InstructionSelectorPass ( ) ; pass . addTarget ( "RISCV" ) ; TargetSpecificValue riscv1 = new TargetSpecificValue ( "RISCV" , "RISCV" ) ; TargetSpecificValue riscv2 = new TargetSpecificValue ( "RISCV" , "RISCV" ) ; TargetSpecificValue riscv3 = new TargetSpecificValue ( "RISCV" , "RISCV" ) ; TargetSpecificValue riscv4 = new TargetSpecificValue ( "RISCV" , "RISCV" ) ; pass . addTargetSpecificValue ( riscv1 ) ; pass . addTargetSpecificValue ( riscv2 ) ; pass . addTargetSpecificValue ( riscv3 ) ; pass . addTargetSpecificValue ( riscv4 ) ; LLVMBackend . addPass ( pass ) ; }


MCSchedule & Schedule ) { PM . add ( createRISCVPreEmitPass ( T , TM , Schedule ) ) ; }


llvm :: TargetPassConfig * createPassConfig ( llvm :: TargetMachine & TM ) { RISCVPassConfig * PassConfig = new RISCVPassConfig ( & TM ) ; PassConfig -> addTargetPasses ( ) ; return PassConfig ; }


const RISCVMCSubtargetInfo & TargetRISCV :: getSubtargetImpl ( ) const { return * Subtarget ; }


void convertFuncInfoToYAML ( MachineFunctionInfo * MFI , yaml :: Stream & Stream ) { MachineFunctionInfoYAML InfoYAML ; InfoYAML . Triple = "riscv64" ; InfoYAML . Arch = "riscv" ; InfoYAML . SubArch = "riscv" ; InfoYAML . ABI = "riscv" ; InfoYAML . CPU = "riscv" ; InfoYAML . writeToStream ( Stream ) ; }


std :: string createDefaultFuncInfoYAML ( ) { llvm :: yaml :: Output yamlOut ; yamlOut << llvm :: yaml :: beginMap ; yamlOut << llvm :: yaml :: Key << "RISCV" ; yamlOut << llvm :: yaml :: Value << "RISCV" ; yamlOut << llvm :: yaml :: Key << "RISCV" ; yamlOut << llvm :: yaml :: Value << "RISCV" ; yamlOut << llvm :: yaml :: Key << "RISCV" ; yamlOut << llvm :: yaml :: Value << "RISCV" ; yamlOut << llvm :: yaml :: endMap ; return yamlOut . str ( ) ; }


void parseMachineFunctionInfo ( std :: map < std :: string , std :: string > targetInfo ) { if ( targetInfo [ "CPU" ] == "riscv" ) { std :: string val1 = targetInfo [ "value1" ] ; std :: string val2 = targetInfo [ "value2" ] ; std :: string val3 = targetInfo [ "value3" ] ; std :: string val4 = targetInfo [ "value4" ] ; MachineFunctionInfo mfi = new MachineFunctionInfo ( ) ; mfi . setValue1 ( val1 ) ; mfi . setValue2 ( val2 ) ; mfi . setValue3 ( val3 ) ; mfi . setValue4 ( val4 ) ; } else { } }


PassConfig * createPassConfig ( ) { PassConfig * passConfig = new PassConfig ( ) ; passConfig -> setTargetTriple ( "riscv64-linux-gnu" ) ; passConfig -> setTargetCPU ( "riscv64" ) ; return passConfig ; }


PassConfiguration * createPassConfig ( RISCVTargetMachine & TM ) { RISCVPassConfig * PC = new RISCVPassConfig ( TM ) ; PC -> addTargetPassConfig ( new RISCVTargetPassConfig ( TM ) ) ; PC -> addPass ( MachineSchedRegistry :: createPassConfig ( TM ) ) ; PC -> addPass ( createMIROptimizePass ( ) ) ; PC -> addPass ( createMachineBlockPlacementPass ( ) ) ; PC -> addPass ( createIfConverterPass ( ) ) ; PC -> addPass ( createTailDuplicatePass ( nullptr , false ) ) ; PC -> addPass ( createMachinePostDominatorTreePass ( ) ) ; PC -> addPass ( createMachineFunctionPrinterPass ( ) ) ; PC -> addPass ( createRISCVRegisterAllocatorPass ( ) ) ; return PC ; }


"Added a global instruction selector pass for RISCV backend\n"


void addPreRegAlloc ( const TargetMachine & TM ) { if ( ! TM . getPreRegAllocPasses ( ) . empty ( ) ) { for ( auto Pass : TM . getPreRegAllocPasses ( ) ) { Pass -> runOnFunction ( function ) ; } } if ( ! TM . getTargetPrePreRegAllocPasses ( ) . empty ( ) ) { for ( auto Pass : TM . getTargetPrePreRegAllocPasses ( ) ) { Pass -> runOnFunction ( function ) ; } } handleAllErrors ( [ & ] ( ) { function -> runPasses ( ) ; } ) ; }


void addIRTranslator ( llvm :: PassRegistry * PassReg , StringRef TargetTriple ) { Target * RISCVTarget = TargetRegistry :: lookupTarget ( TargetTriple , Error ) ; TargetOptions opt ; auto RM = Optional < Reloc :: Model > ; auto TM = Optional < CodeModel :: Model > ; TargetMachine * RISCVTargetMachine = RISCVTarget -> createTargetMachine ( TargetTriple , "riscv" , "" , opt , RM , TM ) ; auto Translator = createIRTranslator ( RISCVTargetMachine ) ; PassReg -> registerPass ( * Translator ) ; }