<s> bool riscv_split_symbol ( rtx temp , rtx addr , machine_mode mode , rtx * low_out , bool in_splitter ) { enum riscv_symbol_type symbol_type ; if ( ( GET_CODE ( addr ) == HIGH && mode == MAX_MACHINE_MODE ) || ! riscv_symbolic_constant_p ( addr , & symbol_type ) || riscv_symbol_insns ( symbol_type ) == 0 || ! riscv_split_symbol_type ( symbol_type ) ) return false ; if ( low_out ) switch ( symbol_type ) { case SYMBOL_ABSOLUTE : { rtx high = gen_rtx_HIGH ( Pmode , copy_rtx ( addr ) ) ; high = riscv_force_temporary ( temp , high , in_splitter ) ; * low_out = gen_rtx_LO_SUM ( Pmode , high , addr ) ; } break ; case SYMBOL_PCREL : { static unsigned seqno ; char buf [ 32 ] ; rtx label ; ssize_t bytes = snprintf ( buf , sizeof ( buf ) , ".LA%u" , seqno ) ; gcc_assert ( ( size_t ) bytes < sizeof ( buf ) ) ; label = gen_rtx_SYMBOL_REF ( Pmode , ggc_strdup ( buf ) ) ; SYMBOL_REF_FLAGS ( label ) |= SYMBOL_FLAG_LOCAL ; if ( ! nonzero_address_p ( addr ) ) SYMBOL_REF_WEAK ( label ) = 1 ; if ( temp == NULL ) temp = gen_reg_rtx ( Pmode ) ; if ( Pmode == DImode ) emit_insn ( gen_auipcdi ( temp , copy_rtx ( addr ) , GEN_INT ( seqno ) ) ) ; else emit_insn ( gen_auipcsi ( temp , copy_rtx ( addr ) , GEN_INT ( seqno ) ) ) ; * low_out = gen_rtx_LO_SUM ( Pmode , temp , label ) ; seqno ++ ; } break ; default : gcc_unreachable ( ) ; } return true ; } </s>

If MODE is MAX_MACHINE_MODE , ADDR appears as a move operand , otherwise it appears in a MEM of that mode . Return true if ADDR is a legitimate constant in that context and can be split into high and low parts . If so , and if LOW_OUT is nonnull , emit the high part and store the low part in * LOW_OUT . Leave * LOW_OUT unchanged otherwise . TEMP is as for riscv_force_temporary and is used to load the high part into a register . When MODE is MAX_MACHINE_MODE , the low part is guaranteed to be a legitimize SET_SRC for an .md pattern , otherwise the low part is guaranteed to be a legitimate address for mode MODE .


<s> Register RISCVRegisterInfo :: getFrameRegister ( const MachineFunction & MF ) const { const TargetFrameLowering * TFI = getFrameLowering ( MF ) ; return TFI -> hasFP ( MF ) ? RISCV :: X8 : RISCV :: X2 ; } </s>


<s> static bool use_real_mask_p ( enum predication_type_index pred ) { return pred == PRED_TYPE_m || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu ; } </s>

Return true if predication is using a real mask operand .


<s> static void riscv_emit_prologue_components ( sbitmap components ) { riscv_process_components ( components , true ) ; } </s>


<s> static void riscv_save_restore_reg ( enum machine_mode mode , int regno , HOST_WIDE_INT offset , riscv_save_restore_fn fn ) { rtx mem ; mem = gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; fn ( gen_rtx_REG ( mode , regno ) , mem ) ; } </s>

Use FN to save or restore register REGNO . MODE is the register 's mode and OFFSET is the offset of its save slot from the current stack pointer .


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

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


"\nEntering Lazy VSETVL PASS and Handling %d basic blocks for "

"\nPhase 1: Compute local backward vector infos\n"

"\nPhase 2: Emit vsetvl instruction within each block\n"

"\nPhase 3: Demands propagation across blocks\n"

"\nPhase 4: PRE vsetvl by Lazy code motion (LCM)\n"

"\nPhase 5: Cleanup AVL and VL operands\n"

"\nPhase 6: Rebuild RTL_SSA to propagate AVL between vsetvls\n"

Lazy vsetvl insertion for optimize > 0 .


<s> inline void function_expander :: add_scalar_move_mask_operand ( machine_mode mode ) { add_input_operand ( mode , gen_scalar_move_mask ( mode ) ) ; } </s>

Add mask operand for scalar move instruction .


<s> static void riscv_for_each_saved_reg ( HOST_WIDE_INT sp_offset , riscv_save_restore_fn fn ) { HOST_WIDE_INT offset ; offset = cfun -> machine -> frame . gp_sp_offset - sp_offset ; for ( int regno = GP_REG_FIRST ; regno <= GP_REG_LAST ; regno ++ ) if ( BITSET_P ( cfun -> machine -> frame . mask , regno - GP_REG_FIRST ) ) { riscv_save_restore_reg ( word_mode , regno , offset , fn ) ; offset -= UNITS_PER_WORD ; } offset = cfun -> machine -> frame . fp_sp_offset - sp_offset ; for ( int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) if ( BITSET_P ( cfun -> machine -> frame . fmask , regno - FP_REG_FIRST ) ) { machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode ; riscv_save_restore_reg ( mode , regno , offset , fn ) ; offset -= GET_MODE_SIZE ( mode ) ; } } </s>

Call FN for each register that is saved by the current function . SP_OFFSET is the offset of the current stack pointer from the start of the frame .


<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
::
EXTRACT_VECTOR_ELT
:
assert
(
Subtarget
.
hasStdExtP
(
)
&&
"Unexpected custom legalisation"
)
;
return
lowerVectorExtract
(
Op
,
DAG
)
;
case
ISD
::
INSERT_VECTOR_ELT
:
assert
(
Subtarget
.
hasStdExtP
(
)
&&
"Unexpected custom legalisation"
)
;
return
lowerVectorInsert
(
Op
,
DAG
)
;
case
ISD
::
BUILD_VECTOR
:
assert
(
Subtarget
.
hasStdExtP
(
)
&&
"Unexpected custom legalisation"
)
;
return
lowerVectorBuild
(
Op
,
DAG
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .


<s> BitVector RISCVRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { BitVector Reserved ( getNumRegs ( ) ) ; const TargetFrameLowering * TFI = MF . getSubtarget ( ) . getFrameLowering ( ) ; Reserved . set ( RISCV :: zero ) ; Reserved . set ( RISCV :: zero_64 ) ; if ( TFI -> hasFP ( MF ) ) { Reserved . set ( RISCV :: fp ) ; Reserved . set ( RISCV :: s0 ) ; Reserved . set ( RISCV :: fp_64 ) ; Reserved . set ( RISCV :: s0_64 ) ; } Reserved . set ( RISCV :: sp ) ; Reserved . set ( RISCV :: sp_64 ) ; Reserved . set ( RISCV :: tp ) ; Reserved . set ( RISCV :: tp_64 ) ; Reserved . set ( RISCV :: gp ) ; Reserved . set ( RISCV :: gp_64 ) ; 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>
MachineBasicBlock
*
RISCVTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
&
MI
,
MachineBasicBlock
*
BB
)
const
{
const
TargetInstrInfo
&
TII
=
*
BB
->
getParent
(
)
->
getSubtarget
(
)
.
getInstrInfo
(
)
;
DebugLoc
DL
=
MI
.
getDebugLoc
(
)
;
assert
(
MI
.
getOpcode
(
)
==
RISCV
::
Select_GPR_Using_CC_GPR
&&
"Unexpected instr type to insert"
)
;
const
BasicBlock
*
LLVM_BB
=
BB
->
getBasicBlock
(
)
;
MachineFunction
::
iterator
I
=
++
BB
->
getIterator
(
)
;
MachineBasicBlock
*
HeadMBB
=
BB
;
MachineFunction
*
F
=
BB
->
getParent
(
)
;
MachineBasicBlock
*
TailMBB
=
F
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
MachineBasicBlock
*
IfFalseMBB
=
F
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
F
->
insert
(
I
,
IfFalseMBB
)
;
F
->
insert
(
I
,
TailMBB
)
;
TailMBB
->
splice
(
TailMBB
->
begin
(
)
,
HeadMBB
,
std
::
next
(
MachineBasicBlock
::
iterator
(
MI
)
)
,
HeadMBB
->
end
(
)
)
;
TailMBB
->
transferSuccessorsAndUpdatePHIs
(
HeadMBB
)
;
HeadMBB
->
addSuccessor
(
IfFalseMBB
)
;
HeadMBB
->
addSuccessor
(
TailMBB
)
;
unsigned
LHS
=
MI
.
getOperand
(
1
)
.
getReg
(
)
;
unsigned
RHS
=
MI
.
getOperand
(
2
)
.
getReg
(
)
;
auto
CC
=
static_cast
<
ISD
::
CondCode
>
(
MI
.
getOperand
(
3
)
.
getImm
(
)
)
;
unsigned
Opcode
=
getBranchOpcodeForIntCondCode
(
CC
)
;
BuildMI
(
HeadMBB
,
DL
,
TII
.
get
(
Opcode
)
)
.
addReg
(
LHS
)
.
addReg
(
RHS
)
.
addMBB
(
TailMBB
)
;
IfFalseMBB
->
addSuccessor
(
TailMBB
)
;
BuildMI
(
*
TailMBB
,
TailMBB
->
begin
(
)
,
DL
,
TII
.
get
(
RISCV
::
PHI
)
,
MI
.
getOperand
(
0
)
.
getReg
(
)
)
.
addReg
(
MI
.
getOperand
(
4
)
.
getReg
(
)
)
.
addMBB
(
HeadMBB
)
.
addReg
(
MI
.
getOperand
(
5
)
.
getReg
(
)
)
.
addMBB
(
IfFalseMBB
)
;
MI
.
eraseFromParent
(
)
;
return
TailMBB
;
}
</s>

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


<s> inline bool function_base :: apply_tail_policy_p ( ) const { return true ; } </s>

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


<s>
void
RISCVOperand
::
print
(
raw_ostream
&
OS
)
const
{
llvm_unreachable
(
"Not implemented"
)
;
}
</s>

print - Print a debug representation of the operand to the given stream .


<s> unsigned RISCVTargetLowering :: ComputeNumSignBitsForTargetNode ( SDValue Op , const APInt & DemandedElts , const SelectionDAG & DAG , unsigned Depth ) const { switch ( Op . getOpcode ( ) ) { default : break ; case RISCVISD :: SELECT_CC : { unsigned Tmp = DAG . ComputeNumSignBits ( Op . getOperand ( 3 ) , DemandedElts , Depth + 1 ) ; if ( Tmp == 1 ) return 1 ; unsigned Tmp2 = DAG . ComputeNumSignBits ( Op . getOperand ( 4 ) , DemandedElts , Depth + 1 ) ; return std :: min ( Tmp , Tmp2 ) ; } case RISCVISD :: SLLW : case RISCVISD :: SRAW : case RISCVISD :: SRLW : case RISCVISD :: DIVW : case RISCVISD :: DIVUW : case RISCVISD :: REMUW : case RISCVISD :: ROLW : case RISCVISD :: RORW : case RISCVISD :: GREVW : case RISCVISD :: GORCW : case RISCVISD :: FSLW : case RISCVISD :: FSRW : case RISCVISD :: SHFLW : case RISCVISD :: UNSHFLW : case RISCVISD :: BCOMPRESSW : case RISCVISD :: BDECOMPRESSW : case RISCVISD :: FCVT_W_RTZ_RV64 : case RISCVISD :: FCVT_WU_RTZ_RV64 : return 33 ; case RISCVISD :: SHFL : case RISCVISD :: UNSHFL : { if ( Op . getValueType ( ) == MVT :: i64 && isa < ConstantSDNode > ( Op . getOperand ( 1 ) ) && ( Op . getConstantOperandVal ( 1 ) & 0x10 ) == 0 ) { unsigned Tmp = DAG . ComputeNumSignBits ( Op . getOperand ( 0 ) , Depth + 1 ) ; if ( Tmp > 32 ) return 33 ; } break ; } case RISCVISD :: VMV_X_S : if ( Op . getOperand ( 0 ) . getScalarValueSizeInBits ( ) > Subtarget . getXLen ( ) ) return 1 ; return Subtarget . getXLen ( ) - Op . getOperand ( 0 ) . getScalarValueSizeInBits ( ) + 1 ; } return 1 ; } </s>

Determine the number of bits in the operation that are sign bits .


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

getFixupKind - Get the fixup kind of this expression .


<s> bool RISCVELFTargetObjectFile :: isConstantInSmallSection ( const DataLayout & DL , const Constant * CN ) const { return isInSmallSection ( DL . getTypeAllocSize ( CN -> getType ( ) ) ) ; } </s>

Return true if this constant should be placed into small data section .


<s> unsigned RISCVTargetLowering :: getJumpTableEncoding ( ) const { if ( Subtarget . is64Bit ( ) && ! isPositionIndependent ( ) && getTargetMachine ( ) . getCodeModel ( ) == CodeModel :: Small ) { return MachineJumpTableInfo :: EK_Custom32 ; } return TargetLowering :: getJumpTableEncoding ( ) ; } </s>

Return the entry encoding for a jump table in the current function .


"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> bool riscv_legitimize_move ( machine_mode mode , rtx dest , rtx src ) { if ( GET_MODE_CLASS ( mode ) == MODE_INT && GET_MODE_SIZE ( mode ) < UNITS_PER_WORD && can_create_pseudo_p ( ) && MEM_P ( src ) ) { rtx temp_reg ; int zero_extend_p ; temp_reg = gen_reg_rtx ( word_mode ) ; zero_extend_p = ( LOAD_EXTEND_OP ( mode ) == ZERO_EXTEND ) ; emit_insn ( gen_extend_insn ( temp_reg , src , word_mode , mode , zero_extend_p ) ) ; riscv_emit_move ( dest , gen_lowpart ( mode , temp_reg ) ) ; return true ; } if ( ! register_operand ( dest , mode ) && ! reg_or_0_operand ( src , mode ) ) { rtx reg ; if ( GET_CODE ( src ) == CONST_INT ) { machine_mode promoted_mode = mode ; if ( GET_MODE_CLASS ( mode ) == MODE_INT && GET_MODE_SIZE ( mode ) < UNITS_PER_WORD ) promoted_mode = word_mode ; if ( splittable_const_int_operand ( src , mode ) ) { reg = gen_reg_rtx ( promoted_mode ) ; riscv_move_integer ( reg , reg , INTVAL ( src ) , mode , FALSE ) ; } else reg = force_reg ( promoted_mode , src ) ; if ( promoted_mode != mode ) reg = gen_lowpart ( mode , reg ) ; } else reg = force_reg ( mode , src ) ; riscv_emit_move ( dest , reg ) ; return true ; } if ( CONSTANT_P ( src ) && ! move_operand ( src , mode ) ) { riscv_legitimize_const_move ( mode , dest , src ) ; set_unique_reg_note ( get_last_insn ( ) , REG_EQUAL , copy_rtx ( src ) ) ; return true ; } if ( MEM_P ( dest ) && ! riscv_legitimate_address_p ( mode , XEXP ( dest , 0 ) , reload_completed ) ) { XEXP ( dest , 0 ) = riscv_force_address ( XEXP ( dest , 0 ) , mode ) ; } if ( MEM_P ( src ) && ! riscv_legitimate_address_p ( mode , XEXP ( src , 0 ) , reload_completed ) ) { XEXP ( src , 0 ) = riscv_force_address ( XEXP ( src , 0 ) , mode ) ; } return false ; } </s>

If ( set DEST SRC ) is not a valid move instruction , emit an equivalent sequence that is valid .


<s> static bool riscv_classify_address ( struct riscv_address_info * info , rtx x , 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> bool RISCVTargetLowering :: isLegalAddImmediate ( int64_t Imm ) const { return isInt < 12 > ( Imm ) ; } </s>

Return true if the specified immediate is legal add immediate , that is the target has add instructions which can add a register and the immediate without having to materialize the immediate into a register .


<s> uint8_t get_ratio ( ) const { return m_ratio ; } </s>


<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
)
;
case
RISCV
::
PEXTRACT_PSEUDO
:
case
RISCV
::
PEXTRACT_PSEUDO_REV
:
return
emitPEXTRACT
(
MI
,
MBB
,
false
)
;
case
RISCV
::
PEXTRACTU_PSEUDO
:
case
RISCV
::
PEXTRACTU_PSEUDO_REV
:
return
emitPEXTRACT
(
MI
,
MBB
,
true
)
;
case
RISCV
::
PINSERT_PSEUDO
:
return
emitPINSERT
(
MI
,
MBB
)
;
case
RISCV
::
PBCLR_PSEUDO
:
return
emitPBCLRSET
(
MI
,
MBB
,
false
)
;
case
RISCV
::
PBSET_PSEUDO
:
return
emitPBCLRSET
(
MI
,
MBB
,
true
)
;
case
RISCV
::
PADDRN_PSEUDO
:
case
RISCV
::
PADDURN_PSEUDO
:
case
RISCV
::
PSUBRN_PSEUDO
:
case
RISCV
::
PSUBURN_PSEUDO
:
return
emitPRN
(
MI
,
MBB
)
;
default
:
llvm_unreachable
(
"Unexpected instr type to insert"
)
;
}
}
</s>


