<s> void RISCVFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const RISCVRegisterInfo * RI = STI . getRegisterInfo ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; Align StackAlign = getStackAlign ( ) ; if ( RI -> needsStackRealignment ( MF ) ) { Align MaxStackAlign = std :: max ( StackAlign , MFI . getMaxAlign ( ) ) ; FrameSize += ( MaxStackAlign . value ( ) - StackAlign . value ( ) ) ; StackAlign = MaxStackAlign ; } uint64_t MaxCallSize = alignTo ( MFI . getMaxCallFrameSize ( ) , StackAlign ) ; MFI . setMaxCallFrameSize ( MaxCallSize ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; } </s>

Determine the frame layout but do not update the machine function .


<s> MVT getScalarShiftAmountTy ( const DataLayout & , EVT LHSTy ) const override { return LHSTy . getSizeInBits ( ) <= 32 ? MVT :: i32 : MVT :: i64 ; } </s>

Return the type to use for a scalar shift opcode , given the shifted amount type .


<s> static bool riscv_in_small_data_p ( const_tree x ) { if ( TREE_CODE ( x ) == STRING_CST || TREE_CODE ( x ) == FUNCTION_DECL ) return false ; if ( TREE_CODE ( x ) == VAR_DECL && DECL_SECTION_NAME ( x ) ) { const char * sec = DECL_SECTION_NAME ( x ) ; return strcmp ( sec , ".sdata" ) == 0 || strcmp ( sec , ".sbss" ) == 0 ; } return riscv_size_ok_for_small_data_p ( int_size_in_bytes ( TREE_TYPE ( x ) ) ) ; } </s>

Return true if EXP should be placed in the small data section .


<s> static bool riscv_valid_offset_p ( rtx x , enum machine_mode mode ) { if ( ! const_arith_operand ( x , Pmode ) ) return false ; if ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD && ! SMALL_OPERAND ( INTVAL ( x ) + GET_MODE_SIZE ( mode ) - UNITS_PER_WORD ) ) return false ; return true ; } </s>

Return true if , for every base register BASE_REG , ( plus BASE_REG X ) can address a value of mode MODE .


<s> bool riscv_split_64bit_move_p ( rtx dest , rtx src ) { if ( TARGET_64BIT ) return false ; if ( TARGET_DOUBLE_FLOAT && ( ( FP_REG_RTX_P ( src ) && FP_REG_RTX_P ( dest ) ) || ( FP_REG_RTX_P ( dest ) && MEM_P ( src ) ) || ( FP_REG_RTX_P ( src ) && MEM_P ( dest ) ) || ( FP_REG_RTX_P ( dest ) && src == CONST0_RTX ( GET_MODE ( src ) ) ) ) ) return false ; return true ; } </s>

Return true if a 64-bit move from SRC to DEST should be split into two .


<s> inline unsigned int function_base :: call_properties ( const function_instance & instance ) const { unsigned int flags = 0 ; if ( instance . any_type_float_p ( ) ) return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS ; return flags ; } </s>

Default implementation of function_base : :call_properties , with conservatively correct behavior for floating-point instructions .


<s>
SDValue
RISCVTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
analyzeOutputArgs
(
DAG
.
getMachineFunction
(
)
,
CCInfo
,
Outs
,
true
,
nullptr
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
RVLocs
.
size
(
)
;
i
<
e
;
++
i
)
{
SDValue
Val
=
OutVals
[
i
]
;
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
assert
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
Full
&&
"Unexpected CCValAssign::LocInfo"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
Val
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

This hook must be implemented to lower outgoing return values , described by the Outs array , into the specified DAG .


<s> bool RISCVInstrInfo :: getMemOperandWithOffsetWidth ( const MachineInstr & LdSt , const MachineOperand * & BaseReg , int64_t & Offset , unsigned & Width , const TargetRegisterInfo * TRI ) const { if ( ! LdSt . mayLoadOrStore ( ) ) return false ; if ( LdSt . getNumExplicitOperands ( ) != 3 ) return false ; if ( ! LdSt . getOperand ( 1 ) . isReg ( ) || ! LdSt . getOperand ( 2 ) . isImm ( ) ) return false ; if ( ! LdSt . hasOneMemOperand ( ) ) return false ; Width = ( * LdSt . memoperands_begin ( ) ) -> getSize ( ) ; BaseReg = & LdSt . getOperand ( 1 ) ; Offset = LdSt . getOperand ( 2 ) . getImm ( ) ; return true ; } </s>

Return true if get the base operand , byte offset of an instruction and the memory width .


<s> static bool riscv_cannot_force_const_mem ( machine_mode mode ATTRIBUTE_UNUSED , rtx x ) { enum riscv_symbol_type type ; rtx base , offset ; subrtx_iterator :: array_type array ; FOR_EACH_SUBRTX ( iter , array , x , ALL ) if ( GET_CODE ( * iter ) == CONST_POLY_INT ) return true ; if ( GET_CODE ( x ) == HIGH ) return true ; split_const ( x , & base , & offset ) ; if ( riscv_symbolic_constant_p ( base , & type ) ) { if ( SMALL_OPERAND ( INTVAL ( offset ) ) && riscv_symbol_insns ( type ) > 0 ) return true ; if ( flag_pic ) return true ; } if ( tls_referenced_p ( x ) ) return true ; return false ; } </s>


<s> static hash_set < set_info * > get_all_sets ( set_info * set , bool real_p , bool phi_p , bool param_p ) { if ( real_p && phi_p && param_p ) return get_all_sets ( safe_dyn_cast < phi_info * > ( set ) , REAL_SET | PHI_SET | BB_HEAD_SET | BB_END_SET ) ; else if ( real_p && param_p ) return get_all_sets ( safe_dyn_cast < phi_info * > ( set ) , REAL_SET | BB_HEAD_SET | BB_END_SET ) ; else if ( real_p ) return get_all_sets ( safe_dyn_cast < phi_info * > ( set ) , REAL_SET ) ; return hash_set < set_info * > ( ) ; } </s>

Recursively find all define instructions . The kind of instruction is specified by the DEF_TYPE .


<s> static bool riscv_classify_address ( struct riscv_address_info * info , rtx x , enum machine_mode mode , bool strict_p ) { switch ( GET_CODE ( x ) ) { case REG : case SUBREG : info -> type = ADDRESS_REG ; info -> reg = x ; info -> offset = const0_rtx ; return riscv_valid_base_register_p ( info -> reg , mode , strict_p ) ; case PLUS : info -> type = ADDRESS_REG ; info -> reg = XEXP ( x , 0 ) ; info -> offset = XEXP ( x , 1 ) ; return ( riscv_valid_base_register_p ( info -> reg , mode , strict_p ) && riscv_valid_offset_p ( info -> offset , mode ) ) ; case LO_SUM : info -> type = ADDRESS_LO_SUM ; info -> reg = XEXP ( x , 0 ) ; info -> offset = XEXP ( x , 1 ) ; info -> symbol_type = riscv_classify_symbolic_expression ( info -> offset ) ; return ( riscv_valid_base_register_p ( info -> reg , mode , strict_p ) && riscv_valid_lo_sum_p ( info -> symbol_type , mode ) ) ; case CONST_INT : info -> type = ADDRESS_CONST_INT ; return SMALL_OPERAND ( INTVAL ( x ) ) ; default : return false ; } } </s>

Return true if X is a valid address for machine mode MODE . If it is , fill in INFO appropriately . STRICT_P is true if REG_OK_STRICT is in effect .


<s>
SDValue
RISCVTargetLowering
::
PerformDAGCombine
(
SDNode
*
N
,
DAGCombinerInfo
&
DCI
)
const
{
SelectionDAG
&
DAG
=
DCI
.
DAG
;
switch
(
N
->
getOpcode
(
)
)
{
default
:
break
;
case
ISD
::
SHL
:
case
ISD
::
SRL
:
case
ISD
::
SRA
:
{
assert
(
Subtarget
.
getXLen
(
)
==
64
&&
"Combine should be 64-bit only"
)
;
if
(
!
DCI
.
isBeforeLegalize
(
)
)
break
;
SDValue
RHS
=
N
->
getOperand
(
1
)
;
if
(
N
->
getValueType
(
0
)
!=
MVT
::
i32
||
RHS
->
getOpcode
(
)
==
ISD
::
Constant
||
(
RHS
->
getOpcode
(
)
==
ISD
::
AssertZext
&&
cast
<
VTSDNode
>
(
RHS
->
getOperand
(
1
)
)
->
getVT
(
)
.
getSizeInBits
(
)
<=
5
)
)
break
;
SDValue
LHS
=
N
->
getOperand
(
0
)
;
SDLoc
DL
(
N
)
;
SDValue
NewRHS
=
DAG
.
getNode
(
ISD
::
AssertZext
,
DL
,
RHS
.
getValueType
(
)
,
RHS
,
DAG
.
getValueType
(
EVT
::
getIntegerVT
(
*
DAG
.
getContext
(
)
,
5
)
)
)
;
return
DCI
.
CombineTo
(
N
,
DAG
.
getNode
(
N
->
getOpcode
(
)
,
DL
,
LHS
.
getValueType
(
)
,
LHS
,
NewRHS
)
)
;
}
case
ISD
::
ANY_EXTEND
:
{
SDValue
Src
=
N
->
getOperand
(
0
)
;
if
(
N
->
getValueType
(
0
)
!=
MVT
::
i64
||
Src
.
getValueType
(
)
!=
MVT
::
i32
)
break
;
if
(
!
isVariableShift
(
Src
)
&&
!
(
Subtarget
.
hasStdExtM
(
)
&&
isVariableSDivUDivURem
(
Src
)
)
)
break
;
SDLoc
DL
(
N
)
;
return
DCI
.
CombineTo
(
N
,
DAG
.
getNode
(
ISD
::
SIGN_EXTEND
,
DL
,
MVT
::
i64
,
Src
)
)
;
}
case
RISCVISD
::
SplitF64
:
{
SDValue
Op0
=
N
->
getOperand
(
0
)
;
if
(
Op0
->
getOpcode
(
)
!=
RISCVISD
::
BuildPairF64
)
break
;
return
DCI
.
CombineTo
(
N
,
Op0
.
getOperand
(
0
)
,
Op0
.
getOperand
(
1
)
)
;
}
}
return
SDValue
(
)
;
}
</s>

This method will be invoked for all target nodes and for any target-independent nodes that the target has registered with invoke it for .


<s> static Align getPrefTypeAlign ( EVT VT , SelectionDAG & DAG ) { return DAG . getDataLayout ( ) . getPrefTypeAlign ( VT . getTypeForEVT ( * DAG . getContext ( ) ) ) ; } </s>

Returns the preferred stack/global alignment for the specified type .


"The number of element should not be zero."

Target-specific combining of register parts into its original value .


<s> void RISCVInstrInfo :: storeRegToStackSlot ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MBBI , unsigned SrcReg , bool isKill , int FrameIdx , const TargetRegisterClass * RC , const TargetRegisterInfo * TRI ) const { DebugLoc DL = MBBI != MBB . end ( ) ? MBBI -> getDebugLoc ( ) : DebugLoc ( ) ; unsigned LoadOpcode , StoreOpcode ; getLoadStoreOpcodes ( RC , LoadOpcode , StoreOpcode ) ; addFrameReference ( BuildMI ( MBB , MBBI , DL , get ( StoreOpcode ) ) . addReg ( SrcReg , getKillRegState ( isKill ) ) , FrameIdx ) ; } </s>

Store the specified register of the given register class to the specified stack frame index .


<s> enum tail_policy get_prefer_tail_policy ( ) { return TAIL_ANY ; } </s>


<s> static int riscv_binary_cost ( rtx x , int single_insns , int double_insns ) { if ( GET_MODE_SIZE ( GET_MODE ( x ) ) == UNITS_PER_WORD * 2 ) return COSTS_N_INSNS ( double_insns ) ; return COSTS_N_INSNS ( single_insns ) ; } </s>

Return the cost of binary operation X , given that the instruction sequence for a word-sized or smaller operation takes SIGNLE_INSNS instructions and that the sequence of a double-word operation takes DOUBLE_INSNS instructions .


Relax the instruction in the given fragment to the next wider instruction .


<s> void RISCVAsmPrinter :: emitInstruction ( const MachineInstr * MI ) { if ( emitPseudoExpansionLowering ( * OutStreamer , MI ) ) return ; MCInst TmpInst ; LowerRISCVMachineInstrToMCInst ( MI , TmpInst , * this ) ; auto * MBB = MI -> getParent ( ) ; auto * RVFI = MI -> getMF ( ) -> getInfo < RISCVMachineFunctionInfo > ( ) ; if ( RVFI -> isHwlpBasicBlock ( MBB ) ) AsmPrinter :: EmitToStreamer ( * OutStreamer , TmpInst ) ; else EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>

Targets should implement this to emit instructions .


<s>
MachineInstr
*
RISCVInstrInfo
::
convertToThreeAddress
(
MachineInstr
&
MI
,
LiveVariables
*
LV
)
const
{
switch
(
MI
.
getOpcode
(
)
)
{
default
:
break
;
case
CASE_WIDEOP_OPCODE_LMULS
(
FWADD_WV
)
:
case
CASE_WIDEOP_OPCODE_LMULS
(
FWSUB_WV
)
:
case
CASE_WIDEOP_OPCODE_LMULS
(
WADD_WV
)
:
case
CASE_WIDEOP_OPCODE_LMULS
(
WADDU_WV
)
:
case
CASE_WIDEOP_OPCODE_LMULS
(
WSUB_WV
)
:
case
CASE_WIDEOP_OPCODE_LMULS
(
WSUBU_WV
)
:
{
unsigned
NewOpc
;
switch
(
MI
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Unexpected opcode"
)
;
CASE_WIDEOP_CHANGE_OPCODE_LMULS
(
FWADD_WV
)
CASE_WIDEOP_CHANGE_OPCODE_LMULS
(
FWSUB_WV
)
CASE_WIDEOP_CHANGE_OPCODE_LMULS
(
WADD_WV
)
CASE_WIDEOP_CHANGE_OPCODE_LMULS
(
WADDU_WV
)
CASE_WIDEOP_CHANGE_OPCODE_LMULS
(
WSUB_WV
)
CASE_WIDEOP_CHANGE_OPCODE_LMULS
(
WSUBU_WV
)
}
MachineBasicBlock
&
MBB
=
*
MI
.
getParent
(
)
;
MachineInstrBuilder
MIB
=
BuildMI
(
MBB
,
MI
,
MI
.
getDebugLoc
(
)
,
get
(
NewOpc
)
)
.
add
(
MI
.
getOperand
(
0
)
)
.
add
(
MI
.
getOperand
(
1
)
)
.
add
(
MI
.
getOperand
(
2
)
)
.
add
(
MI
.
getOperand
(
3
)
)
.
add
(
MI
.
getOperand
(
4
)
)
;
MIB
.
copyImplicitOps
(
MI
)
;
if
(
LV
)
{
unsigned
NumOps
=
MI
.
getNumOperands
(
)
;
for
(
unsigned
I
=
1
;
I
<
NumOps
;
++
I
)
{
MachineOperand
&
Op
=
MI
.
getOperand
(
I
)
;
if
(
Op
.
isReg
(
)
&&
Op
.
isKill
(
)
)
LV
->
replaceKillInstruction
(
Op
.
getReg
(
)
,
MI
,
*
MIB
)
;
}
}
return
MIB
;
}
}
return
nullptr
;
}
</s>

