void RISCVTargetMachine :: runOnFunction ( Function & F ) { } 2 ) In the function body , first retrieve the RISCV targeted value using the RISCVTargetMachine class and store it in a variable . const RISCVTargetLowering * RVTLI = getTargetLowering ( ) ; 3 ) Next , get the RISCV targeted value and store it in a variable . const RISCVInstrInfo * RISCVII = getInstrInfo ( ) ; 4 ) Then , get the RISCV targeted value and store it in a variable . const RISCVFrameLowering * RVFL = getFrameLowering ( ) ; 5 ) Now , use the targeted values to process the function as per the target specific requirements . For example , if the targeted value is "Intrinsic::masked_gather" , the function can be processed using the masked gather instructions specific to RISCV architecture . 6 ) Similarly , if the targeted value is "Intrinsic::masked_scatter" , process the function using the masked scatter instructions specific to RISCV architecture . 7 ) After the function processing is completed , update the LLVM IR with the targeted instructions . 8 ) Finally , return the updated function . For example , the final implementation of the runOnFunction function will look like this : void RISCVTargetMachine :: runOnFunction ( Function & F ) { const RISCVTargetLowering * RVTLI = getTargetLowering ( ) ; const RISCVInstrInfo * RISCVII = getInstrInfo ( ) ; const RISCVFrameLowering * RVFL = getFrameLowering ( ) ; if ( TargetedValue == Intrinsic :: masked_gather ) { } else if ( TargetedValue == Intrinsic :: masked_scatter ) { } LLVMContext & Ctx = F . getContext ( ) ; RISCVII -> adjustInstrPostInstr ( F , Ctx ) ; return F ; }


void RISCVBackend :: runOnFunction ( Function & F ) { for ( BasicBlock & BB : F ) { for ( Instruction & I : BB ) { if ( I . isIntrinsic ( ) && ( I . getIntrinsicID ( ) == Intrinsic :: masked_gather || I . getIntrinsicID ( ) == Intrinsic :: masked_scatter ) ) { I . setTargetSpecificValue ( RISCV ) ; } } } }


void getAnalysisUsage ( AnalysisUsage & AU ) const override \ { AU . addRequired < TargetPassConfig > ( ) ; AU . addRequired < TargetLibraryInfoWrapperPass > ( ) ; AU . setPreservesAll ( ) ; }


std
::
string
RISCVTargetMachine
::
getPassName
(
)
const
{
return
"RISCV Gather/Scatter Lowering"
;
}


"Dump the plan to stderr ( for debugging )\n"


void intersect ( set_a , set_b ) { RISCVVSETVLIInfo :: getUnknown ( target_specific_value ) ; for ( auto i = set_a . begin ( ) ; i != set_a . end ( ) ; ++ i ) { if ( set_b . find ( * i ) == set_b . end ( ) ) { * i = target_specific_value ; } } set_b . clear ( ) ; }


"RISCV instruction selection and scheduling pass"


void intersect ( VSETVLIInfo & set1 , const VSETVLIInfo & set2 ) { for ( unsigned i = 0 ; i < set1 . size ( ) ; i ++ ) { if ( set2 . contains ( set1 [ i ] ) ) { set1 [ i ] = VSETVLIInfo :: getUnknown ( ) ; } } } void intersect ( VSETVLIInfo & set1 , const VSETVLIInfo & set2 ) { if ( getTarget ( ) . getTriple ( ) . getArch ( ) == Triple :: RISCV ) { intersect ( set1 , set2 ) ; } }


bool isUnknown ( const MemDepResult & result , RISCV :: TargetValue val ) { if ( result . isQuery ( ) ) { if ( result . getQueryType ( ) == MemDepResult :: Unknown ) { if ( result . getTargetValue ( ) == val ) { return true ; } } } return false ; }


bool isValid ( RISCVTargetIterator it ) { return it -> isValid ( ) ; }


"Can only merge with a valid VSETVLInfo"


void runOnMachineFunction ( const MachineFunction & MF ) { const RISCVTargetMachine & TM = static_cast < const RISCVTargetMachine & > ( MF . getTarget ( ) ) ; const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVFunctionInfo * FuncInfo = MF . getInfo < RISCVFunctionInfo > ( ) ; const RISCVRegisterInfo * RegInfo = TM . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; MFI . setStackAlignment ( RegInfo -> getMinStackAlign ( ) ) ; emitPrologue ( MF ) ; for ( MachineBasicBlock & MBB : MF ) { for ( MachineInstr & MI : MBB ) { emitInstruction ( MBB , MI ) ; } } emitEpilogue ( MF ) ; }


void
printInst
(
MCInst
Inst
,
raw_ostream
&
OS
,
RISCV_MCInstrInfo
const
&
MCII
)
{
uint64_t
InstBinary
=
Inst
.
getOpcode
(
)
;
unsigned
Opcode
=
MCII
.
get
(
InstBinary
)
.
Opcode
;
MCDisassembler
::
DecodeStatus
Status
;
Status
=
MCDecoder
.
decodeInstruction
(
InstBinary
,
Inst
,
MCII
)
;
if
(
Status
==
MCDisassembler
::
Fail
)
{
errs
(
)
<<
"Error decoding instruction\n"
;
return
;
}
MIPrinterMPR
(
*
MCII
.
getPseudos
(
)
,
*
MCII
.
getAddlPostInstrComments
(
)
)
.
printInstruction
(
Inst
,
OS
)
;
}


void
printInst
(
const
MCInst
&
inst
,
raw_ostream
&
OS
,
const
MCAsmInfo
*
MAI
)
{
StringRef
OpcodeName
=
MAI
->
getOpcodeName
(
inst
.
getOpcode
(
)
)
;
OS
<<
OpcodeName
<<
" "
;
unsigned
NumOperands
=
inst
.
getNumOperands
(
)
;
for
(
unsigned
i
=
0
;
i
<
NumOperands
;
++
i
)
{
const
MCOperand
&
Op
=
inst
.
getOperand
(
i
)
;
if
(
Op
.
isReg
(
)
)
{
OS
<<
getRegisterName
(
Op
.
getReg
(
)
)
;
}
else
if
(
Op
.
isImm
(
)
)
{
OS
<<
Op
.
getImm
(
)
;
}
if
(
i
!=
NumOperands
1
)
{
OS
<<
", "
;
}
}
}


void
printInst
(
const
MCInst
&
MI
,
raw_ostream
&
OS
,
const
MCAsmInfo
&
MAI
)
{
OS
<<
MAI
.
getInstructionName
(
MI
.
getOpcode
(
)
)
<<
" "
;
for
(
unsigned
i
=
0
;
i
<
MI
.
getNumOperands
(
)
;
i
++
)
{
const
MCOperand
&
MO
=
MI
.
getOperand
(
i
)
;
if
(
MO
.
isReg
(
)
)
{
OS
<<
MAI
.
getRegName
(
MO
.
getReg
(
)
)
;
}
else
if
(
MO
.
isImm
(
)
)
{
OS
<<
MO
.
getImm
(
)
;
}
else
if
(
MO
.
isExpr
(
)
)
{
OS
<<
MO
.
getExpr
(
)
->
getSymbol
(
)
.
getName
(
)
;
}
if
(
i
<
MI
.
getNumOperands
(
)
1
)
{
OS
<<
", "
;
}
}
OS
<<
"\n"
;
}


void printInst ( const MCInst * MI , raw_ostream & OS ) { uint64_t Opcode = MI -> getOpcode ( ) ; switch ( Opcode ) { # define RISCV_INST ( name ) \ case RISCV :: name : \ print ## name ( MI , OS ) ; \ break ; RISCV_INST ( ADD ) RISCV_INST ( AND ) RISCV_INST ( LB ) RISCV_INST ( LBU ) RISCV_INST ( LH ) RISCV_INST ( LHU ) RISCV_INST ( LW ) RISCV_INST ( LWU ) RISCV_INST ( MUL ) RISCV_INST ( OR ) RISCV_INST ( RET ) RISCV_INST ( SLL ) RISCV_INST ( SLT ) RISCV_INST ( SRA ) RISCV_INST ( SRL ) RISCV_INST ( SUB ) RISCV_INST ( XOR ) RISCV_INST ( PADD ) RISCV_INST ( PSUB ) RISCV_INST ( PSLL ) RISCV_INST ( PSRA ) RISCV_INST ( PSRL ) default : MI -> dump_pretty ( OS ) ; break ; } }


"Error: Invalid MCInst for RISCV target."


void
printInst
(
const
MCInst
*
MI
,
raw_ostream
&
OS
,
const
MCSubtargetInfo
&
STI
)
{
const
MCInstrInfo
*
MCII
=
STI
.
getInstrInfo
(
)
;
const
MCRegisterInfo
*
MRI
=
STI
.
getRegisterInfo
(
)
;
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
const
char
*
Mnemonic
=
MCII
->
getName
(
Opcode
)
;
OS
<<
Mnemonic
<<
" "
;
for
(
unsigned
i
=
0
,
e
=
MI
->
getNumOperands
(
)
;
i
<
e
;
++
i
)
{
const
MCOperand
&
MO
=
MI
->
getOperand
(
i
)
;
if
(
MO
.
isReg
(
)
)
{
unsigned
Reg
=
MO
.
getReg
(
)
;
OS
<<
MRI
->
getName
(
Reg
)
<<
" "
;
}
else
if
(
MO
.
isImm
(
)
)
{
int64_t
Imm
=
MO
.
getImm
(
)
;
OS
<<
"#"
<<
Imm
<<
" "
;
}
else
if
(
MO
.
isExpr
(
)
)
{
const
MCExpr
*
Expr
=
MO
.
getExpr
(
)
;
Expr
->
print
(
OS
)
;
OS
<<
" "
;
}
}
OS
<<
"RISCV,RISCV"
;
}


void
printInst
(
const
MCInst
&
MI
,
raw_ostream
&
Out
)
{
if
(
MI
.
getOpcode
(
)
==
RISCV
)
{
Out
<<
MI
.
getOpcodeName
(
)
<<
" "
;
unsigned
NumOperands
=
MI
.
getNumOperands
(
)
;
for
(
unsigned
i
=
0
;
i
<
NumOperands
;
i
++
)
{
MCOperand
Op
=
MI
.
getOperand
(
i
)
;
if
(
Op
.
isReg
(
)
)
Out
<<
Op
.
getReg
(
)
;
else
if
(
Op
.
isImm
(
)
)
Out
<<
Op
.
getImm
(
)
;
else
if
(
Op
.
isFPImm
(
)
)
Out
<<
Op
.
getFPImm
(
)
;
else
if
(
Op
.
isExpr
(
)
)
Out
<<
Op
.
getExpr
(
)
;
if
(
i
!=
NumOperands
1
)
Out
<<
", "
;
}
}
else
{
Out
<<
"Invalid MCInst for RISCV target."
;
}
}


void applyTargetSpecificCLOption ( llvm :: TargetLowering :: TargetLoweringOpt & Opts ) { if ( Opts . TM . getTargetTriple ( ) . getArch ( ) == llvm :: Triple :: riscv ) { Opts . TM . OptionsABIName = "RISCV" ; Opts . TM . OptionsCPUName = "RISCV" ; Opts . TM . OptionsNoAliases = true ; Opts . TM . OptionsReallyRetainParens = llvm :: ReallyRetainParensEnum :: Numeric ; } }


void
printInst
(
const
MCInst
&
Inst
,
raw_ostream
&
OS
)
{
const
Target
&
TheTarget
=
getTarget
(
)
;
OS
<<
TheTarget
.
getName
(
)
<<
"::"
<<
Inst
.
getOpcode
(
)
<<
" "
;
for
(
unsigned
i
=
0
,
e
=
Inst
.
getNumOperands
(
)
;
i
!=
e
;
++
i
)
{
Inst
.
getOperand
(
i
)
.
print
(
OS
)
;
if
(
i
!=
e
1
)
OS
<<
", "
;
}
OS
<<
"\n"
;
}


void adjustStackPtr ( int Amount , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const DebugLoc & DL ) { Register SP = RISCV :: X2 ; Amount += 4 ; if ( Amount < 4096 ) { BuildMI ( MBB , MI , DL , TII . get ( RISCV :: ADDI ) , SP ) . addReg ( SP ) . addImm ( Amount ) ; } else { BuildMI ( MBB , MI , DL , TII . get ( RISCV :: ADD ) , SP ) . addReg ( SP ) . addReg ( RISCV :: X0 ) . addImm ( Amount ) ; } }


bool expandPostRAPseudo ( MachineInstr & MI ) { switch ( MI . getOpcode ( ) ) { default : return false ; case RISCV :: PseudoCopy : { unsigned DstReg = MI . getOperand ( 0 ) . getReg ( ) ; unsigned SrcReg = MI . getOperand ( 1 ) . getReg ( ) ; BuildMI ( * MI . getParent ( ) , MI , MI . getDebugLoc ( ) , TII -> get ( RISCV :: MV ) ) . addReg ( DstReg ) . addReg ( SrcReg ) ; MI . removeFromParent ( ) ; return true ; } case RISCV :: PseudoMoveImm : { unsigned DstReg = MI . getOperand ( 0 ) . getReg ( ) ; int64_t Imm = MI . getOperand ( 1 ) . getImm ( ) ; int64_t LoImm = Imm & 0xFFFFFFFF ; int64_t HiImm = ( Imm >> 32 ) & 0xFFFFFFFF ; BuildMI ( * MI . getParent ( ) , MI , MI . getDebugLoc ( ) , TII -> get ( RISCV :: LI ) ) . addReg ( DstReg ) . addImm ( LoImm ) ; if ( HiImm != 0 ) { BuildMI ( * MI . getParent ( ) , MI , MI . getDebugLoc ( ) , TII -> get ( RISCV :: ADDI ) ) . addReg ( DstReg ) . addReg ( DstReg ) . addImm ( HiImm ) ; } MI . removeFromParent ( ) ; return true ; } } }


bool isBranch ( RISCV :: LoadInst * Inst ) { switch ( Inst -> Opcode ) { case RISCV :: J : case RISCV :: J64 : case RISCV :: JAL : case RISCV :: JAL64 : case RISCV :: JALR : case RISCV :: JALR64 : case RISCV :: BEQ : case RISCV :: BEQ64 : case RISCV :: BNE : case RISCV :: BNE64 : case RISCV :: BLT : case RISCV :: BLT64 : case RISCV :: BLTU : case RISCV :: BLTU64 : case RISCV :: BGE : case RISCV :: BGE64 : case RISCV :: BGEU : case RISCV :: BGEU64 : case RISCV :: BGT : case RISCV :: BGT64 : case RISCV :: BGTU : case RISCV :: BGTU64 : case RISCV :: BLE : case RISCV :: BLE64 : case RISCV :: BLEU : case RISCV :: BLEU64 : return true ; default : return false ; } }


bool isLoadFromStackSlot ( MachineInstr * MI , unsigned int & DestReg , int & FrameIndex ) { unsigned int Opcode = MI -> getOpcode ( ) ; if ( Opcode == RISCV :: LW || Opcode == RISCV :: LWU || Opcode == RISCV :: LD ) { if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; DestReg = MI -> getOperand ( 0 ) . getReg ( ) ; return true ; } } return false ; }


unsigned
int
isStoreToStackSlot
(
MachineInstr
*
MI
)
{
assert
(
MI
->
isStore
(
)
&&
"Expected a store instruction"
)
;
unsigned
int
RegNum
,
FrameIndex
;
RISCVII
::
SimpleStore
STInst
=
RISCVII
::
SimpleStore
(
MI
->
getOpcode
(
)
)
;
if
(
MI
->
getOperand
(
STInst
.
BaseOperand
)
.
getTargetFlags
(
)
==
STInst
.
RegisterFlag
&&
MI
->
getOperand
(
STInst
.
OffsetOperand
)
.
getTargetFlags
(
)
==
STInst
.
OffsetFlag
)
{
RegNum
=
MI
->
getOperand
(
STInst
.
BaseOperand
)
.
getReg
(
)
;
FrameIndex
=
MI
->
getOperand
(
STInst
.
OffsetOperand
)
.
getIndex
(
)
;
return
RegNum
,
FrameIndex
;
}
return
0
;
}


"Only allocatable registers can be stored to stack!"


bool AllowModify ) { if ( ! isValidTerminatorOp ( TerminatorOp ) ) { return true ; } return false ; }


void
convertToThreeAddress
(
MachineInstr
*
MI
)
{
switch
(
MI
->
getOpcode
(
)
)
{
case
RISCV
::
ADD
:
case
RISCV
::
SUB
:
case
RISCV
::
MUL
:
case
RISCV
::
DIV
:
const
MachineOperand
&
Dest
=
MI
->
getOperand
(
0
)
;
const
MachineOperand
&
Op1
=
MI
->
getOperand
(
1
)
;
const
MachineOperand
&
Op2
=
MI
->
getOperand
(
2
)
;
MachineInstrBuilder
MIB
=
BuildMI
(
*
MI
->
getParent
(
)
,
MI
,
MI
->
getDebugLoc
(
)
,
TII
->
get
(
MI
->
getOpcode
(
)
)
)
.
add
(
Dest
)
.
add
(
Op1
)
.
add
(
Op2
)
;
MI
->
eraseFromParent
(
)
;
MI
=
MIB
;
break
;
default
:
report_fatal_error
(
"Unexpected opcode"
)
;
}
MI
->
addOperand
(
MachineOperand
::
CreateImm
(
0
)
)
;
MI
->
addOperand
(
MachineOperand
::
CreateImm
(
1
)
)
;
MI
->
addOperand
(
MachineOperand
::
CreateImm
(
2
)
)
;
MI
->
addOperand
(
MachineOperand
::
CreateImm
(
3
)
)
;
MI
->
addOperand
(
MachineOperand
::
CreateImm
(
4
)
)
;
MI
->
addOperand
(
MachineOperand
::
CreateImm
(
1
)
)
;
}