<s> static void riscv_output_mi_thunk ( FILE * file , tree thunk_fndecl ATTRIBUTE_UNUSED , HOST_WIDE_INT delta , HOST_WIDE_INT vcall_offset , tree function ) { rtx this_rtx , temp1 , temp2 , fnaddr ; rtx_insn * insn ; reload_completed = 1 ; emit_note ( NOTE_INSN_PROLOGUE_END ) ; fnaddr = gen_rtx_MEM ( FUNCTION_MODE , XEXP ( DECL_RTL ( function ) , 0 ) ) ; temp1 = gen_rtx_REG ( Pmode , RISCV_PROLOGUE_TEMP_REGNUM ) ; temp2 = gen_rtx_REG ( Pmode , STATIC_CHAIN_REGNUM ) ; if ( aggregate_value_p ( TREE_TYPE ( TREE_TYPE ( function ) ) , function ) ) this_rtx = gen_rtx_REG ( Pmode , GP_ARG_FIRST + 1 ) ; else this_rtx = gen_rtx_REG ( Pmode , GP_ARG_FIRST ) ; if ( delta != 0 ) { rtx offset = GEN_INT ( delta ) ; if ( ! SMALL_OPERAND ( delta ) ) { riscv_emit_move ( temp1 , offset ) ; offset = temp1 ; } emit_insn ( gen_add3_insn ( this_rtx , this_rtx , offset ) ) ; } if ( vcall_offset != 0 ) { rtx addr ; riscv_emit_move ( temp1 , gen_rtx_MEM ( Pmode , this_rtx ) ) ; addr = riscv_add_offset ( temp2 , temp1 , vcall_offset ) ; riscv_emit_move ( temp1 , gen_rtx_MEM ( Pmode , addr ) ) ; emit_insn ( gen_add3_insn ( this_rtx , this_rtx , temp1 ) ) ; } insn = emit_call_insn ( gen_sibcall ( fnaddr , const0_rtx , NULL , const0_rtx ) ) ; SIBLING_CALL_P ( insn ) = 1 ; insn = get_insns ( ) ; split_all_insns_noflow ( ) ; shorten_branches ( insn ) ; final_start_function ( insn , file , 1 ) ; final ( insn , file , 1 ) ; final_end_function ( ) ; reload_completed = 0 ; } </s>

Implement TARGET_ASM_OUTPUT_MI_THUNK . Generate rtl rather than asm text in order to avoid duplicating too much logic from elsewhere .


<s> static rtx get_mask_policy_for_pred ( enum predication_type_index pred ) { if ( pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu ) return gen_int_mode ( MASK_UNDISTURBED , Pmode ) ; return gen_int_mode ( get_prefer_mask_policy ( ) , Pmode ) ; } </s>

Get MASK policy for predication . If predication indicates MU , return the MU . Otherwise , return the prefer default configuration .


<s> bool RISCVTargetLowering :: isDesirableToCommuteWithShift ( const SDNode * N , CombineLevel Level ) const { SDValue N0 = N -> getOperand ( 0 ) ; EVT Ty = N0 . getValueType ( ) ; if ( Ty . isScalarInteger ( ) && ( N0 . getOpcode ( ) == ISD :: ADD || N0 . getOpcode ( ) == ISD :: OR ) ) { auto * C1 = dyn_cast < ConstantSDNode > ( N0 -> getOperand ( 1 ) ) ; auto * C2 = dyn_cast < ConstantSDNode > ( N -> getOperand ( 1 ) ) ; if ( C1 && C2 ) { APInt C1Int = C1 -> getAPIntValue ( ) ; APInt ShiftedC1Int = C1Int << C2 -> getAPIntValue ( ) ; if ( ShiftedC1Int . getMinSignedBits ( ) <= 64 && isLegalAddImmediate ( ShiftedC1Int . getSExtValue ( ) ) ) return true ; if ( C1Int . getMinSignedBits ( ) <= 64 && isLegalAddImmediate ( C1Int . getSExtValue ( ) ) ) return false ; int C1Cost = RISCVMatInt :: getIntMatCost ( C1Int , Ty . getSizeInBits ( ) , Subtarget . is64Bit ( ) ) ; int ShiftedC1Cost = RISCVMatInt :: getIntMatCost ( ShiftedC1Int , Ty . getSizeInBits ( ) , Subtarget . is64Bit ( ) ) ; if ( C1Cost < ShiftedC1Cost ) return false ; } } return true ; } </s>

Return true if it is profitable to move this shift by a constant amount through its operand , adjusting any immediate operands as necessary to preserve semantics .


<s> bool RISCVDAGToDAGISel :: SelectInlineAsmMemoryOperand ( const SDValue & Op , unsigned ConstraintID , std :: vector < SDValue > & OutOps ) { switch ( ConstraintID ) { case InlineAsm :: Constraint_i : case InlineAsm :: Constraint_m : OutOps . push_back ( Op ) ; return false ; default : break ; } return true ; } </s>

SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode , according to the specified constraint .


<s>
MachineBasicBlock
*
RISCVTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
&
MI
,
MachineBasicBlock
*
BB
)
const
{
switch
(
MI
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Unexpected instr type to insert"
)
;
case
RISCV
::
Select_GPR_Using_CC_GPR
:
case
RISCV
::
Select_FPR32_Using_CC_GPR
:
case
RISCV
::
Select_FPR64_Using_CC_GPR
:
break
;
case
RISCV
::
BuildPairF64Pseudo
:
return
emitBuildPairF64Pseudo
(
MI
,
BB
)
;
case
RISCV
::
SplitF64Pseudo
:
return
emitSplitF64Pseudo
(
MI
,
BB
)
;
}
const
TargetInstrInfo
&
TII
=
*
BB
->
getParent
(
)
->
getSubtarget
(
)
.
getInstrInfo
(
)
;
const
BasicBlock
*
LLVM_BB
=
BB
->
getBasicBlock
(
)
;
DebugLoc
DL
=
MI
.
getDebugLoc
(
)
;
MachineFunction
::
iterator
I
=
++
BB
->
getIterator
(
)
;
MachineBasicBlock
*
HeadMBB
=
BB
;
MachineFunction
*
F
=
BB
->
getParent
(
)
;
MachineBasicBlock
*
TailMBB
=
F
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
MachineBasicBlock
*
IfFalseMBB
=
F
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
F
->
insert
(
I
,
IfFalseMBB
)
;
F
->
insert
(
I
,
TailMBB
)
;
TailMBB
->
splice
(
TailMBB
->
begin
(
)
,
HeadMBB
,
std
::
next
(
MachineBasicBlock
::
iterator
(
MI
)
)
,
HeadMBB
->
end
(
)
)
;
TailMBB
->
transferSuccessorsAndUpdatePHIs
(
HeadMBB
)
;
HeadMBB
->
addSuccessor
(
IfFalseMBB
)
;
HeadMBB
->
addSuccessor
(
TailMBB
)
;
unsigned
LHS
=
MI
.
getOperand
(
1
)
.
getReg
(
)
;
unsigned
RHS
=
MI
.
getOperand
(
2
)
.
getReg
(
)
;
auto
CC
=
static_cast
<
ISD
::
CondCode
>
(
MI
.
getOperand
(
3
)
.
getImm
(
)
)
;
unsigned
Opcode
=
getBranchOpcodeForIntCondCode
(
CC
)
;
BuildMI
(
HeadMBB
,
DL
,
TII
.
get
(
Opcode
)
)
.
addReg
(
LHS
)
.
addReg
(
RHS
)
.
addMBB
(
TailMBB
)
;
IfFalseMBB
->
addSuccessor
(
TailMBB
)
;
BuildMI
(
*
TailMBB
,
TailMBB
->
begin
(
)
,
DL
,
TII
.
get
(
RISCV
::
PHI
)
,
MI
.
getOperand
(
0
)
.
getReg
(
)
)
.
addReg
(
MI
.
getOperand
(
4
)
.
getReg
(
)
)
.
addMBB
(
HeadMBB
)
.
addReg
(
MI
.
getOperand
(
5
)
.
getReg
(
)
)
.
addMBB
(
IfFalseMBB
)
;
MI
.
eraseFromParent
(
)
;
return
TailMBB
;
}
</s>