convertToThreeAddress - This method must be implemented by targets that set the M_CONVERTIBLE_TO_3_ADDR flag .


<s> static sbitmap riscv_components_for_bb ( basic_block bb ) { bitmap in = DF_LIVE_IN ( bb ) ; bitmap gen = & DF_LIVE_BB_INFO ( bb ) -> gen ; bitmap kill = & DF_LIVE_BB_INFO ( bb ) -> kill ; sbitmap components = sbitmap_alloc ( FIRST_PSEUDO_REGISTER ) ; bitmap_clear ( components ) ; function_abi_aggregator callee_abis ; rtx_insn * insn ; FOR_BB_INSNS ( bb , insn ) if ( CALL_P ( insn ) ) callee_abis . note_callee_abi ( insn_callee_abi ( insn ) ) ; HARD_REG_SET extra_caller_saves = callee_abis . caller_save_regs ( * crtl -> abi ) ; for ( unsigned int regno = GP_REG_FIRST ; regno <= GP_REG_LAST ; regno ++ ) if ( ! fixed_regs [ regno ] && ! crtl -> abi -> clobbers_full_reg_p ( regno ) && ( TEST_HARD_REG_BIT ( extra_caller_saves , regno ) || bitmap_bit_p ( in , regno ) || bitmap_bit_p ( gen , regno ) || bitmap_bit_p ( kill , regno ) ) ) bitmap_set_bit ( components , regno ) ; for ( unsigned int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) if ( ! fixed_regs [ regno ] && ! crtl -> abi -> clobbers_full_reg_p ( regno ) && ( TEST_HARD_REG_BIT ( extra_caller_saves , regno ) || bitmap_bit_p ( in , regno ) || bitmap_bit_p ( gen , regno ) || bitmap_bit_p ( kill , regno ) ) ) bitmap_set_bit ( components , regno ) ; return components ; } </s>


"Can't store this register to stack slot"


<s> static poly_int64 calculate_x_in_sequence ( rtx reg ) { std :: map < unsigned , rtx > regno_to_rtx ; rtx_insn * insn ; for ( insn = get_insns ( ) ; insn ; insn = NEXT_INSN ( insn ) ) { rtx pat = PATTERN ( insn ) ; rtx dest = SET_DEST ( pat ) ; if ( GET_CODE ( pat ) == CLOBBER ) continue ; if ( SUBREG_P ( dest ) ) continue ; gcc_assert ( REG_P ( dest ) ) ; rtx note = find_reg_equal_equiv_note ( insn ) ; unsigned regno = REGNO ( dest ) ; if ( note ) regno_to_rtx [ regno ] = XEXP ( note , 0 ) ; else regno_to_rtx [ regno ] = SET_SRC ( pat ) ; } return eval_value ( reg , regno_to_rtx ) ; } </s>

Calculate the value of x register in the sequence .


Simple predicate for targets where ! Resolved implies requiring relaxation .


<s> bool RISCVTargetLowering :: shouldSinkOperands ( Instruction * I , SmallVectorImpl < Use * > & Ops ) const { using namespace llvm :: PatternMatch ; if ( ! I -> getType ( ) -> isVectorTy ( ) || ! Subtarget . hasVInstructions ( ) ) return false ; auto IsSinker = [ & ] ( Instruction * I , int Operand ) { switch ( I -> getOpcode ( ) ) { case Instruction :: Add : case Instruction :: Sub : case Instruction :: Mul : case Instruction :: And : case Instruction :: Or : case Instruction :: Xor : case Instruction :: FAdd : case Instruction :: FSub : case Instruction :: FMul : case Instruction :: FDiv : case Instruction :: ICmp : case Instruction :: FCmp : return true ; case Instruction :: Shl : case Instruction :: LShr : case Instruction :: AShr : case Instruction :: UDiv : case Instruction :: SDiv : case Instruction :: URem : case Instruction :: SRem : return Operand == 1 ; case Instruction :: Call : if ( auto * II = dyn_cast < IntrinsicInst > ( I ) ) { switch ( II -> getIntrinsicID ( ) ) { case Intrinsic :: fma : return Operand == 0 || Operand == 1 ; default : return false ; } } return false ; default : return false ; } } ; for ( auto OpIdx : enumerate ( I -> operands ( ) ) ) { if ( ! IsSinker ( I , OpIdx . index ( ) ) ) continue ; Instruction * Op = dyn_cast < Instruction > ( OpIdx . value ( ) . get ( ) ) ; if ( ! Op || any_of ( Ops , [ & ] ( Use * U ) { return U -> get ( ) == Op ; } ) ) continue ; if ( ! match ( Op , m_Shuffle ( m_InsertElt ( m_Undef ( ) , m_Value ( ) , m_ZeroInt ( ) ) , m_Undef ( ) , m_ZeroMask ( ) ) ) ) continue ; for ( Use & U : Op -> uses ( ) ) { Instruction * Insn = cast < Instruction > ( U . getUser ( ) ) ; if ( ! IsSinker ( Insn , U . getOperandNo ( ) ) ) return false ; } Ops . push_back ( & Op -> getOperandUse ( 0 ) ) ; Ops . push_back ( & OpIdx . value ( ) ) ; } return true ; } </s>

Return true if sinking I 's operands to the same basic block as I is profitable , e.g .


<s> bool RISCVMCAsmBackend :: mayNeedRelaxation ( const MCInst & Inst ) const { return getRelaxedOpcode ( Inst . getOpcode ( ) ) != 0 ; } </s>

Check whether the given instruction may need relaxation .


<s>
bool
RISCVInstrInfo
::
isBranchOffsetInRange
(
unsigned
BranchOp
,
int64_t
BrOffset
)
const
{
switch
(
BranchOp
)
{
default
:
llvm_unreachable
(
"Unexpected opcode!"
)
;
case
RISCV
::
BEQ
:
case
RISCV
::
BNE
:
case
RISCV
::
BLT
:
case
RISCV
::
BGE
:
case
RISCV
::
BLTU
:
case
RISCV
::
BGEU
:
return
isIntN
(
13
,
BrOffset
)
;
case
RISCV
::
JAL
:
case
RISCV
::
PseudoBR
:
return
isIntN
(
21
,
BrOffset
)
;
}
}
</s>

Determine if the branch target is in range .

RISCV
RISCV
"Unexpected opcode!"
RISCV::BEQ
RISCV::BNE
RISCV::BLT
RISCV::BGE
RISCV::BLTU
RISCV::BGEU
13
RISCV::JAL
RISCV::PseudoBR
21


For stack frames that ca n't be allocated with a single ADDI instruction , compute the best value to initially allocate . It must at a minimum allocate enough space to spill the callee-saved registers .


<s>
MachineBasicBlock
*
RISCVTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
*
MI
,
MachineBasicBlock
*
MBB
)
const
{
switch
(
MI
->
getOpcode
(
)
)
{
case
RISCV
::
SELECT_CC
:
case
RISCV
::
SELECT_CC64
:
case
RISCV
::
FSELECT_CC_F
:
case
RISCV
::
FSELECT_CC_D
:
return
emitSelectCC
(
MI
,
MBB
)
;
case
RISCV
::
CALL
:
case
RISCV
::
CALLREG
:
case
RISCV
::
CALL64
:
case
RISCV
::
CALLREG64
:
return
emitCALL
(
MI
,
MBB
)
;
default
:
llvm_unreachable
(
"Unexpected instr type to insert"
)
;
}
}
</s>

This method should be implemented by targets that mark instructions with the 'usesCustomInserter ' flag .


"Not all fixup kinds added to Infos array"


<s> bool RISCVTargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT , bool ForCodeSize ) const { if ( VT == MVT :: f16 && ! Subtarget . hasStdExtZfhmin ( ) ) return false ; if ( VT == MVT :: f32 && ! Subtarget . hasStdExtF ( ) ) return false ; if ( VT == MVT :: f64 && ! Subtarget . hasStdExtD ( ) ) return false ; if ( Imm . isNegZero ( ) ) return false ; return Imm . isZero ( ) ; } </s>

Returns true if the target can instruction select the specified FP immediate natively .


<s> bool RISCVFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { MachineFunction * MF = MBB . getParent ( ) ; MachineBasicBlock & EntryBlock = * ( MF -> begin ( ) ) ; const TargetInstrInfo & TII = * MF -> getSubtarget ( ) . getInstrInfo ( ) ; for ( unsigned i = 0 , e = CSI . size ( ) ; i != e ; ++ i ) { unsigned Reg = CSI [ i ] . getReg ( ) ; bool IsRAAndRetAddrIsTaken = ( Reg == RISCV :: ra || Reg == RISCV :: ra_64 ) && MF -> getFrameInfo ( ) -> isReturnAddressTaken ( ) ; if ( ! IsRAAndRetAddrIsTaken ) EntryBlock . addLiveIn ( Reg ) ; bool IsKill = ! IsRAAndRetAddrIsTaken ; const TargetRegisterClass * RC = TRI -> getMinimalPhysRegClass ( Reg ) ; TII . storeRegToStackSlot ( EntryBlock , MI , Reg , IsKill , CSI [ i ] . getFrameIdx ( ) , RC , TRI ) ; } return true ; } </s>

spillCalleeSavedRegisters - Issues instruction ( s ) to spill all callee saved registers and returns true if it is n't possible / profitable to do so by issuing a series of store instructions via storeRegToStackSlot ( ) .


<s> void th_mempair_save_restore_regs ( rtx operands [ 4 ] , bool load_p , machine_mode mode ) { gcc_assert ( th_mempair_operands_p ( operands , load_p , mode ) ) ; th_mempair_order_operands ( operands , load_p , mode ) ; if ( load_p ) th_mempair_restore_regs ( operands ) ; else th_mempair_save_regs ( operands ) ; } </s>

Emit a mempair instruction to save/restore two registers to/from stack .


<s> static void riscv_block_move_straight ( rtx dest , rtx src , HOST_WIDE_INT length ) { HOST_WIDE_INT offset , delta ; unsigned HOST_WIDE_INT bits ; int i ; enum machine_mode mode ; rtx * regs ; bits = MAX ( BITS_PER_UNIT , MIN ( BITS_PER_WORD , MIN ( MEM_ALIGN ( src ) , MEM_ALIGN ( dest ) ) ) ) ; mode = mode_for_size ( bits , MODE_INT , 0 ) . require ( ) ; delta = bits / BITS_PER_UNIT ; regs = XALLOCAVEC ( rtx , length / delta ) ; for ( offset = 0 , i = 0 ; offset + delta <= length ; offset += delta , i ++ ) { regs [ i ] = gen_reg_rtx ( mode ) ; riscv_emit_move ( regs [ i ] , adjust_address ( src , mode , offset ) ) ; } for ( offset = 0 , i = 0 ; offset + delta <= length ; offset += delta , i ++ ) riscv_emit_move ( adjust_address ( dest , mode , offset ) , regs [ i ] ) ; if ( offset < length ) { src = adjust_address ( src , BLKmode , offset ) ; dest = adjust_address ( dest , BLKmode , offset ) ; move_by_pieces ( dest , src , length - offset , MIN ( MEM_ALIGN ( src ) , MEM_ALIGN ( dest ) ) , 0 ) ; } } </s>

Emit straight-line code to move LENGTH bytes from SRC to DEST . Assume that the areas do not overlap .


<s> bool RISCVExpandCoreVHwlpPseudo :: runOnMachineFunction ( MachineFunction & MF ) { if ( ! MF . getSubtarget < RISCVSubtarget > ( ) . hasExtXCoreVHwlp ( ) ) { return false ; } MachineLoopInfo & MLI = getAnalysis < MachineLoopInfo > ( ) ; bool Changed = false ; for ( auto & ML : MLI ) { Changed |= ProcessLoop ( ML , MF ) ; } return Changed ; } </s>

runOnMachineFunction - Emit the function body .


<s> void RISCVFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const RISCVRegisterInfo * RI = STI . getRegisterInfo ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; unsigned StackAlign = getStackAlignment ( ) ; if ( RI -> needsStackRealignment ( MF ) ) { unsigned MaxStackAlign = std :: max ( StackAlign , MFI . getMaxAlignment ( ) ) ; FrameSize += ( MaxStackAlign - StackAlign ) ; StackAlign = MaxStackAlign ; } uint64_t MaxCallSize = alignTo ( MFI . getMaxCallFrameSize ( ) , StackAlign ) ; MFI . setMaxCallFrameSize ( MaxCallSize ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; } </s>

Determine the frame layout but do not update the machine function .


"argument %d of %qE must be an integer constant"

Report that LOCATION has a call to FNDECL in which argument ARGNO was not an integer constant expression . ARGNO counts from zero .


<s>
static
bool
sizeless_type_p
(
const_tree
type
)
{
if
(
type
==
error_mark_node
)
return
NULL_TREE
;
return
lookup_attribute
(
"RVV sizeless type"
,
TYPE_ATTRIBUTES
(
type
)
)
;
}
</s>

Return true if TYPE is a sizeless type .


"Can't load this register from stack slot"

Load the specified register of the given register class from the specified stack frame index .


"Trying RISCV32Only_16 table (16-bit Instruction):\n"

"Trying RISCV_C table (16-bit Instruction):\n"

Returns the disassembly of a single instruction .