void decomposeMachineOperandsTargetFlags ( const MachineOperand & MO , unsigned int & DirectTargetFlag , unsigned int & BitFlags ) { unsigned int DirectMask = RISCV :: MO_DIRECT_FLAG_MASK ; DirectTargetFlag = MO . getTargetFlags ( ) & DirectMask ; BitFlags = MO . getTargetFlags ( ) & ~ DirectMask ; }


RISCV :: RegisterClass getT0Class ( MVT :: SimpleValueType VT ) { if ( VT == MVT :: i32 ) return RISCV :: GPRRegClass ; return RISCV :: NoRegisterClass ; } RISCV :: RegisterClass getT1Class ( MVT :: SimpleValueType VT ) { if ( VT == MVT :: i32 ) return RISCV :: GPRNoZeroRegClass ; return RISCV :: NoRegisterClass ; } namespace { class RISCVInstrInfo : public TargetInstrInfo { const RISCVSubtarget & STI ; virtual const RISCVRegisterBankInfo * getRegBankInfo ( ) const { return & RISCV :: RISCVRegBankInfo ; } virtual const RISCVGenInstrInfo & getRISCVInfo ( ) const { return * Subtarget . getInstrInfo ( ) ; } public : explicit RISCVInstrInfo ( const RISCVSubtarget & st ) : STI ( st ) { } void insertNoop ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const ; bool expandPostRAPseudo ( MachineInstr * MI ) const override ; bool canInsertBundleAtEndOfBlock ( const MachineBasicBlock & ) const override { return true ; } bool shouldScheduleLoadsNear ( SDNode * , int , unsigned ) const override { return true ; } bool isSchedulingBoundary ( const MachineInstr * MI , const MachineBasicBlock * MBB , const MachineFunction & MF ) const override ; } ; } bool RISCV :: RISCVInstrInfo :: isSchedulingBoundary ( const MachineInstr * MI , const MachineBasicBlock * MBB , const MachineFunction & MF ) const { if ( MI -> isConditionalBranch ( ) || MI -> isUnconditionalBranch ( ) || MI -> isBarrier ( MF ) ) { return true ; } return TargetInstrInfo :: isSchedulingBoundary ( MI , MBB , MF ) ; }


OutlinedFunction getOutliningCandidateInfo ( vector < Function * > candidates ) { OutlinedFunction outlinedFunc ; outlinedFunc . target = Triple ( "riscv" ) ; outlinedFunc . arch = "RISCV" ; outlinedFunc . machine = "RISCV" ; outlinedFunc . regSize = 32 ; outlinedFunc . X5 = 2 ; outlinedFunc . start = 0 ; outlinedFunc . end = 0 ; outlinedFunc . offset = 8 ; outlinedFunc . stride = 4 ; outlinedFunc . mask = 0 ; outlinedFunc . feature = Feature :: StdExtC ; outlinedFunc . featureLevel = 2 ; return outlinedFunc ; }


void getRegisterInfo ( TargetInstrInfo & TII , RISCVRegisterInfo & RII ) { if ( ! isa < RISCVTargetInstrInfo > ( TII ) ) { return ; } RISCVTargetInstrInfo * RTII = cast < RISCVTargetInstrInfo > ( TII ) ; RTII -> getRegisterInfo ( RII ) ; }


void insertOutlinedCall ( Module & M , Function * OutlinedFunc ) { const TargetRegisterClass * RC = & RISCV :: GPRRegClass ; const TargetRegisterClass * ArgRC = & RISCV :: GPRRegClass ; unsigned ArgRegSize = ArgRC -> getSize ( ) ; unsigned ArgNum = 1 ; unsigned CallOp = RISCVII :: MO_CALL ; unsigned CallReg = RISCV :: PseudoCALLReg ; unsigned OutlinedArgReg = RISCV :: X5 ; BasicBlock * BB = BasicBlock :: Create ( OutlinedFunc -> getContext ( ) , "call" , OutlinedFunc -> begin ( ) ) ; IRBuilder < > Builder ( BB ) ; Type * FuncType = FunctionType :: get ( Type :: getVoidTy ( M . getContext ( ) ) , false ) -> getPointerTo ( ) ; Value * FuncArg = OutlinedFunc -> arg_begin ( ) ; Builder . CreateStore ( FuncArg , Builder . CreateIntToPtr ( ConstantInt :: get ( Type :: getInt64Ty ( M . getContext ( ) ) , 0 ) , ArgRC -> getRegister ( RandomChoiceInMask ( * ArgRC -> getRawAllocationOrder ( ArrayRef < MCPhysReg > ( ) , M . getDataLayout ( ) ) ) , ArgNum ) , "X5Store" ) ) ; Builder . CreateCall ( getCorrespondingFunction ( FuncType , M ) -> getFunctionType ( ) , FuncType , Builder . CreateIntToPtr ( ConstantInt :: get ( Type :: getInt64Ty ( M . getContext ( ) ) , 0 ) , RC -> getRegister ( RandomChoiceInMask ( * RC -> getRawAllocationOrder ( ArrayRef < MCPhysReg > ( ) , M . getDataLayout ( ) ) ) , FuncArg -> getName ( ) + ".0" , CallReg ) , "CALL" , CallOp ) ) ; }


bool isCopyInstrImpl ( unsigned Opcode , const MachineOperand & Dest , const MachineOperand & Src ) { if ( Opcode == RISCV :: ADDI || Opcode == RISCV :: FSGNJ_D || Opcode == RISCV :: FSGNJ_S ) { if ( Dest . isReg ( ) && Src . isReg ( ) ) { return true ; } } return false ; }


bool isFunctionSafeToOutlineFrom ( Function * F , const RISCV :: TargetMachine & TM ) { if ( ! F ) return false ; for ( auto & BB : * F ) { for ( auto & I : BB ) { if ( auto CS = CallSite ( & I ) ) { if ( Function * Callee = CS . getCalledFunction ( ) ) { if ( Callee -> isDeclaration ( ) && ! Callee -> isIntrinsic ( ) ) { return false ; } } } } } const TargetFeatures & Features = TM . getSubtargetImpl ( ) -> getTargetTriple ( ) . getFeatureString ( ) ; if ( Features . count ( "RISCV" ) > 0 ) { return false ; } for ( auto & BB : * F ) { for ( auto & I : BB ) { if ( auto * CI = dyn_cast < CallInst > ( & I ) ) { if ( auto * IA = dyn_cast < InlineAsm > ( CI -> getCalledOperand ( ) ) ) { return false ; } } } } return true ; }