<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 ( CSI ) ; for ( auto & CS : NonLibcallCSI ) { Register Reg = CS . getReg ( ) ; const TargetRegisterClass * RC = TRI -> getMinimalPhysRegClass ( Reg ) ; TII . storeRegToStackSlot ( MBB , MI , Reg , true , 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 ( ) .


"Can't load this register from stack slot"

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


<s> bool RISCVTargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT , bool ForCodeSize ) const { 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 RISCVAsmBackend :: fixupNeedsRelaxationAdvanced ( const MCFixup & Fixup , bool Resolved , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout , const bool WasForced ) const { if ( ! Resolved && ! WasForced ) return true ; int64_t Offset = int64_t ( Value ) ; switch ( ( unsigned ) Fixup . getKind ( ) ) { default : return false ; case RISCV :: fixup_riscv_rvc_branch : return Offset > 254 || Offset < - 256 ; case RISCV :: fixup_riscv_rvc_jump : return Offset > 2046 || Offset < - 2048 ; } } </s>

Target specific predicate for whether a given fixup requires the associated instruction to be relaxed .


<s> bool isToken ( ) const override { return Kind == Token ; } </s>


<s> static tree build_const_pointer ( tree t ) { return build_pointer_type ( build_qualified_type ( t , TYPE_QUAL_CONST ) ) ; } </s>

Return a representation of `` const T * '' .


<s> virtual bool check ( function_checker & ) const { return true ; } </s>

Perform semantic checks on the call . Return true if the call is valid , otherwise report a suitable error .


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . addRequired < MachineLoopInfo > ( ) ; MachineFunctionPass :: getAnalysisUsage ( AU ) ; } </s>

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


<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
::
BUILD_VECTOR
:
return
lowerBUILD_VECTOR
(
Op
,
DAG
)
;
case
ISD
::
EXTRACT_VECTOR_ELT
:
return
lowerEXTRACT_VECTOR_ELT
(
Op
,
DAG
)
;
case
ISD
::
INSERT_VECTOR_ELT
:
return
lowerINSERT_VECTOR_ELT
(
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
;
}
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .


"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 riscv_can_use_return_insn ( void ) { return ( reload_completed && known_eq ( cfun -> machine -> frame . total_size , 0 ) && ! cfun -> machine -> interrupt_handler_p ) ; } </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>
void
RISCVTTIImpl
::
getUnrollingPreferences
(
Loop
*
L
,
ScalarEvolution
&
SE
,
TTI
::
UnrollingPreferences
&
UP
,
OptimizationRemarkEmitter
*
ORE
)
{
bool
UseDefaultPreferences
=
true
;
if
(
ST
->
getProcFamily
(
)
==
RISCVSubtarget
::
SiFive7
)
UseDefaultPreferences
=
false
;
if
(
UseDefaultPreferences
)
return
BasicTTIImplBase
::
getUnrollingPreferences
(
L
,
SE
,
UP
,
ORE
)
;
UP
.
UpperBound
=
true
;
UP
.
OptSizeThreshold
=
0
;
UP
.
PartialOptSizeThreshold
=
0
;
if
(
L
->
getHeader
(
)
->
getParent
(
)
->
hasOptSize
(
)
)
return
;
SmallVector
<
BasicBlock
*
,
4
>
ExitingBlocks
;
L
->
getExitingBlocks
(
ExitingBlocks
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Loop has:\n"
<<
"Blocks: "
<<
L
->
getNumBlocks
(
)
<<
"\n"
<<
"Exit blocks: "
<<
ExitingBlocks
.
size
(
)
<<
"\n"
)
;
if
(
ExitingBlocks
.
size
(
)
>
2
)
return
;
if
(
L
->
getNumBlocks
(
)
>
4
)
return
;
if
(
getBooleanLoopAttribute
(
L
,
"llvm.loop.isvectorized"
)
)
return
;
InstructionCost
Cost
=
0
;
for
(
auto
*
BB
:
L
->
getBlocks
(
)
)
{
for
(
auto
&
I
:
*
BB
)
{
if
(
I
.
getType
(
)
->
isVectorTy
(
)
)
return
;
if
(
isa
<
CallInst
>
(
I
)
||
isa
<
InvokeInst
>
(
I
)
)
{
if
(
const
Function
*
F
=
cast
<
CallBase
>
(
I
)
.
getCalledFunction
(
)
)
{
if
(
!
isLoweredToCall
(
F
)
)
continue
;
}
return
;
}
SmallVector
<
const
Value
*
>
Operands
(
I
.
operand_values
(
)
)
;
Cost
+=
getUserCost
(
&
I
,
Operands
,
TargetTransformInfo
::
TCK_SizeAndLatency
)
;
}
}
LLVM_DEBUG
(
dbgs
(
)
<<
"Cost of loop: "
<<
Cost
<<
"\n"
)
;
UP
.
Partial
=
true
;
UP
.
Runtime
=
true
;
UP
.
UnrollRemainder
=
true
;
UP
.
UnrollAndJam
=
true
;
UP
.
UnrollAndJamInnerLoopThreshold
=
60
;
if
(
Cost
<
12
)
UP
.
Force
=
true
;
}
</s>

Get target-customized preferences for the generic loop unrolling transformation .


<s> void RISCVTargetLowering :: AdjustInstrPostInstrSelection ( MachineInstr & MI , SDNode * Node ) const { unsigned Opc = MI . getOpcode ( ) ; auto Idx = RISCV :: getNamedOperandIdx ( Opc , RISCV :: OpName :: frm ) ; if ( Idx < 0 ) return ; if ( MI . getOperand ( Idx ) . getImm ( ) != RISCVFPRndMode :: DYN ) return ; if ( MI . readsRegister ( RISCV :: FRM ) ) return ; MI . addOperand ( MachineOperand :: CreateReg ( RISCV :: FRM , false , true ) ) ; } </s>

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

RISCV RISCV RISCV::getNamedOperandIdx RISCV::OpName 0 RISCVFPRndMode::DYN RISCV::FRM RISCV::FRM


"Not all fixup kinds added to Infos array"


<s> const RegisterBankInfo * RISCVSubtarget :: getRegBankInfo ( ) const { return RegBankInfo . get ( ) ; } </s>

If the information for the register banks is available , return it .


<s> void RISCVFrameLowering :: eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator I ) const { const RISCVInstrInfo & TII = * static_cast < const RISCVInstrInfo * > ( MF . getSubtarget ( ) . getInstrInfo ( ) ) ; const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; if ( ! hasReservedCallFrame ( MF ) ) { int64_t Amount = I -> getOperand ( 0 ) . getImm ( ) ; if ( I -> getOpcode ( ) == RISCV :: ADJCALLSTACKDOWN ) Amount = - Amount ; unsigned SP = STI . isRV64 ( ) ? RISCV :: sp_64 : RISCV :: sp ; TII . adjustStackPtr ( SP , Amount , MBB , I ) ; } MBB . erase ( I ) ; } </s>

This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy pseudo instructions ( but only if the Target is using them ) .

RISCV RISCV RISCV RISCV RISCV RISCV 0 RISCV::ADJCALLSTACKDOWN RISCV::sp_64 RISCV::sp


<s> void RISCVPassConfig :: addPreEmitPass2 ( ) { addPass ( createRISCVExpandPseudoPass ( ) ) ; if ( TM -> getOptLevel ( ) != CodeGenOpt :: None ) { addPass ( createRISCVPulpHWLoopsPass ( ) ) ; } } </s>

Targets may add passes immediately before machine code is emitted in this callback .


<s> void riscv_d_register_target_info ( void ) { const struct d_target_info_spec handlers [ ] = { { "floatAbi" , riscv_d_handle_target_float_abi } , { NULL , NULL } , } ; d_add_target_info_handlers ( handlers ) ; } </s>


<s> void function_builder :: apply_predication ( const function_instance & instance , tree return_type , vec < tree > & argument_types ) const { if ( instance . base -> has_merge_operand_p ( ) ) if ( instance . pred == PRED_TYPE_tu || instance . pred == PRED_TYPE_tum || instance . pred == PRED_TYPE_tumu || instance . pred == PRED_TYPE_mu ) argument_types . quick_insert ( 0 , return_type ) ; vector_type_index mask_type_index = function_types [ instance . type . index ] . type_indexes [ RVV_BASE_mask ] ; tree mask_type = builtin_types [ mask_type_index ] . vector ; if ( instance . pred == PRED_TYPE_m || instance . pred == PRED_TYPE_tum || instance . pred == PRED_TYPE_tumu || instance . pred == PRED_TYPE_mu ) argument_types . quick_insert ( 0 , mask_type ) ; if ( instance . base -> apply_vl_p ( ) ) argument_types . quick_push ( size_type_node ) ; } </s>


<s> const MCPhysReg * RISCVRegisterInfo :: getCalleeSavedRegs ( const MachineFunction * MF ) const { return CSR_SaveList ; } </s>


<s> void riscv_expand_float_scc ( rtx target , enum rtx_code code , rtx op0 , rtx op1 ) { riscv_emit_float_compare ( & code , & op0 , & op1 ) ; rtx cmp = riscv_force_binary ( word_mode , code , op0 , op1 ) ; riscv_emit_set ( target , lowpart_subreg ( SImode , cmp , word_mode ) ) ; } </s>

Like riscv_expand_int_scc , but for floating-point comparisons .


<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 :: 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 RISCVTargetLowering :: LowerAsmOperandForConstraint ( SDValue Op , std :: string & Constraint , std :: vector < SDValue > & Ops , SelectionDAG & DAG ) const { if ( Constraint . length ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'I' : if ( auto * C = dyn_cast < ConstantSDNode > ( Op ) ) { uint64_t CVal = C -> getSExtValue ( ) ; if ( isInt < 12 > ( CVal ) ) Ops . push_back ( DAG . getTargetConstant ( CVal , SDLoc ( Op ) , Subtarget . getXLenVT ( ) ) ) ; } return ; case 'J' : if ( auto * C = dyn_cast < ConstantSDNode > ( Op ) ) if ( C -> getZExtValue ( ) == 0 ) Ops . push_back ( DAG . getTargetConstant ( 0 , SDLoc ( Op ) , Subtarget . getXLenVT ( ) ) ) ; return ; case 'K' : if ( auto * C = dyn_cast < ConstantSDNode > ( Op ) ) { uint64_t CVal = C -> getZExtValue ( ) ; if ( isUInt < 5 > ( CVal ) ) Ops . push_back ( DAG . getTargetConstant ( CVal , SDLoc ( Op ) , Subtarget . getXLenVT ( ) ) ) ; } return ; default : break ; } } TargetLowering :: LowerAsmOperandForConstraint ( Op , Constraint , Ops , DAG ) ; } </s>

Lower the specified operand into the Ops vector .


<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
)
;
case
ISD
::
VASTART
:
return
lowerVASTART
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
LowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
return
LowerRETURNADDR
(
Op
,
DAG
)
;
}
}
</s>

RISCV
RISCV
"unimplemented operand"
ISD::GlobalAddress
ISD::BlockAddress
ISD::SELECT
ISD::VASTART
ISD::FRAMEADDR
ISD::RETURNADDR