<s> void RISCVAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { if ( emitPseudoExpansionLowering ( * OutStreamer , MI ) ) return ; MCInst TmpInst ; LowerRISCVMachineInstrToMCInst ( MI , TmpInst , * this ) ; EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>

EmitInstruction - This callback is invoked when an instruction is emitted , to advance the hazard state .


<s> void RISCVAsmPrinter :: emitInstruction ( const MachineInstr * MI ) { if ( emitPseudoExpansionLowering ( * OutStreamer , MI ) ) return ; MCInst TmpInst ; if ( ! lowerRISCVMachineInstrToMCInst ( MI , TmpInst , * this ) ) EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>

Targets should implement this to emit instructions .


<s> inline machine_mode function_expander :: index_mode ( void ) const { return TYPE_MODE ( op_info -> args [ 1 ] . get_tree_type ( type . index ) ) ; } </s>

Return the machine_mode of the corresponding index type .


<s> static bool has_vtype_op ( rtx_insn * rinsn ) { return recog_memoized ( rinsn ) >= 0 && get_attr_has_vtype_op ( rinsn ) ; } </s>

Return true if it is an RVV instruction depends on VTYPE global status register .


<s> unsigned RISCVAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned Kind ) { RISCVOperand & Op = static_cast < RISCVOperand & > ( AsmOp ) ; if ( ! Op . isReg ( ) ) return Match_InvalidOperand ; Register Reg = Op . getReg ( ) ; bool IsRegFPR32 = RISCVMCRegisterClasses [ RISCV :: FPR32RegClassID ] . contains ( Reg ) ; bool IsRegFPR32C = RISCVMCRegisterClasses [ RISCV :: FPR32CRegClassID ] . contains ( Reg ) ; if ( ( IsRegFPR32 && Kind == MCK_FPR64 ) || ( IsRegFPR32C && Kind == MCK_FPR64C ) ) { Op . Reg . RegNum = convertFPR32ToFPR64 ( Reg ) ; return Match_Success ; } return Match_InvalidOperand ; } </s>

Allow a target to add special case operand matching for things that tblgen doesn't/ca n't handle effectively .

RISCV RISCV RISCV RISCV RISCV RISCV::FPR32RegClassID RISCV RISCV::FPR32CRegClassID


<s> static void riscv_legitimize_const_move ( enum machine_mode mode , rtx dest , rtx src ) { rtx base , offset ; if ( splittable_const_int_operand ( src , mode ) ) { riscv_move_integer ( dest , dest , INTVAL ( src ) ) ; return ; } if ( riscv_split_symbol ( dest , src , MAX_MACHINE_MODE , & src ) ) { riscv_emit_set ( dest , src ) ; return ; } if ( riscv_tls_symbol_p ( src ) ) { riscv_emit_move ( dest , riscv_legitimize_tls_address ( src ) ) ; return ; } split_const ( src , & base , & offset ) ; if ( offset != const0_rtx && ( targetm . cannot_force_const_mem ( mode , src ) || can_create_pseudo_p ( ) ) ) { base = riscv_force_temporary ( dest , base ) ; riscv_emit_move ( dest , riscv_add_offset ( NULL , base , INTVAL ( offset ) ) ) ; return ; } src = force_const_mem ( mode , src ) ; riscv_split_symbol ( dest , XEXP ( src , 0 ) , mode , & XEXP ( src , 0 ) ) ; riscv_emit_move ( dest , src ) ; } </s>

Subroutine of riscv_legitimize_move . Move constant SRC into register DEST given that SRC satisfies immediate_operand but does n't satisfy move_operand .


"Can't store this register to stack slot"

Store the specified register of the given register class to the specified stack frame index .


<s> bool RISCVInstrInfo :: analyzeBranch ( MachineBasicBlock & MBB , MachineBasicBlock * & TBB , MachineBasicBlock * & FBB , SmallVectorImpl < MachineOperand > & Cond , bool AllowModify ) const { TBB = FBB = nullptr ; Cond . clear ( ) ; MachineBasicBlock :: iterator I = MBB . getLastNonDebugInstr ( ) ; if ( I == MBB . end ( ) || ! isUnpredicatedTerminator ( * I ) ) return false ; MachineBasicBlock :: iterator FirstUncondOrIndirectBr = MBB . end ( ) ; int NumTerminators = 0 ; for ( auto J = I . getReverse ( ) ; J != MBB . rend ( ) && isUnpredicatedTerminator ( * J ) ; J ++ ) { NumTerminators ++ ; if ( J -> getDesc ( ) . isUnconditionalBranch ( ) || J -> getDesc ( ) . isIndirectBranch ( ) ) { FirstUncondOrIndirectBr = J . getReverse ( ) ; } } if ( AllowModify && FirstUncondOrIndirectBr != MBB . end ( ) ) { while ( std :: next ( FirstUncondOrIndirectBr ) != MBB . end ( ) ) { std :: next ( FirstUncondOrIndirectBr ) -> eraseFromParent ( ) ; NumTerminators -- ; } I = FirstUncondOrIndirectBr ; } if ( I -> getDesc ( ) . isIndirectBranch ( ) ) return true ; if ( NumTerminators > 2 ) return true ; if ( NumTerminators == 1 && I -> getDesc ( ) . isUnconditionalBranch ( ) ) { TBB = I -> getOperand ( 0 ) . getMBB ( ) ; return false ; } if ( NumTerminators == 1 && I -> getDesc ( ) . isConditionalBranch ( ) ) { parseCondBranch ( * I , TBB , Cond ) ; return false ; } if ( NumTerminators == 2 && std :: prev ( I ) -> getDesc ( ) . isConditionalBranch ( ) && I -> getDesc ( ) . isUnconditionalBranch ( ) ) { parseCondBranch ( * std :: prev ( I ) , TBB , Cond ) ; FBB = I -> getOperand ( 0 ) . getMBB ( ) ; return false ; } return true ; } </s>

analyzeBranch - Analyze the branching code at the end of MBB , returning true if it can not be understood ( e.g .


<s> static bool riscv_use_save_libcall ( const struct riscv_frame_info * frame ) { if ( ! TARGET_SAVE_RESTORE || crtl -> calls_eh_return || frame_pointer_needed || cfun -> machine -> interrupt_handler_p ) return false ; return frame -> save_libcall_adjustment != 0 ; } </s>

Determine whether to call GPR save/restore routines .


<s> pass_shorten_memrefs :: regno_map * pass_shorten_memrefs :: analyze ( basic_block bb ) { regno_map * m = hash_map < regno_hash , int > :: create_ggc ( 10 ) ; rtx_insn * insn ; regstat_init_n_sets_and_refs ( ) ; FOR_BB_INSNS ( bb , insn ) { if ( ! NONJUMP_INSN_P ( insn ) ) continue ; rtx pat = PATTERN ( insn ) ; if ( GET_CODE ( pat ) != SET ) continue ; for ( int i = 0 ; i < 2 ; i ++ ) { rtx mem = XEXP ( pat , i ) ; rtx addr ; bool extend = false ; if ( get_si_mem_base_reg ( mem , & addr , & extend ) ) { HOST_WIDE_INT regno = REGNO ( XEXP ( addr , 0 ) ) ; if ( i == 0 ) { if ( XEXP ( pat , 1 ) == CONST0_RTX ( GET_MODE ( XEXP ( pat , 1 ) ) ) ) continue ; } if ( REG_N_REFS ( regno ) < 4 ) continue ; m -> get_or_insert ( regno ) ++ ; } } } regstat_free_n_sets_and_refs ( ) ; return m ; } </s>

Count how many times each regno is referenced as base address for a memory access .


<s> static section * riscv_elf_select_rtx_section ( machine_mode mode , rtx x , unsigned HOST_WIDE_INT align ) { section * s = default_elf_select_rtx_section ( mode , x , align ) ; if ( riscv_size_ok_for_small_data_p ( GET_MODE_SIZE ( mode ) ) ) { if ( startswith ( s -> named . name , ".rodata.cst" ) ) { char * name = ( char * ) alloca ( strlen ( s -> named . name ) + 2 ) ; sprintf ( name , ".s%s" , s -> named . name + 1 ) ; return get_section ( name , s -> named . common . flags , NULL ) ; } if ( s == data_section ) return sdata_section ; } return s ; } </s>

Return a section for X , handling small data .


<s> bool can_be_overloaded_p ( enum predication_type_index pred ) const override { return pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu ; } </s>

Since most of intrinsics can be overloaded , we set it true by default .


"%<-mdiv%> requires %<-march%> to subsume the %<M%> extension"

"requested ABI requires %<-march%> to subsume the %qc extension"

"%<-mpreferred-stack-boundary=%d%> must be between %d and %d"

"%<-mriscv-attribute%> RISC-V ELF attribute requires GNU as 2.32"

"incompatible options %<-mstack-protector-guard=global%> and "

"both %<-mstack-protector-guard-offset%> and "

"%<-mstack-protector-guard-reg%> must be used "

"%qs is not a valid base register in %qs"


<s> bool RISCVRegisterInfo :: isConstantPhysReg ( unsigned PhysReg ) const { return PhysReg == RISCV :: X0 ; } </s>

Returns true if PhysReg is unallocatable and constant throughout the function .


<s>
void
RISCVAsmBackend
::
relaxInstruction
(
const
MCInst
&
Inst
,
const
MCSubtargetInfo
&
STI
,
MCInst
&
Res
)
const
{
switch
(
Inst
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Opcode not expected!"
)
;
case
RISCV
::
C_BEQZ
:
Res
.
setOpcode
(
RISCV
::
BEQ
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
RISCV
::
C_BNEZ
:
Res
.
setOpcode
(
RISCV
::
BNE
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
RISCV
::
C_J
:
Res
.
setOpcode
(
RISCV
::
JAL
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
break
;
case
RISCV
::
C_JAL
:
Res
.
setOpcode
(
RISCV
::
JAL
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X1
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
break
;
}
}
</s>

Relax the instruction in the given fragment to the next wider instruction .


<s> rtx expand_builtin ( unsigned int code , tree exp , rtx target ) { registered_function & rfn = * ( * registered_functions ) [ code ] ; return function_expander ( rfn . instance , rfn . decl , exp , target ) . expand ( ) ; } </s>

Expand a call to the RVV function with subcode CODE . EXP is the call expression and TARGET is the preferred location for the result . Return the value of the lhs .


<s> StringRef getPassName ( ) const override { return RISCV_OPTIMIZE_VSETVL_USES_NAME ; } </s>

getPassName - Return a nice clean name for a pass .


<s> int riscv_load_store_insns ( rtx mem , rtx_insn * insn ) { machine_mode mode ; bool might_split_p ; rtx set ; gcc_assert ( MEM_P ( mem ) ) ; mode = GET_MODE ( mem ) ; might_split_p = true ; if ( GET_MODE_BITSIZE ( mode ) . to_constant ( ) <= 32 ) might_split_p = false ; else if ( GET_MODE_BITSIZE ( mode ) . to_constant ( ) == 64 ) { set = single_set ( insn ) ; if ( set && ! riscv_split_64bit_move_p ( SET_DEST ( set ) , SET_SRC ( set ) ) ) might_split_p = false ; } return riscv_address_insns ( XEXP ( mem , 0 ) , mode , might_split_p ) ; } </s>

Return the number of instructions needed to implement INSN , given that it loads from or stores to MEM .


<s> unsigned RISCVInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { default : { return get ( Opcode ) . getSize ( ) ; } case TargetOpcode :: EH_LABEL : case TargetOpcode :: IMPLICIT_DEF : case TargetOpcode :: KILL : case TargetOpcode :: DBG_VALUE : return 0 ; case RISCV :: PseudoCALL : case RISCV :: PseudoTAIL : case RISCV :: PseudoLLA : case RISCV :: PseudoLA : return 8 ; case TargetOpcode :: INLINEASM : case TargetOpcode :: INLINEASM_BR : { const MachineFunction & MF = * MI . getParent ( ) -> getParent ( ) ; const auto & TM = static_cast < const RISCVTargetMachine & > ( MF . getTarget ( ) ) ; return getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>

Returns the size in bytes of the specified MachineInstr , or ~0U when this function is not implemented by a target .

RISCV RISCV 0 RISCV::PseudoCALL RISCV::PseudoTAIL RISCV::PseudoLLA RISCV::PseudoLA 8 RISCV 0


<s> static void riscv_expand_op ( enum rtx_code code , machine_mode mode , rtx op0 , rtx op1 , rtx op2 ) { if ( can_create_pseudo_p ( ) ) { rtx result ; if ( GET_RTX_CLASS ( code ) == RTX_UNARY ) result = expand_simple_unop ( mode , code , op1 , NULL_RTX , false ) ; else result = expand_simple_binop ( mode , code , op1 , op2 , NULL_RTX , false , OPTAB_DIRECT ) ; riscv_emit_move ( op0 , result ) ; } else { rtx pat ; if ( GET_RTX_CLASS ( code ) == RTX_UNARY ) pat = gen_rtx_fmt_e ( code , mode , op1 ) ; else pat = gen_rtx_fmt_ee ( code , mode , op1 , op2 ) ; emit_insn ( gen_rtx_SET ( op0 , pat ) ) ; } } </s>

Helper function to operation for rtx_code CODE .


<s> bool RISCVAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , const char * ExtraCode , raw_ostream & OS ) { if ( ! AsmPrinter :: PrintAsmOperand ( MI , OpNo , ExtraCode , OS ) ) return false ; if ( ! ExtraCode ) { const MachineOperand & MO = MI -> getOperand ( OpNo ) ; switch ( MO . getType ( ) ) { case MachineOperand :: MO_Immediate : OS << MO . getImm ( ) ; return false ; case MachineOperand :: MO_Register : OS << RISCVInstPrinter :: getRegisterName ( MO . getReg ( ) ) ; return false ; default : break ; } } return true ; } </s>

PrintAsmOperand - Print out an operand for an inline asm expression .


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

This method must be overriden to eliminate abstract frame indices from instructions which may use them .


<s> bool convertSetCCLogicToBitwiseLogic ( EVT VT ) const override { return VT . isScalarInteger ( ) ; } </s>

Use bitwise logic to make pairs of compares more efficient .


<s> static unsigned int riscv_function_arg_boundary ( enum machine_mode mode , const_tree type ) { unsigned int alignment ; if ( type && ! AGGREGATE_TYPE_P ( type ) ) alignment = TYPE_ALIGN ( TYPE_MAIN_VARIANT ( type ) ) ; else alignment = type ? TYPE_ALIGN ( type ) : GET_MODE_ALIGNMENT ( mode ) ; return MIN ( STACK_BOUNDARY , MAX ( PARM_BOUNDARY , alignment ) ) ; } </s>

Implement TARGET_FUNCTION_ARG_BOUNDARY . Every parameter gets at least PARM_BOUNDARY bits of alignment , but will be given anything up to STACK_BOUNDARY bits if the type requires it .


<s> static bool riscv_legitimate_address_p ( machine_mode mode , rtx x , bool strict_p ) { struct riscv_address_info addr ; return riscv_classify_address ( & addr , x , mode , strict_p ) ; } </s>


<s> BitVector RISCVRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { const RISCVFrameLowering * TFI = getFrameLowering ( MF ) ; BitVector Reserved ( getNumRegs ( ) ) ; for ( size_t Reg = 0 ; Reg < getNumRegs ( ) ; Reg ++ ) { if ( MF . getSubtarget < RISCVSubtarget > ( ) . isRegisterReservedByUser ( Reg ) ) markSuperRegs ( Reserved , Reg ) ; } markSuperRegs ( Reserved , RISCV :: X0 ) ; markSuperRegs ( Reserved , RISCV :: X2 ) ; markSuperRegs ( Reserved , RISCV :: X3 ) ; markSuperRegs ( Reserved , RISCV :: X4 ) ; if ( TFI -> hasFP ( MF ) ) markSuperRegs ( Reserved , RISCV :: X8 ) ; if ( TFI -> hasBP ( MF ) ) markSuperRegs ( Reserved , RISCVABI :: getBPReg ( ) ) ; markSuperRegs ( Reserved , RISCV :: VL ) ; markSuperRegs ( Reserved , RISCV :: VTYPE ) ; assert ( checkAllSuperRegsMarked ( Reserved ) ) ; return Reserved ; } </s>

getReservedRegs - Returns a bitset indexed by physical register number indicating if a register is a special register that has particular uses and should be considered unavailable at all times , e.g .


<s> static void riscv_emit_float_compare ( enum rtx_code * code , rtx * op0 , rtx * op1 ) { rtx tmp0 , tmp1 , cmp_op0 = * op0 , cmp_op1 = * op1 ; enum rtx_code fp_code = * code ; * code = NE ; switch ( fp_code ) { case UNORDERED : * code = EQ ; case ORDERED : tmp0 = riscv_force_binary ( word_mode , EQ , cmp_op0 , cmp_op0 ) ; tmp1 = riscv_force_binary ( word_mode , EQ , cmp_op1 , cmp_op1 ) ; * op0 = riscv_force_binary ( word_mode , AND , tmp0 , tmp1 ) ; * op1 = const0_rtx ; break ; case UNEQ : * code = EQ ; tmp0 = riscv_force_binary ( word_mode , EQ , cmp_op0 , cmp_op0 ) ; tmp1 = riscv_force_binary ( word_mode , EQ , cmp_op1 , cmp_op1 ) ; * op0 = riscv_force_binary ( word_mode , AND , tmp0 , tmp1 ) ; * op1 = riscv_force_binary ( word_mode , EQ , cmp_op0 , cmp_op1 ) ; break ; case CODE : \ * code = EQ ; \ * op0 = gen_reg_rtx ( word_mode ) ; \ if ( GET_MODE ( cmp_op0 ) == SFmode && TARGET_64BIT ) \ emit_insn ( gen_f ## CMP ## _quietsfdi4 ( * op0 , cmp_op0 , cmp_op1 ) ) ; \ else if ( GET_MODE ( cmp_op0 ) == SFmode ) \ emit_insn ( gen_f ## CMP ## _quietsfsi4 ( * op0 , cmp_op0 , cmp_op1 ) ) ; \ else if ( GET_MODE ( cmp_op0 ) == DFmode && TARGET_64BIT ) \ emit_insn ( gen_f ## CMP ## _quietdfdi4 ( * op0 , cmp_op0 , cmp_op1 ) ) ; \ else if ( GET_MODE ( cmp_op0 ) == DFmode ) \ emit_insn ( gen_f ## CMP ## _quietdfsi4 ( * op0 , cmp_op0 , cmp_op1 ) ) ; \ else \ gcc_unreachable ( ) ; \ * op1 = const0_rtx ; \ break ; case UNLT : std :: swap ( cmp_op0 , cmp_op1 ) ; gcc_fallthrough ( ) ; UNORDERED_COMPARISON ( UNGT , le ) case UNLE : std :: swap ( cmp_op0 , cmp_op1 ) ; gcc_fallthrough ( ) ; UNORDERED_COMPARISON ( UNGE , lt ) case NE : fp_code = EQ ; * code = EQ ; case EQ : case LE : case LT : case GE : case GT : * op0 = riscv_force_binary ( word_mode , fp_code , cmp_op0 , cmp_op1 ) ; * op1 = const0_rtx ; break ; case LTGT : tmp0 = riscv_force_binary ( word_mode , LT , cmp_op0 , cmp_op1 ) ; tmp1 = riscv_force_binary ( word_mode , GT , cmp_op0 , cmp_op1 ) ; * op0 = riscv_force_binary ( word_mode , IOR , tmp0 , tmp1 ) ; * op1 = const0_rtx ; break ; default : gcc_unreachable ( ) ; } } </s>

Like riscv_emit_int_compare , but for floating-point comparisons .


<s>
static
const
struct
riscv_tune_info
*
riscv_parse_tune
(
const
char
*
tune_string
)
{
const
riscv_cpu_info
*
cpu
=
riscv_find_cpu
(
tune_string
)
;
if
(
cpu
)
tune_string
=
cpu
->
tune
;
for
(
unsigned
i
=
0
;
i
<
ARRAY_SIZE
(
riscv_tune_info_table
)
;
i
++
)
if
(
strcmp
(
riscv_tune_info_table
[
i
]
.
name
,
tune_string
)
==
0
)
return
riscv_tune_info_table
+
i
;
error
(
"unknown cpu %qs for %<-mtune%>"
,
tune_string
)
;
return
riscv_tune_info_table
;
}
</s>

Return the riscv_tune_info entry for the given name string .


"emitPrologue doesn't support framepointer-less functions"

emitProlog/emitEpilog - These methods insert prolog and epilog code into the function .


<s> bool apply_tail_policy_p ( ) const override { return false ; } </s>

We choose to apply tail policy operand by default since most of the intrinsics has tail policy operand .


<s> static unsigned int riscv_hard_regno_nregs ( unsigned int regno , machine_mode mode ) { if ( riscv_v_ext_vector_mode_p ( mode ) ) { if ( maybe_lt ( GET_MODE_SIZE ( mode ) , UNITS_PER_V_REG ) ) return 1 ; return exact_div ( GET_MODE_SIZE ( mode ) , UNITS_PER_V_REG ) . to_constant ( ) ; } if ( regno == VTYPE_REGNUM || regno == VL_REGNUM ) return 1 ; if ( V_REG_P ( regno ) ) return 1 ; if ( FP_REG_P ( regno ) ) return ( GET_MODE_SIZE ( mode ) . to_constant ( ) + UNITS_PER_FP_REG - 1 ) / UNITS_PER_FP_REG ; return ( GET_MODE_SIZE ( mode ) . to_constant ( ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; } </s>


<s> void RISCVFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; if ( hasFP ( MF ) ) { SavedRegs . set ( RISCV :: X1 ) ; SavedRegs . set ( RISCV :: X8 ) ; } if ( hasBP ( MF ) ) SavedRegs . set ( RISCVABI :: getBPReg ( ) ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; if ( MF . getFunction ( ) . hasFnAttribute ( "interrupt" ) && MFI . hasCalls ( ) ) { static const MCPhysReg CSRegs [ ] = { RISCV :: X1 , RISCV :: X5 , RISCV :: X6 , RISCV :: X7 , RISCV :: X10 , RISCV :: X11 , RISCV :: X12 , RISCV :: X13 , RISCV :: X14 , RISCV :: X15 , RISCV :: X16 , RISCV :: X17 , RISCV :: X28 , RISCV :: X29 , RISCV :: X30 , RISCV :: X31 , 0 } ; for ( unsigned i = 0 ; CSRegs [ i ] ; ++ i ) SavedRegs . set ( CSRegs [ i ] ) ; if ( MF . getSubtarget < RISCVSubtarget > ( ) . hasStdExtD ( ) || MF . getSubtarget < RISCVSubtarget > ( ) . hasStdExtF ( ) ) { const MCPhysReg * Regs = MF . getRegInfo ( ) . getCalleeSavedRegs ( ) ; for ( unsigned i = 0 ; Regs [ i ] ; ++ i ) if ( RISCV :: FPR32RegClass . contains ( Regs [ i ] ) || RISCV :: FPR64RegClass . contains ( Regs [ i ] ) ) SavedRegs . set ( Regs [ i ] ) ; } } } </s>

This method determines which of the registers reported by TargetRegisterInfo : :getCalleeSavedRegs ( ) should actually get saved .


<s> static bool riscv_memmodel_needs_amo_acquire ( enum memmodel model ) { switch ( model ) { case MEMMODEL_ACQ_REL : case MEMMODEL_SEQ_CST : case MEMMODEL_SYNC_SEQ_CST : case MEMMODEL_ACQUIRE : case MEMMODEL_CONSUME : case MEMMODEL_SYNC_ACQUIRE : return true ; case MEMMODEL_RELEASE : case MEMMODEL_SYNC_RELEASE : case MEMMODEL_RELAXED : return false ; default : gcc_unreachable ( ) ; } } </s>

Return true if the .AQ suffix should be added to an AMO to implement the acquire portion of memory model MODEL .


<s> bool riscv_epilogue_uses ( unsigned int regno ) { if ( regno == RETURN_ADDR_REGNUM ) return true ; if ( epilogue_completed && cfun -> machine -> interrupt_handler_p ) { if ( df_regs_ever_live_p ( regno ) || ( ! crtl -> is_leaf && call_used_regs [ regno ] ) ) return true ; } return false ; } </s>


<s>
void
RISCVInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MBBI
,
const
DebugLoc
&
DL
,
unsigned
DstReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
if
(
RISCV
::
GPRRegClass
.
contains
(
DstReg
,
SrcReg
)
)
{
BuildMI
(
MBB
,
MBBI
,
DL
,
get
(
RISCV
::
ADDI
)
,
DstReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addImm
(
0
)
;
return
;
}
unsigned
Opc
;
if
(
RISCV
::
FPR32RegClass
.
contains
(
DstReg
,
SrcReg
)
)
Opc
=
RISCV
::
FSGNJ_S
;
else
if
(
RISCV
::
FPR64RegClass
.
contains
(
DstReg
,
SrcReg
)
)
Opc
=
RISCV
::
FSGNJ_D
;
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
get
(
Opc
)
,
DstReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
</s>


<s> RISCVTargetLowering :: ConstraintType RISCVTargetLowering :: getConstraintType ( StringRef Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'f' : case 'v' : return C_RegisterClass ; case 'I' : case 'J' : case 'K' : return C_Immediate ; case 'A' : return C_Memory ; case 'S' : return C_Other ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

Given a constraint letter , return the type of constraint for this target .


<s> bool riscv_can_use_return_insn ( void ) { return reload_completed && cfun -> machine -> frame . total_size == 0 ; } </s>

Return nonzero if this function is known to have a null epilogue . This allows the optimizer to omit jumps to jumps if no stack was created .


<s> inline rtx function_expander :: expand ( ) { return base -> expand ( * this ) ; } </s>


<s> unsigned RISCVInstrInfo :: isLoadFromStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { 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 : break ; } if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } return 0 ; } </s>

isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot , return the virtual or physical register number of the destination along with the FrameIndex of the loaded stack slot .


<s>
void
RISCVInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MBBI
,
const
DebugLoc
&
DL
,
unsigned
DstReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
assert
(
RISCV
::
GPRRegClass
.
contains
(
DstReg
,
SrcReg
)
&&
"Impossible reg-to-reg copy"
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
get
(
RISCV
::
ADDI
)
,
DstReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addImm
(
0
)
;
}
</s>

RISCV
RISCV
RISCV::GPRRegClass
"Impossible reg-to-reg copy"
RISCV::ADDI
0


<s> void RISCVAsmPrinter :: emitBasicBlockEnd ( const MachineBasicBlock & MBB ) { auto * RVFI = MF -> getInfo < RISCVMachineFunctionInfo > ( ) ; RISCVTargetStreamer & RTS = static_cast < RISCVTargetStreamer & > ( * OutStreamer -> getTargetStreamer ( ) ) ; if ( RVFI -> isHwlpBasicBlock ( & MBB ) ) { RTS . emitDirectiveOptionPop ( ) ; } AsmPrinter :: emitBasicBlockEnd ( MBB ) ; } </s>

Targets can override this to emit stuff at the end of a basic block .


<s> const MCExpr * getSubExpr ( ) const { return Expr ; } </s>

getSubExpr - Get the child of this expression .


<s> static rtx riscv_unspec_address_offset ( rtx base , rtx offset , enum riscv_symbol_type symbol_type ) { base = gen_rtx_UNSPEC ( Pmode , gen_rtvec ( 1 , base ) , UNSPEC_ADDRESS_FIRST + symbol_type ) ; if ( offset != const0_rtx ) base = gen_rtx_PLUS ( Pmode , base , offset ) ; return gen_rtx_CONST ( Pmode , base ) ; } </s>

Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE , then add CONST_INT OFFSET to the result .


<s>
StringRef
getPassName
(
)
const
override
{
return
"RISCV gather/scatter lowering"
;
}
</s>

getPassName - Return a nice clean name for a pass .


<s> bool RISCVTargetLowering :: isZExtFree ( SDValue Val , EVT VT2 ) const { if ( auto * LD = dyn_cast < LoadSDNode > ( Val ) ) { EVT MemVT = LD -> getMemoryVT ( ) ; if ( ( MemVT == MVT :: i8 || MemVT == MVT :: i16 || ( Subtarget . is64Bit ( ) && MemVT == MVT :: i32 ) ) && ( LD -> getExtensionType ( ) == ISD :: NON_EXTLOAD || LD -> getExtensionType ( ) == ISD :: ZEXTLOAD ) ) return true ; } return TargetLowering :: isZExtFree ( Val , VT2 ) ; } </s>

Return true if zero-extending the specific node Val to type VT2 is free ( either because it 's implicitly zero-extended such as ARM ldrb / ldrh or because it 's folded such as X86 zero-extending loads ) .


<s> bool RISCVTargetLowering :: CanLowerReturn ( CallingConv :: ID CallConv , MachineFunction & MF , bool IsVarArg , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) const { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , IsVarArg , MF , RVLocs , Context ) ; Optional < unsigned > FirstMaskArgument ; if ( Subtarget . hasStdExtV ( ) ) FirstMaskArgument = preAssignMask ( Outs ) ; for ( unsigned i = 0 , e = Outs . size ( ) ; i != e ; ++ i ) { MVT VT = Outs [ i ] . VT ; ISD :: ArgFlagsTy ArgFlags = Outs [ i ] . Flags ; RISCVABI :: ABI ABI = MF . getSubtarget < RISCVSubtarget > ( ) . getTargetABI ( ) ; if ( CC_RISCV ( MF . getDataLayout ( ) , ABI , i , VT , VT , CCValAssign :: Full , ArgFlags , CCInfo , true , true , nullptr , * this , FirstMaskArgument ) ) return false ; } return true ; } </s>

This hook should be implemented to check whether the return values described by the Outs array can fit into the return registers .

RISCV RISCV ISD::OutputArg 16 0 ISD::ArgFlagsTy RISCVABI::ABI RISCV RISCV


<s> void pass_vsetvl :: transfer_before ( vector_insn_info & info , insn_info * insn ) const { if ( ! has_vtype_op ( insn -> rtl ( ) ) ) return ; const vector_insn_info require = m_vector_manager -> vector_insn_infos [ insn -> uid ( ) ] ; if ( info . valid_p ( ) && ! need_vsetvl ( require , info ) ) return ; info = require ; } </s>

Given an incoming state reaching INSN , modifies that state so that it is minimally compatible with INSN . The resulting state is guaranteed to be semantically legal for INSN , but may not be the state requested by INSN .


<s> static rtx_insn * riscv_call_tls_get_addr ( rtx sym , rtx result ) { rtx a0 = gen_rtx_REG ( Pmode , GP_ARG_FIRST ) , func ; rtx_insn * insn ; if ( ! riscv_tls_symbol ) riscv_tls_symbol = init_one_libfunc ( "__tls_get_addr" ) ; func = gen_rtx_MEM ( FUNCTION_MODE , riscv_tls_symbol ) ; start_sequence ( ) ; emit_insn ( riscv_got_load_tls_gd ( a0 , sym ) ) ; insn = emit_call_insn ( gen_call_value ( result , func , const0_rtx , NULL ) ) ; RTL_CONST_CALL_P ( insn ) = 1 ; use_reg ( & CALL_INSN_FUNCTION_USAGE ( insn ) , a0 ) ; insn = get_insns ( ) ; end_sequence ( ) ; return insn ; } </s>

Return an instruction sequence that calls __tls_get_addr . SYM is the TLS symbol we are referencing and TYPE is the symbol type to use ( either global dynamic or local dynamic ) . RESULT is an RTX for the return value location .


<s> enum riscv_symbol_type riscv_classify_symbolic_expression ( rtx x ) { rtx offset ; split_const ( x , & x , & offset ) ; if ( UNSPEC_ADDRESS_P ( x ) ) return UNSPEC_ADDRESS_TYPE ( x ) ; return riscv_classify_symbol ( x ) ; } </s>

Classify the base of symbolic expression X .


"getIntImmCost can only estimate cost of materialising integers"

Calculate the cost of materializing a 64-bit value .


<s>
void
RISCVAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
,
const
MCSubtargetInfo
*
STI
)
const
{
MCContext
&
Ctx
=
Asm
.
getContext
(
)
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
if
(
!
Value
)
return
;
Value
=
adjustFixupValue
(
Fixup
,
Value
,
Ctx
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
unsigned
NumBytes
=
alignTo
(
Info
.
TargetSize
+
Info
.
TargetOffset
,
8
)
/
8
;
assert
(
Offset
+
NumBytes
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
!=
NumBytes
;
++
i
)
{
Data
[
Offset
+
i
]
|=
uint8_t
(
(
Value
>>
(
i
*
8
)
)
&
0xff
)
;
}
}
</s>

Apply the Value for given Fixup into the provided data fragment , at the offset specified by the fixup and following the fixup kind as appropriate .


<s> bool RISCVInstrInfo :: expandPostRAPseudo ( MachineInstr & MI ) const { switch ( MI . getOpcode ( ) ) { default : return false ; } } </s>

This function is called for all pseudo instructions that remain after register allocation .


"Not all fixup kinds added to Infos array"


<s> inline bool registered_function_hasher :: equal ( value_type value , const compare_type & key ) { return value -> instance == key ; } </s>


<s>
StringRef
RISCVMCExpr
::
getVariantKindName
(
VariantKind
Kind
)
{
switch
(
Kind
)
{
default
:
llvm_unreachable
(
"Invalid ELF symbol kind"
)
;
case
VK_RISCV_LO
:
return
"lo"
;
case
VK_RISCV_HI
:
return
"hi"
;
case
VK_RISCV_PCREL_HI
:
return
"pcrel_hi"
;
}
}
</s>

Convert the variant kind into an ELF-appropriate modifier ( e.g .

RISCV
RISCV
"Invalid ELF symbol kind"
RISCV
"lo"
RISCV
"hi"
RISCV
"pcrel_hi"


<s> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( ( RISCVISD :: NodeType ) Opcode ) { case RISCVISD :: FIRST_NUMBER : break ; case RISCVISD :: RET_FLAG : return "RISCVISD::RET_FLAG" ; case RISCVISD :: URET_FLAG : return "RISCVISD::URET_FLAG" ; case RISCVISD :: SRET_FLAG : return "RISCVISD::SRET_FLAG" ; case RISCVISD :: MRET_FLAG : return "RISCVISD::MRET_FLAG" ; case RISCVISD :: CALL : return "RISCVISD::CALL" ; case RISCVISD :: SELECT_CC : return "RISCVISD::SELECT_CC" ; case RISCVISD :: BuildPairF64 : return "RISCVISD::BuildPairF64" ; case RISCVISD :: SplitF64 : return "RISCVISD::SplitF64" ; case RISCVISD :: TAIL : return "RISCVISD::TAIL" ; case RISCVISD :: SLLW : return "RISCVISD::SLLW" ; case RISCVISD :: SRAW : return "RISCVISD::SRAW" ; case RISCVISD :: SRLW : return "RISCVISD::SRLW" ; case RISCVISD :: DIVW : return "RISCVISD::DIVW" ; case RISCVISD :: DIVUW : return "RISCVISD::DIVUW" ; case RISCVISD :: REMUW : return "RISCVISD::REMUW" ; case RISCVISD :: FMV_W_X_RV64 : return "RISCVISD::FMV_W_X_RV64" ; case RISCVISD :: FMV_X_ANYEXTW_RV64 : return "RISCVISD::FMV_X_ANYEXTW_RV64" ; } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific


<s> static bool riscv_return_in_memory ( const_tree type , const_tree fndecl ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS args ; cumulative_args_t cum = pack_cumulative_args ( & args ) ; memset ( & args , 0 , sizeof args ) ; function_arg_info arg ( const_cast < tree > ( type ) , true ) ; return riscv_pass_by_reference ( cum , arg ) ; } </s>


<s> RISCVProcFamilyEnum getProcFamily ( ) const { return RISCVProcFamily ; } </s>


Return the expected cost of materialization for the given integer immediate of the specified type for a given instruction .


<s> static rtx riscv_add_offset ( rtx temp , rtx reg , HOST_WIDE_INT offset ) { if ( ! SMALL_OPERAND ( offset ) ) { rtx high ; high = gen_int_mode ( CONST_HIGH_PART ( offset ) , Pmode ) ; offset = CONST_LOW_PART ( offset ) ; high = riscv_force_temporary ( temp , high , FALSE ) ; reg = riscv_force_temporary ( temp , gen_rtx_PLUS ( Pmode , high , reg ) , FALSE ) ; } return plus_constant ( Pmode , reg , offset ) ; } </s>

Return a legitimate address for REG + OFFSET . TEMP is as for riscv_force_temporary ; it is only needed when OFFSET is not a SMALL_OPERAND .


<s> static rtx get_vl ( rtx_insn * rinsn ) { if ( has_vl_op ( rinsn ) ) { extract_insn_cached ( rinsn ) ; return recog_data . operand [ get_attr_vl_op_idx ( rinsn ) ] ; } return SET_DEST ( XVECEXP ( PATTERN ( rinsn ) , 0 , 0 ) ) ; } </s>


"RegScavenger required for long branching"

"new block should be inserted for expanding unconditional branch"

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

Insert an unconditional indirect branch at the end of MBB to NewDestBB .


<s> int get_ta ( rtx ta ) { if ( INTVAL ( ta ) == TAIL_ANY ) return INVALID_ATTRIBUTE ; return INTVAL ( ta ) ; } </s>

Get ta according to operand [ tail_op_idx ] .


"There are no defined alternate asm variants"

Print the specified operand of MI , an INLINEASM instruction , using the specified assembler variant as an address .


<s> MCInst RISCVInstrInfo :: getNop ( ) const { if ( STI . getFeatureBits ( ) [ RISCV :: FeatureStdExtC ] ) return MCInstBuilder ( RISCV :: C_NOP ) ; return MCInstBuilder ( RISCV :: ADDI ) . addReg ( RISCV :: X0 ) . addReg ( RISCV :: X0 ) . addImm ( 0 ) ; } </s>

Return the noop instruction to use for a noop .


<s>
SDValue
RISCVTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
report_fatal_error
(
"unimplemented operand"
)
;
case
ISD
::
GlobalAddress
:
return
lowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
lowerBlockAddress
(
Op
,
DAG
)
;
case
ISD
::
ConstantPool
:
return
lowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
lowerGlobalTLSAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT
:
return
lowerSELECT
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
lowerVASTART
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
lowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
return
lowerRETURNADDR
(
Op
,
DAG
)
;
case
ISD
::
SHL_PARTS
:
return
lowerShiftLeftParts
(
Op
,
DAG
)
;
case
ISD
::
SRA_PARTS
:
return
lowerShiftRightParts
(
Op
,
DAG
,
true
)
;
case
ISD
::
SRL_PARTS
:
return
lowerShiftRightParts
(
Op
,
DAG
,
false
)
;
case
ISD
::
BITCAST
:
{
assert
(
Subtarget
.
is64Bit
(
)
&&
Subtarget
.
hasStdExtF
(
)
&&
"Unexpected custom legalisation"
)
;
SDLoc
DL
(
Op
)
;
SDValue
Op0
=
Op
.
getOperand
(
0
)
;
if
(
Op
.
getValueType
(
)
!=
MVT
::
f32
||
Op0
.
getValueType
(
)
!=
MVT
::
i32
)
return
SDValue
(
)
;
SDValue
NewOp0
=
DAG
.
getNode
(
ISD
::
ANY_EXTEND
,
DL
,
MVT
::
i64
,
Op0
)
;
SDValue
FPConv
=
DAG
.
getNode
(
RISCVISD
::
FMV_W_X_RV64
,
DL
,
MVT
::
f32
,
NewOp0
)
;
return
FPConv
;
}
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
LowerINTRINSIC_WO_CHAIN
(
Op
,
DAG
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .


<s> StackOffset RISCVFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , Register & FrameReg ) const { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterInfo * RI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; const auto & CSI = getNonLibcallCSI ( MFI . getCalleeSavedInfo ( ) ) ; int MinCSFI = 0 ; int MaxCSFI = - 1 ; int Offset = MFI . getObjectOffset ( FI ) - getOffsetOfLocalArea ( ) + MFI . getOffsetAdjustment ( ) ; uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount ( MF ) ; if ( CSI . size ( ) ) { MinCSFI = CSI [ 0 ] . getFrameIdx ( ) ; MaxCSFI = CSI [ CSI . size ( ) - 1 ] . getFrameIdx ( ) ; } if ( FI >= MinCSFI && FI <= MaxCSFI ) { FrameReg = RISCV :: X2 ; if ( FirstSPAdjustAmount ) Offset += FirstSPAdjustAmount ; else Offset += MFI . getStackSize ( ) ; } else if ( RI -> needsStackRealignment ( MF ) && ! MFI . isFixedObjectIndex ( FI ) ) { if ( hasBP ( MF ) ) FrameReg = RISCVABI :: getBPReg ( ) ; else FrameReg = RISCV :: X2 ; Offset += MFI . getStackSize ( ) ; if ( FI < 0 ) Offset += RVFI -> getLibCallStackSize ( ) ; } else { FrameReg = RI -> getFrameRegister ( MF ) ; if ( hasFP ( MF ) ) { Offset += RVFI -> getVarArgsSaveSize ( ) ; if ( FI >= 0 ) Offset -= RVFI -> getLibCallStackSize ( ) ; } else { Offset += MFI . getStackSize ( ) ; if ( FI < 0 ) Offset += RVFI -> getLibCallStackSize ( ) ; } } return StackOffset :: getFixed ( Offset ) ; } </s>

getFrameIndexReference - This method should return the base register and offset used to reference a frame index location .


<s> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { case RISCVISD :: NODE : \ return "RISCVISD::" # NODE ; switch ( ( RISCVISD :: NodeType ) Opcode ) { case RISCVISD :: FIRST_NUMBER : break ; NODE_NAME_CASE ( RET_FLAG ) NODE_NAME_CASE ( URET_FLAG ) NODE_NAME_CASE ( SRET_FLAG ) NODE_NAME_CASE ( MRET_FLAG ) NODE_NAME_CASE ( CALL ) NODE_NAME_CASE ( SELECT_CC ) NODE_NAME_CASE ( BuildPairF64 ) NODE_NAME_CASE ( SplitF64 ) NODE_NAME_CASE ( TAIL ) NODE_NAME_CASE ( SLLW ) NODE_NAME_CASE ( SRAW ) NODE_NAME_CASE ( SRLW ) NODE_NAME_CASE ( DIVW ) NODE_NAME_CASE ( DIVUW ) NODE_NAME_CASE ( REMUW ) NODE_NAME_CASE ( ROLW ) NODE_NAME_CASE ( RORW ) NODE_NAME_CASE ( FSLW ) NODE_NAME_CASE ( FSRW ) NODE_NAME_CASE ( FMV_H_X ) NODE_NAME_CASE ( FMV_X_ANYEXTH ) NODE_NAME_CASE ( FMV_W_X_RV64 ) NODE_NAME_CASE ( FMV_X_ANYEXTW_RV64 ) NODE_NAME_CASE ( READ_CYCLE_WIDE ) NODE_NAME_CASE ( GREVI ) NODE_NAME_CASE ( GREVIW ) NODE_NAME_CASE ( GORCI ) NODE_NAME_CASE ( GORCIW ) NODE_NAME_CASE ( VMV_X_S ) NODE_NAME_CASE ( SPLAT_VECTOR_I64 ) NODE_NAME_CASE ( READ_VLENB ) NODE_NAME_CASE ( TRUNCATE_VECTOR ) NODE_NAME_CASE ( VLEFF ) NODE_NAME_CASE ( VLEFF_MASK ) NODE_NAME_CASE ( VLSEGFF ) NODE_NAME_CASE ( VLSEGFF_MASK ) NODE_NAME_CASE ( READ_VL ) NODE_NAME_CASE ( VSLIDEUP ) NODE_NAME_CASE ( VSLIDEDOWN ) NODE_NAME_CASE ( VID ) } return nullptr ; } </s>

RISCV RISCV RISCVISD::NODE "RISCVISD::" RISCVISD::NodeType RISCVISD::FIRST_NUMBER


<s> void RISCVAsmBackend :: applyFixup ( const MCFixup & Fixup , MutableArrayRef < char > Data , uint64_t Value , bool IsPCRel , MCContext & Ctx ) const { return ; } </s>


<s> void RISCVFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; if ( hasFP ( MF ) ) { SavedRegs . set ( RISCV :: X1 ) ; SavedRegs . set ( RISCV :: X8 ) ; } MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; if ( MF . getFunction ( ) . hasFnAttribute ( "interrupt" ) && MFI . hasCalls ( ) ) { static const MCPhysReg CSRegs [ ] = { RISCV :: X1 , RISCV :: X5 , RISCV :: X6 , RISCV :: X7 , RISCV :: X10 , RISCV :: X11 , RISCV :: X12 , RISCV :: X13 , RISCV :: X14 , RISCV :: X15 , RISCV :: X16 , RISCV :: X17 , RISCV :: X28 , RISCV :: X29 , RISCV :: X30 , RISCV :: X31 , 0 } ; for ( unsigned i = 0 ; CSRegs [ i ] ; ++ i ) SavedRegs . set ( CSRegs [ i ] ) ; if ( MF . getSubtarget < RISCVSubtarget > ( ) . hasStdExtD ( ) || MF . getSubtarget < RISCVSubtarget > ( ) . hasStdExtF ( ) ) { const MCPhysReg * Regs = MF . getRegInfo ( ) . getCalleeSavedRegs ( ) ; for ( unsigned i = 0 ; Regs [ i ] ; ++ i ) if ( RISCV :: FPR32RegClass . contains ( Regs [ i ] ) || RISCV :: FPR64RegClass . contains ( Regs [ i ] ) ) SavedRegs . set ( Regs [ i ] ) ; } } } </s>

This method determines which of the registers reported by TargetRegisterInfo : :getCalleeSavedRegs ( ) should actually get saved .


<s> void add_input_operand ( rtx x , machine_mode mode ) { create_input_operand ( & m_ops [ m_opno ++ ] , x , mode ) ; gcc_assert ( m_opno <= MAX_OPERANDS ) ; } </s>

Create op and add it into M_OPS and increase OPNO .


<s> void RISCVFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; Align StackAlign = getStackAlign ( ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; } </s>

Determine the frame layout but do not update the machine function .


<s> outliner :: InstrType RISCVInstrInfo :: getOutliningType ( MachineBasicBlock :: iterator & MBBI , unsigned Flags ) const { MachineInstr & MI = * MBBI ; MachineBasicBlock * MBB = MI . getParent ( ) ; const TargetRegisterInfo * TRI = MBB -> getParent ( ) -> getSubtarget ( ) . getRegisterInfo ( ) ; if ( MI . isPosition ( ) ) { if ( MI . isCFIInstruction ( ) ) return outliner :: InstrType :: Invisible ; return outliner :: InstrType :: Illegal ; } if ( MI . isInlineAsm ( ) ) return outliner :: InstrType :: Illegal ; if ( MI . isTerminator ( ) && ! MBB -> succ_empty ( ) ) return outliner :: InstrType :: Illegal ; if ( MI . isReturn ( ) ) return outliner :: InstrType :: Illegal ; if ( MI . modifiesRegister ( RISCV :: X5 , TRI ) || MI . getDesc ( ) . hasImplicitDefOfPhysReg ( RISCV :: X5 ) ) return outliner :: InstrType :: Illegal ; for ( const auto & MO : MI . operands ( ) ) if ( MO . isMBB ( ) || MO . isBlockAddress ( ) || MO . isCPI ( ) ) return outliner :: InstrType :: Illegal ; if ( MI . isMetaInstruction ( ) ) return outliner :: InstrType :: Invisible ; return outliner :: InstrType :: Legal ; } </s>

Returns how or if MIT should be outlined .


"*** Found COPY instruction from VSETVL"

runOnMachineFunction - Emit the function body .


<s> static bool th_mempair_operand_p ( rtx mem , machine_mode mode ) { if ( ! MEM_SIZE_KNOWN_P ( mem ) ) return false ; gcc_assert ( mode == SImode || mode == DImode ) ; auto mem_sz = MEM_SIZE ( mem ) ; auto mode_sz = GET_MODE_SIZE ( mode ) ; if ( ! known_eq ( mem_sz , mode_sz ) ) return false ; machine_mode mem_mode = GET_MODE ( mem ) ; unsigned shamt = ( mem_mode == DImode ) ? 4 : 3 ; rtx base ; HOST_WIDE_INT offset ; split_plus ( XEXP ( mem , 0 ) , & base , & offset ) ; HOST_WIDE_INT imm2 = offset >> shamt ; if ( imm2 < 0 || imm2 >= 4 ) return false ; if ( ( imm2 << shamt ) != offset ) return false ; return true ; } </s>

Check if the given MEM can be used to define the address of a mempair instruction .


<s> bool RISCVCallLowering :: lowerCall ( MachineIRBuilder & MIRBuilder , CallLoweringInfo & Info ) const { return false ; } </s>

This hook must be implemented to lower the given call instruction , including argument and return value marshalling .


<s> static bool riscv_warn_func_return ( tree decl ) { return ! riscv_naked_function_p ( decl ) ; } </s>


<s> static rtx riscv_function_arg ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool named ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; struct riscv_arg_info info ; if ( mode == VOIDmode ) return NULL ; return riscv_get_arg_info ( & info , cum , mode , type , named , false ) ; } </s>


<s> bool RISCVTargetLowering :: allowsMisalignedMemoryAccesses ( EVT VT , unsigned AddrSpace = 0 , unsigned Align = 1 , MachineMemOperand :: Flags Flags = MachineMemOperand :: MONone , bool * Fast = nullptr ) const { if ( Subtarget . hasNonStdExtPulp ( ) ) { if ( Fast ) { * Fast = false ; } return true ; } return false ; } </s>

Returns true if the target allows unaligned memory accesses of the specified type .


<s> void RISCVFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; SavedRegs . set ( RISCV :: X1 ) ; SavedRegs . set ( RISCV :: X8 ) ; } </s>


<s> rtx function_expander :: use_scalar_move_insn ( insn_code icode ) { machine_mode mode = TYPE_MODE ( TREE_TYPE ( exp ) ) ; int arg_offset = 0 ; add_scalar_move_mask_operand ( mask_mode ( ) ) ; if ( use_real_merge_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_vundef_operand ( mode ) ; for ( int argno = arg_offset ; argno < call_expr_nargs ( exp ) ; argno ++ ) add_input_operand ( argno ) ; add_input_operand ( Pmode , get_tail_policy_for_pred ( pred ) ) ; add_input_operand ( Pmode , get_mask_policy_for_pred ( pred ) ) ; add_input_operand ( Pmode , get_avl_type_rtx ( avl_type :: NONVLMAX ) ) ; return generate_insn ( icode ) ; } </s>

Implement the call using instruction ICODE , with a 1:1 mapping between arguments and input operands .


<s> bool RISCVRemoveRedundancyVSETVL :: runOnMachineFunction ( MachineFunction & MF ) { collectRedundancyVSETVLIInMF ( MF ) ; return removeRedundancy ( ) ; } </s>


<s> bool RISCVTargetLowering :: allowsMisalignedMemoryAccesses ( EVT VT , unsigned AddrSpace , Align Alignment , MachineMemOperand :: Flags Flags , bool * Fast ) const { if ( ! VT . isVector ( ) ) return false ; EVT ElemVT = VT . getVectorElementType ( ) ; if ( Alignment >= ElemVT . getStoreSize ( ) ) { if ( Fast ) * Fast = true ; return true ; } return false ; } </s>


<s> static int riscv_split_integer_cost ( HOST_WIDE_INT val ) { int cost ; unsigned HOST_WIDE_INT loval = sext_hwi ( val , 32 ) ; unsigned HOST_WIDE_INT hival = sext_hwi ( ( val - loval ) >> 32 , 32 ) ; struct riscv_integer_op codes [ RISCV_MAX_INTEGER_OPS ] ; cost = 2 + riscv_build_integer ( codes , loval , VOIDmode ) ; if ( loval != hival ) cost += riscv_build_integer ( codes , hival , VOIDmode ) ; return cost ; } </s>

Return the cost of constructing VAL in the event that a scratch register is available .


<s> static bool th_mempair_check_consecutive_mems ( machine_mode mode , rtx * mem1 , rtx * mem2 , bool * reversed ) { rtx base1 , base2 , offset1 , offset2 ; extract_base_offset_in_addr ( * mem1 , & base1 , & offset1 ) ; extract_base_offset_in_addr ( * mem2 , & base2 , & offset2 ) ; if ( ! base1 || ! base2 ) return false ; if ( rtx_equal_p ( base1 , base2 ) ) { auto size = GET_MODE_SIZE ( mode ) ; if ( known_eq ( UINTVAL ( offset1 ) + size , UINTVAL ( offset2 ) ) ) { * reversed = false ; return true ; } if ( known_eq ( UINTVAL ( offset2 ) + size , UINTVAL ( offset1 ) ) ) { * reversed = true ; return true ; } return false ; } return false ; } </s>

Analyse if a pair of loads/stores MEM1 and MEM2 with given MODE are consecutive so they can be merged into a mempair instruction . RESERVED will be set to true , if a reversal of the accesses is required ( false otherwise ) . Returns true if the accesses can be merged ( even if reversing is necessary ) and false if not .


"Parsing feature error when emitTargetAttributes?"

Emit the build attributes that only depend on the hardware that we expect .


"The number of element should not be zero."

Target-specific splitting of values into parts that fit a register storing a legal type .


<s> static rtx riscv_frame_set ( rtx mem , rtx reg ) { rtx set = gen_rtx_SET ( mem , reg ) ; RTX_FRAME_RELATED_P ( set ) = 1 ; return set ; } </s>

Return a frame-related rtx that stores REG at MEM . REG must be a single register .


<s> EVT RISCVTargetLowering :: getSetCCResultType ( const DataLayout & DL , LLVMContext & Context , EVT VT ) const { if ( ! VT . isVector ( ) ) return getPointerTy ( DL ) ; if ( Subtarget . hasStdExtV ( ) && ( VT . isScalableVector ( ) || Subtarget . useRVVForFixedLengthVectors ( ) ) ) return EVT :: getVectorVT ( Context , MVT :: i1 , VT . getVectorElementCount ( ) ) ; return VT . changeVectorElementTypeToInteger ( ) ; } </s>

Return the value type to use for ISD : :SETCC .


<s> bool RISCVMCExpr :: evaluateAsConstant ( int64_t & Res ) const { MCValue Value ; if ( Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO || Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI || Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD || Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI || Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT ) return false ; if ( ! getSubExpr ( ) -> evaluateAsRelocatable ( Value , nullptr , nullptr ) ) return false ; if ( ! Value . isAbsolute ( ) ) return false ; Res = evaluateAsInt64 ( Value . getConstant ( ) ) ; return true ; } </s>

Evaluates the fixup as a constant value .

RISCV RISCV RISCV RISCV RISCV RISCV RISCV RISCV RISCV RISCV RISCV RISCV


"M-extension must be enabled to calculate the poly_int "

Expand mult operation with constant integer , multiplicand also used as a * temporary register .


<s> void RISCVELFTargetObjectFile :: getModuleMetadata ( Module & M ) { SmallVector < Module :: ModuleFlagEntry , 8 > ModuleFlags ; M . getModuleFlagsMetadata ( ModuleFlags ) ; for ( const auto & MFE : ModuleFlags ) { StringRef Key = MFE . Key -> getString ( ) ; if ( Key == "SmallDataLimit" ) { SSThreshold = mdconst :: extract < ConstantInt > ( MFE . Val ) -> getZExtValue ( ) ; break ; } } } </s>

Get the module-level metadata that the platform cares about .


<s> outliner :: OutlinedFunction RISCVInstrInfo :: getOutliningCandidateInfo ( std :: vector < outliner :: Candidate > & RepeatedSequenceLocs ) const { auto CannotInsertCall = [ ] ( outliner :: Candidate & C ) { const TargetRegisterInfo * TRI = C . getMF ( ) -> getSubtarget ( ) . getRegisterInfo ( ) ; C . initLRU ( * TRI ) ; LiveRegUnits LRU = C . LRU ; return ! LRU . available ( RISCV :: X5 ) ; } ; RepeatedSequenceLocs . erase ( std :: remove_if ( RepeatedSequenceLocs . begin ( ) , RepeatedSequenceLocs . end ( ) , CannotInsertCall ) , RepeatedSequenceLocs . end ( ) ) ; if ( RepeatedSequenceLocs . size ( ) < 2 ) return outliner :: OutlinedFunction ( ) ; unsigned SequenceSize = 0 ; auto I = RepeatedSequenceLocs [ 0 ] . front ( ) ; auto E = std :: next ( RepeatedSequenceLocs [ 0 ] . back ( ) ) ; for ( ; I != E ; ++ I ) SequenceSize += getInstSizeInBytes ( * I ) ; unsigned CallOverhead = 8 ; for ( auto & C : RepeatedSequenceLocs ) C . setCallInfo ( MachineOutlinerDefault , CallOverhead ) ; unsigned FrameOverhead = 4 ; if ( RepeatedSequenceLocs [ 0 ] . getMF ( ) -> getSubtarget ( ) . getFeatureBits ( ) [ RISCV :: FeatureStdExtC ] ) FrameOverhead = 2 ; return outliner :: OutlinedFunction ( RepeatedSequenceLocs , SequenceSize , FrameOverhead , MachineOutlinerDefault ) ; } </s>

Returns a outliner : :OutlinedFunction struct containing target-specific information for a set of outlining candidates .


<s> TargetTransformInfo RISCVTargetMachine :: getTargetTransformInfo ( const Function & F ) { return TargetTransformInfo ( RISCVTTIImpl ( this , F ) ) ; } </s>

Get a TargetTransformInfo implementation for the target .


<s> bool RISCVAsmParser :: processInstruction ( MCInst & Inst , SMLoc IDLoc , MCStreamer & Out ) { Inst . setLoc ( IDLoc ) ; switch ( Inst . getOpcode ( ) ) { default : break ; case RISCV :: PseudoLI : { unsigned Reg = Inst . getOperand ( 0 ) . getReg ( ) ; const MCOperand & Op1 = Inst . getOperand ( 1 ) ; if ( Op1 . isExpr ( ) ) { emitToStreamer ( Out , MCInstBuilder ( RISCV :: ADDI ) . addReg ( Reg ) . addReg ( RISCV :: X0 ) . addExpr ( Op1 . getExpr ( ) ) ) ; return false ; } int64_t Imm = Inst . getOperand ( 1 ) . getImm ( ) ; if ( ! isRV64 ( ) ) Imm = SignExtend64 < 32 > ( Imm ) ; emitLoadImm ( Reg , Imm , Out ) ; return false ; } case RISCV :: PseudoLLA : emitLoadLocalAddress ( Inst , IDLoc , Out ) ; return false ; case RISCV :: PseudoLA : emitLoadAddress ( Inst , IDLoc , Out ) ; return false ; } emitToStreamer ( Out , Inst ) ; return false ; } </s>

Process a single instruction and collect debug info anchors .


<s> unsigned RISCVInstrInfo :: isStoreToStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : return 0 ; case RISCV :: SB : case RISCV :: SH : case RISCV :: SW : case RISCV :: FSH : case RISCV :: FSW : case RISCV :: SD : case RISCV :: FSD : break ; } if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } return 0 ; } </s>

isStoreToStackSlot - If the specified machine instruction is a direct store to a stack slot , return the virtual or physical register number of the source reg along with the FrameIndex of the loaded stack slot .


<s> static bool riscv_tls_symbol_p ( const_rtx x ) { return SYMBOL_REF_P ( x ) && SYMBOL_REF_TLS_MODEL ( x ) != 0 ; } </s>

Return true if X is a thread-local symbol .


<s>
InstructionCost
RISCVTTIImpl
::
getArithmeticReductionCost
(
unsigned
Opcode
,
VectorType
*
VTy
,
Optional
<
FastMathFlags
>
FMF
,
TTI
::
TargetCostKind
CostKind
)
{
if
(
!
isa
<
FixedVectorType
>
(
VTy
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
if
(
VTy
->
getElementType
(
)
->
isIntegerTy
(
1
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
if
(
!
ST
->
useRVVForFixedLengthVectors
(
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
if
(
VTy
->
getScalarSizeInBits
(
)
>
ST
->
getMaxELENForFixedLengthVectors
(
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
int
ISD
=
TLI
->
InstructionOpcodeToISD
(
Opcode
)
;
assert
(
ISD
&&
"Invalid opcode"
)
;
if
(
ISD
!=
ISD
::
ADD
&&
ISD
!=
ISD
::
OR
&&
ISD
!=
ISD
::
XOR
&&
ISD
!=
ISD
::
AND
&&
ISD
!=
ISD
::
FADD
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
InstructionCost
BaseCost
=
2
;
unsigned
VL
=
cast
<
FixedVectorType
>
(
VTy
)
->
getNumElements
(
)
;
std
::
pair
<
InstructionCost
,
MVT
>
LT
=
TLI
->
getTypeLegalizationCost
(
DL
,
VTy
)
;
if
(
TTI
::
requiresOrderedReduction
(
FMF
)
)
return
(
LT
.
first
1
)
+
BaseCost
+
VL
;
return
(
LT
.
first
1
)
+
BaseCost
+
Log2_32_Ceil
(
VL
)
;
}
</s>

Calculate the cost of vector reduction intrinsics .

RISCV
RISCV
1
"Invalid opcode"
ISD::ADD
ISD::OR
ISD::XOR
ISD::AND
ISD::FADD
2
1
1


<s> static bool riscv_interrupt_type_p ( tree type ) { return lookup_attribute ( "interrupt" , TYPE_ATTRIBUTES ( type ) ) != NULL ; } </s>

Return true if function TYPE is an interrupt function .


<s> const char * riscv_output_move ( rtx dest , rtx src ) { enum rtx_code dest_code , src_code ; machine_mode mode ; bool dbl_p ; dest_code = GET_CODE ( dest ) ; src_code = GET_CODE ( src ) ; mode = GET_MODE ( dest ) ; dbl_p = ( GET_MODE_SIZE ( mode ) == 8 ) ; if ( dbl_p && riscv_split_64bit_move_p ( dest , src ) ) return "#" ; if ( dest_code == REG && GP_REG_P ( REGNO ( dest ) ) ) { if ( src_code == REG && FP_REG_P ( REGNO ( src ) ) ) return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.s\t%0,%1" ; if ( src_code == MEM ) switch ( GET_MODE_SIZE ( mode ) ) { case 1 : return "lbu\t%0,%1" ; case 2 : return "lhu\t%0,%1" ; case 4 : return "lw\t%0,%1" ; case 8 : return "ld\t%0,%1" ; } if ( src_code == CONST_INT ) return "li\t%0,%1" ; if ( src_code == HIGH ) return "lui\t%0,%h1" ; if ( symbolic_operand ( src , VOIDmode ) ) switch ( riscv_classify_symbolic_expression ( src ) ) { case SYMBOL_GOT_DISP : return "la\t%0,%1" ; case SYMBOL_ABSOLUTE : return "lla\t%0,%1" ; case SYMBOL_PCREL : return "lla\t%0,%1" ; default : gcc_unreachable ( ) ; } } if ( ( src_code == REG && GP_REG_P ( REGNO ( src ) ) ) || ( src == CONST0_RTX ( mode ) ) ) { if ( dest_code == REG ) { if ( GP_REG_P ( REGNO ( dest ) ) ) return "mv\t%0,%z1" ; if ( FP_REG_P ( REGNO ( dest ) ) ) { if ( ! dbl_p ) return "fmv.s.x\t%0,%z1" ; if ( TARGET_64BIT ) return "fmv.d.x\t%0,%z1" ; gcc_assert ( src == CONST0_RTX ( mode ) ) ; return "fcvt.d.w\t%0,x0" ; } } if ( dest_code == MEM ) switch ( GET_MODE_SIZE ( mode ) ) { case 1 : return "sb\t%z1,%0" ; case 2 : return "sh\t%z1,%0" ; case 4 : return "sw\t%z1,%0" ; case 8 : return "sd\t%z1,%0" ; } } if ( src_code == REG && FP_REG_P ( REGNO ( src ) ) ) { if ( dest_code == REG && FP_REG_P ( REGNO ( dest ) ) ) return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1" ; if ( dest_code == MEM ) return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0" ; } if ( dest_code == REG && FP_REG_P ( REGNO ( dest ) ) ) { if ( src_code == MEM ) return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1" ; } gcc_unreachable ( ) ; } </s>

Return the appropriate instructions to move SRC into DEST . Assume that SRC is operand 1 and DEST is operand 0 .


<s> RISCVTargetLowering :: ConstraintType RISCVTargetLowering :: getConstraintType ( StringRef Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'C' : case 'f' : case 'v' : return C_RegisterClass ; case 'I' : case 'J' : case 'K' : return C_Immediate ; case 'A' : return C_Memory ; case 'S' : return C_Other ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

Given a constraint letter , return the type of constraint for this target .


<s> bool RISCVTargetLowering :: isOffsetFoldingLegal ( const GlobalAddressSDNode * GA ) const { return false ; } </s>

Return true if folding a constant offset with the given GlobalAddress is legal .


<s>
SDValue
RISCVTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
analyzeOutputArgs
(
DAG
.
getMachineFunction
(
)
,
CCInfo
,
Outs
,
true
,
nullptr
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
RVLocs
.
size
(
)
;
i
<
e
;
++
i
)
{
SDValue
Val
=
OutVals
[
i
]
;
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Val
=
packIntoRegLoc
(
DAG
,
Val
,
VA
,
DL
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
Val
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

This hook must be implemented to lower outgoing return values , described by the Outs array , into the specified DAG .


<s> void riscv_expand_conditional_branch ( rtx label , rtx_code code , rtx op0 , rtx op1 ) { if ( FLOAT_MODE_P ( GET_MODE ( op1 ) ) ) riscv_emit_float_compare ( & code , & op0 , & op1 ) ; else riscv_emit_int_compare ( & code , & op0 , & op1 ) ; rtx condition = gen_rtx_fmt_ee ( code , VOIDmode , op0 , op1 ) ; emit_jump_insn ( gen_condjump ( condition , label ) ) ; } </s>

Jump to LABEL if ( CODE OP0 OP1 ) holds .


<s> unsigned RISCVAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned Kind ) { RISCVOperand & Op = static_cast < RISCVOperand & > ( AsmOp ) ; if ( ! Op . isReg ( ) ) return Match_InvalidOperand ; Register Reg = Op . getReg ( ) ; bool IsRegFPR64 = RISCVMCRegisterClasses [ RISCV :: FPR64RegClassID ] . contains ( Reg ) ; bool IsRegFPR64C = RISCVMCRegisterClasses [ RISCV :: FPR64CRegClassID ] . contains ( Reg ) ; if ( ( IsRegFPR64 && Kind == MCK_FPR16 ) || ( IsRegFPR64C && Kind == MCK_FPR32C ) ) { Op . Reg . RegNum = convertFPR64ToFPR32 ( Reg ) ; return Match_Success ; } return Match_InvalidOperand ; } </s>

Allow a target to add special case operand matching for things that tblgen doesn't/ca n't handle effectively .

RISCV RISCV RISCV RISCV RISCV RISCV::FPR64RegClassID RISCV RISCV::FPR64CRegClassID


<s> bool RISCVAsmParser :: ParseDirective ( AsmToken DirectiveID ) { StringRef IDVal = DirectiveID . getString ( ) ; if ( IDVal == ".option" ) return parseDirectiveOption ( ) ; if ( IDVal == ".attribute" ) return parseDirectiveAttribute ( ) ; if ( IDVal == ".insn" ) return parseDirectiveInsn ( DirectiveID . getLoc ( ) ) ; return true ; } </s>

ParseDirective - Parse a target specific assembler directive This method is deprecated , use 'parseDirective ' instead .


"loadRegFromStackSlot didn't insert any code!"

restoreCalleeSavedRegisters - Issues instruction ( s ) to restore all callee saved registers and returns true if it is n't possible / profitable to do so by issuing a series of load instructions via loadRegToStackSlot ( ) .


<s> void riscv_register_pragmas ( void ) { targetm . check_builtin_call = riscv_check_builtin_call ; c_register_pragma ( "riscv" , "intrinsic" , riscv_pragma_intrinsic ) ; } </s>


<s> static int riscv_memory_move_cost ( enum machine_mode mode , reg_class_t rclass , bool in ) { return ( tune_info -> memory_cost + memory_move_secondary_cost ( mode , rclass , in ) ) ; } </s>


"%qs function cannot have different interrupt type"


<s> bool RISCVTTIImpl :: isLoweredToCall ( const Function * F ) { if ( F -> getName ( ) . startswith ( "llvm.riscv.pulp" ) ) return false ; return BaseT :: isLoweredToCall ( F ) ; } </s>

Test whether calls to a function lower to actual program function calls .


<s> bool legitimize_move ( rtx dest , rtx src , machine_mode mask_mode ) { machine_mode mode = GET_MODE ( dest ) ; if ( CONST_VECTOR_P ( src ) ) { expand_const_vector ( dest , src , mask_mode ) ; return true ; } if ( ( known_lt ( GET_MODE_SIZE ( mode ) , BYTES_PER_RISCV_VECTOR ) || GET_MODE_CLASS ( mode ) == MODE_VECTOR_BOOL ) && lra_in_progress ) { emit_insn ( gen_mov_lra ( mode , Pmode , dest , src ) ) ; return true ; } if ( known_ge ( GET_MODE_SIZE ( mode ) , BYTES_PER_RISCV_VECTOR ) && GET_MODE_CLASS ( mode ) != MODE_VECTOR_BOOL ) { if ( MEM_P ( dest ) && ! REG_P ( src ) ) src = force_reg ( mode , src ) ; return false ; } if ( register_operand ( src , mode ) && register_operand ( dest , mode ) ) { emit_insn ( gen_rtx_SET ( dest , src ) ) ; return true ; } if ( ! register_operand ( src , mode ) && ! register_operand ( dest , mode ) ) { rtx tmp = gen_reg_rtx ( mode ) ; if ( MEM_P ( src ) ) emit_vlmax_op ( code_for_pred_mov ( mode ) , tmp , src , mask_mode ) ; else emit_move_insn ( tmp , src ) ; src = tmp ; } if ( satisfies_constraint_vu ( src ) ) return false ; emit_vlmax_op ( code_for_pred_mov ( mode ) , dest , src , mask_mode ) ; return true ; } </s>

Expand a pre-RA RVV data move from SRC to DEST . It expands move for RVV fractional vector modes .


<s> static bool riscv_symbol_binds_local_p ( const_rtx x ) { if ( SYMBOL_REF_P ( x ) ) return ( SYMBOL_REF_DECL ( x ) ? targetm . binds_local_p ( SYMBOL_REF_DECL ( x ) ) : SYMBOL_REF_LOCAL_P ( x ) ) ; else return false ; } </s>


<s> unsigned int get_ratio ( machine_mode mode ) { if ( TARGET_MIN_VLEN == 32 ) return mode_vtype_infos . ratio_for_min_vlen32 [ mode ] ; else return mode_vtype_infos . ratio_for_min_vlen64 [ mode ] ; } </s>


<s> static void riscv_conditional_register_usage ( void ) { if ( TARGET_RVE ) { for ( int r = 16 ; r <= 31 ; r ++ ) fixed_regs [ r ] = 1 ; } if ( riscv_abi == ABI_ILP32E ) { for ( int r = 16 ; r <= 31 ; r ++ ) call_used_regs [ r ] = 1 ; } if ( ! TARGET_HARD_FLOAT ) { for ( int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) fixed_regs [ regno ] = call_used_regs [ regno ] = 1 ; } if ( UNITS_PER_FP_ARG == 0 ) { for ( int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) call_used_regs [ regno ] = 1 ; } if ( ! TARGET_VECTOR ) { for ( int regno = V_REG_FIRST ; regno <= V_REG_LAST ; regno ++ ) fixed_regs [ regno ] = call_used_regs [ regno ] = 1 ; fixed_regs [ VTYPE_REGNUM ] = call_used_regs [ VTYPE_REGNUM ] = 1 ; fixed_regs [ VL_REGNUM ] = call_used_regs [ VL_REGNUM ] = 1 ; } } </s>


"RegScavenger required for long branching"

"new block should be inserted for expanding unconditional branch"

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

Insert an unconditional indirect branch at the end of MBB to NewDestBB .


<s>
SDValue
RISCVTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
report_fatal_error
(
"unimplemented operand"
)
;
case
ISD
::
GlobalAddress
:
return
lowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
lowerBlockAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT
:
return
lowerSELECT
(
Op
,
DAG
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .

RISCV
RISCV
"unimplemented operand"
ISD::GlobalAddress
ISD::BlockAddress
ISD::SELECT


<s> bool RISCVFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , ArrayRef < CalleeSavedInfo > CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return true ; MachineFunction * MF = MBB . getParent ( ) ; const TargetInstrInfo & TII = * MF -> getSubtarget ( ) . getInstrInfo ( ) ; DebugLoc DL ; if ( MI != MBB . end ( ) && ! MI -> isDebugInstr ( ) ) DL = MI -> getDebugLoc ( ) ; const char * SpillLibCall = getSpillLibCallName ( * MF , CSI ) ; if ( SpillLibCall ) { BuildMI ( MBB , MI , DL , TII . get ( RISCV :: PseudoCALLReg ) , RISCV :: X5 ) . addExternalSymbol ( SpillLibCall , RISCVII :: MO_CALL ) . setMIFlag ( MachineInstr :: FrameSetup ) ; for ( auto & CS : CSI ) MBB . addLiveIn ( CS . getReg ( ) ) ; } const auto & NonLibcallCSI = getNonLibcallCSI ( * MF , CSI ) ; for ( auto & CS : NonLibcallCSI ) { Register Reg = CS . getReg ( ) ; const TargetRegisterClass * RC = TRI -> getMinimalPhysRegClass ( Reg ) ; TII . storeRegToStackSlot ( MBB , MI , Reg , ! MBB . isLiveIn ( Reg ) , CS . getFrameIdx ( ) , RC , TRI ) ; } return true ; } </s>

spillCalleeSavedRegisters - Issues instruction ( s ) to spill all callee saved registers and returns true if it is n't possible / profitable to do so by issuing a series of store instructions via storeRegToStackSlot ( ) .


<s> void RISCVDAGToDAGISel :: PostprocessISelDAG ( ) { doPeepholeLoadStoreOffset ( ) ; } </s>

PostprocessISelDAG ( ) - This hook allows the target to hack on the graph right after selection .


<s>
SDValue
RISCVTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
analyzeOutputArgs
(
DAG
.
getMachineFunction
(
)
,
CCInfo
,
Outs
,
true
,
nullptr
)
;
SDValue
Glue
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
RVLocs
.
size
(
)
;
i
<
e
;
++
i
)
{
SDValue
Val
=
OutVals
[
i
]
;
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
if
(
VA
.
getLocVT
(
)
==
MVT
::
i32
&&
VA
.
getValVT
(
)
==
MVT
::
f64
)
{
assert
(
VA
.
isRegLoc
(
)
&&
"Expected return via registers"
)
;
SDValue
SplitF64
=
DAG
.
getNode
(
RISCVISD
::
SplitF64
,
DL
,
DAG
.
getVTList
(
MVT
::
i32
,
MVT
::
i32
)
,
Val
)
;
SDValue
Lo
=
SplitF64
.
getValue
(
0
)
;
SDValue
Hi
=
SplitF64
.
getValue
(
1
)
;
unsigned
RegLo
=
VA
.
getLocReg
(
)
;
unsigned
RegHi
=
RegLo
+
1
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
RegLo
,
Lo
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
RegLo
,
MVT
::
i32
)
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
RegHi
,
Hi
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
RegHi
,
MVT
::
i32
)
)
;
}
else
{
Val
=
packIntoRegLoc
(
DAG
,
Val
,
VA
,
DL
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
Val
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
}
RetOps
[
0
]
=
Chain
;
if
(
Glue
.
getNode
(
)
)
{
RetOps
.
push_back
(
Glue
)
;
}
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>


"getIntImmCost can only estimate cost of materialising integers"

Return the expected cost of materialization for the given integer immediate of the specified type for a given instruction .


<s> static rtx_insn * riscv_sr_match_prologue ( rtx_insn * * body ) { rtx_insn * insn , * bb_note ; * body = NULL ; for ( insn = get_insns ( ) ; insn != NULL ; insn = NEXT_INSN ( insn ) ) if ( NOTE_P ( insn ) && NOTE_KIND ( insn ) == NOTE_INSN_PROLOGUE_END ) { * body = NEXT_INSN ( insn ) ; break ; } if ( insn == NULL || PREV_INSN ( insn ) == NULL ) return NULL ; for ( bb_note = PREV_INSN ( PREV_INSN ( insn ) ) ; bb_note != NULL ; bb_note = PREV_INSN ( bb_note ) ) { if ( ! NOTE_P ( bb_note ) ) return NULL ; if ( NOTE_KIND ( bb_note ) == NOTE_INSN_BASIC_BLOCK ) break ; if ( NOTE_KIND ( bb_note ) != NOTE_INSN_DELETED && NOTE_KIND ( bb_note ) != NOTE_INSN_FUNCTION_BEG ) return NULL ; } if ( bb_note == NULL ) return NULL ; insn = PREV_INSN ( insn ) ; if ( INSN_P ( insn ) && INSN_CODE ( insn ) == CODE_FOR_gpr_save && GET_CODE ( PATTERN ( insn ) ) == PARALLEL && GET_CODE ( XVECEXP ( PATTERN ( insn ) , 0 , 0 ) ) == UNSPEC_VOLATILE && ( GET_CODE ( XVECEXP ( XVECEXP ( PATTERN ( insn ) , 0 , 0 ) , 0 , 0 ) ) == CONST_INT ) && INTVAL ( XVECEXP ( XVECEXP ( PATTERN ( insn ) , 0 , 0 ) , 0 , 0 ) ) == 0 ) return insn ; return NULL ; } </s>

Look in the function prologue for a call to the save stub . Ensure that the instruction is as we expect ( see detail below ) and if the instruction matches return a pointer to it . Otherwise , return NULL . We expect the function prologue to look like this : ( note NOTE_INSN_BASIC_BLOCK ) ( insn ( parallel [ ( unspec_volatile [ ( const_int 2 [ 0x2 ] ) ] UNSPECV_GPR_SAVE ) ( clobber ( reg : SI 5 t0 ) ) ( clobber ( reg : SI 6 t1 ) ) ] ) ( note NOTE_INSN_PROLOGUE_END ) Between the NOTE_INSN_BASIC_BLOCK and the GPR_SAVE insn we might find other notes of type NOTE_INSN_DELETED and/or NOTE_INSN_FUNCTION_BEG . The parameter BODY is updated to point to the first instruction after the NOTE_INSN_PROLOGUE_END or will be updated to NULL if the prologue end note was not found .


<s> BitVector RISCVRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { const TargetFrameLowering * TFI = getFrameLowering ( MF ) ; BitVector Reserved ( getNumRegs ( ) ) ; markSuperRegs ( Reserved , RISCV :: X0 ) ; markSuperRegs ( Reserved , RISCV :: X1 ) ; markSuperRegs ( Reserved , RISCV :: X2 ) ; markSuperRegs ( Reserved , RISCV :: X3 ) ; markSuperRegs ( Reserved , RISCV :: X4 ) ; if ( TFI -> hasFP ( MF ) ) markSuperRegs ( Reserved , RISCV :: X8 ) ; assert ( checkAllSuperRegsMarked ( Reserved ) ) ; return Reserved ; } </s>

getReservedRegs - Returns a bitset indexed by physical register number indicating if a register is a special register that has particular uses and should be considered unavailable at all times , e.g .


<s> void RISCVTargetLowering :: computeKnownBitsForTargetNode ( const SDValue Op , KnownBits & Known , const APInt & DemandedElts , const SelectionDAG & DAG , unsigned Depth ) const { if ( Op . getOpcode ( ) != RISCVISD :: SELECT_CC ) return ; KnownBits Known2 ; DAG . computeKnownBits ( Op -> getOperand ( 3 ) , Known , Depth + 1 ) ; DAG . computeKnownBits ( Op -> getOperand ( 4 ) , Known2 , Depth + 1 ) ; Known . Zero &= Known2 . Zero ; Known . One &= Known2 . One ; } </s>

Determine which of the bits specified in Mask are known to be either zero or one and return them in the KnownZero/KnownOne bitsets .


<s>
unsigned
getReg
(
)
const
override
{
assert
(
Kind
==
KindReg
&&
"Not a register"
)
;
return
Reg
.
Num
;
}
</s>

Returns the register associated with this edge .


<s> void riscv_expand_prologue ( void ) { struct riscv_frame_info * frame = & cfun -> machine -> frame ; poly_int64 size = frame -> total_size ; unsigned mask = frame -> mask ; rtx insn ; if ( flag_stack_usage_info ) current_function_static_stack_size = constant_lower_bound ( size ) ; if ( cfun -> machine -> naked_p ) return ; if ( riscv_use_save_libcall ( frame ) ) { rtx dwarf = NULL_RTX ; dwarf = riscv_adjust_libcall_cfi_prologue ( ) ; size -= frame -> save_libcall_adjustment ; insn = emit_insn ( riscv_gen_gpr_save_insn ( frame ) ) ; frame -> mask = 0 ; RTX_FRAME_RELATED_P ( insn ) = 1 ; REG_NOTES ( insn ) = dwarf ; } if ( ( frame -> mask | frame -> fmask ) != 0 ) { HOST_WIDE_INT step1 = riscv_first_stack_step ( frame ) ; if ( size . is_constant ( ) ) step1 = MIN ( size . to_constant ( ) , step1 ) ; insn = gen_add3_insn ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - step1 ) ) ; RTX_FRAME_RELATED_P ( emit_insn ( insn ) ) = 1 ; size -= step1 ; riscv_for_each_saved_reg ( size , riscv_save_reg , false , false ) ; } frame -> mask = mask ; if ( frame_pointer_needed ) { insn = gen_add3_insn ( hard_frame_pointer_rtx , stack_pointer_rtx , GEN_INT ( ( frame -> hard_frame_pointer_offset - size ) . to_constant ( ) ) ) ; RTX_FRAME_RELATED_P ( emit_insn ( insn ) ) = 1 ; riscv_emit_stack_tie ( ) ; } if ( known_gt ( size , 0 ) ) { poly_int64 scalable_frame ( 0 , 0 ) ; if ( ! size . is_constant ( ) ) { poly_int64 scalable_frame = size ; scalable_frame . coeffs [ 0 ] = size . coeffs [ 1 ] ; riscv_v_adjust_scalable_frame ( stack_pointer_rtx , scalable_frame , false ) ; size -= scalable_frame ; } HOST_WIDE_INT constant_frame = size . to_constant ( ) ; if ( constant_frame == 0 ) return ; if ( SMALL_OPERAND ( - constant_frame ) ) { insn = gen_add3_insn ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - constant_frame ) ) ; RTX_FRAME_RELATED_P ( emit_insn ( insn ) ) = 1 ; } else { riscv_emit_move ( RISCV_PROLOGUE_TEMP ( Pmode ) , GEN_INT ( - constant_frame ) ) ; emit_insn ( gen_add3_insn ( stack_pointer_rtx , stack_pointer_rtx , RISCV_PROLOGUE_TEMP ( Pmode ) ) ) ; insn = plus_constant ( Pmode , stack_pointer_rtx , - constant_frame ) ; insn = gen_rtx_SET ( stack_pointer_rtx , insn ) ; riscv_set_frame_expr ( insn ) ; } } } </s>


<s> bool RISCVAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , const char * ExtraCode , raw_ostream & OS ) { if ( ! AsmPrinter :: PrintAsmOperand ( MI , OpNo , ExtraCode , OS ) ) return false ; const MachineOperand & MO = MI -> getOperand ( OpNo ) ; if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'z' : if ( MO . isImm ( ) && MO . getImm ( ) == 0 ) { OS << RISCVInstPrinter :: getRegisterName ( RISCV :: X0 ) ; return false ; } break ; case 'i' : if ( ! MO . isReg ( ) ) OS << 'i' ; return false ; } } switch ( MO . getType ( ) ) { case MachineOperand :: MO_Immediate : OS << MO . getImm ( ) ; return false ; case MachineOperand :: MO_Register : OS << RISCVInstPrinter :: getRegisterName ( MO . getReg ( ) ) ; return false ; default : break ; } return true ; } </s>

PrintAsmOperand - Print out an operand for an inline asm expression .


<s> bool RISCVTargetLowering :: getTgtMemIntrinsic ( IntrinsicInfo & Info , const CallInst & I , MachineFunction & MF , unsigned Intrinsic ) const { switch ( Intrinsic ) { default : return false ; 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 : PointerType * PtrTy = cast < PointerType > ( I . getArgOperand ( 0 ) -> getType ( ) ) ; Info . opc = ISD :: INTRINSIC_W_CHAIN ; Info . memVT = MVT :: getVT ( PtrTy -> getElementType ( ) ) ; Info . ptrVal = I . getArgOperand ( 0 ) ; Info . offset = 0 ; Info . align = 4 ; Info . flags = MachineMemOperand :: MOLoad | MachineMemOperand :: MOStore | MachineMemOperand :: MOVolatile ; return true ; } } </s>

Given an intrinsic , checks if on the target the intrinsic will need to map to a MemIntrinsicNode ( touches memory ) .


<s> riscv_vector :: vlmul_type get_vlmul ( ) const { return m_vlmul ; } </s>

Helper function to get VLMUL operand . We always have VLMUL value for all RVV instructions that have VTYPE OP .


<s> static void riscv_emit_int_order_test ( enum rtx_code code , bool * invert_ptr , rtx target , rtx cmp0 , rtx cmp1 ) { enum machine_mode mode ; mode = GET_MODE ( cmp0 ) ; if ( riscv_canonicalize_int_order_test ( & code , & cmp1 , mode ) ) riscv_emit_binary ( code , target , cmp0 , cmp1 ) ; else { enum rtx_code inv_code = reverse_condition ( code ) ; if ( ! riscv_canonicalize_int_order_test ( & inv_code , & cmp1 , mode ) ) { cmp1 = force_reg ( mode , cmp1 ) ; riscv_emit_int_order_test ( code , invert_ptr , target , cmp0 , cmp1 ) ; } else if ( invert_ptr == 0 ) { rtx inv_target = riscv_force_binary ( GET_MODE ( target ) , inv_code , cmp0 , cmp1 ) ; riscv_emit_binary ( XOR , target , inv_target , const1_rtx ) ; } else { * invert_ptr = ! * invert_ptr ; riscv_emit_binary ( inv_code , target , cmp0 , cmp1 ) ; } } } </s>

Compare CMP0 and CMP1 using ordering test CODE and store the result in TARGET . CMP0 and TARGET are register_operands . If INVERT_PTR is nonnull , it 's OK to set TARGET to the inverse of the result and flip * INVERT_PTR instead .