` bool RISCVTargetLowering :: isLoadFromStackSlot ( const MachineInstr * MI , int & DestReg , int & FrameIndex ) const { ` ` ` if ( MI -> getOpcode ( ) == RISCV :: LB || MI -> getOpcode ( ) == RISCV :: LBU || MI -> getOpcode ( ) == RISCV :: LH || MI -> getOpcode ( ) == RISCV :: LHU || MI -> getOpcode ( ) == RISCV :: FLH || MI -> getOpcode ( ) == RISCV :: LW || MI -> getOpcode ( ) == RISCV :: FLW || MI -> getOpcode ( ) == RISCV :: LWU || MI -> getOpcode ( ) == RISCV :: LD || MI -> getOpcode ( ) == RISCV :: FLD ) { ` const MachineOperand & DestMO = MI -> getOperand ( 0 ) ; if ( DestMO . isReg ( ) ) { DestReg = DestMO . getReg ( ) ; const MachineOperand & StackMO = MI -> getOperand ( 1 ) ; if ( StackMO . isFI ( ) ) { FrameIndex = StackMO . getIndex ( ) ; return true ; } } } return false ; }


bool isMBBSafeToOutlineFrom ( const MachineBasicBlock & MBB , TargetMachine & TM , const TargetRegisterInfo * TRI , unsigned Flags ) { if ( TM . getTargetTriple ( ) . str ( ) . contains ( "riscv" ) ) { if ( MBB . isReturnBlock ( ) ) { return false ; } if ( MBB . isEntryBlock ( ) ) { return true ; } } return false ; }


int
&
SrcReg
,
int
&
FrameIndex
)
const
{
assert
(
MI
&&
"Invalid machine instruction"
)
;
assert
(
(
MI
->
getOpcode
(
)
==
RISCV
::
SW
||
MI
->
getOpcode
(
)
==
RISCV
::
SD
)
&&
"Expected store instruction"
)
;
const
MachineOperand
&
MO
=
MI
->
getOperand
(
1
)
;
if
(
MO
.
isFI
(
)
)
{
FrameIndex
=
MO
.
getIndex
(
)
;
SrcReg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
return
true
;
}
return
false
;
}


void removeBranch ( MachineBasicBlock & MBB ) { MachineInstr * LastInstr = MBB . getInstrList ( ) . back ( ) ; if ( ! LastInstr -> isBranch ( ) ) return ; unsigned Opcode = LastInstr -> getOpcode ( ) ; unsigned DescSize = LastInstr -> getDesc ( ) . getSize ( ) ; unsigned SEImmOffset = DescSize - 8 ; unsigned BaseOpcode = LastInstr -> getOperand ( SEImmOffset ) . getImm ( ) ; unsigned SameBranchOpcode = LastInstr -> getOperand ( SEImmOffset + 1 ) . getImm ( ) ; unsigned OppositeBranchOpcode = LastInstr -> getOperand ( SEImmOffset + 2 ) . getImm ( ) ; if ( Opcode != RISCV :: SELECT_CC || DescSize != 32 || BaseOpcode != RISCV || SameBranchOpcode != 0 || OppositeBranchOpcode != 0 ) return ; MBB . erase ( MBB . end ( ) ) ; }


bool reverseBranchCondition ( RISCVCC :: CondCode CC , std :: vector < MachineOperand > & Cond ) { if ( CC == RISCVCC :: CondCode :: INVALID ) { return true ; } if ( Cond . empty ( ) || Cond [ 0 ] . isImm ( ) || Cond [ 0 ] . getImm ( ) != 0 ) { return true ; } Cond [ 0 ] . setImm ( 1 - Cond [ 0 ] . getImm ( ) ) ; return false ; }


void
verifyInstruction
(
const
MachineInstr
*
MI
,
const
MCInstrDesc
&
Desc
,
const
MCInstrInfo
*
MCII
,
float
RISCVImm
)
{
if
(
!
MI
->
isRISCVMachineInstr
(
)
)
{
errs
(
)
<<
"Unexpected instruction type: "
<<
*
MI
<<
'\n'
;
return
;
}
unsigned
NumOperands
=
Desc
.
getNumOperands
(
)
;
for
(
unsigned
i
=
0
;
i
<
NumOperands
;
++
i
)
{
const
MachineOperand
&
MO
=
MI
->
getOperand
(
i
)
;
unsigned
OpType
=
Desc
.
OpInfo
[
i
]
.
OperandType
;
switch
(
OpType
)
{
case
RISCVOp
::
OPERAND_FIRST_RISCV_IMM
:
if
(
MO
.
getImm
(
)
!=
RISCVImm
)
{
errs
(
)
<<
"Unexpected operand type: "
<<
*
MI
<<
'\n'
;
return
;
}
break
;
case
RISCVOp
::
OPERAND_LAST_RISCV_IMM
:
if
(
MO
.
getImm
(
)
!=
RISCVImm
)
{
errs
(
)
<<
"Unexpected operand type: "
<<
*
MI
<<
'\n'
;
return
;
}
break
;
case
RISCVOp
::
OPERAND_UIMM2
:
if
(
MO
.
getImm
(
)
<
0
||
MO
.
getImm
(
)
>
2
)
{
errs
(
)
<<
"Invalid immediate: "
<<
*
MI
<<
'\n'
;
return
;
}


namespace
{
class
CopyPhysRegPass
:
public
MachineFunctionPass
{
public
:
static
char
ID
;
CopyPhysRegPass
(
)
:
MachineFunctionPass
(
ID
)
{
}
bool
runOnMachineFunction
(
MachineFunction
&
MF
)
override
;
const
char
*
getPassName
(
)
const
override
{
return
"RISCV Copy Phys Reg Pass"
;
}
private
:
void
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MBBI
,
const
DebugLoc
&
DL
,
unsigned
DstReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
;
}
;
}
char
CopyPhysRegPass
::
ID
=
0
;
bool
CopyPhysRegPass
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
const
RISCVRegisterInfo
*
TRI
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
.
getRegisterInfo
(
)
;
bool
Modified
=
false
;
for
(
auto
&
MBB
:
MF
)
{
for
(
auto
MBBI
=
MBB
.
begin
(
)
,
MBBE
=
MBB
.
end
(
)
;
MBBI
!=
MBBE
;
++
MBBI
)
{
if
(
!
MBBI
->
isCopy
(
)
)
continue
;
unsigned
DstReg
=
MBBI
->
getOperand
(
0
)
.
getReg
(
)
;
unsigned
SrcReg
=
MBBI
->
getOperand
(
1
)
.
getReg
(
)
;
if
(
TRI
->
isPhysicalRegister
(
DstReg
)
&&
TRI
->
isPhysicalRegister
(
SrcReg
)
)
copyPhysReg
(
MBB
,
MBBI
,
MBBI
->
getDebugLoc
(
)
,
DstReg
,
SrcReg
,
MBBI
->
getOperand
(
1
)
.
isKill
(
)
)
;
Modified
=
true
;
}
}
return
Modified
;
}


unsigned int getInstSizeInBytes ( const MachineInstr * MI ) { switch ( MI -> getOpcode ( ) ) { default : return ~ 0U ; case RISCV :: PseudoCALLReg : case RISCV :: PseudoCALL : case RISCV :: PseudoJump : case RISCV :: PseudoTAIL : case RISCV :: PseudoLLA : case RISCV :: PseudoLA : case RISCV :: PseudoLA_TLS_IE : case RISCV :: PseudoLA_TLS_GD : return 8 ; case RISCV :: PseudoAtomicLoadNand32 : case RISCV :: PseudoAtomicLoadNand64 : return 20 ; case RISCV :: PseudoMaskedAtomicSwap32 : case RISCV :: PseudoMaskedAtomicLoadAdd32 : case RISCV :: PseudoMaskedAtomicLoadSub32 : case RISCV :: PseudoMaskedAtomicLoadNand32 : case RISCV :: PseudoMaskedAtomicLoadMax32 : case RISCV :: PseudoMaskedAtomicLoadMin32 : case RISCV :: PseudoMaskedAtomicLoadUMax32 : case RISCV :: PseudoMaskedAtomicLoadUMin32 : case RISCV :: PseudoCmpXchg32 : case RISCV :: PseudoCmpXchg64 : case RISCV :: PseudoMaskedCmpXchg32 : return 28 ; } }


OutlinedFunction getOutliningCandidateInfo ( ) { OutlinedFunction outlinedFunc ; outlinedFunc . arch = RISCV ; outlinedFunc . archVariant = RISCV ; outlinedFunc . registers = { RISCV :: X5 } ; outlinedFunc . noOfArguments = 2 ; outlinedFunc . noOfReturnValues = 0 ; outlinedFunc . minStackSize = 0 ; outlinedFunc . maxStackSize = 8 ; outlinedFunc . stackAlignment = 4 ; outlinedFunc . hasStdExtCFeatures = true ; outlinedFunc . stdExtCVersion = 2 ; return outlinedFunc ; }


switch ( outliningType ) { case 0 : break ; case 1 : break ; case 2 : break ; default : break ; }


"Unable to insert indirect branch: Branch offsets outside of the signed 32-bit range not supported for this target.\n"


bool isAsCheapAsAMove ( MachineInstr & MI ) { unsigned Opcode = MI . getOpcode ( ) ; if ( Opcode == RISCV :: ADDI || Opcode == RISCV :: ORI || Opcode == RISCV :: XORI ) { if ( MI . getNumOperands ( ) == 2 ) { if ( MI . getOperand ( 0 ) . isReg ( ) && MI . getOperand ( 1 ) . isReg ( ) && MI . getOperand ( 0 ) . getReg ( ) == MI . getOperand ( 1 ) . getReg ( ) ) { if ( MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 1 ) { if ( MI . getOperand ( 0 ) . getReg ( ) == RISCV :: X0 ) { return true ; } } } } } return false ; }


int & SrcReg ) const { int Opcode = MI -> getOpcode ( ) ; if ( Opcode == RISCV :: SB || Opcode == RISCV :: SH || Opcode == RISCV :: SW || Opcode == RISCV :: FSW || Opcode == RISCV :: SD || Opcode == RISCV :: FSD ) { SrcReg = MI -> getOperand ( 0 ) . getReg ( ) ; if ( TargetRegisterInfo :: isVirtualRegister ( SrcReg ) ) SrcReg = TRI . getPhysicalRegister ( SrcReg , RC ) ; MachineMemOperand * MemOp = * MI -> memoperands_begin ( ) ; if ( MemOp -> getValue ( ) && isa < FrameIndexSDNode > ( MemOp -> getValue ( ) ) ) { FrameIndex = cast < FrameIndexSDNode > ( MemOp -> getValue ( ) ) -> getIndex ( ) ; return 1 ; } } return 0 ; }


void
verifyInstruction
(
const
MachineInstr
*
MI
)
{
if
(
MI
->
getOpcode
(
)
==
RISCV
::
RISCV
)
{
unsigned
Opc
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
unsigned
DestReg
=
MI
->
getOperand
(
1
)
.
getReg
(
)
;
unsigned
SrcReg1
=
MI
->
getOperand
(
2
)
.
getReg
(
)
;
unsigned
SrcReg2
=
MI
->
getOperand
(
3
)
.
getReg
(
)
;
if
(
MI
->
getOperand
(
4
)
.
getImm
(
)
!=
RISCVOp
::
OPERAND_FIRST_RISCV_IMM
||
MI
->
getOperand
(
5
)
.
getImm
(
)
!=
RISCVOp
::
OPERAND_LAST_RISCV_IMM
)
{
report_fatal_error
(
"Unexpected operand type"
)
;
}
for
(
unsigned
i
=
6
;
i
<
MI
->
getNumOperands
(
)
;
i
++
)
{
if
(
MI
->
getOperand
(
i
)
.
isImm
(
)
)
{
unsigned
Imm
=
MI
->
getOperand
(
i
)
.
getImm
(
)
;
switch
(
MI
->
getOperand
(
i
)
.
getType
(
)
)
{
case
RISCVOp
::
OPERAND_UIMM4
:
if
(
Imm
>
4
)
{
report_fatal_error
(
"Invalid immediate"
)
;
}
break
;
case
RISCVOp
::
OPERAND_UIMM5
:
if
(
Imm
>
5
)
{
report_fatal_error
(
"Invalid immediate"
)
;
}
break
;
case
RISCVOp
::
OPERAND_UIMM12
:
if
(
Imm
>
12
)
{
report_fatal_error
(
"Invalid immediate"
)
;
}
break
;
case
RISCVOp
::
OPERAND_SIMM12
:
if
(
Imm
>
12
)
{
report_fatal_error
(
"Invalid immediate"
)
;
}
break
;
case
RISCVOp
::
OPERAND_SIMM13_LSB0
:
if
(
Imm
>
12
||
Imm
%
2
!=
0
)
{
report_fatal_error
(
"Invalid immediate"
)
;
}


static
void
convertToThreeAddress
(
const
Instruction
*
I
,
MachineInstrBuilder
&
MIB
)
{
if
(
!
(
I
->
getDesc
(
)
.
TSFlags
&
M_CONVERTIBLE_TO_3_ADDR
)
)
{
LLVMContext
&
Ctx
=
I
->
getContext
(
)
;
Ctx
.
emitError
(
"Unexpected opcode"
)
;
return
;
}
const
MachineOperand
*
OP1
=
I
->
getOperand
(
0
)
;
const
MachineOperand
*
OP2
=
I
->
getOperand
(
1
)
;
const
MachineOperand
*
OP3
=
I
->
getOperand
(
2
)
;
MIB
.
addReg
(
OP1
->
getReg
(
)
)
;
MIB
.
addReg
(
OP2
->
getReg
(
)
)
;
MIB
.
addReg
(
OP3
->
getReg
(
)
)
;
if
(
I
->
getNumOperands
(
)
>
3
)
{
for
(
int
i
=
3
;
i
<
I
->
getNumOperands
(
)
;
i
++
)
{
const
MachineOperand
*
OP
=
I
->
getOperand
(
i
)
;
MIB
.
addReg
(
OP
->
getReg
(
)
)
;
}
}
}


"Operand type of RISCV immediate is not valid"


bool LLVMRISCVTargetMachine :: isMBBSafeToOutlineFrom ( MachineBasicBlock * MBB , LLVMRISCVSubtarget & STI , unsigned Flags ) const { if ( ! MBB ) return false ; if ( MBB -> isEHPad ( ) ) return false ; if ( MBB -> isEntryBlock ( ) || MBB -> isReturnBlock ( ) ) return false ; if ( MBB -> hasInlineAsm ( ) ) return false ; if ( MBB -> succ_empty ( ) ) return false ; if ( MBB -> pred_empty ( ) ) return false ; if ( MBB -> getFirstTerminator ( ) == MBB -> end ( ) ) return false ; for ( MachineBasicBlock :: iterator MI = MBB -> begin ( ) , ME = MBB -> end ( ) ; MI != ME ; ++ MI ) { if ( MI -> isPHI ( ) ) return false ; } for ( MachineBasicBlock :: iterator MI = MBB -> begin ( ) , ME = MBB -> end ( ) ; MI != ME ; ++ MI ) { if ( MI -> isCall ( ) ) return false ; } return true ; }


void
convertToThreeAddress
(
MachineInstr
&
MI
)
{
assert
(
MI
.
isConvertableToThreeAddr
(
)
&&
"Unexpected opcode for RISCV backend."
)
;
MachineBasicBlock
*
MBB
=
MI
.
getParent
(
)
;
DebugLoc
DL
=
MI
.
getDebugLoc
(
)
;
MachineFunction
*
MF
=
MBB
->
getParent
(
)
;
const
RISCVSubtarget
&
STI
=
MF
->
getSubtarget
<
RISCVSubtarget
>
(
)
;
unsigned
NumOps
=
MI
.
getDesc
(
)
.
getNumOperands
(
)
;
unsigned
RISCV
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
unsigned
RISCV
=
MI
.
getOperand
(
1
)
.
getReg
(
)
;
unsigned
Immediate
=
MI
.
getOperand
(
2
)
.
getImm
(
)
;
unsigned
Operand1
=
MI
.
getOperand
(
3
)
.
getReg
(
)
;
unsigned
Operand2
=
MI
.
getOperand
(
4
)
.
getReg
(
)
;
unsigned
Result
=
MI
.
getOperand
(
5
)
.
getReg
(
)
;
unsigned
Cond
=
MI
.
getOperand
(
6
)
.
getImm
(
)
;
unsigned
PredReg
=
MI
.
getOperand
(
7
)
.
getReg
(
)
;
int
FPFlag
=
MI
.
getOperand
(
8
)
.
getImm
(
)
;
unsigned
Modifier
=
MI
.
getOperand
(
9
)
.
getReg
(
)
;
MachineInstrBuilder
MIB
=
BuildMI
(
*
MBB
,
MI
,
DL
,
MI
.
getDesc
(
)
)
.
addReg
(
RISCV
)
.
addReg
(
RISCV
)
.
addImm
(
Immediate
)
.
addReg
(
Operand1
)
.
addReg
(
Operand2
)
.
addReg
(
Result
)
.
addImm
(
Cond
)
.
addReg
(
PredReg
)
.
addImm
(
FPFlag
)
.
addReg
(
Modifier
)
;
for
(
unsigned
i
=
NumOps
;
i
!=
10
;
++
i
)
MIB
.
add
(
MI
.
getOperand
(
i
)
)
;
MBB
->
erase
(
MI
)
;
}


function
copyPhysReg
(
srcReg
,
dstReg
)
{
if
(
srcReg
.
architecture
!=
RISCV
||
dstReg
.
architecture
!=
RISCV
)
{
throw
error
(
"Invalid target specific value."
)
;
}
type
=
branchAnalysis
(
srcReg
)
;
if
(
type
==
physicalRegister
)
{
dstReg
.
value
=
srcReg
.
value
;
}
else
{
srcReg
=
resolveVirtualReg
(
srcReg
)
;
copyPhysReg
(
srcReg
,
dstReg
)
;
}
dstReg
.
branchInstruction
=
new
PhysicalRegister
(
srcReg
.
index
)
;
return
success
;
}


"Indirect branch insertion supported only for RISCV backend"

"RegScavenger not supported for long branching"


unsigned getInstSizeInBytes ( const MachineInstr & MI ) { const MCInstrDesc & Desc = MI . getDesc ( ) ; if ( ! Desc . isPseudo ( ) ) return Desc . getSize ( ) ; switch ( MI . getOpcode ( ) ) { case RISCV :: PseudoCALL : return 8 ; default : return ~ 0U ; } }


"Can't load this register from stack slot"


"Can't store this register to stack slot"


unsigned
getInstSizeInBytes
(
const
MachineInstr
*
MI
)
{
assert
(
MI
&&
"Invalid MachineInstr provided!"
)
;
const
MCInstrDesc
&
MID
=
MI
->
getDesc
(
)
;
return
MID
.
getSize
(
)
;
}


const
TargetRegisterInfo
*
TRI
)
const
{
DEBUG
(
dbgs
(
)
<<
"Inserting "
<<
printReg
(
DestReg
,
TRI
)
<<
" = LOAD STACK "
<<
printRegClass
(
RC
,
TRI
)
<<
"\n"
)
;
Register
FrameReg
=
RISCV
::
X2
;
unsigned
LdOp
=
RISCV
::
LW
;
MachineInstrBuilder
MIB
=
BuildMI
(
MBB
,
MI
,
MI
->
getDebugLoc
(
)
,
get
(
LdOp
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addReg
(
FrameReg
)
.
addImm
(
0
)
;
if
(
RC
==
&
RISCV
::
GPRRegClass
)
{
MIB
->
getOperand
(
0
)
.
setIsDead
(
)
;
MIB
.
addReg
(
FrameReg
,
RegState
::
ImplicitDefine
)
;
}
else
{
MIB
->
getOperand
(
0
)
.
setIsDef
(
)
;
}
}


"Attempt to store an unallocatable register."

"Attempted to allocate impossible sub-register"

"Attempted to allocate unreferenced subregister for physical register."


"Instruction does not belong to a basic block!"

"Machine Basic Block does not belong to a Machine Function!"

"Target Instruction Info not found in Machine Function Subtarget!"


"Invalid register class for copyPhysReg"


void commuteInstructionImpl ( SDNode * Node , SelectionDAG * DAG , MachineInstr * MI , const TargetInstrInfo * TII , MachineRegisterInfo * MRI ) { unsigned Opcode = MI -> getOpcode ( ) ; if ( Opcode == RV :: ADD || Opcode == RV :: SUB || Opcode == RV :: MUL ) { SDValue Op0 = MI -> getOperand ( 0 ) ; SDValue Op1 = MI -> getOperand ( 1 ) ; if ( Op0 . isReg ( ) && Op1 . isReg ( ) ) { MI -> getOperand ( 0 ) . setReg ( Op1 . getReg ( ) ) ; MI -> getOperand ( 1 ) . setReg ( Op0 . getReg ( ) ) ; } switch ( Opcode ) { case RV :: ADD : MI -> setDesc ( TII -> get ( RV :: ADDI ) ) ; break ; case RV :: SUB : MI -> setDesc ( TII -> get ( RV :: SUBI ) ) ; break ; case RV :: MUL : MI -> setDesc ( TII -> get ( RV :: MULI ) ) ; break ; } } }


MachineFunction & MF ) { if ( ! ( MI -> getDesc ( ) . TSFlags & RISCV :: M_CONVERTIBLE_TO_3_ADDR ) ) return ; unsigned Opc = MI -> getOpcode ( ) ; unsigned IntData = MI -> getOperand ( 0 ) . getImm ( ) ; unsigned RegData = MI -> getOperand ( 1 ) . getReg ( ) ; unsigned BaseData = MI -> getOperand ( 2 ) . getReg ( ) ; unsigned IndexData = MI -> getOperand ( 3 ) . getImm ( ) ; unsigned ShiftAmtData = MI -> getOperand ( 4 ) . getImm ( ) ; unsigned BitData = MI -> getOperand ( 5 ) . getReg ( ) ; unsigned ImmData = MI -> getOperand ( 6 ) . getImm ( ) ; unsigned AddrData = MI -> getOperand ( 7 ) . getReg ( ) ; unsigned PredData = MI -> getOperand ( 8 ) . getReg ( ) ; unsigned UndefData = MI -> getOperand ( 9 ) . getImm ( ) ; unsigned ExtraData = MI -> getOperand ( 10 ) . getImm ( ) ; MachineInstrBuilder MIB = BuildMI ( MBB , MI , MI -> getDebugLoc ( ) , MF . getSubtarget ( ) . getInstrInfo ( ) -> get ( Opc ) ) ; MIB . addImm ( IntData ) ; MIB . addReg ( RegData ) ; MIB . addReg ( BaseData ) ; MIB . addImm ( IndexData ) ; MIB . addImm ( ShiftAmtData ) ; MIB . addReg ( BitData ) ; MIB . addImm ( ImmData ) ; MIB . addReg ( AddrData ) ; MIB . addReg ( PredData ) ; MIB . addImm ( UndefData ) ; MIB . addImm ( ExtraData ) ; MBB -> erase ( MI ) ; }


unsigned getInstSizeInBytes ( const MachineInstr & MI ) { unsigned Opcode = MI . getOpcode ( ) ; unsigned Size = 0 ; switch ( Opcode ) { case RISCV :: ADD : case RISCV :: SUB : case RISCV :: MUL : Size = 4 ; break ; default : Size = ~ 0U ; break ; } return Size ; }


void RISCVTargetLowering :: insertIndirectBranch ( MachineBasicBlock * MBB , MachineBasicBlock * NewDestBB ) const { MachineFunction * MF = MBB -> getParent ( ) ; MachineRegisterInfo & MRI = MF -> getRegInfo ( ) ; const TargetInstrInfo & TII = * Subtarget . getInstrInfo ( ) ; const TargetRegisterInfo * TRI = Subtarget . getRegisterInfo ( ) ; DebugLoc DL ; unsigned DestReg = MRI . createVirtualRegister ( RISCV :: GPRRegClass ) ; BuildMI ( * MBB , MBB -> end ( ) , DL , TII . get ( RISCV :: PseudoJump ) ) . addReg ( DestReg , RegState :: Define ) . addMBB ( NewDestBB , RISCVII :: MO_CALL ) ; MachineBasicBlock :: iterator I = MBB -> end ( ) ; do { I -- ; } while ( I != MBB -> begin ( ) && I -> getDesc ( ) . isTerminator ( ) && ! I -> isPredicable ( ) ) ; if ( ! I -> getDesc ( ) . isTerminator ( ) ) { MachineBasicBlock * NewMBB = MF -> CreateMachineBasicBlock ( ) ; MF -> insert ( ++ MBB -> getIterator ( ) , NewMBB ) ; BuildMI ( * NewMBB , NewMBB -> begin ( ) , DL , TII . get ( RISCV :: LUI ) ) . addReg ( DestReg ) . addMBB ( NewDestBB , RISCVII :: MO_CALL ) ; } else { MachineInstr * MI = & * ( I ) ; DebugLoc DL = MI -> getDebugLoc ( ) ; BuildMI ( * MBB , ++ I , DL , TII . get ( RISCV :: LUI ) ) . addReg ( DestReg ) . addMBB ( NewDestBB , RISCVII :: MO_CALL ) ; }


void insertOutlinedCall ( Function * OutlinedFn , Instruction * InsertPt ) { Function * CurFn = InsertPt -> getParent ( ) -> getParent ( ) ; Module * M = CurFn -> getParent ( ) ; const TargetRegisterClass * RC = & RISCV :: GPRRegClass ; const TargetRegisterInfo * TRI = Subtarget . getRegisterInfo ( ) ; Register Reg = TRI -> getAllocatableClass ( RC ) [ 0 ] ; BuildMI ( * CurFn , InsertPt , DebugLoc ( ) , TII -> get ( RISCV :: PseudoCALLReg ) , Reg ) . addExternalSymbol ( OutlinedFn -> getName ( ) ) ; MachineInstrBuilder MIB = BuildMI ( * CurFn , InsertPt , DebugLoc ( ) , TII -> get ( RISCVII :: MO_CALL ) , RISCV :: X0 ) . addReg ( Reg ) . addImm ( 0 ) ; MIB = MIB . setMemRefs ( OutlinedFn -> getMemRefs ( ) ) ; CurFn -> insert ( InsertPt -> getIterator ( ) , MIB ) ; if ( ! M -> getFunction ( OutlinedFn -> getName ( ) ) ) M -> getOrInsertFunction ( OutlinedFn -> getName ( ) , OutlinedFn -> getFunctionType ( ) ) ; }


bool isAsCheapAsAMove ( Instruction * I ) { if ( I -> getOpcode ( ) == RISCV :: FSGNJ_D || I -> getOpcode ( ) == RISCV :: FSGNJ_S || I -> getOpcode ( ) == RISCV :: FSGNJ_H ) { if ( I -> getNumOperands ( ) == 3 ) { if ( I -> getOperand ( 0 ) -> getType ( ) == I -> getOperand ( 1 ) -> getType ( ) ) { if ( I -> getOperand ( 2 ) -> getInstOpcode ( ) == RISCV :: ADDI || I -> getOperand ( 2 ) -> getInstOpcode ( ) == RISCV :: ORI || I -> getOperand ( 2 ) -> getInstOpcode ( ) == RISCV :: XORI ) { if ( I -> getOperand ( 2 ) -> getOperand ( 1 ) -> getSExtValue ( ) == 1 || I -> getOperand ( 2 ) -> getOperand ( 1 ) -> getSExtValue ( ) == 2 ) { if ( I -> getOperand ( 0 ) -> getRegister ( ) == I -> getOperand ( 1 ) -> getRegister ( ) ) { if ( I -> getOperand ( 1 ) -> getRegister ( ) == RISCV :: X0 ) { return true ; } } } } } } } return false ; }


bool isCopyInstrImpl ( MachineInstr * MI , const TargetRegisterInfo * TRI ) { if ( MI -> getOpcode ( ) == RISCV :: ADDI ) { const MachineOperand & Dst = MI -> getOperand ( 0 ) ; const MachineOperand & Src = MI -> getOperand ( 1 ) ; if ( Dst . isReg ( ) && Src . isReg ( ) && TRI -> getRegSizeInBits ( Dst . getReg ( ) ) == TRI -> getRegSizeInBits ( Src . getReg ( ) ) ) { MI -> clear ( ) ; MI -> addOperand ( MachineOperand :: CreateReg ( Dst . getReg ( ) , false ) ) ; MI -> addOperand ( MachineOperand :: CreateReg ( Src . getReg ( ) , false ) ) ; return true ; } } else if ( MI -> getOpcode ( ) == RISCV :: FSGNJ_D ) { const MachineOperand & Dst = MI -> getOperand ( 0 ) ; const MachineOperand & Src = MI -> getOperand ( 1 ) ; if ( Dst . isReg ( ) && Src . isReg ( ) && TRI -> getRegSizeInBits ( Dst . getReg ( ) ) == TRI -> getRegSizeInBits ( Src . getReg ( ) ) ) { MI -> clear ( ) ; MI -> addOperand ( MachineOperand :: CreateReg ( Dst . getReg ( ) , false ) ) ; MI -> addOperand ( MachineOperand :: CreateReg ( Src . getReg ( ) , false ) ) ; return true ; } }


"Unexpected first operand type - expected a RISCV immediate\n"

's value fails to meet these constraints, the function will set isValid to false and output an error message using the Report stream. For example: if (Inst.getOperand(0).getImm() < 0 || Inst.getOperand(0).getImm() > 2) {   Report << "Immediate operand must be between 0 and 2\n";   isValid = false; }


enum OutliningType { NoOutlining , JSRCall , MoveRegonizing , VariableCall , DynamicCall } ; ` ` ` 3. Define the body of the function : The function will check the value of the target - specific values RISCV and RISCV :: X5 . If both are not equal to RISCV :: X5 , it will return NoOutlining , which indicates that outlining should not be performed . Otherwise , the value of RISCV :: X5 will be checked and based on it , the appropriate OutliningType will be returned . The code for this function can be written as : ` ` ` OutliningType RISCVTargetMachine :: getOutliningType ( const RISCVSubtarget * STI ) { bool hasMIT = STI -> getRegisterInfo ( ) -> getSubRegIndexLaneMask ( RISCV :: X5 ) ; if ( TargetVersoin == 1 ) { return OutliningType :: NoOutlining ; } if ( TargetVersoin == 2 ) { if ( hasMIT ) return OutliningType :: JSRCall ; return OutliningType :: MoveRegonizing ; } if ( TargetVersoin == 3 ) { if ( hasMIT ) return OutliningType :: VariableCall ; return OutliningType :: DynamicCall ; } }


bool shouldOutlineFromFunctionByDefault ( ) { if ( Triple . getArch ( ) == Triple :: riscv32 || Triple . getArch ( ) == Triple :: riscv64 ) { return true ; } return false ; }


"Can't load this register from stack slot"


"Can't store this register to stack slot"


void insertBranch ( MachineBasicBlock * MBB , MachineBasicBlock * TargetBlock ) { BuildMI ( MBB , MBB -> end ( ) , DebugLoc ( ) , TII -> get ( RISCV :: PseudoCBR ) ) . addMBB ( TargetBlock ) . addImm ( 0 ) . addImm ( 0 ) . addImm ( 1 ) . addImm ( 2 ) . addImm ( 1 ) . addImm ( 2 ) . setMemRefs ( nullptr ) ; MachineInstr * BrInst = MBB -> end ( ) ; BrInst -> getOperand ( 0 ) . setIsJTI ( ) ; BrInst -> setDesc ( TII -> get ( RISCV :: PseudoBR ) ) ; BrInst -> setFlags ( RISCVABI :: isCheriPureCapABI ) ; }


void insertIndirectBranch ( MachineBasicBlock & MBB , MachineBasicBlock * NewDestBB ) { MachineFunction * MF = MBB . getParent ( ) ; MachineInstrBuilder MIB ; bool RequiresRegScavenger = MF -> getInfo < RISCVFunctionInfo > ( ) -> requiresRegScavengerForLongBranch ( ) ; if ( RequiresRegScavenger ) { MachineBasicBlock * ExpandMBB = MF -> CreateMachineBasicBlock ( MBB . getBasicBlock ( ) ) ; MF -> insert ( MF -> iterator_to ( MBB ) , ExpandMBB ) ; MBB . replaceInstrWithBranch ( * MBB . instr_begin ( ) , ExpandMBB ) ; } MIB = BuildMI ( MBB , MBB . getFirstTerminator ( ) , MBB . findRegisterDefOperandIdx ( RISCV :: GP , false , true ) , RISCV :: PseudoCJump ) ; MIB . addMBB ( NewDestBB ) ; MIB . addReg ( RISCV :: GPCRRegClass ) ; MIB . addImm ( RISCV :: PseudoJump ) ; MIB . addImm ( RISCVII :: MO_CALL ) ; MIB . addImm ( 0 ) ; MIB . addImm ( 8 ) ; MIB . addGlobalAddress ( NewDestBB -> getSymbol ( ) , 0 , RISCVII :: MO_NONE ) ; if ( RISCVABI :: isCheriPureCapABI ( MF -> getFunction ( ) . getCallingConv ( ) ) ) { MIB . addReg ( RISCV :: GPCRRegClass ) ; } else { MIB . addReg ( RISCV :: GPRRegClass ) ; } MBB . insert ( MBB . getFirstTerminator ( ) , MIB ) ; }


enum RISCVInstType { CMove = RISCV :: CMove , CIncOffset = RISCV :: CIncOffset , CIncOffsetImm = RISCV :: CIncOffsetImm , FSGNJ_D = RISCV :: FSGNJ_D , FSGNJ_S = RISCV :: FSGNJ_S , ADDI = RISCV :: ADDI , ORI = RISCV :: ORI , XORI = RISCV :: XORI } ; Next , we will define a function called isAsCheapAsAMove that takes in an instruction and returns a boolean : bool isAsCheapAsAMove ( const RISCVInstType Inst ) { } Inside the function , we will use a switch statement to check for each type of instruction and return true if it exists in our list of target specific values : switch ( Inst ) { case RISCVInstType :: CMove : case RISCVInstType :: CIncOffset : case RISCVInstType :: CIncOffsetImm : case RISCVInstType :: FSGNJ_D : case RISCVInstType :: FSGNJ_S : case RISCVInstType :: ADDI : case RISCVInstType :: ORI : case RISCVInstType :: XORI : return true ; default : return false ; } This ensures that if the instruction matches one of the specified types , the function will return true . If it does not match , it will return false . Finally , we can add in the target specific values to make sure the function returns the correct value : bool isAsCheapAsAMove ( const RISCVInstType Inst ) { switch ( Inst ) { case RISCVInstType :: CMove : case RISCVInstType :: CIncOffset : case RISCVInstType :: CIncOffsetImm : case RISCVInstType :: FSGNJ_D : case RISCVInstType :: FSGNJ_S : case RISCVInstType :: ADDI : case RISCVInstType :: ORI : case RISCVInstType :: XORI : return true ; default : return false ; } }


's sign.   if (instr->isBranch()) {     int64_t BranchOffset = instr->getOperand(0).getImm();     int64_t CurrentPC = instr->getAddr() + 4;      bool isNegative = (BranchOffset >> 11) & 1;     int64_t Offset = (isNegative) ? -1 * (BranchOffset & 0x7FF) : BranchOffset & 0x7FF;     int64_t BranchAddress = CurrentPC + Offset;     if (BranchAddress > (CurrentPC + 2048) || BranchAddress < (CurrentPC - 2048)) {        return false;      }   }


int & Offset ) { switch ( MI -> getOpcode ( ) ) { default : return 0 ; case RISCV :: LB : case RISCV :: LBU : case RISCV :: LH : case RISCV :: LHU : case RISCV :: FLH : case RISCV :: LW : case RISCV :: FLW : case RISCV :: LWU : case RISCV :: LD : case RISCV :: FLD : case RISCV :: LC_64 : case RISCV :: LC_128 : case RISCV :: CLB : case RISCV :: CLBU : case RISCV :: CLH : case RISCV :: CLHU : case RISCV :: CLW : case RISCV :: CFLW : case RISCV :: CLWU : case RISCV :: CLD : case RISCV :: CFLD : case RISCV :: CLC_64 : case RISCV :: CLC_128 : if ( MI -> mayLoad ( ) ) { if ( MI -> getNumOperands ( ) == 3 && MI -> getOperand ( 0 ) . isReg ( ) && MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) ) { NumBytes = MI -> getOperand ( 2 ) . getImm ( ) ; Offset = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } } return 0 ; } }


uint64_t RISCVInstrInfo :: getInstSizeInBytes ( const MachineInstr * MI ) const { switch ( MI -> getOpcode ( ) ) { case RISCV :: PseudoCALLReg : case RISCV :: PseudoCALL : case RISCV :: PseudoJump : case RISCV :: PseudoTAIL : case RISCV :: PseudoLLA : case RISCV :: PseudoLA : case RISCV :: PseudoLA_TLS_IE : case RISCV :: PseudoLA_TLS_GD : return 8 ; default : return ~ 0U ; } }


bool
isBranchOffsetInRange
(
unsigned
Opcode
,
int64_t
Offset
)
{
switch
(
Opcode
)
{
default
:
llvm_unreachable
(
"Unexpected opcode!"
)
;
case
RISCV
::
BEQ
:
case
RISCV
::
BNE
:
case
RISCV
::
BLT
:
case
RISCV
::
BGE
:
case
RISCV
::
BLTU
:
case
RISCV
::
BGEU
:
case
RISCV
::
CV_BEQIMM
:
case
RISCV
::
CV_BNEIMM
:
return
Offset
>=
2048
&&
Offset
<
2048
;
case
RISCV
::
JAL
:
case
RISCV
::
PseudoBR
:
case
RISCV
::
PseudoJump
:
return
Offset
>=
524288
&&
Offset
<
524288
;
case
RISCV
::
HWPLBranch
:
return
Offset
>=
1024
&&
Offset
<
1024
;
}
}


bool
reverseBranchCondition
(
ConditionList
&
cond
)
{
if
(
cond
.
size
(
)
!=
3
)
{
return
true
;
}
CondCode
opCode
=
(
CondCode
)
cond
[
0
]
;
uint64_t
lhs
=
cond
[
1
]
;
uint64_t
rhs
=
cond
[
2
]
;
switch
(
opCode
)
{
case
RISCV
::
HwlpBranch
:
cond
[
1
]
=
rhs
;
cond
[
2
]
=
lhs
;
return
false
;
default
:
report_fatal_error
(
"Invalid branch condition!"
)
;
return
true
;
}
}


Function * buildOutlinedFrame ( Function & F , Module & M , LLVMContext & Context ) { FunctionType * FuncType = F . getFunctionType ( ) ; std :: string OutlinedName = F . getName ( ) . str ( ) + "_outlined" ; Function * OutlinedFunc = Function :: Create ( FuncType , Function :: ExternalLinkage , OutlinedName , & M ) ; TargetSpecificValue RISCV_JALR = 0 ; TargetSpecificValue RISCV_X0 = 0 ; TargetSpecificValue RISCV_X5 = 0 ; BasicBlock * EntryBB = BasicBlock :: Create ( Context , "entry" , OutlinedFunc ) ; Argument * FuncArgs = OutlinedFunc -> arg_begin ( ) ; IRBuilder < > Builder ( EntryBB ) ; std :: map < Value * , Value * > ValueMap ; for ( auto & Arg : F . args ( ) ) { AllocaInst * Alloca = Builder . CreateAlloca ( Arg . getType ( ) ) ; ValueMap [ & Arg ] = Alloca ; Builder . CreateStore ( & Arg , Alloca ) ; FuncArgs ++ ; }


define i64 copyPhysReg ( i64 sourceReg , i64 destReg , regClass regClass , i16 CSI , i16 TRI ) { if ( sourceReg == destReg ) { return 0 ; } if ( regClass == RISCV :: GPRRegClass ) { ADDI ( destReg , sourceReg , 0 ) ; } else if ( regClass == RISCV :: FPR32RegClass ) { FSGNJ_S ( destReg , sourceReg ) ; }


unsigned int getInstSizeInBytes ( const MachineInstr * MI ) { int Size = 0 ; const MCInstrDesc & Desc = MI -> getDesc ( ) ; if ( Desc . isCall ( ) ) { const MachineOperand & Op = MI -> getOperand ( 0 ) ; if ( Op . isReg ( ) ) Size += 4 ; } if ( Desc . isCall ( ) || Desc . isTailCall ( ) ) Size += 4 ; if ( Desc . isLoad ( ) || Desc . isMoveImmediate ( ) ) { const MachineOperand & Base = MI -> getOperand ( 0 ) ; if ( Base . isReg ( ) ) Size += 4 ; if ( Base . isImm ( ) ) Size += 4 ; } return Size ; }


# define RISCV_LOAD_OPCODES { RISCV :: LB , RISCV :: LBU , RISCV :: LH , RISCV :: LHU , RISCV :: LW , RISCV :: FLW , RISCV :: LWU , RISCV :: LD , RISCV :: FLD , RISCV :: VLE_V_um , RISCV :: VLE_V_um } std :: pair < unsigned , int > isLoadFromStackSlot ( MachineInstr * MI , const int * TargetSpecificValues ) { unsigned RegNum = 0 ; int FrameIndex = 0 ; for ( int i = 0 ; TargetSpecificValues [ i ] != 0 ; i ++ ) { if ( MI -> getOpcode ( ) == TargetSpecificValues [ i ] ) { MachineOperand Src = MI -> getOperand ( 1 ) ; if ( Src . isFI ( ) ) { FrameIndex = Src . getIndex ( ) ; MachineOperand Dest = MI -> getOperand ( 0 ) ; if ( Dest . isReg ( ) ) { RegNum = Dest . getReg ( ) ; } } break ; } } return std :: make_pair ( RegNum , FrameIndex ) ; }


* the instruction is not a store to stack slot , returns { - 1 , 0 } . * / std :: pair < int , unsigned int > isStoreToStackSlot ( const MachineInstr * MI , const MachineRegisterInfo & MRI ) { if ( ! MI -> isStore ( ) ) return { - 1 , 0 } ; const MachineOperand & MO = MI -> getOperand ( 0 ) ; if ( ! MO . isFI ( ) ) return { - 1 , 0 } ; unsigned int FrameIdx = MO . getIndex ( ) ; const MachineOperand & SrcMO = MI -> getOperand ( 1 ) ; if ( ! SrcMO . isReg ( ) ) return { - 1 , 0 } ; unsigned int RegNum = SrcMO . getReg ( ) ; if ( TargetRegisterInfo :: isVirtualRegister ( RegNum ) ) { const MachineRegisterInfo :: VirtRegInfo * VirtReg = MRI . getVRegInfo ( RegNum ) ; RegNum = VirtReg -> PhysReg ; } return { RegNum , FrameIdx } ; }


void storeRegToStackSlot ( reg , regClass , stackIndex , MBB , DL , MF ) { if ( MF . getSubtarget < RISCVSubtarget > ( ) . isRISCV64 ( ) ) { if ( regClass == RISCV :: GPRRegClass ) { MBB . addInstr ( RISCV :: SD , DL , MBB . getMoveImmediate ( DL , stackIndex ) , reg ) ; } else if ( regClass == RISCV :: FPR32RegClass ) { MBB . addInstr ( RISCV :: FSW , DL , MBB . getMoveImmediate ( DL , stackIndex ) , reg ) ; } else if ( regClass == RISCV :: FPR64RegClass ) { MBB . addInstr ( RISCV :: FSD , DL , MBB . getMoveImmediate ( DL , stackIndex ) , reg ) ; } else if ( regClass == RISCV :: VGRRegClass ) { MBB . addInstr ( RISCV :: VSE_V_um , DL , MBB . getMoveImmediate ( DL , stackIndex ) , reg ) ; } else if ( regClass == RISCV :: VPRRegClass ) { MBB . addInstr ( RISCV :: VSE_V_um , DL , MBB . getMoveImmediate ( DL , stackIndex ) , reg ) ; } else if ( regClass == RISCV :: VQRRegClass ) { MBB . addInstr ( RISCV :: VSE_V_um , DL , MBB . getMoveImmediate ( DL , stackIndex ) , reg ) ; } else if ( regClass == RISCV :: VORRegClass ) { MBB . addInstr ( RISCV :: VSE_V_um , DL , MBB . getMoveImmediate ( DL , stackIndex ) , reg ) ; }


"Can only store to RISCV GPR register class"


unsigned getInstSizeInBytes ( const MachineInstr * MI ) { const unsigned Opcode = MI -> getOpcode ( ) ; if ( Opcode == RISCV :: PseudoCALL || Opcode == RISCV :: PseudoTAIL ) { return 4 ; } if ( Opcode == RISCV :: PseudoLLA ) { return 8 ; } return ~ 0U ; }


void insertIndirectBranch ( MachineBasicBlock & MBB , MachineBasicBlock & NewDestBB , bool RegScavenger , bool newBlock , unsigned size , int & ErrorCode , unsigned BitSize , unsigned GPRRegClass , unsigned LUIOpcode , unsigned LOOpcode , unsigned PseudoBRINDOpcode , unsigned GPRReg , int ImmOffset ) { if ( ImmOffset > INT32_MAX || ImmOffset < INT32_MIN ) { ErrorCode = RISCV :: TARGET_ERROR ; return ; } if ( RegScavenger ) { unsigned Reg = MBB . getParent ( ) -> getRegScavenger ( ) . FindUnusedReg ( & RI ) ; if ( ! Reg ) { ErrorCode = RISCV :: REG_SCAVENGE_ERROR ; return ; }


namespace { class RISCVFunctionInfo final : public MachineFunctionInfo { const MachineMemOperand * SpillAutoIncBytes ; public : RISCVFunctionInfo ( MachineFunction & MF ) : SpillAutoIncBytes ( nullptr ) { } virtual ~ RISCVFunctionInfo ( ) { } } ; class RISCVFrameLowering final : public TargetFrameLowering { const RISCVSubtarget & STI ; public : RISCVFrameLowering ( const RISCVSubtarget & STI ) : TargetFrameLowering ( TargetFrameLowering :: StackGrowsDown , 8 , 0 ) , STI ( STI ) { } void emitPrologue ( MachineFunction & MF , MachineBasicBlock & MBB ) const override { } void emitEpilogue ( MachineFunction & MF , MachineBasicBlock & MBB ) const override { } bool isFPCloseToIncomingSP ( ) const override { return false ; } } ; } void RISCVVectorRegisterClass :: addRegisterOperands ( MachineInstrBuilder & MIB , unsigned OpFlags ) const { for ( auto MO : Registers ) { MIB . addReg ( MO . getReg ( ) , getFlags ( ) | OpFlags ) ; } }


"Can't store this register to stack slot"


unsigned int getInstSizeInBytes ( const MachineInstr * MI ) { unsigned int Size = 0 ; switch ( MI -> getOpcode ( ) ) { case RISCV :: PseudoCALL : case RISCV :: PseudoTAIL : case RISCV :: PseudoLLA : case RISCV :: PseudoLA : Size = 8 ; break ; default : Size = ~ 0U ; break ; } return Size ; }


unsigned int getInstSizeInBytes ( const MachineInstr & MI ) { const MCInstrDesc & MCID = MI . getDesc ( ) ; switch ( MI . getOpcode ( ) ) { case RISCV :: PseudoCALL : case RISCV :: PseudoTAIL : return 8 ; default : if ( MCID . isTargetSpecific ( ) ) { const RISCVInstrInfo * TII = static_cast < const RISCVInstrInfo * > ( MI . getMF ( ) . getSubtarget ( ) . getInstrInfo ( ) ) ; if ( TII ) { MachineOperand MO = MI . getOperand ( 3 ) ; if ( MO . getSubReg ( ) ) return TII -> getInstSizeInBytes ( MCID , MO . getSubReg ( ) ) ; } } return ~ 0U ; } }


bool isCopyInstrImpl ( MachineInstr * MI , const MCInstrDesc & MCID , unsigned ByteSize ) { unsigned NumOperands = MI -> getNumExplicitOperands ( ) ; if ( NumOperands != 2 ) { return false ; } MachineOperand Dest = MI -> getOperand ( 0 ) ; MachineOperand Source = MI -> getOperand ( 1 ) ; if ( ! Dest . isReg ( ) || ! Source . isReg ( ) ) { return false ; } if ( ! TargetRegisterInfo :: isPhysicalRegister ( Dest . getReg ( ) ) || ! TargetRegisterInfo :: isPhysicalRegister ( Source . getReg ( ) ) ) { return false ; } if ( MI -> getOpcode ( ) != RISCV :: ADDI ) { return false ; } if ( ByteSize != 4 ) { return false ; } unsigned DestRegNum = RegisterInfo :: virtReg2Index ( Dest . getReg ( ) ) ; unsigned SourceRegNum = RegisterInfo :: virtReg2Index ( Source . getReg ( ) ) ; if ( DestRegNum + 1 != SourceRegNum ) { return false ; } if ( ! RISCV :: FSGNJ_D . contains ( Dest . getReg ( ) ) && ! RISCV :: FSGNJ_S . contains ( Source . getReg ( ) ) ) { return false ; } return true ; }


bool analyzeBranch ( MachineBasicBlock & MBB ) { const auto & Instructions = MBB . instrs ( ) ; for ( const auto & I : Instructions ) { if ( I . getOperand ( RISCV :: CCMASK_ANY ) != nullptr ) { return true ; } } return false ; } ` ` ` This function can be called by the RISCV backend whenever a MachineFunction is being processed . For example , in FunctionRISCV . cpp , we can add a call to the analyzeBranch function before performing any other actions on the MBB : ` ` ` void FunctionRISCV :: emitFunction ( MachineFunction & MF ) { bool IsBranchCodeClear = analyzeBranch ( MF . front ( ) ) ; }


void
expandPostRAPseudo
(
MachineInstr
*
MI
)
{
MachineFunction
*
MF
=
MI
->
getParent
(
)
->
getParent
(
)
;
MachineBasicBlock
&
MBB
=
*
MI
->
getParent
(
)
;
MachineRegisterInfo
&
MRI
=
MF
->
getRegInfo
(
)
;
const
TargetInstrInfo
*
TII
=
MF
->
getSubtarget
(
)
.
getInstrInfo
(
)
;
const
TargetRegisterInfo
*
TRI
=
MF
->
getSubtarget
(
)
.
getRegisterInfo
(
)
;
uint16_t
Opcode
=
MI
->
getOpcode
(
)
;
switch
(
Opcode
)
{
default
:
{
llvm_unreachable
(
"Unhandled pseudo instruction"
)
;
break
;
}
case
RISCV
::
PseudoInstruction1
:
{
Register
DestReg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
Register
SrcReg1
=
MI
->
getOperand
(
1
)
.
getReg
(
)
;
Register
SrcReg2
=
MI
->
getOperand
(
2
)
.
getReg
(
)
;
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
MachineInstrBuilder
MIB
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
->
get
(
Opcode
)
.
addReg
(
DestReg
)
.
addReg
(
SrcReg1
)
.
addReg
(
SrcReg2
)
)
;
MIB
.
addImm
(
RISCV
::
RISCV
)
;
MRI
.
replaceRegWith
(
DestReg
,
RISCV
::
RISCV
)
;
MRI
.
replaceRegWith
(
SrcReg1
,
RISCV
::
RISCV
)
;
MRI
.
replaceRegWith
(
SrcReg2
,
RISCV
::
RISCV
)
;
MI
->
eraseFromParent
(
)
;
break
;
}
}
}


int & FrameIndex ) { const MachineOperand & DestOp = MI -> getOperand ( 0 ) ; if ( DestOp . isReg ( ) ) { DestReg = MR -> getInstrInfo ( ) -> getFrameRegister ( * MF ) ; const MachineOperand & SrcOp = MI -> getOperand ( 1 ) ; if ( SrcOp . isFI ( ) ) { FrameIndex = SrcOp . getFrameIndex ( ) ; return true ; } } return false ; }


unsigned isStoreToStackSlot ( const MachineInstr * MI , int & VirtOrPhysReg , int & FrameIndex ) { if ( MI -> getOpcode ( ) != RISCV :: SIMPLESTORE ) return 0 ; VirtOrPhysReg = MI -> getOperand ( 0 ) . getReg ( ) ; FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return 1 ; }


bool
isBranchOffsetInRange
(
unsigned
Opcode
,
int64_t
Offset
)
{
switch
(
Opcode
)
{
case
RISCV
::
BEQ
:
case
RISCV
::
BNE
:
case
RISCV
::
BLT
:
case
RISCV
::
BGE
:
case
RISCV
::
BLTU
:
case
RISCV
::
BGEU
:
case
RISCV
::
P_BEQIMM
:
case
RISCV
::
P_BNEIMM
:
case
RISCV
::
PseudoBR
:
case
RISCV
::
LoopBranch
:
return
(
Offset
>=
4095
&&
Offset
<=
4094
)
;
case
RISCV
::
JAL
:
return
(
Offset
>=
1048575
&&
Offset
<=
1048574
)
;
default
:
llvm_unreachable
(
"Unexpected opcode!"
)
;
}
}


void reverseBranchCondition ( std :: vector < MachineOperand > & CondList ) { if ( CondList . size ( ) != 3 ) { return true ; } if ( ( ! CondList [ 0 ] . isReg ( ) && ! CondList [ 0 ] . isImm ( ) ) || ! CondList [ 1 ] . isImm ( ) || ! CondList [ 2 ] . isImm ( ) ) { return true ; } if ( CondList [ 0 ] . isImm ( ) && CondList [ 0 ] . getImm ( ) != RISCV ) { return true ; } if ( CondList [ 1 ] . getImm ( ) != RISCV :: LoopBranch ) { return true ; } if ( CondList [ 2 ] . getImm ( ) != 0 ) { return true ; } if ( CondList [ 0 ] . isReg ( ) ) { CondList [ 0 ] . setImm ( - 1 ) ; } else { CondList [ 0 ] . setImm ( 0 ) ; } return false ; }


unsigned int getInstSizeInBytes ( const MachineInstr * MI ) { unsigned int Size = 0 ; unsigned int Opcode = MI -> getOpcode ( ) ; switch ( Opcode ) { case RISCV :: ADDI : case RISCV :: ANDI : case RISCV :: AUIPC : case RISCV :: BEQ : case RISCV :: BNE : case RISCV :: JAL : case RISCV :: JALR : case RISCV :: LB : case RISCV :: LBU : case RISCV :: LH : case RISCV :: LHU : case RISCV :: LUI : case RISCV :: ORI : case RISCV :: SB : case RISCV :: SH : case RISCV :: SLLI : case RISCV :: SLTI : case RISCV :: SLTIU : case RISCV :: SRAI : case RISCV :: SRLI : case RISCV :: XORI : Size = 4 ; break ; case RISCV :: PseudoCALL : case RISCV :: PseudoTAIL : Size = 8 ; break ; case RISCV :: PseudoLLA : case RISCV :: PseudoLA : case RISCV :: PseudoLA_TLS_IE : case RISCV :: PseudoLA_TLS_GD : Size = 8 + MI -> getOperand ( 2 ) . getImm ( ) * 4 ; break ; default : Size = ~ 0U ; } return Size ; }


const char * FailMsg ) { if ( RegClass . contains ( SrcReg ) && RegClass . contains ( DstReg ) ) { return ; }


unsigned int getInstSizeInBytes ( const MachineInstr & MI ) { switch ( MI . getOpcode ( ) ) { case RISCV :: PseudoCALL : case RISCV :: PseudoTAIL : return 8 ; default : return ~ 0U ; } }


bool isBranchOffsetInRange ( int opcode , int offset ) { if ( opcode == RISCV :: BEQ || opcode == RISCV :: BNE || opcode == RISCV :: BLT || opcode == RISCV :: BGE || opcode == RISCV :: BLTU || opcode == RISCV :: BGEU || opcode == RISCV :: JAL || opcode == RISCV :: PseudoBR ) { if ( offset >= - 2048 && offset <= 2047 ) { return true ; } else { return false ; } } else { return false ; } }


int & DestReg , int & FrameIndex ) const { if ( MI -> getOpcode ( ) == RISCV :: LB || MI -> getOpcode ( ) == RISCV :: LBU || MI -> getOpcode ( ) == RISCV :: LH || MI -> getOpcode ( ) == RISCV :: LHU || MI -> getOpcode ( ) == RISCV :: LW || MI -> getOpcode ( ) == RISCV :: FLW || MI -> getOpcode ( ) == RISCV :: LWU || MI -> getOpcode ( ) == RISCV :: LD || MI -> getOpcode ( ) == RISCV :: FLD ) { DestReg = MI -> getOperand ( 0 ) . getReg ( ) ; FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return true ; } return false ; }


"Cannot access stack slot beyond the stack size"


void removeBranch ( MachineBasicBlock * MBB ) { MachineInstr * LastInstr = MBB -> getFirstTerminator ( ) ; if ( ! LastInstr ) return ; if ( ! LastInstr -> isBranch ( ) ) return ; if ( ! LastInstr -> isIdenticalTo ( MachineInstr :: Create ( TargetOpcode :: COPY , DebugLoc ( ) , false , false ) , TargetOpcode :: COPY , DebugLoc ( ) , false , false ) , 0 , 0 , 0 , MachineInstr :: Create ( TargetOpcode :: ORI , DebugLoc ( ) , false , false ) , MachineInstr :: Create ( TargetOpcode :: SLTI , DebugLoc ( ) , false , false ) , MachineInstr :: Create ( TargetOpcode :: SLTI , DebugLoc ( ) , false , false ) ) ) return ; MBB -> erase ( LastInstr ) ; }


bool
reverseBranchCondition
(
CONST_STRING_LIST
ConditionList
)
{
if
(
ConditionList
.
size
(
)
!=
3
)
{
return
true
;
}
std
::
string
CondCode
=
ConditionList
[
0
]
;
int
CondFlag
=
std
::
stoi
(
ConditionList
[
1
]
)
;
if
(
CondCode
!=
"RISCV"
||
CondFlag
!=
3
)
{
return
true
;
}
if
(
CondCode
==
"BEQ"
||
CondCode
==
"BNE"
||
CondCode
==
"BLT"
||
CondCode
==
"BGE"
||
CondCode
==
"BLTU"
||
CondCode
==
"BGEU"
)
{
if
(
CondCode
==
"BEQ"
)
{
CondCode
=
"BNE"
;
}
else
if
(
CondCode
==
"BNE"
)
{
CondCode
=
"BEQ"
;
}
else
if
(
CondCode
==
"BLT"
)
{
CondCode
=
"BGE"
;
}
else
if
(
CondCode
==
"BGE"
)
{
CondCode
=
"BLT"
;
}
else
if
(
CondCode
==
"BLTU"
)
{
CondCode
=
"BGEU"
;
}
else
if
(
CondCode
==
"BGEU"
)
{
CondCode
=
"BLTU"
;
}
ConditionList
.
clear
(
)
;
ConditionList
.
push_back
(
CondCode
)
;
ConditionList
.
push_back
(
std
::
to_string
(
CondFlag
)
)
;
ConditionList
.
push_back
(
"Invalid branch condition!"
)
;
return
false
;
}
return
true
;
}


std
::
string
getName
(
const
Function
&
F
)
{
LLVMContext
&
Context
=
F
.
getContext
(
)
;
Constant
*
name
=
ConstantDataArray
::
getString
(
Context
,
"RISCV"
,
true
)
;
GlobalVariable
*
gv
=
new
GlobalVariable
(
*
F
.
getParent
(
)
,
name
->
getType
(
)
,
true
,
GlobalValue
::
PrivateLinkage
,
name
,
"plan_name"
)
;
Constant
*
zero
=
ConstantInt
::
get
(
Type
::
getInt32Ty
(
Context
)
,
0
)
;
Value
*
indices
[
]
=
{
zero
,
zero
}
;
Constant
*
name_address
=
ConstantExpr
::
getGetElementPtr
(
gv
,
indices
)
;
LoadInst
*
load_name
=
new
LoadInst
(
name_address
,
"plan_name"
)
;
std
::
string
result
=
""
;
result
+=
load_name
->
getName
(
)
.
str
(
)
;
unsigned
VF
=
F
.
getAttributes
(
)
.
getVectorizationFactor
(
)
;
unsigned
UF
=
F
.
getAttributes
(
)
.
getUnrollFactor
(
)
;
result
+=
" with VF="
+
std
::
to_string
(
VF
)
+
" and UF="
+
std
::
to_string
(
UF
)
;
return
result
;
}


void select ( Instruction I ) { if ( I . getTargetSpecificValue ( ) == RISCV ) { } else if ( I . getTargetSpecificValue ( ) == RISCV ) { } else { } }


void
dump
(
)
{
std
::
cerr
<<
"RISCV\n"
;
std
::
cerr
<<
"RISCVAddressingMode = "
<<
RISCVAddressingMode
<<
"\n"
;
std
::
cerr
<<
"Base = "
<<
Base
<<
"\n"
;
std
::
cerr
<<
"0 = null\n"
;
std
::
cerr
<<
"Offset = "
<<
Offset
<<
"\n"
;
}


"RISCV DAG->DAG Pattern Instruction Selection"


't have any other target specific values to check for. Example usage: if (isValidOffset(Mode, Offset)) { } else { }


std :: pair < SDValue , SDValue > SelectInlineAsmMemoryOperand ( const SDValue & N , char Constraint , SelectionDAG & CurDAG ) { if ( Constraint != 'RISCV' && Constraint != 'riscv' ) { return std :: make_pair ( SDValue ( ) , SDValue ( ) ) ; }


void Select ( const RISCVTargetLowering * TLI , SDNode * Node , std :: vector < SDValue > & OutOps ) { unsigned Opcode = Node -> getOpcode ( ) ; if ( Opcode == ISD :: Constant ) { uint64_t Val = cast < ConstantSDNode > ( Node ) -> getZExtValue ( ) ; SDValue ConstNode = DAG . getTargetConstant ( Val , SDLoc ( Node ) , MVT :: i32 ) ; OutOps . push_back ( ConstNode ) ; return ; } if ( Opcode == ISD :: FrameIndex ) { int FrameIdx = cast < FrameIndexSDNode > ( Node ) -> getIndex ( ) ; SDValue FrameIdxNode = DAG . getTargetFrameIndex ( FrameIdx , MVT :: i32 ) ; OutOps . push_back ( FrameIdxNode ) ; return ; } if ( Opcode == ISD :: ADD ) { SDValue Op0 = Node -> getOperand ( 0 ) ; SDValue Op1 = Node -> getOperand ( 1 ) ; if ( Op0 . getOpcode ( ) == RISCVISD :: CONSTANT && Op1 . getOpcode ( ) == RISCVISD :: FRAME_INDEX ) { SDValue Addi = DAG . getNode ( RISCVISD :: ADDI , SDLoc ( Node ) , MVT :: i32 , Op0 , Op1 ) ; OutOps . push_back ( Addi ) ; return ; } } SelectionDAG :: SelectNodeTo ( Node , RISCV :: X0 ) ; }


SDValue RISCVTargetLowering :: SelectInlineAsmMemoryOperand ( SDValue Op , unsigned ConstraintCode , const SDLoc & DL , SelectionDAG & DAG ) { if ( ConstantSDNode * C = dyn_cast < ConstantSDNode > ( Op ) ) return CurDAG -> getTargetConstant ( * C -> getConstantIntValue ( ) , DL , Op . getValueType ( ) ) ; switch ( ConstraintCode ) { case RISCV : { return CurDAG -> getTargetGlobalAddress ( cast < GlobalAddressSDNode > ( Op ) -> getGlobal ( ) , DL , Op . getValueType ( ) ) ; } case RISCV : { return CurDAG -> getTargetJumpTable ( cast < JumpTableSDNode > ( Op ) -> getIndex ( ) , Op . getValueType ( ) ) ; }


void RISCVTargetLowering :: PostprocessISelDAG ( MachineInstr * MI ) { if ( MI -> getOpcode ( ) == RISCV :: ADD ) { MI -> setDesc ( get ( RISCV :: OR ) ) ; } }


switch
(
N
->
getOpcode
(
)
)
{
case
RISCV
::
X0
:
if
(
N
->
getOperand
(
0
)
.
getOpcode
(
)
==
ISD
::
FrameIndex
)
{
SDValue
Imm
=
CurDAG
->
getTargetConstant
(
N
->
getOperand
(
0
)
.
getOperand
(
1
)
->
getIndex
(
)
,
0
,
MVT
::
i64
)
;
return
CurDAG
->
getMachineNode
(
RISCV
::
ADDI
,
SDLoc
(
N
)
,
N
->
getValueType
(
0
)
,
N
->
getOperand
(
0
)
.
getOperand
(
0
)
,
Imm
)
;
}
llvm_unreachable
(
"Unsupported operation!"
)
;
case
ISD
::
SRL
:
SDValue
Imm
=
CurDAG
->
getTargetConstant
(
1
,
SDLoc
(
N
)
,
MVT
::
i64
)
;
return
CurDAG
->
getMachineNode
(
RISCV
::
SRLIW
,
SDLoc
(
N
)
,
N
->
getValueType
(
0
)
,
N
->
getOperand
(
0
)
,
Imm
)
;
case
RISCVISD
::
READ_CYCLE_WIDE
:
return
CurDAG
->
getMachineNode
(
RISCV
::
ReadCycleWide
,
SDLoc
(
N
)
,
N
->
getVTList
(
)
,
N
->
getOperand
(
0
)
,
N
->
getOperand
(
1
)
)
;
default
:
llvm_unreachable
(
"Unsupported operation!"
)
;
}


void PostprocessISelDAG ( SelectionDAG & DAG ) { for ( SelectionDAG :: allnodes_iterator I = DAG . allnodes_begin ( ) , E = DAG . allnodes_end ( ) ; I != E ; I ++ ) { if ( I -> getOpcode ( ) == ISD :: ADD ) { SDValue NewNode = DAG . getNode ( RISCVISD :: ADD , SDLoc ( I ) , MVT :: i32 , I -> getOperand ( 0 ) , I -> getOperand ( 1 ) ) ; DAG . ReplaceAllUsesOfValueWith ( SDValue ( I , 0 ) , NewNode ) ; } } }


"RISCV PreprocessISelDAG - Replaced node with target specific value\n"


SDValue RISCVTargetLowering :: Select ( SDValue Node , LLVMContext & Context ) { if ( Node . getValueType ( ) == RISCV :: X0 ) { return Node ; } if ( Node . isConstant ( ) && Node . getValueType ( ) . isInteger ( ) ) { return CurDAG -> getTargetConstant ( RISCV :: X0 , Node . getValueType ( ) ) ; } return TargetLowering :: Select ( Node , Context ) ; }


void RISCVTargetLowering :: PostprocessISelDAG ( TargetMachine & TM , SelectionDAG & DAG ) { const RISCVSubtarget & ST = TM . getSubtarget < RISCVSubtarget > ( ) ; SelectionDAG :: allnodes_iterator NI = DAG . allnodes_begin ( ) ; while ( NI != DAG . allnodes_end ( ) ) { if ( NI -> getOpcode ( ) == ISD :: LOAD ) { SDValue Ptr = NI -> getOperand ( 1 ) ; EVT VT = NI -> getValueType ( 0 ) ; SDNode * LoadOpt = RISCVTargetLowering :: CustomFoldLoad ( Ptr , VT , DAG ) ; if ( LoadOpt ) { DAG . ReplaceAllUsesOfValueWith ( SDValue ( NI , 0 ) , SDValue ( LoadOpt , 0 ) ) ; DAG . RemoveDeadNode ( NI ) ; } } ++ NI ; } DAG . finalizeLowering ( ) ; }


void RISCVTargetLowering :: Select ( SDNode * N ) const { switch ( N -> getOpcode ( ) ) { case ISD :: Constant : { break ; } default : { SelectCode ( N ) ; break ; } } }


"Unexpected number of operands in SPLAT_VECTOR_SPLIT_I64_VL instruction!"

"Unexpected VTs in SPLAT_VECTOR_SPLIT_I64_VL instruction!"


bool RISCVTargetLowering :: Select ( MachineInstr * I , const RISCVInstrInfo & II , const RISCVRegisterInfo & RI , const RISCVFrameLowering & FL , SelectionDAG & DAG ) { if ( ! isRISCVInstr ( * I ) ) return false ; unsigned Opcode = I -> getOpcode ( ) ; switch ( Opcode ) { case RISCV :: X0 : { SDValue Reg = DAG . getRegister ( RISCV :: X0 , MVT :: i64 ) ; I = DAG . UpdateNodeOperands ( I , Reg ) ; return true ; } case RISCV :: ADDI : { SDValue Op1 = DAG . getRegister ( RISCV :: X0 , MVT :: i64 ) ; SDValue Op2 = DAG . getConstant ( 0 , MVT :: i64 ) ; I = DAG . UpdateNodeOperands ( I , Op1 , Op2 ) ; return true ; } case RISCV :: SRL : { SDValue Op1 = DAG . getConstant ( 1 , MVT :: i64 ) ; SDValue Op2 = DAG . getConstant ( 0xffffffff , MVT :: i64 ) ; I = DAG . UpdateNodeOperands ( I , Op1 , Op2 ) ; return true ; } case RISCV :: SRLIW : { SDValue Op1 = DAG . getConstant ( 0 , MVT :: i32 ) ; SDValue Op2 = DAG . getConstant ( 0xffffffff , MVT :: i32 ) ; I = DAG . UpdateNodeOperands ( I , Op1 , Op2 ) ; return true ; } default : return false ; } }


namespace
{
class
RISCVDAGToDAGISel
:
public
SelectionDAGISel
{
RISCVSubtarget
&
Subtarget
;
const
RISCVTargetLowering
&
Lowering
;
public
:
explicit
RISCVDAGToDAGISel
(
RISCVTargetMachine
&
TM
,
CodeGenOpt
::
Level
OptLevel
)
:
SelectionDAGISel
(
TM
,
OptLevel
)
,
Subtarget
(
TM
.
getSubtarget
<
RISCVSubtarget
>
(
)
)
,
Lowering
(
*
TM
.
getTargetLowering
(
)
)
{
}
void
Select
(
SDNode
*
Node
)
override
{
LLVM_DEBUG
(
dbgs
(
)
<<
"\nSelecting: "
)
;
DebugLoc
dl
=
Node
->
getDebugLoc
(
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"\n== "
;
Node
->
dump
(
&
DAG
)
)
;
return
;
}
if
(
trySelect
(
Node
)
)
return
;
SelectCode
(
Node
)
;
}


bool RISCVTargetLowering :: Select ( MachineInstrBuilder & MIB , MachineOperand * Op ) { if ( MIB . getOpcode ( ) == RISCV :: ADDI && Op -> isFI ( ) ) { SDValue Constant = DAG . getNode ( RISCVISD :: Constant , SDLoc ( Op ) , MVT :: i32 , MIB . getOperand ( 1 ) ) ; SDValue X0 = DAG . getNode ( RISCVISD :: X0 , SDLoc ( Op ) , MVT :: i32 ) ; SDValue FrameIndex = DAG . getNode ( RISCVISD :: FrameIndex , SDLoc ( Op ) , MVT :: i32 , Op -> getIndex ( ) ) ; SDValue Equal = DAG . getNode ( RISCVISD :: Equal , SDLoc ( Op ) , MVT :: i1 , X0 , FrameIndex ) ; SDValue NewLine = DAG . getNode ( RISCVISD :: Newline , SDLoc ( Op ) , MVT :: Other ) ; SDValue ADDI = DAG . getNode ( RISCVISD :: ADDI , SDLoc ( Op ) , MVT :: i32 , Constant , NewLine ) ; MIB . addUse ( ADDI ) ; return true ; } return false ; }


void
RISCVTargetLowering
::
PreprocessISelDAG
(
)
{
SelectionDAG
&
DAG
=
DAG
.
getGraph
(
)
;
const
RISCVTargetMachine
&
TM
=
(
const
RISCVTargetMachine
&
)
DAG
.
getTarget
(
)
.
getTargetMachine
(
)
;
for
(
SelectionDAG
::
allnodes_iterator
I
=
DAG
.
allnodes_begin
(
)
,
E
=
DAG
.
allnodes_end
(
)
;
I
!=
E
;
++
I
)
{
if
(
I
->
getOpcode
(
)
==
RISCVISD
::
SPLAT_VECTOR_SPLIT_I64_VL
&&
I
->
getNumOperands
(
)
!=
3
)
{
const
SDValue
&
N0
=
I
->
getOperand
(
0
)
;
const
SDValue
&
N1
=
I
->
getOperand
(
1
)
;
const
SDValue
&
N2
=
I
->
getOperand
(
2
)
;
SDLoc
DL
(
I
)
;
SDValue
Ops
[
]
=
{
N0
,
N1
,
N2
}
;
SDValue
TF
=
DAG
.
getMergeValues
(
Ops
)
;
SDValue
ErrMsg
=
DAG
.
getConstant
(
"Unexpected number of operands"
,
DL
,
MVT
::
Other
)
;
SDValue
NewNode
=
DAG
.
getNode
(
ISD
::
TokenFactor
,
DL
,
MVT
::
Other
,
TF
,
ErrMsg
)
;
DAG
.
ReplaceAllUsesOfValueWith
(
SDValue
(
I
,
0
)
,
SDValue
(
NewNode
.
getNode
(
)
,
0
)
)
;
}
}
}


const SDLoc & DL , SelectionDAG & DAG ) { const RISCVSubtarget & Subtarget = DAG . getTarget ( ) . getSubtarget < RISCVSubtarget > ( ) ; switch ( ConstraintCode ) { case 'R' : if ( Op . getValueType ( ) == MVT :: i32 ) { return Op ; } break ; case 'K' : if ( Op . getValueType ( ) == MVT :: i32 || Op . getValueType ( ) == MVT :: i64 ) { return Op ; } break ; case 'A' : if ( Op . getValueType ( ) == MVT :: i32 && Subtarget . hasRV32D ( ) ) { return Op ; } else if ( Op . getValueType ( ) == MVT :: i64 && Subtarget . hasRV64D ( ) ) { return Op ; } break ; case 'J' : if ( Op . getValueType ( ) == MVT :: i32 && Subtarget . hasRV32C ( ) ) { return Op ; } else if ( Op . getValueType ( ) == MVT :: i64 && Subtarget . hasRV64C ( ) ) { return Op ; } break ; } return SDValue ( ) ; }


MVT getScalarShiftAmountTy ( Type * ShiftAmtTy ) { if ( ! ShiftAmtTy -> isIntegerTy ( ) ) { return MVT ( ) ; } unsigned int BitWidth = ShiftAmtTy -> getIntegerBitWidth ( ) ; if ( BitWidth == RISCV_PTR_SIZE ) { return ( MVT ) RISCV_MVT_I32 ; } else if ( BitWidth == RISCV_PTR_SIZE * 2 ) { return ( MVT ) RISCV_MVT_I64 ; } else { return MVT ( ) ; } }


MVT :: SimpleValueType getSetCCResultType ( ISD :: CondCode cc , MVT :: i32 VT ) { if ( VT != MVT :: i32 ) { return MVT :: Other ; } switch ( cc ) { case ISD :: SETNE : case ISD :: SETEQ : case ISD :: SETGT : case ISD :: SETLT : case ISD :: SETGE : case ISD :: SETLE : return MVT :: i1 ; default : return MVT :: Other ; } }


bool isFMAFasterThanFMulAndFAdd ( const TargetMachine & TM ) { const RISCVSubtarget & STI = TM . getSubtarget < RISCVSubtarget > ( ) ; const MCInstrInfo * MCII = TM . getMCInstrInfo ( ) ; const MCInstrDesc & FMA = MCII -> get ( RISCV :: FMA_D ) ; int FMAProcRes = getProcResource ( FMA , STI ) ; int FMulAddRes = getProcResource ( RISCV :: FMUL_D , STI ) + getProcResource ( RISCV :: FADD_D , STI ) ; return FMAProcRes < FMulAddRes ; }


void addLiveIn ( MachineBasicBlock * MBB , Register Reg ) { if ( ! MBB ) return ; if ( ! Reg . isRISCV ( ) ) return ; MBB -> addLiveIn ( Reg , RISCV ) ; }


SelectionDAG & DAG ) { const TargetRegisterClass * RC = RISCV :: GPRRegClass ; const unsigned NumGPRs = RC -> getNumRegs ( ) ; bool Flag = true ; if ( RegInfo -> getNumAllocatableRegs ( * RC ) < NumReturnRegs ) { Flag = false ; } for ( unsigned int i = 0 ; i < Outs . size ( ) ; ++ i ) { MVT ArgVT = Outs [ i ] . VT ; uint64_t ArgSize = EVT ( ArgVT ) . getSizeInBits ( ) ; if ( ArgSize > NumReturnRegs * 8 ) { Flag = false ; break ; } } return Flag ; }


if
(
!
MI
->
getDesc
(
)
.
usesCustomInserter
(
)
)
{
llvm_unreachable
(
"Unexpected instr type to insert"
)
;
}
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
unsigned
OpSize
=
MI
->
getDesc
(
)
.
getSize
(
)
;
const
MCInstrDesc
&
MCID
=
MI
->
getDesc
(
)
;
unsigned
Width
=
MCID
.
getSize
(
)
;
switch
(
Opcode
)
{
case
RISCV
::
SELECT_CC
:
case
RISCV
::
SELECT_CC64
:
EmitInstrRegRegImm
(
BB
,
I
,
DL
,
RISCV
::
SELECT_CC
,
RISCV
::
SELECT_CC64
)
;
break
;
case
RISCV
::
FSELECT_CC_F
:
case
RISCV
::
FSELECT_CC_D
:
EmitInstrRegRegImm
(
BB
,
I
,
DL
,
RISCV
::
FSELECT_CC_F
,
RISCV
::
FSELECT_CC_D
)
;
break
;
case
RISCV
::
CALL
:
case
RISCV
::
CALLREG
:
case
RISCV
::
CALL64
:
case
RISCV
::
CALLREG64
:
EmitInstrCall
(
BB
,
I
,
DL
,
RISCV
::
CALL
,
RISCV
::
CALLREG
,
RISCV
::
CALL64
,
RISCV
::
CALLREG64
)
;
break
;
default
:
llvm_unreachable
(
"Unexpected instr type to insert"
)
;
}


string getConstraintType ( char constraintLetter ) { switch ( constraintLetter ) { case 'G' : return "RegisterClass" ; case 'C' : return "Immediate" ; case 'R' : return "Register" ; default : return "" ; } }


llvm :: ArrayRef < llvm :: MCPhysReg > RISCVTargetLowering :: getExceptionPointerRegister ( ) { static const llvm :: MCPhysReg regs [ ] = { RISCV :: X10 , RISCV :: X11 , RISCV :: X12 , RISCV :: X13 } ; return llvm :: ArrayRef < llvm :: MCPhysReg > ( regs ) ; }


unsigned getExceptionSelectorRegister ( const RISCVSubtarget & ST ) { return RISCV :: evec_64 ; }


std :: string getRegForInlineAsmConstraint ( std :: string PRC ) { } ` ` ` Solution : ` ` ` std :: string getRegForInlineAsmConstraint ( std :: string PRC ) { std :: vector < std :: string > tokens ; std :: stringstream ss ( PRC ) ; std :: string token ; while ( std :: getline ( ss , token , ',' ) ) { tokens . push_back ( token ) ; } if ( tokens . size ( ) > 6 ) { return tokens [ 6 ] ; } else { return "" ; } }


int getSingleConstraintMatchWeight ( std :: string constraint , OperandType opType ) { int weight = 0 ; if ( constraint == "RISCV" || opType == RISCV ) { weight += 1 ; } if ( constraint == "8" || opType == 8 ) { weight += 2 ; } if ( constraint == "12" || opType == 12 ) { weight += 3 ; } if ( constraint == "16" || opType == 16 ) { weight += 4 ; } if ( constraint == "20" || opType == 20 ) { weight += 5 ; }


if
(
targetNode
==
"RISCV,RISCV,0,0,"
Unexpected
node
type
.
""
)
{
print
(
"Error: Unexpected node type."
)
;
}
else
{
print
(
"Target node: "
+
targetNode
.
getName
(
)
)
;
}


StringRef getTargetNodeName ( TargetMachine * TM , bool Verbose ) { if ( TM -> getTargetTriple ( ) . isRISCV ( ) ) { if ( Verbose ) return "RISCV" ; else return "R" ; } return "" ; }


void RISCVTargetMachine :: Initialize ( RISCVTarget & RI , RISCVSubtarget & STI ) { RI . setFeatureEnabled ( TheRISCVTargetFeatures . Component . floatABI ( ) , STI . useSoftFloat ( ) ) ; RI . setFeatureEnabled ( TheRISCVTargetFeatures . Component . fp64 ( ) , STI . useFP64 ( ) ) ; STI . InstrInfo . reset ( new RISCVInstrInfo ( RI ) ) ; STI . RegInfo . reset ( new RISCVRegisterInfo ( RI ) ) ; STI . FrameLowering . reset ( new RISCVFrameLowering ( STI ) ) ; STI . TSInfo . reset ( new RISCVTargetSubtargetInfo ( STI ) ) ; STI . ISel . reset ( new RISCVInstructionSelector ( STI , * this ) ) ; }


bool isFPImmLegal ( const RISCVSubtarget * Subtarget , double Val , EVT VT ) { if ( ! Subtarget -> hasFP64 ( ) && VT != MVT :: f32 ) return false ; if ( Val < - 4095.5 || Val > 4095.5 ) return false ; if ( VT == MVT :: f64 && ( Val > 4095.5 || Val < - 262143.5 ) ) return false ; return true ; }


bool isOffsetFoldingLegal ( const ConstantOffsetAddr & Offset , const GlobalAddressOperand & Addr ) { if ( Addr . getTargetSymbol ( ) == nullptr ) { return false ; } RISCVSubtarget ST ( Addr . getTargetSymbol ( ) -> getParent ( ) -> getTargetTriple ( ) , Addr . getTargetSymbol ( ) -> getName ( ) ) ; if ( ! ST . isRISCV ( ) ) { return false ; } if ( Offset . baseOffset == 0 ) { return true ; } int64_t BaseOffset = Offset . baseOffset . getValue ( ) ; if ( Offset . symbolOffset != 0 ) { return false ; } else if ( BaseOffset < 0 ) { return false ; } else if ( BaseOffset % ST . getStackAlignment ( ) != 0 ) { return false ; } return true ; }


"Unexpected operand value for RISCV target!"

"Unexpected operand value for 1 target!"

"Unexpected operand value for 0 target!"

"Unexpected operand value for 8 target!"

"Unexpected operand value for 12 target!"

"Unexpected operand value for 16 target!"

"Unexpected operand value for 20 target!"

"Unexpected operand value for 0x7fffffff target!"


unsigned ArgFlags ) { LLT Ty = MIRBuilder . getMRI ( ) -> getType ( VReg ) ; if ( ! Ty . isScalar ( ) ) return false ; const RISCVTargetLowering & TLI = * MF . getSubtarget < RISCVSubtarget > ( ) . getTargetLowering ( ) ; EVT VT = TLI . getValueType ( VT ) ; SDValue Flag = MIRBuilder . buildTargetInstr ( RISCV :: RET_FLAG , { VT } , ArgFlags ) -> getValue ( 0 ) ; MIRBuilder . buildInstr ( RISCVISD :: RET_FLAG ) . addUse ( Flag ) . addImm ( 1 ) . addImm ( 1 ) ; MIRBuilder . getMBB ( ) . addSuccessor ( MIRBuilder . getMBB ( ) ) ; return true ; }


StringRef getTargetNodeName ( unsigned Opcode ) { switch ( Opcode ) { default : return "" ; case RISCV :: RISCV : return "RISCV" ; 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 :: 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" ; } }


Function * LowerOperation ( Operation * op ) { if ( ! op || ! RISCVTargetSupported ( op -> getOpcode ( ) ) ) { return nullptr ; } const OperationTarget * target = op -> getTarget ( ) ; if ( target -> isUnimplementedOperand ( ) ) { return nullptr ; } switch ( op -> getOpcode ( ) ) { case ISD :: GlobalAddress : break ; case ISD :: BlockAddress : break ; case ISD :: ConstantPool : break ; case ISD :: SELECT : break ; case ISD :: VASTART : break ; case ISD :: FRAMEADDR : break ; case ISD :: RETURNADDR : break ; default : break ; } return nullptr ; } bool RISCVTargetSupported ( ISD :: Opcode opcode ) { switch ( opcode ) { case ISD :: GlobalAddress : case ISD :: BlockAddress : case ISD :: ConstantPool : case ISD :: SELECT : case ISD :: VASTART : case ISD :: FRAMEADDR : case ISD :: RETURNADDR : return true ; default : return false ; } }


SelectionDAG & DAG ) const { if ( Outs . size ( ) > 0 ) { EVT RetVT = getPointerTy ( DAG . getDataLayout ( ) ) ; MVT RetMVT = RetVT . getSimpleVT ( ) . SimpleTy ; SDValue Flag = DAG . getTargetConstant ( RISCVISD :: RET_FLAG , DL , RetMVT ) ; return DAG . getNode ( RISCVISD :: RET_FLAG , DL , MVT :: Other , Chain , Flag ) ; } return SDValue ( ) ; }


RISCVCC :: RISCV Subtarget ) { for ( unsigned I = 0 , E = Outs . size ( ) ; I < E ; ++ I ) { ISD :: OutputArg & Out = Outs . get ( I ) ; const RISCVCC :: ArgFlagsTy & Flags = Out . Flags ; switch ( Flags . getByValType ( ) ) { case ISD :: ArgFlagsTy :: ByValNever : continue ; case ISD :: ArgFlagsTy :: ByVal : if ( Flags . isNest ( ) || Flags . isInAlloca ( ) ) return false ; else continue ; default : RISCVABI :: ABI CallABI = Flags . isInConsecutiveRegs ( ) ? RISCVABI :: ABI_O32 : Flags . isSRet ( ) ? RISCVABI :: ABI_SRet : Flags . isByVal ( ) ? ( RISCVABI :: ABI ) ABI : RISCVABI :: ABI_NA ; if ( Flags . isByVal ( ) && ( CallABI == RISCVABI :: ABI_NA || LLVMABINameForRISCVABI ( CallABI ) == "gnuabi64" ) ) CallABI = RISCVABI :: ABI_O32 ; if ( ( I != E - 1 && ( ByValOrInsnReg || Flags . isZExt ( ) || Flags . isSRet ( ) || CallABI != RISCVABI :: ABI_NA ) ) || ! Out . getEmitterSavesLocalFrame ( ) ) return false ; } } return true ; }


"Invalid opcode used in ComputeNumSignBitsForTargetNode"


"Unexpected number of operands for ReadCycleWide instruction"

"Invalid destination register for ReadCycleWide instruction"

"ReadCycleWide is only to be used on riscv32"


RISCV :: X10 getExceptionPointerRegister ( ) { return RISCV :: X10 ; }


RISCV :: X11 getExceptionSelectorRegister ( int physicalReg ) { return RISCV :: X11 ; }


bool getTgtMemIntrinsic ( Intrinsic :: ID ID ) { switch ( ID ) { 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 ; default : return false ; } }


bool isDesirableToCommuteWithShift ( unsigned Opcode , const SDNode * N ) { if ( Opcode != ISD :: ADD && Opcode != ISD :: OR ) { return false ; } if ( ! isa < ConstantSDNode > ( N -> getOperand ( 0 ) ) || ! isa < ConstantSDNode > ( N -> getOperand ( 1 ) ) ) { return false ; } const ConstantSDNode * Op0 = cast < ConstantSDNode > ( N -> getOperand ( 0 ) ) ; const ConstantSDNode * Op1 = cast < ConstantSDNode > ( N -> getOperand ( 1 ) ) ; if ( ! Op0 -> isInt64 ( ) || ! Op0 -> isInt64 ( ) ) { return false ; } int Cost = RISCVMatInt :: getIntMatCost ( Opcode , MVT :: i64 , MVT :: i64 ) ; int NewCost = RISCVMatInt :: getIntMatCost ( Opcode , MVT :: i64 , MVT :: i64 , true ) ; if ( NewCost < Cost ) { int Diff = Op0 -> getZExtValue ( ) - Op1 -> getZExtValue ( ) ; SDNode * NewOp = DAG . getConstant ( Diff , SDLoc ( N ) , MVT :: i64 ) ; SDValue Ops [ ] = { N -> getOperand ( 0 ) , NewOp } ; if ( DAG . isKnownToBeAPowerOfTwo ( Diff ) ) { return true ; } } return false ; }


RISCVTargetLowering :: LowerOperation ( ISD :: NodeType & Node , SelectionDAG & DAG ) { switch ( Node . Opcode ) { case RISCVISD :: GlobalAddress : { GlobalAddressSDNode * GAGetNode = cast < GlobalAddressSDNode > ( Node ) ; SDValue GlobalAddr = DAG . getTargetGlobalAddress ( GAGetNode -> getGlobal ( ) , Node , 0 , MVT :: i32 ) ; SDValue Result = DAG . getNode ( ISD :: LOAD , Node , GAGetNode -> getValueType ( 0 ) , DAG . getConstant ( 0 , Node . getValueType ( 1 ) ) , GlobalAddr , DAG . getTargetConstant ( 0 , Node . getValueType ( 1 ) ) , NULL , 0 ) ; DAG . ReplaceAllUsesWith ( Node , Result ) ; break ; } case RISCVISD :: BlockAddress : { BlockAddressSDNode * BAGetNode = cast < BlockAddressSDNode > ( Node ) ; SDValue GlobalAddr = DAG . getTargetGlobalAddress ( BAGetNode -> getBlockAddress ( ) , Node , 0 , MVT :: i32 ) ; SDValue Result = DAG . getNode ( ISD :: ADD , Node , BAGetNode -> getValueType ( 0 ) , GlobalAddr , DAG . getConstant ( BAGetNode -> getOffset ( ) , Node . getValueType ( 1 ) ) , NULL , 0 ) ; DAG . ReplaceAllUsesWith ( Node , Result ) ; break ; } case RISCVISD :: ConstantPool : { ConstantPoolSDNode * CPLoadNode = cast < ConstantPoolSDNode > ( Node ) ; SDValue GlobalAddr = DAG . getTargetGlobalAddress ( CPLoadNode -> getConstVal ( ) , Node , 0 , CPLoadNode -> getValueType ( 0 ) ) ; SDValue Result = DAG . getNode ( ISD :: LOAD , Node , CPLoadNode -> getValueType ( 0 ) , DAG . getConstant ( 0 , Node . getValueType ( 1 ) ) , GlobalAddr , DAG . getTargetConstant ( 0 , Node . getValueType ( 1 ) ) , NULL , 0 ) ; DAG . ReplaceAllUsesWith ( Node , Result ) ; break ; }


void ReplaceNodeResults ( SDNode * N , SmallVectorImpl < SDValue > & Results , SelectionDAG & DAG ) { unsigned Opcode = N -> getOpcode ( ) ; if ( Opcode == RISCVISD :: READ_CYCLE_WIDE ) { SDValue Op1 = N -> getOperand ( 0 ) ; SDValue Op2 = N -> getOperand ( 1 ) ; SDValue Op3 = N -> getOperand ( 2 ) ; SmallVector < SDValue , 2 > NewResults ; if ( Op1 . getValueType ( ) == MVT :: i32 && Op2 . getValueType ( ) == MVT :: Other && Op3 . getValueType ( ) == MVT :: i32 ) { ConstantSDNode * Immediate = dyn_cast < ConstantSDNode > ( Op1 ) ; if ( Immediate ) { const APInt & ImmVal = Immediate -> getAPIntValue ( ) ; float FImmVal = ( float ) ImmVal . getZExtValue ( ) ; SDValue FVal = DAG . getConstantFP ( FImmVal , MVT :: f32 ) ; SDValue CustomOp = DAG . getNode ( RISCVISD :: FMV_X_ANYEXTW_RV64 , SDLoc ( N ) , MVT :: i64 , FVal ) ; SDValue UnnormVal = DAG . getNode ( ISD :: TRUNCATE , SDLoc ( N ) , MVT :: i32 , CustomOp ) ; NewResults . push_back ( UnnormVal ) ; NewResults . push_back ( Op3 ) ; Results . swap ( NewResults ) ; return ; } } }


OptionSet < RI32 :: InstructSet > getSubtarget ( ) const { return is64Bit ( ) ? RI32 :: RV64I : RI32 :: RV32I ; }


RISCVTargetMachine & TM ) { if ( ! N0 -> getType ( ) -> isIntegerTy ( ) || ! N1 -> getType ( ) -> isIntegerTy ( ) ) { return false ; } if ( ! isa < Constant > ( N0 ) && ! isa < Constant > ( N1 ) ) { return false ; } if ( TargetFolder ( TM ) . isWidenedConstant ( N0 ) && TargetFolder ( TM ) . isWidenedConstant ( N1 ) ) { return false ; } if ( TargetFolder ( TM ) . isUndef ( N0 ) && TargetFolder ( TM ) . isUndef ( N1 ) ) { return false ; } if ( TM . getRegInfo ( ) . isPhysicalRegister ( N0 ) ) { return false ; } if ( TM . getRegInfo ( ) . isPhysicalRegister ( N1 ) ) { return false ; } if ( TM . getRegInfo ( ) . isInefficientToMaterialize ( N0 ) || TM . getRegInfo ( ) . isInefficientToMaterialize ( N1 ) ) { return false ; } if ( TM . getInstrInfo ( ) . getNumOfStoredConstantPool ( N0 ) == 0 && TM . getInstrInfo ( ) . getNumOfStoredConstantPool ( N1 ) == 0 ) { return false ; } return true ; }


MVT :: SimpleValueType VT ) { if ( ! STI . hasStdExtF ( ) || VT != MVT :: f32 || VT != MVT :: f64 ) { return false ; } if ( VT == MVT :: f32 && ! llvm :: APFloat :: isIEEEsingle ( FPImm ) ) { return false ; } if ( VT == MVT :: f64 && ! llvm :: APFloat :: isIEEEdouble ( FPImm ) ) { return false ; } return true ; }


"LowerOperation will not lower linked operands"


bool isEligibleForTailCallOptimization ( CallInst * Call ) { Target LoweredTarget = Call -> getTarget ( ) ; if ( LoweredTarget == "RISCV" ) { TargetFlags DisableFlags = Call -> getTargetFlags ( ) ; if ( DisableFlags [ "disable-tail-calls" ] == "true" ) { TargetFlags InterruptFlag = Call -> getTargetFlags ( ) ; if ( InterruptFlag [ "interrupt" ] == 0 ) { Target SpecificTarget = Call -> getTarget ( ) ; if ( SpecificTarget == "RISCV" ) { Target Architecture = Call -> getTarget ( ) ; if ( Architecture == "RISCV" ) { Target SpecificArchitecture = Call -> getTarget ( ) ; if ( SpecificArchitecture == "RISCV" ) { Target SpecificFeature = Call -> getTarget ( ) ; if ( SpecificFeature == "16" ) { return true ; } } } } } } }


bool isDesirableToCommuteWithShift ( Instruction * shiftInst ) { BinaryOperator * binOp = dyn_cast < BinaryOperator > ( shiftInst ) ; Value * shiftOperand = binOp -> getOperand ( 1 ) ; if ( binOp -> getOpcode ( ) != Instruction :: Add && binOp -> getOpcode ( ) != Instruction :: Or ) { return false ; } Value * otherOperand = binOp -> getOperand ( 0 ) ; if ( otherOperand == shiftOperand ) { otherOperand = binOp -> getOperand ( 1 ) ; } if ( ! isa < ConstantInt > ( otherOperand ) ) { return false ; }


"Tail call optimization requires a void return type"


"Target specific name for Opcode %u is %s"


"Non-register return value is not supported!"


unsigned int getNumRegistersForCallingConv ( CallingConv :: ID callingConv , EVT type ) { if ( callingConv == CallingConv :: RISCV && type == MVT :: f16 ) { return 1 ; } return 0 ; }


RegisterType getRegisterTypeForCallingConv ( CallingConv :: ID CC , const RISCVTargetMachine & Target ) { if ( CC == CallingConv :: RV32E ) { return RegisterType :: GPR ; } else { if ( Target . hasFeature ( Feature :: F16 ) ) { return RegisterType :: FPR ; } else if ( Target . hasFeature ( Feature :: F32 ) ) { return RegisterType :: FR ; } else { return RegisterType :: GPR ; } } }


MVT :: SimpleValueType getSetCCResultType ( const RISCVSubtarget & Subtarget , EVT VT ) { if ( Subtarget . getTargetTriple ( ) . getArch ( ) == Triple :: riscv && VT . getSimpleVT ( ) == MVT :: i1 ) { return MVT :: i1 ; } return getTypeToTransformTo ( VT . getSimpleVT ( ) ) ; }


bool hasAndNot ( RISCV target , RISCV value ) { if ( target == RISCV ) { if ( ( ~ value ) & value ) { return true ; } else { return false ; } } } int main ( ) { RISCV target ; RISCV value ; bool result = hasAndNot ( target , value ) ; return 0 ; }


bool isFPImmLegal ( const RISCVSubtarget & STI , EVT VT , const APFloat & Imm ) { switch ( VT . SimpleTy ) { case MVT :: f16 : return false ; case MVT :: f32 : return Imm . isFloat ( ) ; case MVT :: f64 : return Imm . isDouble ( ) ; default : return false ; } }


bool
shouldSinkOperands
(
const
Instruction
*
I
,
const
BasicBlock
*
BB
)
{
assert
(
I
&&
"Invalid instruction"
)
;
assert
(
BB
&&
"Invalid basic block"
)
;
if
(
I
->
getOpcode
(
)
==
Intrinsic
::
fma
&&
!
I
->
mayHaveSideEffects
(
)
)
{
Value
*
Op1
=
I
->
getOperand
(
0
)
;
Value
*
Op2
=
I
->
getOperand
(
1
)
;
Value
*
Op3
=
I
->
getOperand
(
2
)
;
if
(
Op1
->
getParent
(
)
==
BB
&&
Op2
->
getParent
(
)
==
BB
&&
Op3
->
getParent
(
)
==
BB
)
{
ConstantFP
*
C1
=
dyn_cast
<
ConstantFP
>
(
Op1
)
;
ConstantFP
*
C2
=
dyn_cast
<
ConstantFP
>
(
Op2
)
;
ConstantFP
*
C3
=
dyn_cast
<
ConstantFP
>
(
Op3
)
;
if
(
C1
&&
C2
&&
C3
)
{
return
true
;
}
}
}
return
false
;
}


bool allowsMisalignedMemoryAccesses ( int targetType , string target ) { if ( target == "RISCV,RISCV" ) { switch ( targetType ) { case 1 : return true ; case 2 : return true ; case 4 : return true ; case 8 : return true ; default : return false ; } } else { return false ; } }


bool CanLowerReturn ( const MachineFunction * MF , CallingConv :: ID CC , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) { if ( CC != CallingConv :: RISCV && CC != CallingConv :: RISCV64 ) return false ; const RISCVABIInfo & ABI = MF -> getTarget ( ) . getABI ( ) ; for ( unsigned i = 0 , e = Outs . size ( ) ; i != e ; ++ i ) { const ISD :: OutputArg & Out = Outs [ i ] ; if ( Out . VT . isInteger ( ) ) { unsigned BitSize = Out . VT . getSizeInBits ( ) ; if ( BitSize >= ABI . getReturnRegSizeInBits ( ) ) return false ; } else if ( Out . VT . isFloatingPoint ( ) ) { unsigned BitSize = Out . VT . getSizeInBits ( ) ; if ( BitSize >= ABI . getReturnRegSizeInBits ( ) ) return false ; } else if ( Out . VT . isVector ( ) ) { EVT EltVT = Out . VT . getVectorElementType ( ) ; if ( EltVT . isInteger ( ) || EltVT . isFloatingPoint ( ) ) { unsigned BitSize = EltVT . getSizeInBits ( ) ; if ( BitSize >= ABI . getReturnRegSizeInBits ( ) ) return false ; } else return false ; }


int ComputeNumSignBitsForTargetNode ( const SDValue & N , const SelectionDAG & DAG ) { unsigned NumSignBits = 0 ; EVT VT = N . getValueType ( ) ; int Opcode = N . getOpcode ( ) ; if ( Opcode == RISCVISD :: SELECT_CC || Opcode == RISCVISD :: SLLW || Opcode == RISCVISD :: SRAW || Opcode == RISCVISD :: SRLW || Opcode == RISCVISD :: DIVW || Opcode == RISCVISD :: DIVUW || Opcode == RISCVISD :: REMUW || Opcode == RISCVISD :: ROLW || Opcode == RISCVISD :: RORW || Opcode == RISCVISD :: GREVW || Opcode == RISCVISD :: GORCW || Opcode == RISCVISD :: FSLW || Opcode == RISCVISD :: FSRW || Opcode == RISCVISD :: SHFLW || Opcode == RISCVISD :: UNSHFLW || Opcode == RISCVISD :: BCOMPRESSW || Opcode == RISCVISD :: BDECOMPRESSW || Opcode == RISCVISD :: FCVT_W_RTZ_RV64 || Opcode == RISCVISD :: FCVT_WU_RTZ_RV64 || Opcode == RISCVISD :: SHFL || Opcode == RISCVISD :: UNSHFL || Opcode == RISCVISD :: VMV_X_S ) { if ( VT == MVT :: i64 || VT == MVT :: f64 ) { NumSignBits = 1 ; } } return NumSignBits ; }


bool convertSelectOfConstantsToMath ( Value * Cond , Constant * C1 , Constant * C2 , TargetMachine * TM ) { if ( TM -> getTargetTriple ( ) . getArch ( ) == Triple :: riscv ) { if ( ConstantInt * CI = dyn_cast < ConstantInt > ( Cond ) ) { if ( CI -> isZero ( ) ) { return true ; } } if ( ConstantInt * CI = dyn_cast < ConstantInt > ( Cond ) ) { if ( CI -> isOne ( ) ) { return true ; } }


"This method should only be called on instructions with the 'usesCustomInserter' flag."


void emitLeadingFence ( RISCV , RISCV ) { if ( RISCV == "RISCV32" ) { emit ( Instruction1 ) ; emit ( Instruction2 ) ; emit ( Instruction3 ) ; } else if ( RISCV == "RISCV64" ) { emit ( Instruction4 ) ; emit ( Instruction5 ) ; emit ( Instruction6 ) ; } else { emit ( ErrorInstruction ) ; } emit ( RISCV ) ; emit ( RISCV ) ; emit ( RISCV ) ; }


unsigned
getAddr
(
const
MachineInstr
*
MI
)
{
unsigned
Addr
;
switch
(
MI
->
getOpcode
(
)
)
{
case
RISCV
::
PseudoLLA
:
Addr
=
(
uint32_t
)
MI
->
getOperand
(
0
)
.
getImm
(
)
+
(
uint32_t
)
MI
->
getOperand
(
1
)
.
getImm
(
)
;
break
;
case
RISCV
::
PseudoLA
:
Addr
=
(
uint32_t
)
MI
->
getOperand
(
0
)
.
getImm
(
)
+
MI
->
getOperand
(
1
)
.
getImm
(
)
;
break
;
default
:
errs
(
)
<<
"Unsupported code model for lowering\n"
;
return
0
;
}
return
Addr
;
}


llvm :: Register getExceptionPointerRegister ( const llvm :: MachineFunction & MF ) { const llvm :: TargetInstrInfo * TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; if ( TII -> getRegisterInfo ( ) . isPhysicalRegister ( RISCV :: X10 ) ) { return llvm :: Register :: fromReg ( RISCV :: X10 ) ; } return llvm :: Register :: fromReg ( 0 ) ; }


ISD :: ExtendType getExtendForAtomicCmpSwapArg ( RISCVTargetMachine & TM , ISD :: NodeType CmpSwapType ) { if ( ! TM . getSubtarget < RISCVSubtarget > ( ) . hasStdExtA ( ) ) { return ISD :: ANY_EXTEND ; } if ( CmpSwapType == ISD :: SIGN_EXTEND ) { return ISD :: SIGN_EXTEND ; } return ISD :: ZERO_EXTEND ; }


llvm
::
ISD
::
NodeType
getExtendForAtomicOps
(
llvm
::
RISCV
::
AtomicOps
op
)
{
switch
(
op
)
{
case
llvm
::
RISCV
::
AtomicOps
::
ZERO_EXTEND
:
return
llvm
::
ISD
::
ZERO_EXTEND
;
case
llvm
::
RISCV
::
AtomicOps
::
SIGN_EXTEND
:
return
llvm
::
ISD
::
SIGN_EXTEND
;
case
llvm
::
RISCV
::
AtomicOps
::
ANY_EXTEND
:
return
llvm
::
ISD
::
ANY_EXTEND
;
default
:
llvm_unreachable
(
"Invalid RISCV AtomicOp specified!"
)
;
}
}


"This function is only supported for RISCV target"


unsigned getPrefTypeAlign ( Type * Ty , const DataLayout & DL , unsigned RISCV ) { unsigned PrefStack = DL . getPrefTypeAlignment ( Ty ) ; unsigned PrefStackBytes = RISCV / 8 ; if ( PrefStack < PrefStackBytes ) return PrefStackBytes ; return PrefStack ; }


"Error: Trying to obtain reserved register \""


MVT :: SimpleValueType getSetCCResultType ( MVT :: SimpleValueType OpVT1 , MVT :: SimpleValueType OpVT2 ) { if ( OpVT1 != MVT :: i1 || OpVT2 != MVT :: i1 ) { return MVT :: i32 ; } return MVT :: i1 ; }


Value * getTargetNode ( const MachineInstr * MI , const RISCVtargetInstrInfo * TII , const RISCVSubtarget * ST ) { if ( MI -> isBranch ( ) ) { uint64_t targetAddress = MI -> getOperand ( 1 ) . getImm ( ) ; Value * targetNode = ConstantInt :: get ( IntegerType :: get ( TargetMachineDataLayout . getIntPtrType ( * ST -> getLLVMTargetMachine ( ) -> getDataLayout ( ) ) ) , targetAddress ) ; return targetNode ; } else if ( MI -> isCall ( ) || MI -> isReturn ( ) ) { std :: string functionName = TII -> getCallOpcodeToName ( MI -> getOpcode ( ) ) ; GlobalValue * targetFunction = new GlobalVariable ( MI -> getModule ( ) , IntegerType :: get ( TargetMachineDataLayout . getIntPtrType ( * ST -> getLLVMTargetMachine ( ) -> getDataLayout ( ) ) ) , false , GlobalValue :: ExternalLinkage , nullptr , functionName ) ; return targetFunction ; } else { return nullptr ; } }


EVT getVPExplicitVectorLengthTy ( TargetSubtargetInfo STI ) { StringRef TargetID = STI . getTargetTriple ( ) . getArch ( ) ; if ( TargetID == "riscv32" ) { return EVT :: getIntegerVT ( 32 ) ; } else if ( TargetID == "riscv64" ) { return EVT :: getIntegerVT ( 64 ) ; } else { return EVT ( ) ; } }


bool isEligibleForTailCallOptimization ( CallInst * CI , TargetMachine * TM ) { if ( TM -> getTargetTriple ( ) . getArch ( ) != Triple :: RISCV ) return false ; if ( ! CI -> isDirectCall ( ) ) return false ; Function * F = CI -> getCalledFunction ( ) ; if ( ! F -> hasInternalLinkage ( ) ) return false ; if ( F -> getName ( ) == "interrupt" ) return false ; if ( ! F -> getReturnType ( ) -> isVoidTy ( ) ) return false ; return true ; }


bool isFMAFasterThanFMulAndFAdd ( ) { if ( Target . getID ( ) == Target :: RISCV ) { if ( DstTy == MVT :: f16 || DstTy == MVT :: f32 || DstTy == MVT :: f64 ) { if ( Target . getFMAOpLatency ( ) < Target . getFpuShuffleOpLatency ( ) ) { return true ; } } } return false ; }


bool isFPImmLegal ( MVT :: SimpleValueType VT , const RISCVSubtarget & STI ) { if ( VT != MVT :: f16 && VT != MVT :: f32 && VT != MVT :: f64 ) return false ; switch ( VT ) { case MVT :: f16 : return STI . hasF16 ( ) ; case MVT :: f32 : return STI . hasF32 ( ) ; case MVT :: f64 : return STI . hasF64 ( ) ; } return false ; }


bool isMulAddWithConstProfitable ( int RISCV , int RISCV , int c1 , int c2 , int target_specific_value1 , int target_specific_value2 ) { if ( target_specific_value1 != RISCV || target_specific_value2 != RISCV ) { return false ; } if ( ( c2 & ( c2 - 1 ) ) != 0 ) { return false ; } if ( c1 * c2 < c1 || c1 * c2 < c2 ) { return false ; } if ( c1 * c2 > ( 1 << RISCV ) - 1 ) { return false ; } if ( x -> containsOnlyUsesOf ( Arg ) && ( c1 & ( 1 << RISCV ) - 1 ) == c1 && ( c2 & ( 1 << RISCV ) - 1 ) == c2 ) { return true ; } return false ; }


"The number of elements should not be zero."


bool RISCVTargetMachine :: mayBeEmittedAsTailCall ( CallInst * CI ) { if ( ! CI ) { return false ; } Value * TargetValue = CI -> getArgOperand ( 0 ) ; if ( isa < ConstantInt > ( TargetValue ) ) { ConstantInt * TargetInt = cast < ConstantInt > ( TargetValue ) ; if ( TargetInt -> getValue ( ) . equals ( RISCV ) ) { return true ; } } return false ; }


bool shouldExtendTypeInLibCall ( RISCV , RISCV , RISCVABI :: ABI , RISCVABI :: ABI_LP64 , MVT :: f32 ) { if ( RISCV != RISCV ) { return false ; } if ( RISCVABI :: ABI == RISCVABI :: ABI || RISCVABI :: ABI == RISCVABI :: ABI_LP64 ) { if ( MVT :: f32 == MVT :: f32 ) { return true ; } } return false ; }


bool shouldSignExtendTypeInLibCall ( RISCV :: ValueType VT ) { return VT == RISCV :: MVT :: i32 ; }


bool shouldSinkOperands ( MachineInstr * I ) { if ( I -> getOpcode ( ) == RISCV :: FMADD || I -> getOpcode ( ) == RISCV :: FMSUB || I -> getOpcode ( ) == RISCV :: FMADDS || I -> getOpcode ( ) == RISCV :: FMSUBS ) { if ( I -> getNumOperands ( ) == 3 ) { if ( I -> getOperand ( 0 ) . getParent ( ) == I -> getOperand ( 1 ) . getParent ( ) && I -> getOperand ( 0 ) . getParent ( ) == I -> getOperand ( 2 ) . getParent ( ) ) { if ( ! I -> getOperand ( 0 ) . isTied ( ) && ! I -> getOperand ( 1 ) . isTied ( ) && ! I -> getOperand ( 2 ) . isTied ( ) ) { return ! I -> getOperand ( 0 ) . getParent ( ) -> isLiveIn ( I -> getOperand ( 0 ) . getReg ( ) ) && ! I -> getOperand ( 1 ) . getParent ( ) -> isLiveIn ( I -> getOperand ( 1 ) . getReg ( ) ) && ! I -> getOperand ( 2 ) . getParent ( ) -> isLiveIn ( I -> getOperand ( 2 ) . getReg ( ) ) ; } } } } return false ; }


void RISCVTargetLowering :: AdjustInstrPostInstrSelection ( MachineInstr * MI ) { if ( MI -> getDesc ( ) . hasPostISelHook ( ) ) { unsigned Opcode = MI -> getOpcode ( ) ; unsigned RISCVOpCodes = RISCV :: getNamedOperandIdx ( Opcode , RISCV :: OpName ) ; if ( RISCVOpCodes != 0 ) { unsigned RoundingMode = RISCVFPRndMode :: DYN ; unsigned FrameReg = RISCV :: FRM ; MI -> addOperand ( MachineOperand :: CreateImm ( RISCVOpCodes ) ) ; MI -> addOperand ( MachineOperand :: CreateImm ( RoundingMode ) ) ; MI -> addOperand ( MachineOperand :: CreateImm ( FrameReg ) ) ; } } }