<s>
void
RISCVAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
)
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
FullSize
=
getSize
(
Fixup
.
getKind
(
)
)
;
unsigned
NumBytes
=
(
Info
.
TargetSize
+
7
)
/
8
;
assert
(
Offset
+
NumBytes
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
!=
FullSize
;
++
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
vector_insn_info
::
compatible_p
(
const
vl_vtype_info
&
curr_info
)
const
{
gcc_assert
(
!
uninit_p
(
)
&&
"Can't handle uninitialized info"
)
;
if
(
empty_p
(
)
)
return
false
;
if
(
unknown_p
(
)
)
return
false
;
if
(
!
demand_p
(
DEMAND_AVL
)
)
if
(
m_sew
==
curr_info
.
get_sew
(
)
)
return
true
;
return
compatible_avl_p
(
curr_info
)
&&
compatible_vtype_p
(
curr_info
)
;
}
</s>

Determine whether the vector instructions requirements represented by Require are compatible with the previous vsetvli instruction represented by this . INSN is the instruction whose requirements we 're considering .


<s> unsigned int calculate_ratio ( unsigned int sew , enum vlmul_type vlmul ) { unsigned int ratio ; switch ( vlmul ) { case LMUL_1 : ratio = sew ; break ; case LMUL_2 : ratio = sew / 2 ; break ; case LMUL_4 : ratio = sew / 4 ; break ; case LMUL_8 : ratio = sew / 8 ; break ; case LMUL_F8 : ratio = sew * 8 ; break ; case LMUL_F4 : ratio = sew * 4 ; break ; case LMUL_F2 : ratio = sew * 2 ; break ; default : gcc_unreachable ( ) ; } return ratio ; } </s>


<s>
void
RISCVMCCodeEmitter
::
encodeInstruction
(
const
MCInst
&
MI
,
raw_ostream
&
OS
,
SmallVectorImpl
<
MCFixup
>
&
Fixups
,
const
MCSubtargetInfo
&
STI
)
const
{
const
MCInstrDesc
&
Desc
=
MCII
.
get
(
MI
.
getOpcode
(
)
)
;
unsigned
Size
=
Desc
.
getSize
(
)
;
switch
(
Size
)
{
default
:
llvm_unreachable
(
"Unhandled encodeInstruction length!"
)
;
case
2
:
{
uint16_t
Bits
=
getBinaryCodeForInstr
(
MI
,
Fixups
,
STI
)
;
support
::
endian
::
Writer
<
support
::
little
>
(
OS
)
.
write
<
uint16_t
>
(
Bits
)
;
break
;
}
case
4
:
{
uint32_t
Bits
=
getBinaryCodeForInstr
(
MI
,
Fixups
,
STI
)
;
support
::
endian
::
Writer
<
support
::
little
>
(
OS
)
.
write
(
Bits
)
;
break
;
}
}
++
MCNumEmitted
;
}
</s>

Encode the given Inst to bytes and append to CB .

RISCV
RISCV
"Unhandled encodeInstruction length!"
2
support::endian
support::little
4
support::endian
support::little


<s> bool riscv_expand_conditional_move ( rtx dest , rtx op , rtx cons , rtx alt ) { machine_mode mode = GET_MODE ( dest ) ; rtx_code code = GET_CODE ( op ) ; rtx op0 = XEXP ( op , 0 ) ; rtx op1 = XEXP ( op , 1 ) ; if ( TARGET_XTHEADCONDMOV && GET_MODE_CLASS ( mode ) == MODE_INT && reg_or_0_operand ( cons , mode ) && reg_or_0_operand ( alt , mode ) && GET_MODE ( op ) == mode && GET_MODE ( op0 ) == mode && GET_MODE ( op1 ) == mode && ( code == EQ || code == NE ) ) { riscv_expand_conditional_move_onesided ( dest , cons , alt , code , op0 , op1 ) ; return true ; } else if ( TARGET_SFB_ALU && mode == word_mode ) { riscv_emit_int_compare ( & code , & op0 , & op1 ) ; rtx cond = gen_rtx_fmt_ee ( code , GET_MODE ( op0 ) , op0 , op1 ) ; cons = force_reg ( GET_MODE ( dest ) , cons ) ; emit_insn ( gen_rtx_SET ( dest , gen_rtx_IF_THEN_ELSE ( GET_MODE ( dest ) , cond , cons , alt ) ) ) ; return true ; } return false ; } </s>

Emit a cond move : If OP holds , move CONS to DEST ; else move ALT to DEST . Return 0 if expansion failed .


<s>
void
RISCVDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
if
(
Node
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
Node
->
setNodeId
(
1
)
;
return
;
}
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
MVT
XLenVT
=
Subtarget
->
getXLenVT
(
)
;
SDLoc
DL
(
Node
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
switch
(
Opcode
)
{
case
ISD
::
Constant
:
{
auto
ConstNode
=
cast
<
ConstantSDNode
>
(
Node
)
;
if
(
VT
==
XLenVT
&&
ConstNode
->
isNullValue
(
)
)
{
SDValue
New
=
CurDAG
->
getCopyFromReg
(
CurDAG
->
getEntryNode
(
)
,
SDLoc
(
Node
)
,
RISCV
::
X0
,
XLenVT
)
;
ReplaceNode
(
Node
,
New
.
getNode
(
)
)
;
return
;
}
break
;
}
case
ISD
::
FrameIndex
:
{
SDValue
Imm
=
CurDAG
->
getTargetConstant
(
0
,
DL
,
XLenVT
)
;
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
ReplaceNode
(
Node
,
CurDAG
->
getMachineNode
(
RISCV
::
ADDI
,
DL
,
VT
,
TFI
,
Imm
)
)
;
return
;
}
}
SelectCode
(
Node
)
;
}
</s>

Main hook for targets to transform nodes into machine nodes .


<s> bool RISCVAsmBackend :: shouldInsertExtraNopBytesForCodeAlign ( const MCAlignFragment & AF , unsigned & Size ) { const MCSubtargetInfo * STI = AF . getSubtargetInfo ( ) ; if ( ! STI -> getFeatureBits ( ) [ RISCV :: FeatureRelax ] ) return false ; bool HasStdExtC = STI -> getFeatureBits ( ) [ RISCV :: FeatureStdExtC ] ; unsigned MinNopLen = HasStdExtC ? 2 : 4 ; if ( AF . getAlignment ( ) <= MinNopLen ) { return false ; } else { Size = AF . getAlignment ( ) - MinNopLen ; return true ; } } </s>

Hook to check if extra nop bytes must be inserted for alignment directive .

RISCV RISCV RISCV::FeatureRelax RISCV::FeatureStdExtC 2 4


<s> int RISCVFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , unsigned & FrameReg ) const { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterInfo * RI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; const std :: vector < CalleeSavedInfo > & CSI = 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 += MF . getFrameInfo ( ) . getStackSize ( ) ; } else if ( RI -> needsStackRealignment ( MF ) && ! MFI . isFixedObjectIndex ( FI ) ) { if ( hasBP ( MF ) ) FrameReg = RISCVABI :: getBPReg ( ) ; else FrameReg = RISCV :: X2 ; Offset += MF . getFrameInfo ( ) . getStackSize ( ) ; } else { FrameReg = RI -> getFrameRegister ( MF ) ; if ( hasFP ( MF ) ) Offset += RVFI -> getVarArgsSaveSize ( ) ; else Offset += MF . getFrameInfo ( ) . getStackSize ( ) ; } return Offset ; } </s>

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


<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 : 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 8 RISCV 0


"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 RISCVRedundantCopyElimination :: runOnMachineFunction ( MachineFunction & MF ) { if ( skipFunction ( MF . getFunction ( ) ) ) return false ; TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MRI = & MF . getRegInfo ( ) ; bool Changed = false ; for ( MachineBasicBlock & MBB : MF ) Changed |= optimizeBlock ( MBB ) ; return Changed ; } </s>

runOnMachineFunction - Emit the function body .


<s>
void
RISCVMCCodeEmitter
::
encodeInstruction
(
const
MCInst
&
MI
,
raw_ostream
&
OS
,
SmallVectorImpl
<
MCFixup
>
&
Fixups
,
const
MCSubtargetInfo
&
STI
)
const
{
verifyInstructionPredicates
(
MI
,
computeAvailableFeatures
(
STI
.
getFeatureBits
(
)
)
)
;
const
MCInstrDesc
&
Desc
=
MCII
.
get
(
MI
.
getOpcode
(
)
)
;
unsigned
Size
=
Desc
.
getSize
(
)
;
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCALLReg
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCALL
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoTAIL
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoJump
)
{
expandFunctionCall
(
MI
,
OS
,
Fixups
,
STI
)
;
MCNumEmitted
+=
2
;
return
;
}
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoAddTPRel
)
{
expandAddTPRel
(
MI
,
OS
,
Fixups
,
STI
)
;
MCNumEmitted
+=
1
;
return
;
}
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVMSGEU_VX
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVMSGE_VX
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVMSGEU_VX_M
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVMSGE_VX_M
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVMSGEU_VX_M_T
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVMSGE_VX_M_T
)
{
expandVMSGE
(
MI
,
OS
,
Fixups
,
STI
)
;
return
;
}
switch
(
Size
)
{
default
:
llvm_unreachable
(
"Unhandled encodeInstruction length!"
)
;
case
2
:
{
uint16_t
Bits
=
getBinaryCodeForInstr
(
MI
,
Fixups
,
STI
)
;
support
::
endian
::
write
<
uint16_t
>
(
OS
,
Bits
,
support
::
little
)
;
break
;
}
case
4
:
{
uint32_t
Bits
=
getBinaryCodeForInstr
(
MI
,
Fixups
,
STI
)
;
support
::
endian
::
write
(
OS
,
Bits
,
support
::
little
)
;
break
;
}
}
++
MCNumEmitted
;
}
</s>


<s> MCELFStreamer & RISCVTargetELFStreamer :: getStreamer ( ) { return static_cast < MCELFStreamer & > ( Streamer ) ; } </s>

Return the output streamer for the assembler .


<s> static bool check_required_extensions ( const function_instance & instance ) { rvv_type_info type_info = instance . type ; uint64_t required_extensions = type_info . required_extensions ; const rvv_op_info * op_info = instance . op_info ; if ( required_extensions_p ( op_info -> ret . base_type ) ) { enum vector_type_index ret_type_idx = op_info -> ret . get_function_type_index ( type_info . index ) ; if ( ret_type_idx == NUM_VECTOR_TYPES ) return false ; required_extensions |= get_required_extensions ( ret_type_idx ) ; } for ( unsigned i = 0 ; op_info -> args [ i ] . base_type != NUM_BASE_TYPES ; ++ i ) { if ( ! required_extensions_p ( op_info -> args [ i ] . base_type ) ) continue ; enum vector_type_index vector_type = op_info -> args [ i ] . get_function_type_index ( type_info . index ) ; if ( vector_type == NUM_VECTOR_TYPES ) return false ; required_extensions |= get_required_extensions ( vector_type ) ; if ( op_info -> args [ i ] . base_type == RVV_BASE_eew64_index ) required_extensions |= RVV_REQUIRE_RV64BIT ; } uint64_t riscv_isa_flags = 0 ; if ( TARGET_VECTOR_ELEN_FP_32 ) riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_32 ; if ( TARGET_VECTOR_ELEN_FP_64 ) riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_64 ; if ( TARGET_VECTOR_ELEN_64 ) riscv_isa_flags |= RVV_REQUIRE_ELEN_64 ; if ( TARGET_64BIT ) riscv_isa_flags |= RVV_REQUIRE_RV64BIT ; if ( TARGET_FULL_V ) riscv_isa_flags |= RVV_REQUIRE_FULL_V ; if ( TARGET_MIN_VLEN > 32 ) riscv_isa_flags |= RVV_REQUIRE_MIN_VLEN_64 ; uint64_t missing_extensions = required_extensions & ~ riscv_isa_flags ; if ( missing_extensions != 0 ) return false ; return true ; } </s>

Check whether all the RVV_REQUIRE_ * values in REQUIRED_EXTENSIONS are enabled .


"insertBranch must not be told to insert a fallthrough"

"RISCV branch conditions have two components!"

Insert branch code into the end of the specified MachineBasicBlock .


<s> void RISCVPassConfig :: addPreEmitPass ( ) { addPass ( createRISCVBranchSelectionPass ( ) ) ; } </s>

This pass may be implemented by targets that want to run passes immediately before machine code is emitted .


<s> bool RISCVTargetLowering :: mergeStoresAfterLegalization ( EVT VT ) const { return ! Subtarget . useRVVForFixedLengthVectors ( ) || ( VT . isFixedLengthVector ( ) && VT . getVectorElementType ( ) == MVT :: i1 ) ; } </s>

Do not merge vector stores after legalization because that may conflict with x86-specific store splitting optimizations .


"ReadCycleWrite is only to be used on riscv32"

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


<s>
void
RISCVTargetELFStreamer
::
finish
(
)
{
RISCVTargetStreamer
::
finish
(
)
;
MCAssembler
&
MCA
=
getStreamer
(
)
.
getAssembler
(
)
;
const
FeatureBitset
&
Features
=
STI
.
getFeatureBits
(
)
;
RISCVABI
::
ABI
ABI
=
getTargetABI
(
)
;
unsigned
EFlags
=
MCA
.
getELFHeaderEFlags
(
)
;
if
(
Features
[
RISCV
::
FeatureStdExtC
]
)
EFlags
|=
ELF
::
EF_RISCV_RVC
;
switch
(
ABI
)
{
case
RISCVABI
::
ABI_ILP32
:
case
RISCVABI
::
ABI_LP64
:
break
;
case
RISCVABI
::
ABI_ILP32F
:
case
RISCVABI
::
ABI_LP64F
:
EFlags
|=
ELF
::
EF_RISCV_FLOAT_ABI_SINGLE
;
break
;
case
RISCVABI
::
ABI_ILP32D
:
case
RISCVABI
::
ABI_LP64D
:
EFlags
|=
ELF
::
EF_RISCV_FLOAT_ABI_DOUBLE
;
break
;
case
RISCVABI
::
ABI_ILP32E
:
EFlags
|=
ELF
::
EF_RISCV_RVE
;
break
;
case
RISCVABI
::
ABI_Unknown
:
llvm_unreachable
(
"Improperly initialised target ABI"
)
;
}
MCA
.
setELFHeaderEFlags
(
EFlags
)
;
}
</s>

finish - after all the new live ranges have been created , compute the remaining live range , and rewrite instructions to use the new registers .


<s> rtx riscv_emit_move ( rtx dest , rtx src ) { return ( can_create_pseudo_p ( ) ? emit_move_insn ( dest , src ) : emit_move_insn_1 ( dest , src ) ) ; } </s>

Emit a move from SRC to DEST . Assume that the move expanders can handle all moves if ! can_create_pseudo_p ( ) . The distinction is important because , unlike emit_move_insn , the move expanders know how to force Pmode objects into the constant pool even when the constant pool address is not itself legitimate .


<s> bool RISCVMCAsmBackend :: writeNopData ( uint64_t Count , MCObjectWriter * OW ) const { for ( uint64_t I = 0 ; I != Count ; ++ I ) OW -> write8 ( 7 ) ; return true ; } </s>

Write an ( optimal ) nop sequence of Count bytes to the given output .


<s> static void riscv_conditional_register_usage ( void ) { if ( ! TARGET_HARD_FLOAT ) { for ( int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) fixed_regs [ regno ] = call_used_regs [ regno ] = 1 ; } } </s>


<s> Value * RISCVTargetLowering :: emitMaskedAtomicCmpXchgIntrinsic ( IRBuilderBase & Builder , AtomicCmpXchgInst * CI , Value * AlignedAddr , Value * CmpVal , Value * NewVal , Value * Mask , AtomicOrdering Ord ) const { unsigned XLen = Subtarget . getXLen ( ) ; Value * Ordering = Builder . getIntN ( XLen , static_cast < uint64_t > ( Ord ) ) ; Intrinsic :: ID CmpXchgIntrID = Intrinsic :: riscv_masked_cmpxchg_i32 ; if ( XLen == 64 ) { CmpVal = Builder . CreateSExt ( CmpVal , Builder . getInt64Ty ( ) ) ; NewVal = Builder . CreateSExt ( NewVal , Builder . getInt64Ty ( ) ) ; Mask = Builder . CreateSExt ( Mask , Builder . getInt64Ty ( ) ) ; CmpXchgIntrID = Intrinsic :: riscv_masked_cmpxchg_i64 ; } Type * Tys [ ] = { AlignedAddr -> getType ( ) } ; Function * MaskedCmpXchg = Intrinsic :: getDeclaration ( CI -> getModule ( ) , CmpXchgIntrID , Tys ) ; Value * Result = Builder . CreateCall ( MaskedCmpXchg , { AlignedAddr , CmpVal , NewVal , Mask , Ordering } ) ; if ( XLen == 64 ) Result = Builder . CreateTrunc ( Result , Builder . getInt32Ty ( ) ) ; return Result ; } </s>

Perform a masked cmpxchg using a target-specific intrinsic .


<s> void RISCVInstrInfo :: buildOutlinedFrame ( MachineBasicBlock & MBB , MachineFunction & MF , const outliner :: OutlinedFunction & OF ) const { bool Changed = true ; while ( Changed ) { Changed = false ; auto I = MBB . begin ( ) ; auto E = MBB . end ( ) ; for ( ; I != E ; ++ I ) { if ( I -> isCFIInstruction ( ) ) { I -> removeFromParent ( ) ; Changed = true ; break ; } } } MBB . insert ( MBB . end ( ) , BuildMI ( MF , DebugLoc ( ) , get ( RISCV :: JALR ) ) . addReg ( RISCV :: X0 , RegState :: Define ) . addReg ( RISCV :: X5 ) . addImm ( 0 ) ) ; } </s>

Insert a custom frame for outlined functions .


<s> bool RISCVAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , unsigned AsmVariant , const char * ExtraCode , raw_ostream & OS ) { if ( ExtraCode && * ExtraCode == 'n' ) { if ( ! MI -> getOperand ( OpNo ) . isImm ( ) ) return true ; OS << - int64_t ( MI -> getOperand ( OpNo ) . getImm ( ) ) ; } else { printOperand ( MI , OpNo , OS ) ; } return false ; } </s>

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


<s> BitVector RISCVRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { const RISCVFrameLowering * TFI = getFrameLowering ( MF ) ; const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; BitVector Reserved ( getNumRegs ( ) ) ; for ( size_t Reg = 0 ; Reg < getNumRegs ( ) ; Reg ++ ) { if ( STI . 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 , RISCV :: X9 ) ; markSuperRegs ( Reserved , RISCV :: C0 ) ; markSuperRegs ( Reserved , RISCV :: C2 ) ; markSuperRegs ( Reserved , RISCV :: C3 ) ; markSuperRegs ( Reserved , RISCV :: C4 ) ; if ( TFI -> hasFP ( MF ) ) markSuperRegs ( Reserved , RISCV :: C8 ) ; if ( TFI -> hasBP ( MF ) ) markSuperRegs ( Reserved , RISCV :: C9 ) ; markSuperRegs ( Reserved , RISCV :: DDC ) ; markSuperRegs ( Reserved , RISCV :: VL ) ; markSuperRegs ( Reserved , RISCV :: VTYPE ) ; markSuperRegs ( Reserved , RISCV :: VXSAT ) ; markSuperRegs ( Reserved , RISCV :: VXRM ) ; markSuperRegs ( Reserved , RISCV :: FRM ) ; markSuperRegs ( Reserved , RISCV :: FFLAGS ) ; markSuperRegs ( Reserved , RISCV :: FCSR ) ; 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> bool RISCVInstrInfo :: shouldOutlineFromFunctionByDefault ( MachineFunction & MF ) const { return MF . getFunction ( ) . hasMinSize ( ) ; } </s>

Return true if the function should be outlined from by default .


<s>
void
print
(
raw_ostream
&
OS
)
const
override
{
auto
RegName
=
[
]
(
unsigned
Reg
)
{
if
(
Reg
)
return
RISCVInstPrinter
::
getRegisterName
(
Reg
)
;
else
return
"noreg"
;
}
;
switch
(
Kind
)
{
case
KindTy
::
Immediate
:
OS
<<
*
getImm
(
)
;
break
;
case
KindTy
::
Register
:
OS
<<
"<register "
<<
RegName
(
getReg
(
)
)
<<
">"
;
break
;
case
KindTy
::
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
case
KindTy
::
SystemRegister
:
OS
<<
"<sysreg: "
<<
getSysReg
(
)
<<
'>'
;
break
;
case
KindTy
::
VType
:
OS
<<
"<vtype: "
;
RISCVVType
::
printVType
(
getVType
(
)
,
OS
)
;
OS
<<
'>'
;
break
;
}
}
</s>

print - Print a debug representation of the operand to the given stream .

RISCV
RISCV
"noreg"
"<register "
">"
"'"
"'"
"<sysreg: "
"<vtype: "
RISCV


<s> static bool riscv_secondary_memory_needed ( machine_mode mode , reg_class_t class1 , reg_class_t class2 ) { return ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD && ( class1 == FP_REGS ) != ( class2 == FP_REGS ) ) ; } </s>

Implement TARGET_SECONDARY_MEMORY_NEEDED . When floating-point registers are wider than integer ones , moves between them must go through memory .


<s> static bool riscv_pass_by_reference ( cumulative_args_t cum_v , const function_arg_info & arg ) { HOST_WIDE_INT size = arg . type_size_in_bytes ( ) ; struct riscv_arg_info info ; CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; if ( cum != NULL ) { riscv_get_arg_info ( & info , cum , arg . mode , arg . type , arg . named , false ) ; if ( info . num_fprs ) return false ; } return ! IN_RANGE ( size , 0 , 2 * UNITS_PER_WORD ) ; } </s>


<s> void riscv_expand_prologue ( void ) { struct riscv_frame_info * frame = & cfun -> machine -> frame ; HOST_WIDE_INT size = frame -> total_size ; unsigned mask = frame -> mask ; rtx insn ; if ( cfun -> machine -> naked_p ) { if ( flag_stack_usage_info ) current_function_static_stack_size = 0 ; return ; } if ( flag_stack_usage_info ) current_function_static_stack_size = size ; if ( riscv_use_save_libcall ( frame ) ) { rtx dwarf = NULL_RTX ; dwarf = riscv_adjust_libcall_cfi_prologue ( ) ; frame -> mask = 0 ; size -= frame -> save_libcall_adjustment ; insn = emit_insn ( gen_gpr_save ( GEN_INT ( mask ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; REG_NOTES ( insn ) = dwarf ; } if ( ( frame -> mask | frame -> fmask ) != 0 ) { HOST_WIDE_INT step1 = MIN ( size , riscv_first_stack_step ( frame ) ) ; 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 ) ; } 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 ) ) ; RTX_FRAME_RELATED_P ( emit_insn ( insn ) ) = 1 ; riscv_emit_stack_tie ( ) ; } if ( size > 0 ) { if ( SMALL_OPERAND ( - size ) ) { insn = gen_add3_insn ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - size ) ) ; RTX_FRAME_RELATED_P ( emit_insn ( insn ) ) = 1 ; } else { riscv_emit_move ( RISCV_PROLOGUE_TEMP ( Pmode ) , GEN_INT ( - size ) ) ; emit_insn ( gen_add3_insn ( stack_pointer_rtx , stack_pointer_rtx , RISCV_PROLOGUE_TEMP ( Pmode ) ) ) ; insn = plus_constant ( Pmode , stack_pointer_rtx , - size ) ; insn = gen_rtx_SET ( stack_pointer_rtx , insn ) ; riscv_set_frame_expr ( insn ) ; } } } </s>


<s> bool RISCVTargetMachine :: isNoopAddrSpaceCast ( unsigned SrcAS , unsigned DstAS ) const { const bool SrcIsCheri = isCheriPointer ( SrcAS , nullptr ) ; const bool DestIsCheri = isCheriPointer ( DstAS , nullptr ) ; if ( ( SrcIsCheri || DestIsCheri ) && ( SrcIsCheri != DestIsCheri ) ) return false ; return true ; } </s>

Returns true if a cast between SrcAS and DestAS is a noop .


<s> static bool riscv_function_ok_for_sibcall ( tree decl ATTRIBUTE_UNUSED , tree exp ATTRIBUTE_UNUSED ) { if ( TARGET_SAVE_RESTORE ) return false ; if ( cfun -> machine -> naked_p ) return false ; return true ; } </s>


<s>
const
MCPhysReg
*
RISCVRegisterInfo
::
getCalleeSavedRegs
(
const
MachineFunction
*
MF
)
const
{
auto
&
Subtarget
=
MF
->
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
MF
->
getFunction
(
)
.
getCallingConv
(
)
==
CallingConv
::
GHC
)
return
CSR_NoRegs_SaveList
;
if
(
MF
->
getFunction
(
)
.
hasFnAttribute
(
"interrupt"
)
)
{
if
(
Subtarget
.
hasStdExtD
(
)
)
return
Subtarget
.
hasCheri
(
)
CSR_XLEN_CLEN_F64_Interrupt_SaveList
:
CSR_XLEN_F64_Interrupt_SaveList
;
if
(
Subtarget
.
hasStdExtF
(
)
)
return
Subtarget
.
hasCheri
(
)
CSR_XLEN_CLEN_F32_Interrupt_SaveList
:
CSR_XLEN_F32_Interrupt_SaveList
;
return
Subtarget
.
hasCheri
(
)
CSR_XLEN_CLEN_Interrupt_SaveList
:
CSR_Interrupt_SaveList
;
}
switch
(
Subtarget
.
getTargetABI
(
)
)
{
default
:
llvm_unreachable
(
"Unrecognized ABI"
)
;
case
RISCVABI
::
ABI_ILP32
:
case
RISCVABI
::
ABI_LP64
:
return
CSR_ILP32_LP64_SaveList
;
case
RISCVABI
::
ABI_IL32PC64
:
case
RISCVABI
::
ABI_L64PC128
:
return
CSR_IL32PC64_L64PC128_SaveList
;
case
RISCVABI
::
ABI_ILP32F
:
case
RISCVABI
::
ABI_LP64F
:
return
CSR_ILP32F_LP64F_SaveList
;
case
RISCVABI
::
ABI_IL32PC64F
:
case
RISCVABI
::
ABI_L64PC128F
:
return
CSR_IL32PC64F_L64PC128F_SaveList
;
case
RISCVABI
::
ABI_ILP32D
:
case
RISCVABI
::
ABI_LP64D
:
return
CSR_ILP32D_LP64D_SaveList
;
case
RISCVABI
::
ABI_IL32PC64D
:
case
RISCVABI
::
ABI_L64PC128D
:
return
CSR_IL32PC64D_L64PC128D_SaveList
;
}
}
</s>


<s>
void
RISCVDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
MVT
XLenVT
=
Subtarget
->
getXLenVT
(
)
;
DEBUG
(
dbgs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
Node
->
setNodeId
(
1
)
;
return
;
}
EVT
VT
=
Node
->
getValueType
(
0
)
;
if
(
Opcode
==
ISD
::
Constant
&&
VT
==
XLenVT
)
{
auto
*
ConstNode
=
cast
<
ConstantSDNode
>
(
Node
)
;
if
(
ConstNode
->
isNullValue
(
)
)
{
SDValue
New
=
CurDAG
->
getCopyFromReg
(
CurDAG
->
getEntryNode
(
)
,
SDLoc
(
Node
)
,
RISCV
::
X0
,
XLenVT
)
;
ReplaceNode
(
Node
,
New
.
getNode
(
)
)
;
return
;
}
}
SelectCode
(
Node
)
;
}
</s>

Main hook for targets to transform nodes into machine nodes .

RISCV
RISCV
"Selecting: "
"\n"
"== "
"\n"
1
0
ISD::Constant
RISCV::X0


<s> registered_function & function_builder :: add_function ( const function_instance & instance , const char * name , tree fntype , tree attrs , bool placeholder_p ) { unsigned int code = vec_safe_length ( registered_functions ) ; code = ( code << RISCV_BUILTIN_SHIFT ) + RISCV_BUILTIN_VECTOR ; tree decl = placeholder_p ? integer_zero_node : simulate_builtin_function_decl ( input_location , name , fntype , code , NULL , attrs ) ; registered_function & rfn = * ggc_alloc < registered_function > ( ) ; rfn . instance = instance ; rfn . decl = decl ; vec_safe_push ( registered_functions , & rfn ) ; return rfn ; } </s>

Add a function called NAME with type FNTYPE and attributes ATTRS . INSTANCE describes what the function does .


<s> bool RISCVTargetLowering :: decomposeMulByConstant ( LLVMContext & Context , EVT VT , SDValue C ) const { if ( VT . isScalarInteger ( ) ) { if ( ! Subtarget . is64Bit ( ) && Subtarget . hasStdExtM ( ) ) return false ; if ( auto * ConstNode = dyn_cast < ConstantSDNode > ( C . getNode ( ) ) ) { if ( ConstNode -> getAPIntValue ( ) . getBitWidth ( ) > 8 * sizeof ( int64_t ) ) return false ; int64_t Imm = ConstNode -> getSExtValue ( ) ; if ( isPowerOf2_64 ( Imm + 1 ) || isPowerOf2_64 ( Imm - 1 ) || isPowerOf2_64 ( 1 - Imm ) || isPowerOf2_64 ( - 1 - Imm ) ) return true ; } } return false ; } </s>

Return true if it is profitable to transform an integer multiplication-by-constant into simpler operations like shifts and adds .


<s> bool RISCVInstrInfo :: isAsCheapAsAMove ( const MachineInstr & MI ) const { const unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { default : break ; case RISCV :: ADDI : case RISCV :: ORI : case RISCV :: XORI : return ( MI . getOperand ( 1 ) . isReg ( ) && MI . getOperand ( 1 ) . getReg ( ) == RISCV :: X0 ) ; } return MI . isAsCheapAsAMove ( ) ; } </s>

Return true if the instruction is as cheap as a move instruction .


<s> void RISCVPassConfig :: addISelPrepare ( ) { TargetPassConfig :: addISelPrepare ( ) ; } </s>

Add common passes that perform LLVM IR to IR transforms in preparation for instruction selection .


<s> void RISCVTargetStreamer :: emitTargetAttributes ( const MCSubtargetInfo & STI ) { if ( STI . hasFeature ( RISCV :: FeatureRV32E ) ) emitAttribute ( RISCVAttrs :: STACK_ALIGN , RISCVAttrs :: ALIGN_4 ) ; else emitAttribute ( RISCVAttrs :: STACK_ALIGN , RISCVAttrs :: ALIGN_16 ) ; std :: string Arch = "rv32" ; if ( STI . hasFeature ( RISCV :: Feature64Bit ) ) Arch = "rv64" ; if ( STI . hasFeature ( RISCV :: FeatureRV32E ) ) Arch += "e1p9" ; else Arch += "i2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtM ) ) Arch += "_m2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtA ) ) Arch += "_a2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtF ) ) Arch += "_f2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtD ) ) Arch += "_d2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtC ) ) Arch += "_c2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtB ) ) Arch += "_b0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtV ) ) Arch += "_v0p10" ; if ( STI . hasFeature ( RISCV :: FeatureExtZfh ) ) Arch += "_zfh0p1" ; if ( STI . hasFeature ( RISCV :: FeatureExtZba ) ) Arch += "_zba0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbb ) ) Arch += "_zbb0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbc ) ) Arch += "_zbc0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbe ) ) Arch += "_zbe0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbf ) ) Arch += "_zbf0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbm ) ) Arch += "_zbm0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbp ) ) Arch += "_zbp0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbproposedc ) ) Arch += "_zbproposedc0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbr ) ) Arch += "_zbr0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbs ) ) Arch += "_zbs0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbt ) ) Arch += "_zbt0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZvamo ) ) Arch += "_zvamo0p10" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZvlsseg ) ) Arch += "_zvlsseg0p10" ; emitTextAttribute ( RISCVAttrs :: ARCH , Arch ) ; } </s>

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


<s> static bool riscv_check_builtin_call ( location_t loc , vec < location_t > arg_loc , tree fndecl , tree orig_fndecl , unsigned int nargs , tree * args ) { unsigned int code = DECL_MD_FUNCTION_CODE ( fndecl ) ; unsigned int subcode = code >> RISCV_BUILTIN_SHIFT ; switch ( code & RISCV_BUILTIN_CLASS ) { case RISCV_BUILTIN_GENERAL : return true ; case RISCV_BUILTIN_VECTOR : return riscv_vector :: check_builtin_call ( loc , arg_loc , subcode , orig_fndecl , nargs , args ) ; } gcc_unreachable ( ) ; } </s>


<s> MachineBasicBlock :: iterator RISCVInstrInfo :: insertOutlinedCall ( Module & M , MachineBasicBlock & MBB , MachineBasicBlock :: iterator & It , MachineFunction & MF , const outliner :: Candidate & C ) const { It = MBB . insert ( It , BuildMI ( MF , DebugLoc ( ) , get ( RISCV :: PseudoCALLReg ) , RISCV :: X5 ) . addGlobalAddress ( M . getNamedValue ( MF . getName ( ) ) , 0 , RISCVII :: MO_CALL ) ) ; return It ; } </s>

Insert a call to an outlined function into the program .


<s> void RISCVTargetLowering :: LowerAsmOperandForConstraint ( SDValue Op , std :: string & Constraint , std :: vector < SDValue > & Ops , SelectionDAG & DAG ) const { if ( Constraint . length ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'I' : if ( ConstantSDNode * C = dyn_cast < ConstantSDNode > ( Op ) ) if ( isUInt < 8 > ( C -> getZExtValue ( ) ) ) Ops . push_back ( DAG . getTargetConstant ( C -> getZExtValue ( ) , SDLoc ( Op ) , Op . getValueType ( ) ) ) ; return ; case 'J' : if ( ConstantSDNode * C = dyn_cast < ConstantSDNode > ( Op ) ) if ( isUInt < 12 > ( C -> getZExtValue ( ) ) ) Ops . push_back ( DAG . getTargetConstant ( C -> getZExtValue ( ) , SDLoc ( Op ) , Op . getValueType ( ) ) ) ; return ; case 'K' : if ( ConstantSDNode * C = dyn_cast < ConstantSDNode > ( Op ) ) if ( isInt < 16 > ( C -> getSExtValue ( ) ) ) Ops . push_back ( DAG . getTargetConstant ( C -> getSExtValue ( ) , SDLoc ( Op ) , Op . getValueType ( ) ) ) ; return ; case 'L' : if ( ConstantSDNode * C = dyn_cast < ConstantSDNode > ( Op ) ) if ( isInt < 20 > ( C -> getSExtValue ( ) ) ) Ops . push_back ( DAG . getTargetConstant ( C -> getSExtValue ( ) , SDLoc ( Op ) , Op . getValueType ( ) ) ) ; return ; case 'M' : if ( ConstantSDNode * C = dyn_cast < ConstantSDNode > ( Op ) ) if ( C -> getZExtValue ( ) == 0x7fffffff ) Ops . push_back ( DAG . getTargetConstant ( C -> getZExtValue ( ) , SDLoc ( Op ) , Op . getValueType ( ) ) ) ; return ; } } TargetLowering :: LowerAsmOperandForConstraint ( Op , Constraint , Ops , DAG ) ; } </s>

Lower the specified operand into the Ops vector .


<s> void RISCVTargetObjectFile :: Initialize ( MCContext & Ctx , const TargetMachine & TM ) { TargetLoweringObjectFileELF :: Initialize ( Ctx , TM ) ; InitializeELF ( TM . Options . UseInitArray ) ; } </s>

This method must be called before any actual lowering is done .


<s> static SDValue getTargetNode ( JumpTableSDNode * N , SDLoc DL , EVT Ty , SelectionDAG & DAG , unsigned Flags ) { return DAG . getTargetJumpTable ( N -> getIndex ( ) , Ty , Flags ) ; } </s>

Retrieve the target node this edge connects to .


<s> static rtx_insn * riscv_sr_match_epilogue ( void ) { rtx_insn * insn , * start ; for ( insn = get_insns ( ) ; insn != NULL ; insn = NEXT_INSN ( insn ) ) if ( NOTE_P ( insn ) && NOTE_KIND ( insn ) == NOTE_INSN_EPILOGUE_BEG ) { insn = NEXT_INSN ( insn ) ; break ; } if ( insn == NULL ) return NULL ; start = insn ; if ( INSN_CODE ( insn ) != CODE_FOR_stack_tiesi && INSN_CODE ( insn ) != CODE_FOR_stack_tiedi ) return NULL ; insn = NEXT_INSN ( insn ) ; if ( INSN_P ( insn ) && GET_CODE ( PATTERN ( insn ) ) == USE ) insn = NEXT_INSN ( insn ) ; if ( ! INSN_P ( insn ) || INSN_CODE ( insn ) != CODE_FOR_gpr_restore ) return NULL ; insn = NEXT_INSN ( insn ) ; if ( ! INSN_P ( insn ) || INSN_CODE ( insn ) != CODE_FOR_gpr_restore_return ) return NULL ; return start ; } </s>

Find the first instruction in the epilogue of the current function , and return a pointer to that instruction if , and only if , the epilogue has the correct structure that would allow us to optimize out the call to _riscv_restore_0 .


<s> static bool required_extensions_p ( enum rvv_base_type type ) { return type == RVV_BASE_eew8_index || type == RVV_BASE_eew16_index || type == RVV_BASE_eew32_index || type == RVV_BASE_eew64_index || type == RVV_BASE_float_vector || type == RVV_BASE_double_trunc_float_vector || type == RVV_BASE_double_trunc_vector || type == RVV_BASE_widen_lmul1_vector || type == RVV_BASE_eew8_interpret || type == RVV_BASE_eew16_interpret || type == RVV_BASE_eew32_interpret || type == RVV_BASE_eew64_interpret || type == RVV_BASE_vlmul_ext_x2 || type == RVV_BASE_vlmul_ext_x4 || type == RVV_BASE_vlmul_ext_x8 || type == RVV_BASE_vlmul_ext_x16 || type == RVV_BASE_vlmul_ext_x32 || type == RVV_BASE_vlmul_ext_x64 ; } </s>

Return true if the type has required_extensions .


<s> std :: pair < unsigned , const TargetRegisterClass * > RISCVTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'd' : case 'r' : if ( Subtarget . isRV64 ( ) ) return std :: make_pair ( 0U , & RISCV :: GR64BitRegClass ) ; return std :: make_pair ( 0U , & RISCV :: GR32BitRegClass ) ; case 'f' : if ( Subtarget . hasD ( ) ) return std :: make_pair ( 0U , & RISCV :: FP64BitRegClass ) ; else if ( Subtarget . hasF ( ) ) return std :: make_pair ( 0U , & RISCV :: FP32BitRegClass ) ; else if ( Subtarget . isRV64 ( ) ) return std :: make_pair ( 0U , & RISCV :: GR64BitRegClass ) ; return std :: make_pair ( 0U , & RISCV :: GR32BitRegClass ) ; } } return TargetLowering :: getRegForInlineAsmConstraint ( TRI , Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


"Don't know how to custom type legalize this operation!"

ReplaceNodeResults - Replace the results of node with an illegal result type with new values built out of custom code .


<s>
StringRef
RISCVMCExpr
::
getVariantKindName
(
VariantKind
Kind
)
{
switch
(
Kind
)
{
case
VK_RISCV_Invalid
:
case
VK_RISCV_None
:
llvm_unreachable
(
"Invalid ELF symbol kind"
)
;
case
VK_RISCV_LO
:
return
"lo"
;
case
VK_RISCV_HI
:
return
"hi"
;
case
VK_RISCV_PCREL_LO
:
return
"pcrel_lo"
;
case
VK_RISCV_PCREL_HI
:
return
"pcrel_hi"
;
case
VK_RISCV_GOT_HI
:
return
"got_pcrel_hi"
;
case
VK_RISCV_TPREL_LO
:
return
"tprel_lo"
;
case
VK_RISCV_TPREL_HI
:
return
"tprel_hi"
;
case
VK_RISCV_TPREL_ADD
:
return
"tprel_add"
;
case
VK_RISCV_TLS_GOT_HI
:
return
"tls_ie_pcrel_hi"
;
case
VK_RISCV_TLS_GD_HI
:
return
"tls_gd_pcrel_hi"
;
case
VK_RISCV_CALL
:
return
"call"
;
case
VK_RISCV_CALL_PLT
:
return
"call_plt"
;
case
VK_RISCV_32_PCREL
:
return
"32_pcrel"
;
}
llvm_unreachable
(
"Invalid ELF symbol kind"
)
;
}
</s>

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

RISCV
RISCV
RISCV
RISCV
"Invalid ELF symbol kind"
RISCV
"lo"
RISCV
"hi"
RISCV
"pcrel_lo"
RISCV
"pcrel_hi"
RISCV
"got_pcrel_hi"
RISCV
"tprel_lo"
RISCV
"tprel_hi"
RISCV
"tprel_add"
RISCV
"tls_ie_pcrel_hi"
RISCV
"tls_gd_pcrel_hi"
RISCV
"call"
RISCV
"call_plt"
RISCV
"32_pcrel"
"Invalid ELF symbol kind"


<s> bool RISCVFrameLowering :: hasReservedCallFrame ( const MachineFunction & MF ) const { const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; return isInt < 12 > ( MFI -> getMaxCallFrameSize ( ) + getStackAlignment ( ) ) && ! MFI -> hasVarSizedObjects ( ) ; } </s>

hasReservedCallFrame - Under normal circumstances , when a frame pointer is not required , we reserve argument space for call sites in the function immediately on entry to the current function .


<s> unsigned RISCVInstrInfo :: isStoreToStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { return isSimpleMove ( MI , FrameIndex , RISCVII :: SimpleStore ) ; } </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 int riscv_arg_partial_bytes ( cumulative_args_t cum , const function_arg_info & generic_arg ) { struct riscv_arg_info arg ; riscv_get_arg_info ( & arg , get_cumulative_args ( cum ) , generic_arg . mode , generic_arg . type , generic_arg . named , false ) ; return arg . stack_p ? arg . num_gprs * UNITS_PER_WORD : 0 ; } </s>


<s> static unsigned riscv_pass_aggregate_in_fpr_pair_p ( const_tree type , riscv_aggregate_field fields [ 2 ] ) { int n = riscv_flatten_aggregate_argument ( type , fields ) ; for ( int i = 0 ; i < n ; i ++ ) if ( ! SCALAR_FLOAT_TYPE_P ( fields [ i ] . type ) ) return 0 ; return n > 0 ? n : 0 ; } </s>

See whether TYPE is a record whose fields should be returned in one or two floating-point registers . If so , populate FIELDS accordingly .


<s> void RISCVPassConfig :: addPreSched2 ( ) { } </s>

This method may be implemented by targets that want to run passes after prolog-epilog insertion and before the second instruction scheduling pass .


<s> bool RISCVAsmBackend :: mayNeedRelaxation ( const MCInst & Inst , const MCSubtargetInfo & STI ) const { return getRelaxedOpcode ( Inst . getOpcode ( ) ) != Inst . getOpcode ( ) ; } </s>

Check whether the given instruction may need relaxation .


<s> MachineBasicBlock :: iterator RISCVFrameLowering :: eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const { unsigned SPReg = RISCV :: X2 ; DebugLoc DL = MI -> getDebugLoc ( ) ; if ( ! hasReservedCallFrame ( MF ) ) { int64_t Amount = MI -> getOperand ( 0 ) . getImm ( ) ; if ( Amount != 0 ) { Amount = alignSPAdjust ( Amount ) ; if ( MI -> getOpcode ( ) == RISCV :: ADJCALLSTACKDOWN ) Amount = - Amount ; adjustReg ( MBB , MI , DL , SPReg , SPReg , Amount , MachineInstr :: NoFlags ) ; } } return MBB . erase ( MI ) ; } </s>

This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy pseudo instructions ( but only if the Target is using them ) .


<s> bool lowerOperand ( const MachineOperand & MO , MCOperand & MCOp ) const { return LowerRISCVMachineOperandToMCOperand ( MO , MCOp , * this ) ; } </s>

Wrapper for MCInstLowering.lowerOperand ( ) for the tblgen'erated pseudo lowering .


<s>
MachineInstr
*
RISCVInstrInfo
::
convertToThreeAddress
(
MachineInstr
&
MI
,
LiveVariables
*
LV
,
LiveIntervals
*
LIS
)
const
{
switch
(
MI
.
getOpcode
(
)
)
{
default
:
break
;
case
CASE_WIDEOP_OPCODE_LMULS_MF4
(
FWADD_WV
)
:
case
CASE_WIDEOP_OPCODE_LMULS_MF4
(
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_MF4
(
FWADD_WV
)
CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4
(
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
)
;
}
}
if
(
LIS
)
{
SlotIndex
Idx
=
LIS
->
ReplaceMachineInstrInMaps
(
MI
,
*
MIB
)
;
if
(
MI
.
getOperand
(
0
)
.
isEarlyClobber
(
)
)
{
LiveInterval
&
LI
=
LIS
->
getInterval
(
MI
.
getOperand
(
1
)
.
getReg
(
)
)
;
LiveRange
::
Segment
*
S
=
LI
.
getSegmentContaining
(
Idx
)
;
if
(
S
->
end
==
Idx
.
getRegSlot
(
true
)
)
S
->
end
=
Idx
.
getRegSlot
(
)
;
}
}
return
MIB
;
}
}
return
nullptr
;
}
</s>

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


<s>
void
pass_vsetvl
::
compute_local_backward_infos
(
const
bb_info
*
bb
)
{
vector_insn_info
change
;
change
.
set_empty
(
)
;
auto
&
block_info
=
m_vector_manager
->
vector_block_infos
[
bb
->
index
(
)
]
;
block_info
.
reaching_out
=
change
;
for
(
insn_info
*
insn
:
bb
->
reverse_real_nondebug_insns
(
)
)
{
auto
&
info
=
m_vector_manager
->
vector_insn_infos
[
insn
->
uid
(
)
]
;
if
(
info
.
uninit_p
(
)
)
info
=
change
;
else
if
(
info
.
unknown_p
(
)
)
change
=
info
;
else
{
gcc_assert
(
info
.
valid_p
(
)
&&
"Unexpected Invalid demanded info"
)
;
if
(
change
.
valid_p
(
)
)
{
if
(
!
(
propagate_avl_across_demands_p
(
change
,
info
)
&&
!
reg_available_p
(
insn
,
change
)
)
&&
change
.
compatible_p
(
info
)
)
{
info
=
change
.
merge
(
info
)
;
if
(
vsetvl_insn_p
(
insn
->
rtl
(
)
)
)
change_vsetvl_insn
(
insn
,
info
)
;
}
}
change
=
info
;
}
}
block_info
.
local_dem
=
change
;
if
(
block_info
.
local_dem
.
empty_p
(
)
)
block_info
.
reaching_out
=
block_info
.
local_dem
;
}
</s>

Compute demanded information by backward data-flow analysis .

riscv
"Unexpected Invalid demanded info"


<s> RISCV :: FixupKind getFixupKind ( ) const { return getFixupKind ( Kind ) ; } </s>

getFixupKind - Get the fixup kind of this expression .


<s>
bool
RISCVAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
OperandVector
&
Operands
)
{
Operands
.
push_back
(
RISCVOperand
::
createToken
(
Name
,
NameLoc
,
isRV64
(
)
)
)
;
if
(
getLexer
(
)
.
is
(
AsmToken
::
EndOfStatement
)
)
return
false
;
if
(
parseOperand
(
Operands
)
)
return
true
;
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
getLexer
(
)
.
Lex
(
)
;
if
(
parseOperand
(
Operands
)
)
return
true
;
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
getParser
(
)
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token"
)
;
}
getParser
(
)
.
Lex
(
)
;
return
false
;
}
</s>

ParseInstruction - Parse one assembly instruction .


<s> void RISCVFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const RISCVRegisterInfo * RI = STI . getRegisterInfo ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; uint64_t StackAlign = RI -> needsStackRealignment ( MF ) ? MFI . getMaxAlignment ( ) : getStackAlignment ( ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; } </s>

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


<s> bool RISCVMCAsmBackend :: fixupNeedsRelaxation ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * Fragment , const MCAsmLayout & Layout ) const { Value = extractBitsForFixup ( Fixup . getKind ( ) , Value ) ; return ( int16_t ) Value != ( int64_t ) Value ; } </s>

Simple predicate for targets where ! Resolved implies requiring relaxation .


<s> static void riscv_print_operand_address ( FILE * file , machine_mode mode ATTRIBUTE_UNUSED , rtx x ) { struct riscv_address_info addr ; if ( riscv_classify_address ( & addr , x , word_mode , true ) ) switch ( addr . type ) { case ADDRESS_REG : riscv_print_operand ( file , addr . offset , 0 ) ; fprintf ( file , "(%s)" , reg_names [ REGNO ( addr . reg ) ] ) ; return ; case ADDRESS_LO_SUM : riscv_print_operand_reloc ( file , addr . offset , false ) ; fprintf ( file , "(%s)" , reg_names [ REGNO ( addr . reg ) ] ) ; return ; case ADDRESS_CONST_INT : output_addr_const ( file , x ) ; fprintf ( file , "(%s)" , reg_names [ GP_REG_FIRST ] ) ; return ; case ADDRESS_SYMBOLIC : output_addr_const ( file , riscv_strip_unspec_address ( x ) ) ; return ; } gcc_unreachable ( ) ; } </s>


<s> MCObjectWriter * RISCVAsmBackend :: createObjectWriter ( raw_pwrite_stream & OS ) const { return createRISCVELFObjectWriter ( OS , OSABI , Is64Bit ) ; } </s>

Create a new MCObjectWriter instance for use by the assembler backend to emit the final object file .


<s> bool RISCVInstrInfo :: isMBBSafeToOutlineFrom ( MachineBasicBlock & MBB , unsigned & Flags ) const { return true ; } </s>

Optional target hook that returns true if MBB is safe to outline from , and returns any target-specific information in Flags .


"Should use capability adjustments if and only if ABI is purecap"


<s> MCObjectWriter * createObjectWriter ( raw_pwrite_stream & OS ) const override { return createRISCVObjectWriter ( OS , OSABI ) ; } </s>


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

Create output and add it into M_OPS and increase OPNO .


<s> static int riscv_register_move_cost ( machine_mode mode , reg_class_t from , reg_class_t to ) { return riscv_secondary_memory_needed ( mode , from , to ) ? 8 : 2 ; } </s>


<s> TargetPassConfig * RISCVTargetMachine :: createPassConfig ( PassManagerBase & PM ) { return new RISCVPassConfig ( this , PM ) ; } </s>

Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of CodeGen passes .


<s> int 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 Offset ; } </s>

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


<s> static rtx riscv_force_address ( rtx x , enum machine_mode mode ) { if ( ! riscv_legitimate_address_p ( mode , x , false ) ) x = force_reg ( Pmode , x ) ; return x ; } </s>

If X is not a valid address for mode MODE , force it into a register .


<s> static opt_scalar_float_mode riscv_floatn_mode ( int n , bool extended ) { if ( ! extended && n == 16 ) return HFmode ; return default_floatn_mode ( n , extended ) ; } </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_LO
:
return
"pcrel_lo"
;
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_lo"
RISCV
"pcrel_hi"


<s> void RISCVTargetStreamer :: emitTargetAttributes ( const MCSubtargetInfo & STI ) { if ( STI . hasFeature ( RISCV :: FeatureRV32E ) ) emitAttribute ( RISCVAttrs :: STACK_ALIGN , RISCVAttrs :: ALIGN_4 ) ; else emitAttribute ( RISCVAttrs :: STACK_ALIGN , RISCVAttrs :: ALIGN_16 ) ; std :: string Arch = "rv32" ; if ( STI . hasFeature ( RISCV :: Feature64Bit ) ) Arch = "rv64" ; if ( STI . hasFeature ( RISCV :: FeatureRV32E ) ) Arch += "e1p9" ; else Arch += "i2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtM ) ) Arch += "_m2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtA ) ) Arch += "_a2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtF ) ) Arch += "_f2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtD ) ) Arch += "_d2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtC ) ) Arch += "_c2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtB ) ) Arch += "_b0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtV ) ) Arch += "_v1p0" ; if ( STI . hasFeature ( RISCV :: FeatureExtZfh ) ) Arch += "_zfh0p1" ; if ( STI . hasFeature ( RISCV :: FeatureExtZba ) ) Arch += "_zba0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbb ) ) Arch += "_zbb0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbc ) ) Arch += "_zbc0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbe ) ) Arch += "_zbe0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbf ) ) Arch += "_zbf0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbm ) ) Arch += "_zbm0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbp ) ) Arch += "_zbp0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbproposedc ) ) Arch += "_zbproposedc0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbr ) ) Arch += "_zbr0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbs ) ) Arch += "_zbs0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZbt ) ) Arch += "_zbt0p93" ; if ( STI . hasFeature ( RISCV :: FeatureExtZvamo ) ) Arch += "_zvamo1p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZvlsseg ) ) Arch += "_zvlsseg1p0" ; emitTextAttribute ( RISCVAttrs :: ARCH , Arch ) ; } </s>

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


<s> bool RISCVDAGToDAGISel :: SelectInlineAsmMemoryOperand ( const SDValue & Op , unsigned ConstraintID , std :: vector < SDValue > & OutOps ) { switch ( ConstraintID ) { case InlineAsm :: Constraint_i : case InlineAsm :: Constraint_m : OutOps . push_back ( Op ) ; return false ; case InlineAsm :: Constraint_A : OutOps . push_back ( Op ) ; return false ; default : break ; } return true ; } </s>

SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode , according to the specified constraint .


<s> void RISCVFrameLowering :: emitEpilogue ( MachineFunction & MF , MachineBasicBlock & MBB ) const { MachineBasicBlock :: iterator MBBI = MBB . getLastNonDebugInstr ( ) ; MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; RISCVFunctionInfo * RISCVFI = MF . getInfo < RISCVFunctionInfo > ( ) ; const RISCVRegisterInfo * RegInfo = static_cast < const RISCVRegisterInfo * > ( MF . getSubtarget ( ) . getRegisterInfo ( ) ) ; const RISCVInstrInfo & TII = * static_cast < const RISCVInstrInfo * > ( MF . getSubtarget ( ) . getInstrInfo ( ) ) ; DebugLoc dl = MBBI -> getDebugLoc ( ) ; const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; unsigned SP = STI . isRV64 ( ) ? RISCV :: sp_64 : RISCV :: sp ; unsigned FP = STI . isRV64 ( ) ? RISCV :: fp_64 : RISCV :: fp ; unsigned ZERO = STI . isRV64 ( ) ? RISCV :: zero_64 : RISCV :: zero ; unsigned ADDu = STI . isRV64 ( ) ? RISCV :: ADD64 : RISCV :: ADD ; if ( hasFP ( MF ) ) { MachineBasicBlock :: iterator I = MBBI ; for ( unsigned i = 0 ; i < MFI -> getCalleeSavedInfo ( ) . size ( ) ; ++ i ) -- I ; BuildMI ( MBB , I , dl , TII . get ( ADDu ) , SP ) . addReg ( FP ) . addReg ( ZERO ) ; } if ( RISCVFI -> getCallsEhReturn ( ) ) { const TargetRegisterClass * RC = & RISCV :: GR32BitRegClass ; MachineBasicBlock :: iterator I = MBBI ; for ( unsigned i = 0 ; i < MFI -> getCalleeSavedInfo ( ) . size ( ) ; ++ i ) -- I ; for ( int J = 0 ; J < 4 ; ++ J ) { TII . loadRegFromStackSlot ( MBB , I , ehDataReg ( J ) , RISCVFI -> getEhDataRegFI ( J ) , RC , RegInfo ) ; } } uint64_t StackSize = MFI -> getStackSize ( ) ; if ( ! StackSize ) return ; TII . adjustStackPtr ( SP , StackSize , MBB , MBBI ) ; } </s>


<s> void RISCVPassConfig :: addPreEmitPass ( ) { addPass ( & BranchRelaxationPassID ) ; } </s>

This pass may be implemented by targets that want to run passes immediately before machine code is emitted .


"LowerFormalArguments Unhandled argument type: "

This hook must be implemented to lower the incoming ( formal ) arguments , described by the Ins array , into the specified DAG .


<s> void function_builder :: allocate_argument_types ( const function_instance & instance , vec < tree > & argument_types ) const { for ( unsigned int i = 0 ; instance . op_info -> args [ i ] . base_type != NUM_BASE_TYPES ; ++ i ) argument_types . quick_push ( instance . op_info -> args [ i ] . get_tree_type ( instance . type . index ) ) ; } </s>


<s> void riscv_split_doubleword_move ( rtx dest , rtx src ) { rtx low_dest ; low_dest = riscv_subword ( dest , false ) ; if ( REG_P ( low_dest ) && reg_overlap_mentioned_p ( low_dest , src ) ) { riscv_emit_move ( riscv_subword ( dest , true ) , riscv_subword ( src , true ) ) ; riscv_emit_move ( low_dest , riscv_subword ( src , false ) ) ; } else { riscv_emit_move ( low_dest , riscv_subword ( src , false ) ) ; riscv_emit_move ( riscv_subword ( dest , true ) , riscv_subword ( src , true ) ) ; } } </s>

Split a doubleword move from SRC to DEST . On 32-bit targets , this function handles 64-bit moves for which riscv_split_64bit_move_p holds . For 64-bit targets , this function handles 128-bit moves .


<s>
void
handle_pragma_vector
(
)
{
if
(
function_table
)
{
error
(
"duplicate definition of %qs"
,
"riscv_vector.h"
)
;
return
;
}
rvv_switcher
rvv
;
for
(
unsigned
int
type_i
=
0
;
type_i
<
NUM_VECTOR_TYPES
;
++
type_i
)
register_vector_type
(
(
enum
vector_type_index
)
type_i
)
;
function_table
=
new
hash_table
<
registered_function_hasher
>
(
1023
)
;
function_builder
builder
;
for
(
unsigned
int
i
=
0
;
i
<
ARRAY_SIZE
(
function_groups
)
;
++
i
)
builder
.
register_function_group
(
function_groups
[
i
]
)
;
}
</s>

Implement # pragma riscv intrinsic vector .


"loadRegFromStackSlot didn't insert any code!"

"Save/restore libcall not implemented for purecap"

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
addExpr
(
MCInst
&
Inst
,
const
MCExpr
*
Expr
)
const
{
assert
(
Expr
&&
"Expr shouldn't be null!"
)
;
int64_t
Imm
=
0
;
RISCVMCExpr
::
VariantKind
VK
=
RISCVMCExpr
::
VK_RISCV_None
;
bool
IsConstant
=
evaluateConstantImm
(
Expr
,
Imm
,
VK
)
;
if
(
IsConstant
)
Inst
.
addOperand
(
MCOperand
::
createImm
(
Imm
)
)
;
else
Inst
.
addOperand
(
MCOperand
::
createExpr
(
Expr
)
)
;
}
</s>

RISCV
"Expr shouldn't be null!"
0
RISCV
RISCV
RISCV


<s>
void
RISCVDAGToDAGISel
::
PreprocessISelDAG
(
)
{
for
(
SelectionDAG
::
allnodes_iterator
I
=
CurDAG
->
allnodes_begin
(
)
,
E
=
CurDAG
->
allnodes_end
(
)
;
I
!=
E
;
)
{
SDNode
*
N
=
&
*
I
++
;
if
(
N
->
getOpcode
(
)
!=
RISCVISD
::
SPLAT_VECTOR_SPLIT_I64_VL
)
continue
;
assert
(
N
->
getNumOperands
(
)
==
3
&&
"Unexpected number of operands"
)
;
MVT
VT
=
N
->
getSimpleValueType
(
0
)
;
SDValue
Lo
=
N
->
getOperand
(
0
)
;
SDValue
Hi
=
N
->
getOperand
(
1
)
;
SDValue
VL
=
N
->
getOperand
(
2
)
;
assert
(
VT
.
getVectorElementType
(
)
==
MVT
::
i64
&&
VT
.
isScalableVector
(
)
&&
Lo
.
getValueType
(
)
==
MVT
::
i32
&&
Hi
.
getValueType
(
)
==
MVT
::
i32
&&
"Unexpected VTs!"
)
;
MachineFunction
&
MF
=
CurDAG
->
getMachineFunction
(
)
;
RISCVMachineFunctionInfo
*
FuncInfo
=
MF
.
getInfo
<
RISCVMachineFunctionInfo
>
(
)
;
SDLoc
DL
(
N
)
;
int
FI
=
FuncInfo
->
getMoveF64FrameIndex
(
MF
)
;
MachinePointerInfo
MPI
=
MachinePointerInfo
::
getFixedStack
(
MF
,
FI
)
;
const
TargetLowering
&
TLI
=
CurDAG
->
getTargetLoweringInfo
(
)
;
SDValue
StackSlot
=
CurDAG
->
getFrameIndex
(
FI
,
TLI
.
getPointerTy
(
CurDAG
->
getDataLayout
(
)
)
)
;
SDValue
Chain
=
CurDAG
->
getEntryNode
(
)
;
Lo
=
CurDAG
->
getStore
(
Chain
,
DL
,
Lo
,
StackSlot
,
MPI
,
Align
(
8
)
)
;
SDValue
OffsetSlot
=
CurDAG
->
getMemBasePlusOffset
(
StackSlot
,
TypeSize
::
Fixed
(
4
)
,
DL
)
;
Hi
=
CurDAG
->
getStore
(
Chain
,
DL
,
Hi
,
OffsetSlot
,
MPI
.
getWithOffset
(
4
)
,
Align
(
8
)
)
;
Chain
=
CurDAG
->
getNode
(
ISD
::
TokenFactor
,
DL
,
MVT
::
Other
,
Lo
,
Hi
)
;
SDVTList
VTs
=
CurDAG
->
getVTList
(
{
VT
,
MVT
::
Other
}
)
;
SDValue
IntID
=
CurDAG
->
getTargetConstant
(
Intrinsic
::
riscv_vlse
,
DL
,
MVT
::
i64
)
;
SDValue
Ops
[
]
=
{
Chain
,
IntID
,
CurDAG
->
getUNDEF
(
VT
)
,
StackSlot
,
CurDAG
->
getRegister
(
RISCV
::
X0
,
MVT
::
i64
)
,
VL
}
;
SDValue
Result
=
CurDAG
->
getMemIntrinsicNode
(
ISD
::
INTRINSIC_W_CHAIN
,
DL
,
VTs
,
Ops
,
MVT
::
i64
,
MPI
,
Align
(
8
)
,
MachineMemOperand
::
MOLoad
)
;
I
;
CurDAG
->
ReplaceAllUsesOfValueWith
(
SDValue
(
N
,
0
)
,
Result
)
;
++
I
;
CurDAG
->
DeleteNode
(
N
)
;
}
}
</s>

PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts .


"  Found lowered global address with one use: "

runOnMachineFunction - Emit the function body .


<s> static bool riscv_compressed_lw_address_p ( rtx x ) { struct riscv_address_info addr ; bool result = riscv_classify_address ( & addr , x , GET_MODE ( x ) , reload_completed ) ; if ( ! result || addr . type != ADDRESS_REG || ( reload_completed && ! riscv_compressed_reg_p ( REGNO ( addr . reg ) ) && addr . reg != stack_pointer_rtx ) || ! riscv_compressed_lw_offset_p ( addr . offset ) ) return false ; return result ; } </s>

Return true if load/store from/to address x can be compressed .


<s> bool function_instance :: reads_global_state_p ( ) const { unsigned int flags = call_properties ( ) ; if ( flags & CP_READ_FPCR ) return true ; return flags & ( CP_READ_MEMORY | CP_READ_CSR ) ; } </s>

Return true if calls to the function could read some form of global state .


<s> static sbitmap riscv_get_separate_components ( void ) { HOST_WIDE_INT offset ; sbitmap components = sbitmap_alloc ( FIRST_PSEUDO_REGISTER ) ; bitmap_clear ( components ) ; if ( riscv_use_save_libcall ( & cfun -> machine -> frame ) || cfun -> machine -> interrupt_handler_p || ! cfun -> machine -> frame . gp_sp_offset . is_constant ( ) ) return components ; offset = cfun -> machine -> frame . gp_sp_offset . to_constant ( ) ; for ( unsigned int regno = GP_REG_FIRST ; regno <= GP_REG_LAST ; regno ++ ) if ( BITSET_P ( cfun -> machine -> frame . mask , regno - GP_REG_FIRST ) ) { if ( SMALL_OPERAND ( offset ) ) bitmap_set_bit ( components , regno ) ; offset -= UNITS_PER_WORD ; } offset = cfun -> machine -> frame . fp_sp_offset . to_constant ( ) ; for ( unsigned int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) if ( BITSET_P ( cfun -> machine -> frame . fmask , regno - FP_REG_FIRST ) ) { machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode ; if ( SMALL_OPERAND ( offset ) ) bitmap_set_bit ( components , regno ) ; offset -= GET_MODE_SIZE ( mode ) . to_constant ( ) ; } if ( frame_pointer_needed ) bitmap_clear_bit ( components , HARD_FRAME_POINTER_REGNUM ) ; bitmap_clear_bit ( components , RETURN_ADDR_REGNUM ) ; return components ; } </s>


<s> unsigned RISCVRegisterInfo :: getFrameRegister ( const MachineFunction & MF ) const { return RISCV :: X8 ; } </s>


<s> int riscv_regno_mode_ok_for_base_p ( int regno , enum machine_mode mode ATTRIBUTE_UNUSED , bool strict_p ) { if ( ! HARD_REGISTER_NUM_P ( regno ) ) { if ( ! strict_p ) return true ; regno = reg_renumber [ regno ] ; } if ( regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM ) return true ; return GP_REG_P ( regno ) ; } </s>

Return true if register REGNO is a valid base register for mode MODE . STRICT_P is true if REG_OK_STRICT is in effect .


<s> void RISCVInstPrinter :: printRegName ( raw_ostream & O , unsigned RegNo ) const { O << getRegisterName ( RegNo ) ; } </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 .