<s>
static
void
riscv_print_operand
(
FILE
*
file
,
rtx
op
,
int
letter
)
{
enum
machine_mode
mode
=
GET_MODE
(
op
)
;
enum
rtx_code
code
=
GET_CODE
(
op
)
;
switch
(
letter
)
{
case
'h'
:
if
(
code
==
HIGH
)
op
=
XEXP
(
op
,
0
)
;
riscv_print_operand_reloc
(
file
,
op
,
true
)
;
break
;
case
'R'
:
riscv_print_operand_reloc
(
file
,
op
,
false
)
;
break
;
case
'C'
:
fputs
(
GET_RTX_NAME
(
code
)
,
file
)
;
break
;
case
'A'
:
if
(
riscv_memmodel_needs_amo_acquire
(
(
enum
memmodel
)
INTVAL
(
op
)
)
)
fputs
(
".aq"
,
file
)
;
break
;
case
'F'
:
if
(
riscv_memmodel_needs_release_fence
(
(
enum
memmodel
)
INTVAL
(
op
)
)
)
fputs
(
"fence iorw,ow; "
,
file
)
;
break
;
default
:
switch
(
code
)
{
case
REG
:
if
(
letter
&&
letter
!=
'z'
)
output_operand_lossage
(
"invalid use of '%%%c'"
,
letter
)
;
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
op
)
]
)
;
break
;
case
MEM
:
if
(
letter
&&
letter
!=
'z'
)
output_operand_lossage
(
"invalid use of '%%%c'"
,
letter
)
;
else
output_address
(
mode
,
XEXP
(
op
,
0
)
)
;
break
;
default
:
if
(
letter
==
'z'
&&
op
==
CONST0_RTX
(
GET_MODE
(
op
)
)
)
fputs
(
reg_names
[
GP_REG_FIRST
]
,
file
)
;
else
if
(
letter
&&
letter
!=
'z'
)
output_operand_lossage
(
"invalid use of '%%%c'"
,
letter
)
;
else
output_addr_const
(
file
,
riscv_strip_unspec_address
(
op
)
)
;
break
;
}
}
}
</s>

Implement TARGET_PRINT_OPERAND . The RISCV-specific operand codes are : ' h' Print the high-part relocation associated with OP , after stripping any outermost HIGH . ' R' Print the low-part relocation associated with OP . ' C' Print the integer branch condition for comparison OP . ' A' Print the atomic operation suffix for memory model OP . ' F' Print a FENCE if the memory model requires a release . ' z' Print x0 if OP is zero , otherwise print OP normally .

riscv
0
".aq"
"fence iorw,ow; "
"invalid use of '%%%c'"
"%s"
"invalid use of '%%%c'"
0
"invalid use of '%%%c'"


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 .


"READ_CYCLE_WIDE is only used on riscv32"

Main hook for targets to transform nodes into machine nodes .


<s> void add_all_one_mask_operand ( machine_mode mode ) { add_input_operand ( CONSTM1_RTX ( mode ) , mode ) ; } </s>

Since we may normalize vop/vop_tu/vop_m/vop_tumu .. into a single patter . We add a fake all true mask for the intrinsics that do n't need a real mask .


<s> static unsigned int riscv_hard_regno_nregs ( unsigned int regno , machine_mode mode ) { if ( FP_REG_P ( regno ) ) return ( GET_MODE_SIZE ( mode ) + UNITS_PER_FP_REG - 1 ) / UNITS_PER_FP_REG ; return ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; } </s>


<s> void RISCVPassConfig :: addPreEmitPass2 ( ) { addPass ( createRISCVExpandPseudoPass ( ) ) ; addPass ( createRISCVExpandAtomicPseudoPass ( ) ) ; } </s>

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


<s> bool RISCVGatherScatterLowering :: runOnFunction ( Function & F ) { if ( skipFunction ( F ) ) return false ; auto & TPC = getAnalysis < TargetPassConfig > ( ) ; auto & TM = TPC . getTM < RISCVTargetMachine > ( ) ; ST = & TM . getSubtarget < RISCVSubtarget > ( F ) ; if ( ! ST -> hasStdExtV ( ) || ! ST -> useRVVForFixedLengthVectors ( ) ) return false ; TLI = ST -> getTargetLowering ( ) ; DL = & F . getParent ( ) -> getDataLayout ( ) ; LI = & getAnalysis < LoopInfoWrapperPass > ( ) . getLoopInfo ( ) ; SmallVector < IntrinsicInst * , 4 > Gathers ; SmallVector < IntrinsicInst * , 4 > Scatters ; bool Changed = false ; for ( BasicBlock & BB : F ) { for ( Instruction & I : BB ) { IntrinsicInst * II = dyn_cast < IntrinsicInst > ( & I ) ; if ( II && II -> getIntrinsicID ( ) == Intrinsic :: masked_gather && isa < FixedVectorType > ( II -> getType ( ) ) ) { Gathers . push_back ( II ) ; } else if ( II && II -> getIntrinsicID ( ) == Intrinsic :: masked_scatter && isa < FixedVectorType > ( II -> getArgOperand ( 0 ) -> getType ( ) ) ) { Scatters . push_back ( II ) ; } } } for ( auto * II : Gathers ) Changed |= tryCreateStridedLoadStore ( II , II -> getType ( ) , II -> getArgOperand ( 0 ) , II -> getArgOperand ( 1 ) ) ; for ( auto * II : Scatters ) Changed |= tryCreateStridedLoadStore ( II , II -> getArgOperand ( 0 ) -> getType ( ) , II -> getArgOperand ( 1 ) , II -> getArgOperand ( 2 ) ) ; while ( ! MaybeDeadPHIs . empty ( ) ) { if ( auto * Phi = dyn_cast_or_null < PHINode > ( MaybeDeadPHIs . pop_back_val ( ) ) ) RecursivelyDeleteDeadPHINode ( Phi ) ; } return Changed ; } </s>

runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass .


<s> bool RISCVTargetLowering :: shouldExtendTypeInLibCall ( EVT Type ) const { RISCVABI :: ABI ABI = Subtarget . getTargetABI ( ) ; if ( ( ABI == RISCVABI :: ABI_LP64 || ABI == RISCVABI :: ABI_L64PC128 ) && ( Type == MVT :: f32 ) ) return false ; return true ; } </s>

Returns true if arguments should be extended in lib calls .


<s> MachineBasicBlock :: iterator eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const override { 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> void RISCVPassConfig :: addPreEmitPass2 ( ) { addPass ( createRISCVExpandPseudoPass ( ) ) ; } </s>


<s> static bool read_vl_insn_p ( rtx_insn * rinsn ) { return recog_memoized ( rinsn ) >= 0 && get_attr_type ( rinsn ) == TYPE_RDVL ; } </s>

Return true if the instruction is read vl instruction .


<s> static insn_info * extract_single_source ( set_info * set ) { if ( ! set ) return nullptr ; if ( set -> insn ( ) -> is_real ( ) ) return set -> insn ( ) ; if ( ! set -> insn ( ) -> is_phi ( ) ) return nullptr ; hash_set < set_info * > sets = get_all_sets ( set , true , false , true ) ; insn_info * first_insn = ( * sets . begin ( ) ) -> insn ( ) ; if ( first_insn -> is_artificial ( ) ) return nullptr ; for ( const set_info * set : sets ) { if ( set -> insn ( ) -> is_artificial ( ) ) return nullptr ; if ( ! source_equal_p ( set -> insn ( ) , first_insn ) ) return nullptr ; } return first_insn ; } </s>

Helper function to get single same real RTL source . return NULL if it is not a single real RTL source .


<s> TargetLowering :: AtomicExpansionKind RISCVTargetLowering :: shouldExpandAtomicRMWInIR ( AtomicRMWInst * AI ) const { unsigned Size = AI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; if ( Size == 8 || Size == 16 ) return AtomicExpansionKind :: MaskedIntrinsic ; return AtomicExpansionKind :: None ; } </s>

Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW , if at all .


<s> bool riscv_legitimize_move ( machine_mode mode , rtx dest , rtx src ) { if ( ! register_operand ( dest , mode ) && ! reg_or_0_operand ( src , mode ) ) { riscv_emit_move ( dest , force_reg ( mode , src ) ) ; 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> SDValue RISCVTargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { SelectionDAG & DAG = DCI . DAG ; switch ( N -> getOpcode ( ) ) { default : break ; case RISCVISD :: SplitF64 : { SDValue Op0 = N -> getOperand ( 0 ) ; if ( Op0 -> getOpcode ( ) == RISCVISD :: BuildPairF64 ) return DCI . CombineTo ( N , Op0 . getOperand ( 0 ) , Op0 . getOperand ( 1 ) ) ; SDLoc DL ( N ) ; if ( ! ( Op0 . getOpcode ( ) == ISD :: FNEG || Op0 . getOpcode ( ) == ISD :: FABS ) || ! Op0 . getNode ( ) -> hasOneUse ( ) ) break ; SDValue NewSplitF64 = DAG . getNode ( RISCVISD :: SplitF64 , DL , DAG . getVTList ( MVT :: i32 , MVT :: i32 ) , Op0 . getOperand ( 0 ) ) ; SDValue Lo = NewSplitF64 . getValue ( 0 ) ; SDValue Hi = NewSplitF64 . getValue ( 1 ) ; APInt SignBit = APInt :: getSignMask ( 32 ) ; if ( Op0 . getOpcode ( ) == ISD :: FNEG ) { SDValue NewHi = DAG . getNode ( ISD :: XOR , DL , MVT :: i32 , Hi , DAG . getConstant ( SignBit , DL , MVT :: i32 ) ) ; return DCI . CombineTo ( N , Lo , NewHi ) ; } assert ( Op0 . getOpcode ( ) == ISD :: FABS ) ; SDValue NewHi = DAG . getNode ( ISD :: AND , DL , MVT :: i32 , Hi , DAG . getConstant ( ~ SignBit , DL , MVT :: i32 ) ) ; return DCI . CombineTo ( N , Lo , NewHi ) ; } case RISCVISD :: SLLW : case RISCVISD :: SRAW : case RISCVISD :: SRLW : { SDValue LHS = N -> getOperand ( 0 ) ; SDValue RHS = N -> getOperand ( 1 ) ; APInt LHSMask = APInt :: getLowBitsSet ( LHS . getValueSizeInBits ( ) , 32 ) ; APInt RHSMask = APInt :: getLowBitsSet ( RHS . getValueSizeInBits ( ) , 5 ) ; if ( ( SimplifyDemandedBits ( N -> getOperand ( 0 ) , LHSMask , DCI ) ) || ( SimplifyDemandedBits ( N -> getOperand ( 1 ) , RHSMask , DCI ) ) ) return SDValue ( ) ; break ; } } return SDValue ( ) ; } </s>

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


<s> static void register_vector_type ( vector_type_index type ) { tree vectype = abi_vector_types [ type ] ; if ( ! vectype ) return ; tree id = get_identifier ( vector_types [ type ] . name ) ; tree decl = build_decl ( input_location , TYPE_DECL , id , vectype ) ; decl = lang_hooks . decls . pushdecl ( decl ) ; if ( decl && TREE_CODE ( decl ) == TYPE_DECL && TREE_TYPE ( decl ) != error_mark_node && TYPE_MAIN_VARIANT ( TREE_TYPE ( decl ) ) == vectype ) vectype = TREE_TYPE ( decl ) ; builtin_types [ type ] . vector = vectype ; builtin_types [ type ] . vector_ptr = build_pointer_type ( vectype ) ; } </s>

Register vector type TYPE under its risv_vector.h name .


<s> bool isImm ( int64_t MinValue , int64_t MaxValue ) const { return Kind == KindImm && inRange ( Imm , MinValue , MaxValue ) ; } </s>


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

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


<s> int RISCVTTIImpl :: getIntImmCost ( Intrinsic :: ID IID , unsigned Idx , const APInt & Imm , Type * Ty ) { return TTI :: TCC_Free ; } </s>

Calculate the cost of materializing a 64-bit value .


<s> static rtx riscv_split_integer ( HOST_WIDE_INT val , enum machine_mode mode ) { unsigned HOST_WIDE_INT loval = sext_hwi ( val , 32 ) ; unsigned HOST_WIDE_INT hival = sext_hwi ( ( val - loval ) >> 32 , 32 ) ; rtx hi = gen_reg_rtx ( mode ) , lo = gen_reg_rtx ( mode ) ; riscv_move_integer ( hi , hi , hival ) ; riscv_move_integer ( lo , lo , loval ) ; hi = gen_rtx_fmt_ee ( ASHIFT , mode , hi , GEN_INT ( 32 ) ) ; hi = force_reg ( mode , hi ) ; return gen_rtx_fmt_ee ( PLUS , mode , hi , lo ) ; } </s>

Try to split a 64b integer into 32b parts , then reassemble .


Return an array that contains the direct target flag values and their names .

RISCV RISCV RISCV "riscv-call" "riscv-plt" "riscv-lo" "riscv-hi" "riscv-pcrel-lo" "riscv-pcrel-hi" "riscv-got-hi" "riscv-tprel-lo" "riscv-tprel-hi" "riscv-tprel-add" "riscv-tls-got-hi" "riscv-tls-gd-hi" "riscv-captab-pcrel-hi" "riscv-tprel-cincoffset" "riscv-tls-ie-captab-pcrel-hi" "riscv-tls-gd-captab-pcrel-hi" "riscv-ccall"


<s> bool isImm ( ) const override { return Kind == Immediate ; } </s>


<s> bool RISCVAsmBackend :: shouldForceRelocation ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target ) { if ( Fixup . getKind ( ) >= FirstLiteralRelocationKind ) return true ; switch ( Fixup . getTargetKind ( ) ) { default : break ; case FK_Data_1 : case FK_Data_2 : case FK_Data_4 : case FK_Data_8 : if ( Target . isAbsolute ( ) ) return false ; break ; case RISCV :: fixup_riscv_got_hi20 : case RISCV :: fixup_riscv_tls_got_hi20 : case RISCV :: fixup_riscv_tls_gd_hi20 : case RISCV :: fixup_riscv_captab_pcrel_hi20 : case RISCV :: fixup_riscv_tls_ie_captab_pcrel_hi20 : case RISCV :: fixup_riscv_tls_gd_captab_pcrel_hi20 : return true ; } return STI . getFeatureBits ( ) [ RISCV :: FeatureRelax ] || ForceRelocs ; } </s>

Hook to check if a relocation is needed for some target specific reason .


<s> static int riscv_issue_rate ( void ) { return tune_param -> issue_rate ; } </s>

Return the number of instructions that can be issued per cycle .


<s> bool RISCVFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; return MF . getTarget ( ) . Options . DisableFramePointerElim ( MF ) || RegInfo -> hasStackRealignment ( MF ) || MFI . hasVarSizedObjects ( ) || MFI . isFrameAddressTaken ( ) ; } </s>

hasFP - Return true if the specified function should have a dedicated frame pointer register .


<s>
void
RISCVMCAsmBackend
::
relaxInstruction
(
const
MCInst
&
Inst
,
MCInst
&
Res
)
const
{
unsigned
Opcode
=
getRelaxedOpcode
(
Inst
.
getOpcode
(
)
)
;
assert
(
Opcode
&&
"Unexpected insn to relax"
)
;
Res
=
Inst
;
Res
.
setOpcode
(
Opcode
)
;
}
</s>

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


"getIntImmCost can only estimate cost of materialising integers"


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

"READCYCLECOUNTER only has custom type legalization on riscv32"

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


<s>
bool
RISCVAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
OperandVector
&
Operands
)
{
if
(
getSTI
(
)
.
getFeatureBits
(
)
[
RISCV
::
FeatureRelax
]
)
{
auto
*
Assembler
=
getTargetStreamer
(
)
.
getStreamer
(
)
.
getAssemblerPtr
(
)
;
if
(
Assembler
!=
nullptr
)
{
RISCVAsmBackend
&
MAB
=
static_cast
<
RISCVAsmBackend
&
>
(
Assembler
->
getBackend
(
)
)
;
MAB
.
setForceRelocs
(
)
;
}
}
Operands
.
push_back
(
RISCVOperand
::
createToken
(
Name
,
NameLoc
,
isRV64
(
)
)
)
;
if
(
getLexer
(
)
.
is
(
AsmToken
::
EndOfStatement
)
)
{
getParser
(
)
.
Lex
(
)
;
return
false
;
}
if
(
parseOperand
(
Operands
,
Name
)
)
return
true
;
unsigned
OperandIdx
=
1
;
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
getLexer
(
)
.
Lex
(
)
;
if
(
parseOperand
(
Operands
,
Name
)
)
return
true
;
++
OperandIdx
;
}
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 .

RISCV
RISCV
RISCV::FeatureRelax
RISCV
RISCV
RISCV
1
"unexpected token"


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

getTargetNodeName - This method returns the name of a target specific


<s>
bool
RISCVAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
OperandVector
&
Operands
)
{
if
(
getSTI
(
)
.
getFeatureBits
(
)
[
RISCV
::
FeatureRelax
]
)
{
auto
*
Assembler
=
getTargetStreamer
(
)
.
getStreamer
(
)
.
getAssemblerPtr
(
)
;
if
(
Assembler
!=
nullptr
)
{
RISCVAsmBackend
&
MAB
=
static_cast
<
RISCVAsmBackend
&
>
(
Assembler
->
getBackend
(
)
)
;
MAB
.
setForceRelocs
(
)
;
}
}
Operands
.
push_back
(
RISCVOperand
::
createToken
(
Name
,
NameLoc
,
isRV64
(
)
)
)
;
if
(
getLexer
(
)
.
is
(
AsmToken
::
EndOfStatement
)
)
return
false
;
if
(
parseOperand
(
Operands
,
Name
)
)
return
true
;
unsigned
OperandIdx
=
1
;
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
getLexer
(
)
.
Lex
(
)
;
if
(
parseOperand
(
Operands
,
Name
)
)
return
true
;
++
OperandIdx
;
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
getParser
(
)
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token"
)
;
}
getParser
(
)
.
Lex
(
)
;
return
false
;
}
</s>


<s> void RISCVFrameLowering :: processFunctionBeforeFrameFinalized ( MachineFunction & MF , RegScavenger * RS ) const { const RISCVRegisterInfo * RegInfo = MF . getSubtarget < RISCVSubtarget > ( ) . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterClass * RC = & RISCV :: GPRRegClass ; auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; int64_t RVVStackSize = assignRVVStackObjectOffsets ( MFI ) ; RVFI -> setRVVStackSize ( RVVStackSize ) ; const RISCVInstrInfo & TII = * MF . getSubtarget < RISCVSubtarget > ( ) . getInstrInfo ( ) ; if ( ! isInt < 11 > ( MFI . estimateStackSize ( MF ) ) || hasRVVSpillWithFIs ( MF , TII ) ) { int RegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC ) , RegInfo -> getSpillAlign ( * RC ) , false ) ; RS -> addScavengingFrameIndex ( RegScavFI ) ; if ( RVVStackSize != 0 ) { int RVVRegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC ) , RegInfo -> getSpillAlign ( * RC ) , false ) ; RS -> addScavengingFrameIndex ( RVVRegScavFI ) ; } } if ( MFI . getCalleeSavedInfo ( ) . empty ( ) || RVFI -> useSaveRestoreLibCalls ( MF ) ) { RVFI -> setCalleeSavedStackSize ( 0 ) ; return ; } unsigned Size = 0 ; for ( const auto & Info : MFI . getCalleeSavedInfo ( ) ) { int FrameIdx = Info . getFrameIdx ( ) ; if ( MFI . getStackID ( FrameIdx ) != TargetStackID :: Default ) continue ; Size += MFI . getObjectSize ( FrameIdx ) ; } RVFI -> setCalleeSavedStackSize ( Size ) ; if ( RVVStackSize && ! hasFP ( MF ) && Size % 8 != 0 ) { RVFI -> setRVVPadding ( getStackAlign ( ) . value ( ) ) ; } } </s>

processFunctionBeforeFrameFinalized - This method is called immediately before the specified function 's frame layout ( MF.getFrameInfo ( ) ) is finalized .


<s> bool RISCVTargetLowering :: isShuffleMaskLegal ( ArrayRef < int > M , EVT VT ) const { if ( ShuffleVectorSDNode :: isSplatMask ( M . data ( ) , VT ) ) return true ; if ( ! isTypeLegal ( VT ) ) return false ; MVT SVT = VT . getSimpleVT ( ) ; bool SwapSources ; int LoSrc , HiSrc ; return ( isElementRotate ( LoSrc , HiSrc , M ) > 0 ) || isInterleaveShuffle ( M , SVT , SwapSources , Subtarget ) ; } </s>

Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations , those with specific masks .


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


<s> bool RISCVTargetLowering :: shouldConvertFpToSat ( unsigned Op , EVT FPVT , EVT VT ) const { if ( ! isOperationLegalOrCustom ( Op , VT ) || ! FPVT . isSimple ( ) ) return false ; switch ( FPVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: f16 : return Subtarget . hasStdExtZfh ( ) ; case MVT :: f32 : return Subtarget . hasStdExtF ( ) ; case MVT :: f64 : return Subtarget . hasStdExtD ( ) ; default : return false ; } } </s>

Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min ( max ( fptoi ) ) saturation patterns .


"ReadCycleWrite is only to be used on riscv32"

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


<s> unsigned int call_properties ( const function_instance & ) const override { return CP_READ_MEMORY | CP_WRITE_CSR ; } </s>

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


<s> bool RISCVDAGToDAGISel :: SelectInlineAsmMemoryOperand ( const SDValue & Op , unsigned ConstraintID , std :: vector < SDValue > & OutOps ) { switch ( ConstraintID ) { 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>
bool
RISCVAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
OperandVector
&
Operands
)
{
if
(
!
mnemonicIsValid
(
Name
,
0
)
)
{
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
NameLoc
,
"unknown instruction"
)
;
}
Operands
.
push_back
(
RISCVOperand
::
createToken
(
Name
,
NameLoc
)
)
;
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
if
(
parseOperand
(
Operands
,
Name
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token in argument list"
)
;
}
if
(
getLexer
(
)
.
is
(
AsmToken
::
LBrac
)
)
return
true
;
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
Parser
.
Lex
(
)
;
if
(
parseOperand
(
Operands
,
Name
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token in argument list"
)
;
}
if
(
getLexer
(
)
.
is
(
AsmToken
::
LParen
)
&&
parseParenSuffix
(
Name
,
Operands
)
)
return
true
;
}
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token in argument list"
)
;
}
Parser
.
Lex
(
)
;
return
false
;
}
</s>

RISCV
RISCV
0
"unknown instruction"
RISCV
"unexpected token in argument list"
"unexpected token in argument list"
"unexpected token in argument list"


<s> void pass_vsetvl :: compute_probabilities ( void ) { if ( ! optimize ) return ; edge e ; edge_iterator ei ; for ( const bb_info * bb : crtl -> ssa -> bbs ( ) ) { basic_block cfg_bb = bb -> cfg_bb ( ) ; auto & curr_prob = m_vector_manager -> vector_block_infos [ cfg_bb -> index ] . probability ; if ( ENTRY_BLOCK_PTR_FOR_FN ( cfun ) == cfg_bb ) curr_prob = profile_probability :: always ( ) ; if ( EXIT_BLOCK_PTR_FOR_FN ( cfun ) == cfg_bb ) continue ; gcc_assert ( curr_prob . initialized_p ( ) ) ; FOR_EACH_EDGE ( e , ei , cfg_bb -> succs ) { auto & new_prob = m_vector_manager -> vector_block_infos [ e -> dest -> index ] . probability ; if ( ! new_prob . initialized_p ( ) ) new_prob = curr_prob * e -> probability ; else if ( new_prob == profile_probability :: always ( ) ) continue ; else new_prob += curr_prob * e -> probability ; } } } </s>


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

Simple m_vsetvl_insert vsetvl for optimize == 0 .


<s> static const char * riscv_mangle_type ( const_tree type ) { if ( TREE_CODE ( type ) == REAL_TYPE && TYPE_PRECISION ( type ) == 16 ) return "DF16_" ; if ( TYPE_NAME ( type ) != NULL ) { const char * res = riscv_vector :: mangle_builtin_type ( type ) ; if ( res ) return res ; } return NULL ; } </s>


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

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


<s> BitVector RISCVRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { BitVector Reserved ( getNumRegs ( ) ) ; markSuperRegs ( Reserved , RISCV :: X0 ) ; markSuperRegs ( Reserved , RISCV :: X1 ) ; markSuperRegs ( Reserved , RISCV :: X2 ) ; markSuperRegs ( Reserved , RISCV :: X3 ) ; markSuperRegs ( Reserved , RISCV :: X4 ) ; markSuperRegs ( Reserved , RISCV :: X8 ) ; markSuperRegs ( Reserved , RISCV :: VCFG ) ; assert ( checkAllSuperRegsMarked ( Reserved ) ) ; return Reserved ; } </s>

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


<s> void RISCVDAGToDAGISel :: PostprocessISelDAG ( ) { SelectionDAG :: allnodes_iterator Position = CurDAG -> allnodes_end ( ) ; bool MadeChange = false ; while ( Position != CurDAG -> allnodes_begin ( ) ) { SDNode * N = & * -- Position ; if ( N -> use_empty ( ) || ! N -> isMachineOpcode ( ) ) continue ; MadeChange |= doPeepholeSExtW ( N ) ; MadeChange |= doPeepholeLoadStoreADDI ( N ) ; } if ( MadeChange ) CurDAG -> RemoveDeadNodes ( ) ; } </s>

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


<s> VariantKind getKind ( ) const { return Kind ; } </s>


<s> tree riscv_builtin_decl ( unsigned int code , bool initialize_p ATTRIBUTE_UNUSED ) { if ( code >= ARRAY_SIZE ( riscv_builtins ) ) return error_mark_node ; return riscv_builtin_decls [ code ] ; } </s>


<s> RISCVSubtarget & RISCVSubtarget :: initializeSubtargetDependencies ( const Triple & TT , StringRef CPU , StringRef TuneCPU , StringRef FS , StringRef ABIName ) { bool Is64Bit = TT . isArch64Bit ( ) ; std :: string CPUName = std :: string ( CPU ) ; std :: string TuneCPUName = std :: string ( TuneCPU ) ; if ( CPUName . empty ( ) ) CPUName = Is64Bit ? "generic-rv64" : "generic-rv32" ; if ( TuneCPUName . empty ( ) ) TuneCPUName = CPUName ; ParseSubtargetFeatures ( CPUName , TuneCPUName , FS ) ; if ( Is64Bit ) { XLenVT = MVT :: i64 ; XLen = 64 ; } TargetABI = RISCVABI :: computeTargetABI ( TT , getFeatureBits ( ) , ABIName ) ; RISCVFeatures :: validate ( TT , getFeatureBits ( ) ) ; return * this ; } </s>

initializeSubtargetDependencies - Initializes using a CPU , a TuneCPU , and feature string so that we can use initializer lists for subtarget initialization .


<s> void riscv_split_doubleword_move ( rtx dest , rtx src ) { if ( ! TARGET_64BIT && TARGET_XTHEADFMV ) { if ( FP_REG_RTX_P ( dest ) ) { rtx low_src = riscv_subword ( src , false ) ; rtx high_src = riscv_subword ( src , true ) ; emit_insn ( gen_th_fmv_hw_w_x ( dest , high_src , low_src ) ) ; return ; } if ( FP_REG_RTX_P ( src ) ) { rtx low_dest = riscv_subword ( dest , false ) ; rtx high_dest = riscv_subword ( dest , true ) ; emit_insn ( gen_th_fmv_x_w ( low_dest , src ) ) ; emit_insn ( gen_th_fmv_x_hw ( high_dest , src ) ) ; return ; } } rtx 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 RISCVFrameLowering :: processFunctionBeforeFrameFinalized ( MachineFunction & MF , RegScavenger * RS ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterClass * RC = & RISCV :: GPRRegClass ; auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; int64_t RVVStackSize = assignRVVStackObjectOffsets ( MFI ) ; RVFI -> setRVVStackSize ( RVVStackSize ) ; if ( ! isInt < 11 > ( MFI . estimateStackSize ( MF ) ) || RVVStackSize != 0 ) { int RegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC ) , RegInfo -> getSpillAlign ( * RC ) , false ) ; RS -> addScavengingFrameIndex ( RegScavFI ) ; if ( RVVStackSize != 0 ) { int RVVRegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC ) , RegInfo -> getSpillAlign ( * RC ) , false ) ; RS -> addScavengingFrameIndex ( RVVRegScavFI ) ; } } if ( MFI . getCalleeSavedInfo ( ) . empty ( ) || RVFI -> useSaveRestoreLibCalls ( MF ) ) { RVFI -> setCalleeSavedStackSize ( 0 ) ; return ; } unsigned Size = 0 ; for ( const auto & Info : MFI . getCalleeSavedInfo ( ) ) { int FrameIdx = Info . getFrameIdx ( ) ; if ( MFI . getStackID ( FrameIdx ) != TargetStackID :: Default ) continue ; Size += MFI . getObjectSize ( FrameIdx ) ; } RVFI -> setCalleeSavedStackSize ( Size ) ; if ( RVVStackSize && ! hasFP ( MF ) && Size % 8 != 0 ) { RVFI -> setRVVPadding ( getStackAlign ( ) . value ( ) ) ; } } </s>


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

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


<s> static void build_one ( function_builder & b , const function_group_info & group , unsigned int pred_idx , unsigned int vec_type_idx ) { auto_vec < tree , 21 > argument_types ; function_instance function_instance ( group . base_name , * group . base , * group . shape , group . ops_infos . types [ vec_type_idx ] , group . preds [ pred_idx ] , & group . ops_infos ) ; tree return_type = group . ops_infos . ret . get_tree_type ( group . ops_infos . types [ vec_type_idx ] . index ) ; b . allocate_argument_types ( function_instance , argument_types ) ; b . apply_predication ( function_instance , return_type , argument_types ) ; b . add_unique_function ( function_instance , ( * group . shape ) , return_type , argument_types ) ; } </s>

Add one function instance for GROUP , using operand suffix at index OI , mode suffix at index PAIR & & bi and predication suffix at index pred_idx .


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

getPassName - Return a nice clean name for a pass .


<s> void riscv_move_integer ( rtx temp , rtx dest , HOST_WIDE_INT value , machine_mode orig_mode , bool in_splitter ) { struct riscv_integer_op codes [ RISCV_MAX_INTEGER_OPS ] ; machine_mode mode ; int i , num_ops ; rtx x ; bool can_create_pseudo = can_create_pseudo_p ( ) && ! in_splitter ; mode = GET_MODE ( dest ) ; num_ops = riscv_build_integer ( codes , value , orig_mode ) ; if ( can_create_pseudo && num_ops > 2 && num_ops >= riscv_split_integer_cost ( value ) ) x = riscv_split_integer ( value , mode ) ; else { codes [ 0 ] . value = trunc_int_for_mode ( codes [ 0 ] . value , mode ) ; x = GEN_INT ( codes [ 0 ] . value ) ; for ( i = 1 ; i < num_ops ; i ++ ) { if ( ! can_create_pseudo ) x = riscv_emit_set ( temp , x ) ; else x = force_reg ( mode , x ) ; codes [ i ] . value = trunc_int_for_mode ( codes [ i ] . value , mode ) ; x = gen_rtx_fmt_ee ( codes [ i ] . code , mode , x , GEN_INT ( codes [ i ] . value ) ) ; } } riscv_emit_set ( dest , x ) ; } </s>

Load VALUE into DEST . TEMP is as for riscv_force_temporary .


<s> void RISCVPassConfig :: addPreRegAlloc ( ) { if ( TM -> getOptLevel ( ) != CodeGenOpt :: None ) { addPass ( createRISCVMergeBaseOffsetOptPass ( ) ) ; addPass ( createRISCVCleanupVSETVLIPass ( ) ) ; } } </s>

This method may be implemented by targets that want to run passes immediately before register allocation .


<s> unsigned RISCVTargetLowering :: ComputeNumSignBitsForTargetNode ( SDValue Op , const APInt & DemandedElts , const SelectionDAG & DAG , unsigned Depth ) const { switch ( Op . getOpcode ( ) ) { default : break ; case RISCVISD :: SLLW : case RISCVISD :: SRAW : case RISCVISD :: SRLW : case RISCVISD :: DIVW : case RISCVISD :: DIVUW : case RISCVISD :: REMUW : case RISCVISD :: ROLW : case RISCVISD :: RORW : case RISCVISD :: GREVW : case RISCVISD :: GORCW : case RISCVISD :: FSLW : case RISCVISD :: FSRW : case RISCVISD :: SHFLW : case RISCVISD :: UNSHFLW : case RISCVISD :: BCOMPRESSW : case RISCVISD :: BDECOMPRESSW : return 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> void RISCVPassConfig :: addPreEmitPass ( ) { addPass ( & BranchRelaxationPassID ) ; addPass ( createRISCVMakeCompressibleOptPass ( ) ) ; } </s>

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


<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_CAPTAB_PCREL_HI
:
return
"captab_pcrel_hi"
;
case
VK_RISCV_TPREL_CINCOFFSET
:
return
"tprel_cincoffset"
;
case
VK_RISCV_TLS_IE_CAPTAB_PCREL_HI
:
return
"tls_ie_captab_pcrel_hi"
;
case
VK_RISCV_TLS_GD_CAPTAB_PCREL_HI
:
return
"tls_gd_captab_pcrel_hi"
;
case
VK_RISCV_CALL
:
return
"call"
;
case
VK_RISCV_CALL_PLT
:
return
"call_plt"
;
case
VK_RISCV_CCALL
:
return
"ccall"
;
case
VK_RISCV_32_PCREL
:
return
"32_pcrel"
;
}
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
"captab_pcrel_hi"
RISCV
"tprel_cincoffset"
RISCV
"tls_ie_captab_pcrel_hi"
RISCV
"tls_gd_captab_pcrel_hi"
RISCV
"call"
RISCV
"call_plt"
RISCV
"ccall"
RISCV
"32_pcrel"
"Invalid ELF symbol kind"


<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 : return 8 ; case TargetOpcode :: INLINEASM : { 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 .


<s>
SDValue
RISCVTargetLowering
::
getAddr
(
NodeTy
*
N
,
SelectionDAG
&
DAG
,
bool
IsLocal
)
const
{
SDLoc
DL
(
N
)
;
EVT
Ty
=
getPointerTy
(
DAG
.
getDataLayout
(
)
)
;
if
(
isPositionIndependent
(
)
)
{
SDValue
Addr
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
0
)
;
if
(
IsLocal
)
return
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
PseudoLLA
,
DL
,
Ty
,
Addr
)
,
0
)
;
return
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
PseudoLA
,
DL
,
Ty
,
Addr
)
,
0
)
;
}
switch
(
getTargetMachine
(
)
.
getCodeModel
(
)
)
{
default
:
report_fatal_error
(
"Unsupported code model for lowering"
)
;
case
CodeModel
::
Small
:
{
SDValue
AddrHi
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
RISCVII
::
MO_HI
)
;
SDValue
AddrLo
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
RISCVII
::
MO_LO
)
;
SDValue
MNHi
=
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
LUI
,
DL
,
Ty
,
AddrHi
)
,
0
)
;
return
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
ADDI
,
DL
,
Ty
,
MNHi
,
AddrLo
)
,
0
)
;
}
case
CodeModel
::
Medium
:
{
SDValue
Addr
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
0
)
;
return
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
PseudoLLA
,
DL
,
Ty
,
Addr
)
,
0
)
;
}
}
}
</s>

Return the address accessed by this recipe .


<s> rtx riscv_expand_builtin ( tree exp , rtx target , rtx subtarget ATTRIBUTE_UNUSED , machine_mode mode ATTRIBUTE_UNUSED , int ignore ATTRIBUTE_UNUSED ) { tree fndecl = TREE_OPERAND ( CALL_EXPR_FN ( exp ) , 0 ) ; unsigned int fcode = DECL_MD_FUNCTION_CODE ( fndecl ) ; const struct riscv_builtin_description * d = & riscv_builtins [ fcode ] ; switch ( d -> builtin_type ) { case RISCV_BUILTIN_DIRECT : return riscv_expand_builtin_direct ( d -> icode , target , exp , true ) ; case RISCV_BUILTIN_DIRECT_NO_TARGET : return riscv_expand_builtin_direct ( d -> icode , target , exp , false ) ; } gcc_unreachable ( ) ; } </s>


<s> gimple * fold ( gimple_folder & f ) const override { auto_vec < tree > vargs ( gimple_call_num_args ( f . call ) - 1 ) ; for ( unsigned i = 0 ; i < gimple_call_num_args ( f . call ) ; i ++ ) { if ( i == gimple_call_num_args ( f . call ) - 2 ) continue ; vargs . quick_push ( gimple_call_arg ( f . call , i ) ) ; } gimple * repl = gimple_build_call_vec ( gimple_call_fn ( f . call ) , vargs ) ; gimple_call_set_lhs ( repl , f . lhs ) ; tree new_vl = gimple_call_arg ( f . call , gimple_call_num_args ( f . call ) - 2 ) ; if ( integer_zerop ( new_vl ) ) { return repl ; } tree tmp_var = create_tmp_var ( size_type_node , "new_vl" ) ; tree decl = get_read_vl_decl ( ) ; gimple * g = gimple_build_call ( decl , 0 ) ; gimple_call_set_lhs ( g , tmp_var ) ; tree indirect = fold_build2 ( MEM_REF , size_type_node , gimple_call_arg ( f . call , gimple_call_num_args ( f . call ) - 2 ) , build_int_cst ( build_pointer_type ( size_type_node ) , 0 ) ) ; gassign * assign = gimple_build_assign ( indirect , tmp_var ) ; gsi_insert_after ( f . gsi , assign , GSI_SAME_STMT ) ; gsi_insert_after ( f . gsi , g , GSI_SAME_STMT ) ; return repl ; } </s>

Try to fold the call . Return the new statement on success and null on failure .


"Lowering returned the wrong number of results!"

This callback is invoked by the type legalizer to legalize nodes with an illegal operand type but legal result types .


<s> bool RISCVTargetLowering :: isEligibleForTailCallOptimization ( CCState & CCInfo , CallLoweringInfo & CLI , MachineFunction & MF , const SmallVector < CCValAssign , 16 > & ArgLocs ) const { auto & Callee = CLI . Callee ; auto CalleeCC = CLI . CallConv ; auto IsVarArg = CLI . IsVarArg ; auto & Outs = CLI . Outs ; auto & Caller = MF . getFunction ( ) ; auto CallerCC = Caller . getCallingConv ( ) ; if ( Caller . getFnAttribute ( "disable-tail-calls" ) . getValueAsString ( ) == "true" ) return false ; if ( Caller . hasFnAttribute ( "interrupt" ) ) return false ; if ( IsVarArg ) return false ; if ( CCInfo . getNextStackOffset ( ) != 0 ) return false ; for ( auto & VA : ArgLocs ) if ( VA . getLocInfo ( ) == CCValAssign :: Indirect ) return false ; auto IsCallerStructRet = Caller . hasStructRetAttr ( ) ; auto IsCalleeStructRet = Outs . empty ( ) ? false : Outs [ 0 ] . Flags . isSRet ( ) ; if ( IsCallerStructRet || IsCalleeStructRet ) return false ; if ( GlobalAddressSDNode * G = dyn_cast < GlobalAddressSDNode > ( Callee ) ) { const GlobalValue * GV = G -> getGlobal ( ) ; if ( GV -> hasExternalWeakLinkage ( ) ) return false ; } const RISCVRegisterInfo * TRI = Subtarget . getRegisterInfo ( ) ; const uint32_t * CallerPreserved = TRI -> getCallPreservedMask ( MF , CallerCC ) ; if ( CalleeCC != CallerCC ) { const uint32_t * CalleePreserved = TRI -> getCallPreservedMask ( MF , CalleeCC ) ; if ( ! TRI -> regmaskSubsetEqual ( CallerPreserved , CalleePreserved ) ) return false ; } for ( auto & Arg : Outs ) if ( Arg . Flags . isByVal ( ) ) return false ; return true ; } </s>

Returns true if the call can be lowered as a tail call .

RISCV RISCV 16 "disable-tail-calls" "true" "interrupt" 0 0 RISCV


<s> rtx function_expander :: use_contiguous_store_insn ( insn_code icode ) { gcc_assert ( call_expr_nargs ( exp ) > 0 ) ; machine_mode mode = TYPE_MODE ( builtin_types [ type . index ] . vector ) ; int arg_offset = 0 ; add_mem_operand ( mode , use_real_mask_p ( pred ) ? 1 : 0 ) ; if ( use_real_mask_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_all_one_mask_operand ( mask_mode ( ) ) ; arg_offset ++ ; for ( int argno = arg_offset ; argno < call_expr_nargs ( exp ) ; argno ++ ) add_input_operand ( argno ) ; return generate_insn ( icode ) ; } </s>


<s> void pass_vsetvl :: compute_local_properties ( void ) { basic_block cfg_bb ; for ( const bb_info * bb : crtl -> ssa -> bbs ( ) ) { unsigned int curr_bb_idx = bb -> index ( ) ; const auto local_dem = m_vector_manager -> vector_block_infos [ curr_bb_idx ] . local_dem ; const auto reaching_out = m_vector_manager -> vector_block_infos [ curr_bb_idx ] . reaching_out ; for ( size_t i = 0 ; i < m_vector_manager -> vector_exprs . length ( ) ; i ++ ) { const vector_insn_info * expr = m_vector_manager -> vector_exprs [ i ] ; if ( local_dem . real_dirty_p ( ) || local_dem . valid_p ( ) || local_dem . unknown_p ( ) || has_vsetvl_killed_avl_p ( bb , local_dem ) ) bitmap_clear_bit ( m_vector_manager -> vector_transp [ curr_bb_idx ] , i ) ; if ( find_reg_killed_by ( bb , expr -> get_avl ( ) ) ) { hash_set < set_info * > sets = get_all_sets ( expr -> get_avl_source ( ) , true , false , false ) ; if ( any_set_in_bb_p ( sets , bb ) ) bitmap_clear_bit ( m_vector_manager -> vector_transp [ curr_bb_idx ] , i ) ; } } if ( local_dem . valid_p ( ) || local_dem . real_dirty_p ( ) || ( has_vsetvl_killed_avl_p ( bb , local_dem ) && vlmax_avl_p ( local_dem . get_avl ( ) ) ) ) if ( anticipatable_occurrence_p ( bb , local_dem ) ) bitmap_set_bit ( m_vector_manager -> vector_antic [ curr_bb_idx ] , m_vector_manager -> get_expr_id ( local_dem ) ) ; if ( reaching_out . valid_or_dirty_p ( ) ) { auto_vec < size_t > available_list = m_vector_manager -> get_all_available_exprs ( reaching_out ) ; for ( size_t i = 0 ; i < available_list . length ( ) ; i ++ ) { const vector_insn_info * expr = m_vector_manager -> vector_exprs [ available_list [ i ] ] ; if ( reaching_out . real_dirty_p ( ) || has_vsetvl_killed_avl_p ( bb , reaching_out ) || available_occurrence_p ( bb , * expr ) ) bitmap_set_bit ( m_vector_manager -> vector_comp [ curr_bb_idx ] , available_list [ i ] ) ; } } } FOR_EACH_BB_FN ( cfg_bb , cfun ) { bitmap_ior ( m_vector_manager -> vector_kill [ cfg_bb -> index ] , m_vector_manager -> vector_transp [ cfg_bb -> index ] , m_vector_manager -> vector_comp [ cfg_bb -> index ] ) ; bitmap_not ( m_vector_manager -> vector_kill [ cfg_bb -> index ] , m_vector_manager -> vector_kill [ cfg_bb -> index ] ) ; } FOR_EACH_BB_FN ( cfg_bb , cfun ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , cfg_bb -> preds ) if ( e -> flags & EDGE_COMPLEX ) { bitmap_clear ( m_vector_manager -> vector_antic [ cfg_bb -> index ] ) ; bitmap_clear ( m_vector_manager -> vector_transp [ cfg_bb -> index ] ) ; } } } </s>

Compute the local properties of each recorded expression . Local properties are those that are defined by the block , irrespective of other blocks . An expression is transparent in a block if its operands are not modified in the block . An expression is computed ( locally available ) in a block if it is computed at least once and expression would contain the same value if the computation was moved to the end of the block . An expression is locally anticipatable in a block if it is computed at least once and expression would contain the same value if the computation was moved to the beginning of the block .


<s> bool check_builtin_call ( location_t location , vec < location_t > , unsigned int code , tree fndecl , unsigned int nargs , tree * args ) { const registered_function & rfn = * ( * registered_functions ) [ code ] ; return function_checker ( location , rfn . instance , fndecl , TREE_TYPE ( rfn . decl ) , nargs , args ) . check ( ) ; } </s>

Perform any semantic checks needed for a call to the SVE function with subcode CODE , such as testing for integer constant expressions . The call occurs at location LOCATION and has NARGS arguments , given by ARGS . FNDECL is the original function decl , before overload resolution . Return true if the call is valid , otherwise report a suitable error .


<s> static bool get_default_ta ( ) { return ( bool ) ( get_prefer_tail_policy ( ) & 0x1 || ( get_prefer_tail_policy ( ) >> 1 & 0x1 ) ) ; } </s>


<s> const TargetRegisterClass * getPointerRegClass ( const MachineFunction & MF , unsigned Kind = 0 ) const override { return & RISCV :: GPRRegClass ; } </s>

getPointerRegClass - Returns a TargetRegisterClass used for pointer values .


<s> static bool riscv_save_reg_p ( unsigned int regno ) { bool call_saved = ! global_regs [ regno ] && ! call_used_or_fixed_reg_p ( regno ) ; bool might_clobber = crtl -> saves_all_registers || df_regs_ever_live_p ( regno ) ; if ( call_saved && might_clobber ) return true ; if ( regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed ) return true ; if ( regno == RETURN_ADDR_REGNUM && crtl -> calls_eh_return ) return true ; if ( cfun -> machine -> interrupt_handler_p ) { if ( regno == GP_REG_FIRST ) return false ; if ( regno == STACK_POINTER_REGNUM ) return false ; if ( regno == GP_REGNUM || regno == THREAD_POINTER_REGNUM ) return false ; if ( df_regs_ever_live_p ( regno ) || ( ! crtl -> is_leaf && call_used_or_fixed_reg_p ( regno ) ) ) return true ; } return false ; } </s>

Return true if the current function must save register REGNO .


<s> static void riscv_for_each_saved_reg ( HOST_WIDE_INT sp_offset , riscv_save_restore_fn fn , bool epilogue , bool maybe_eh_return ) { HOST_WIDE_INT offset ; offset = cfun -> machine -> frame . gp_sp_offset - sp_offset ; for ( unsigned int regno = GP_REG_FIRST ; regno <= GP_REG_LAST ; regno ++ ) if ( BITSET_P ( cfun -> machine -> frame . mask , regno - GP_REG_FIRST ) ) { bool handle_reg = TRUE ; if ( epilogue && ! maybe_eh_return && crtl -> calls_eh_return ) { unsigned int i , regnum ; for ( i = 0 ; ( regnum = EH_RETURN_DATA_REGNO ( i ) ) != INVALID_REGNUM ; i ++ ) if ( regno == regnum ) { handle_reg = FALSE ; break ; } } if ( handle_reg ) riscv_save_restore_reg ( word_mode , regno , offset , fn ) ; offset -= UNITS_PER_WORD ; } offset = cfun -> machine -> frame . fp_sp_offset - sp_offset ; 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 ; 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> bool RISCVTargetLowering :: isLegalICmpImmediate ( int64_t Imm ) const { return isInt < 12 > ( Imm ) ; } </s>

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


<s>
void
print
(
raw_ostream
&
OS
)
const
override
{
switch
(
Kind
)
{
case
KindTy
::
Immediate
:
OS
<<
*
getImm
(
)
;
break
;
case
KindTy
::
Register
:
OS
<<
"<register x"
;
OS
<<
getReg
(
)
<<
">"
;
break
;
case
KindTy
::
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
case
KindTy
::
SystemRegister
:
OS
<<
"<sysreg: "
<<
getSysReg
(
)
<<
'>'
;
break
;
case
KindTy
::
VType
:
SmallString
<
32
>
VTypeBuf
;
OS
<<
"<vtype: "
<<
getVType
(
VTypeBuf
)
<<
'>'
;
break
;
}
}
</s>

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

RISCV
"<register x"
">"
"'"
"'"
"<sysreg: "
32
"<vtype: "


<s> unsigned int riscv_hard_regno_nregs ( int regno , enum machine_mode mode ) { if ( FP_REG_P ( regno ) ) return ( GET_MODE_SIZE ( mode ) + UNITS_PER_FP_REG - 1 ) / UNITS_PER_FP_REG ; return ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; } </s>


<s> void RISCVELFTargetObjectFile :: 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> bool function_instance :: could_trap_p ( ) const { unsigned int flags = call_properties ( ) ; if ( flags & CP_RAISE_FP_EXCEPTIONS ) return true ; if ( flags & ( CP_READ_MEMORY | CP_WRITE_MEMORY ) ) return true ; return false ; } </s>

Return true if calls to the function could raise a signal .


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

Like riscv_emit_int_compare , but for floating-point comparisons .


<s> unsigned RISCVTTIImpl :: getRegUsageForType ( Type * Ty ) { TypeSize Size = Ty -> getPrimitiveSizeInBits ( ) ; if ( Ty -> isVectorTy ( ) ) { if ( Size . isScalable ( ) && ST -> hasVInstructions ( ) ) return divideCeil ( Size . getKnownMinValue ( ) , RISCV :: RVVBitsPerBlock ) ; if ( ST -> useRVVForFixedLengthVectors ( ) ) return divideCeil ( Size , ST -> getMinRVVVectorSizeInBits ( ) ) ; } return BaseT :: getRegUsageForType ( Ty ) ; } </s>

Returns the estimated number of registers required to represent Ty .


<s> enum vlmul_type get_vlmul ( machine_mode mode ) { if ( TARGET_MIN_VLEN == 32 ) return mode_vtype_infos . vlmul_for_min_vlen32 [ mode ] ; else return mode_vtype_infos . vlmul_for_min_vlen64 [ mode ] ; } </s>

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


<s> const MCPhysReg * RISCVRegisterInfo :: getCalleeSavedRegs ( const MachineFunction * MF ) const { if ( MF -> getFunction ( ) . hasFnAttribute ( "interrupt" ) ) { if ( MF -> getSubtarget < RISCVSubtarget > ( ) . hasStdExtD ( ) ) return CSR_XLEN_F64_Interrupt_SaveList ; if ( MF -> getSubtarget < RISCVSubtarget > ( ) . hasStdExtF ( ) ) return CSR_XLEN_F32_Interrupt_SaveList ; return CSR_Interrupt_SaveList ; } return CSR_SaveList ; } </s>


<s> static bool vsetvl_discard_result_insn_p ( rtx_insn * rinsn ) { if ( ! vector_config_insn_p ( rinsn ) ) return false ; return ( INSN_CODE ( rinsn ) == CODE_FOR_vsetvl_discard_resultdi || INSN_CODE ( rinsn ) == CODE_FOR_vsetvl_discard_resultsi ) ; } </s>

Return true if it is vsetvl zero , rs1 .


<s> unsigned RISCVInstrInfo :: removeBranch ( MachineBasicBlock & MBB , int * BytesRemoved ) const { if ( BytesRemoved ) * BytesRemoved = 0 ; MachineBasicBlock :: iterator I = MBB . getLastNonDebugInstr ( ) ; if ( I == MBB . end ( ) ) return 0 ; if ( ! I -> getDesc ( ) . isUnconditionalBranch ( ) && ! I -> getDesc ( ) . isConditionalBranch ( ) ) return 0 ; if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; I -> eraseFromParent ( ) ; I = MBB . end ( ) ; if ( I == MBB . begin ( ) ) return 1 ; -- I ; if ( ! I -> getDesc ( ) . isConditionalBranch ( ) ) return 1 ; if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; I -> eraseFromParent ( ) ; return 2 ; } </s>

Remove the branching code at the end of the specific MBB .


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

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


<s> bool RISCVDAGToDAGISel :: runOnMachineFunction ( MachineFunction & MF ) { bool ret = SelectionDAGISel :: runOnMachineFunction ( MF ) ; processFunctionAfterISel ( MF ) ; return ret ; } </s>

runOnMachineFunction - Emit the function body .


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

Process a single instruction and collect debug info anchors .


<s> bool RISCVAsmBackend :: writeNopData ( uint64_t Count , MCObjectWriter * OW ) const { bool HasStdExtC = STI . getFeatureBits ( ) [ RISCV :: FeatureStdExtC ] ; unsigned MinNopLen = HasStdExtC ? 2 : 4 ; if ( ( Count % MinNopLen ) != 0 ) return false ; uint64_t Nop32Count = Count / 4 ; for ( uint64_t i = Nop32Count ; i != 0 ; -- i ) OW -> write32 ( 0x13 ) ; if ( HasStdExtC ) { uint64_t Nop16Count = ( Count - Nop32Count * 4 ) / 2 ; for ( uint64_t i = Nop16Count ; i != 0 ; -- i ) OW -> write16 ( 0x01 ) ; } return true ; } </s>

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


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

Determine whether to call GPR save/restore routines .


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

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


<s>
unsigned
RISCVMCCodeEmitter
::
getMachineOpValue
(
const
MCInst
&
MI
,
const
MCOperand
&
MO
,
SmallVectorImpl
<
MCFixup
>
&
Fixups
,
const
MCSubtargetInfo
&
STI
)
const
{
if
(
MO
.
isReg
(
)
)
return
Ctx
.
getRegisterInfo
(
)
->
getEncodingValue
(
MO
.
getReg
(
)
)
;
if
(
MO
.
isImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
llvm_unreachable
(
"Unhandled expression!"
)
;
return
0
;
}
</s>

getMachineOpValue - Return binary encoding of operand .


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

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

Returns the disassembly of a single instruction .


<s> bool riscv_v_ext_vector_mode_p ( machine_mode mode ) { case MODE ## mode : \ return REQUIREMENT ; switch ( mode ) { default : return false ; } return false ; } </s>

Return true if mode is the RVV enabled mode . For example : 'VNx1DI ' mode is disabled if MIN_VLEN == 32 . 'VNx1SI ' mode is enabled if MIN_VLEN == 32 .


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


<s> ISD :: NodeType getExtendForAtomicOps ( ) const override { return ISD :: SIGN_EXTEND ; } </s>

Returns how the platform 's atomic operations are extended ( ZERO_EXTEND , SIGN_EXTEND , or ANY_EXTEND ) .


<s>
SDValue
RISCVTargetLowering
::
getAddr
(
NodeTy
*
N
,
SelectionDAG
&
DAG
,
bool
IsLocal
)
const
{
SDLoc
DL
(
N
)
;
EVT
Ty
=
getPointerTy
(
DAG
.
getDataLayout
(
)
)
;
if
(
isPositionIndependent
(
)
)
{
SDValue
Addr
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
0
)
;
if
(
IsLocal
)
return
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
PseudoLLA
,
DL
,
Ty
,
Addr
)
,
0
)
;
SDValue
Load
=
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
PseudoLA
,
DL
,
Ty
,
Addr
)
,
0
)
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
MachineMemOperand
*
MemOp
=
MF
.
getMachineMemOperand
(
MachinePointerInfo
::
getGOT
(
MF
)
,
MachineMemOperand
::
MOLoad
|
MachineMemOperand
::
MODereferenceable
|
MachineMemOperand
::
MOInvariant
,
LLT
(
Ty
.
getSimpleVT
(
)
)
,
Align
(
Ty
.
getFixedSizeInBits
(
)
/
8
)
)
;
DAG
.
setNodeMemRefs
(
cast
<
MachineSDNode
>
(
Load
.
getNode
(
)
)
,
{
MemOp
}
)
;
return
Load
;
}
switch
(
getTargetMachine
(
)
.
getCodeModel
(
)
)
{
default
:
report_fatal_error
(
"Unsupported code model for lowering"
)
;
case
CodeModel
::
Small
:
{
SDValue
AddrHi
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
RISCVII
::
MO_HI
)
;
SDValue
AddrLo
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
RISCVII
::
MO_LO
)
;
SDValue
MNHi
=
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
LUI
,
DL
,
Ty
,
AddrHi
)
,
0
)
;
return
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
ADDI
,
DL
,
Ty
,
MNHi
,
AddrLo
)
,
0
)
;
}
case
CodeModel
::
Medium
:
{
SDValue
Addr
=
getTargetNode
(
N
,
DL
,
Ty
,
DAG
,
0
)
;
return
SDValue
(
DAG
.
getMachineNode
(
RISCV
::
PseudoLLA
,
DL
,
Ty
,
Addr
)
,
0
)
;
}
}
}
</s>

Return the address accessed by this recipe .


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

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


<s> SMLoc getStartLoc ( ) const override { return StartLoc ; } </s>

getStartLoc - Get the location of the first token of this operand .


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


<s> TargetLowering :: AtomicExpansionKind RISCVTargetLowering :: shouldExpandAtomicCmpXchgInIR ( AtomicCmpXchgInst * CI ) const { unsigned Size = CI -> getCompareOperand ( ) -> getType ( ) -> getPrimitiveSizeInBits ( ) ; if ( Size == 8 || Size == 16 ) return AtomicExpansionKind :: MaskedIntrinsic ; return AtomicExpansionKind :: None ; } </s>

Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass .


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


<s>
bool
RISCVInsertVSETVLI
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
const
RISCVSubtarget
&
ST
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
!
ST
.
hasVInstructions
(
)
)
return
false
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Entering InsertVSETVLI for "
<<
MF
.
getName
(
)
<<
"\n"
)
;
TII
=
ST
.
getInstrInfo
(
)
;
MRI
=
&
MF
.
getRegInfo
(
)
;
assert
(
BlockInfo
.
empty
(
)
&&
"Expect empty block infos"
)
;
BlockInfo
.
resize
(
MF
.
getNumBlockIDs
(
)
)
;
for
(
MachineBasicBlock
&
MBB
:
MF
)
doLocalPrepass
(
MBB
)
;
bool
HaveVectorOp
=
false
;
for
(
const
MachineBasicBlock
&
MBB
:
MF
)
{
HaveVectorOp
|=
computeVLVTYPEChanges
(
MBB
)
;
BlockData
&
BBInfo
=
BlockInfo
[
MBB
.
getNumber
(
)
]
;
BBInfo
.
Exit
=
BBInfo
.
Change
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Initial exit state of "
<<
printMBBReference
(
MBB
)
<<
" is "
<<
BBInfo
.
Exit
<<
"\n"
)
;
}
if
(
!
HaveVectorOp
)
{
BlockInfo
.
clear
(
)
;
return
false
;
}
for
(
const
MachineBasicBlock
&
MBB
:
MF
)
{
WorkList
.
push
(
&
MBB
)
;
BlockInfo
[
MBB
.
getNumber
(
)
]
.
InQueue
=
true
;
}
while
(
!
WorkList
.
empty
(
)
)
{
const
MachineBasicBlock
&
MBB
=
*
WorkList
.
front
(
)
;
WorkList
.
pop
(
)
;
computeIncomingVLVTYPE
(
MBB
)
;
}
for
(
MachineBasicBlock
&
MBB
:
MF
)
doPRE
(
MBB
)
;
for
(
MachineBasicBlock
&
MBB
:
MF
)
emitVSETVLIs
(
MBB
)
;
for
(
MachineBasicBlock
&
MBB
:
MF
)
doLocalPostpass
(
MBB
)
;
for
(
MachineBasicBlock
&
MBB
:
MF
)
{
for
(
MachineInstr
&
MI
:
MBB
)
{
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVSETVLI
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoVSETIVLI
)
{
Register
VRegDef
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
if
(
VRegDef
!=
RISCV
::
X0
&&
MRI
->
use_nodbg_empty
(
VRegDef
)
)
MI
.
getOperand
(
0
)
.
setReg
(
RISCV
::
X0
)
;
}
}
}
BlockInfo
.
clear
(
)
;
return
HaveVectorOp
;
}
</s>

RISCV
RISCV
RISCV
RISCV
"Entering InsertVSETVLI for "
"\n"
"Expect empty block infos"
"Initial exit state of "
" is "
"\n"
RISCV::PseudoVSETVLI
RISCV::PseudoVSETIVLI
0
RISCV::X0
0
RISCV::X0


<s> unsigned int pass_vsetvl :: execute ( function * ) { if ( n_basic_blocks_for_fn ( cfun ) <= 0 ) return 0 ; split_all_insns ( ) ; if ( ! has_vector_insn ( cfun ) ) return 0 ; init ( ) ; if ( ! optimize ) simple_vsetvl ( ) ; else lazy_vsetvl ( ) ; done ( ) ; return 0 ; } </s>


<s> unsigned RISCVInstrInfo :: isLoadFromStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { return isSimpleMove ( MI , FrameIndex , RISCVII :: SimpleLoad ) ; } </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> Register RISCVRegisterInfo :: getFrameRegister ( const MachineFunction & MF ) const { const RISCVFrameLowering * TFI = getFrameLowering ( MF ) ; return TFI -> hasFP ( MF ) ? TFI -> getFPReg ( ) : TFI -> getSPReg ( ) ; } </s>


<s> rtx get_avl_type_rtx ( enum avl_type type ) { return gen_int_mode ( type , Pmode ) ; } </s>


<s> Instruction * RISCVTargetLowering :: emitLeadingFence ( IRBuilderBase & Builder , Instruction * Inst , AtomicOrdering Ord ) const { if ( isa < LoadInst > ( Inst ) && Ord == AtomicOrdering :: SequentiallyConsistent ) return Builder . CreateFence ( Ord ) ; if ( isa < StoreInst > ( Inst ) && isReleaseOrStronger ( Ord ) ) return Builder . CreateFence ( AtomicOrdering :: Release ) ; return nullptr ; } </s>


<s> MachineBasicBlock :: iterator RISCVFrameLowering :: eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const { Register 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 RISCVTargetLowering :: CanLowerReturn ( CallingConv :: ID CallConv , MachineFunction & MF , bool IsVarArg , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) const { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , IsVarArg , MF , RVLocs , Context ) ; return CCInfo . CheckReturn ( Outs , Subtarget . isRV64 ( ) ? RetCC_RISCV64 : RetCC_RISCV32 ) ; } </s>

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

RISCV RISCV ISD::OutputArg 16 RISCV RISCV


<s> LLVM_DUMP_METHOD void dump ( ) const { print ( dbgs ( ) ) ; dbgs ( ) << "\n" ; } </s>

Dump the plan to stderr ( for debugging ) .


<s> void RISCVAsmPrinter :: emitEndOfAsmFile ( Module & M ) { RISCVTargetStreamer & RTS = static_cast < RISCVTargetStreamer & > ( * OutStreamer -> getTargetStreamer ( ) ) ; if ( TM . getTargetTriple ( ) . isOSBinFormatELF ( ) ) RTS . finishAttributeSection ( ) ; } </s>

This virtual method can be overridden by targets that want to emit something at the end of their file .


<s> static void emit_pred_op ( unsigned icode , rtx mask , rtx dest , rtx src , rtx len , machine_mode mask_mode , bool vlmax_p ) { insn_expander < 8 > e ; machine_mode mode = GET_MODE ( dest ) ; e . add_output_operand ( dest , mode ) ; if ( mask ) e . add_input_operand ( mask , GET_MODE ( mask ) ) ; else e . add_all_one_mask_operand ( mask_mode ) ; e . add_vundef_operand ( mode ) ; e . add_input_operand ( src , GET_MODE ( src ) ) ; if ( len ) e . add_input_operand ( len , Pmode ) ; else { rtx vlmax = gen_reg_rtx ( Pmode ) ; emit_vlmax_vsetvl ( mode , vlmax ) ; e . add_input_operand ( vlmax , Pmode ) ; } if ( GET_MODE_CLASS ( mode ) != MODE_VECTOR_BOOL ) e . add_policy_operand ( get_prefer_tail_policy ( ) , get_prefer_mask_policy ( ) ) ; if ( vlmax_p ) e . add_avl_type_operand ( avl_type :: VLMAX ) ; else e . add_avl_type_operand ( avl_type :: NONVLMAX ) ; e . expand ( ( enum insn_code ) icode , MEM_P ( dest ) || MEM_P ( src ) ) ; } </s>

Emit an RVV unmask & & vl mov from SRC to DEST .


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

getPassName - Return a nice clean name for a pass .


<s> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( ( RISCVISD :: NodeType ) Opcode ) { case RISCVISD :: FIRST_NUMBER : break ; case RISCVISD :: RET_FLAG : return "RISCVISD::RET_FLAG" ; case RISCVISD :: CALL : return "RISCVISD::CALL" ; case RISCVISD :: SELECT_CC : return "RISCVISD::SELECT_CC" ; } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific


<s> static void register_builtin_type ( vector_type_index type , tree eltype , machine_mode mode ) { builtin_types [ type ] . scalar = eltype ; builtin_types [ type ] . scalar_ptr = build_pointer_type ( eltype ) ; builtin_types [ type ] . scalar_const_ptr = build_const_pointer ( eltype ) ; if ( ! riscv_v_ext_vector_mode_p ( mode ) ) return ; tree vectype = build_vector_type_for_mode ( eltype , mode ) ; gcc_assert ( VECTOR_MODE_P ( TYPE_MODE ( vectype ) ) && TYPE_MODE ( vectype ) == mode && TYPE_MODE_RAW ( vectype ) == mode && TYPE_ALIGN ( vectype ) <= 128 && known_eq ( tree_to_poly_uint64 ( TYPE_SIZE ( vectype ) ) , GET_MODE_BITSIZE ( mode ) ) ) ; vectype = build_distinct_type_copy ( vectype ) ; gcc_assert ( vectype == TYPE_MAIN_VARIANT ( vectype ) ) ; SET_TYPE_STRUCTURAL_EQUALITY ( vectype ) ; TYPE_ARTIFICIAL ( vectype ) = 1 ; TYPE_INDIVISIBLE_P ( vectype ) = 1 ; add_vector_type_attribute ( vectype , vector_types [ type ] . mangled_name ) ; make_type_sizeless ( vectype ) ; abi_vector_types [ type ] = vectype ; lang_hooks . types . register_builtin_type ( vectype , vector_types [ type ] . abi_name ) ; } </s>

Helper function for register a single built-in RVV ABI type .


<s> bool function_checker :: require_immediate_range ( unsigned int argno , HOST_WIDE_INT min , HOST_WIDE_INT max ) const { gcc_assert ( argno < m_nargs ) ; tree arg = m_args [ argno ] ; HOST_WIDE_INT actual = tree_to_uhwi ( arg ) ; if ( ! IN_RANGE ( actual , min , max ) ) { report_out_of_range ( argno , actual , min , max ) ; return false ; } return true ; } </s>

Check that argument REL_ARGNO is an integer constant expression in the range [ MIN , MAX ] . REL_ARGNO counts from the end of the predication arguments .


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

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


<s> bool RISCVRegisterInfo :: isAsmClobberable ( const MachineFunction & MF , MCRegister PhysReg ) const { return ! MF . getSubtarget < RISCVSubtarget > ( ) . isRegisterReservedByUser ( PhysReg ) ; } </s>

Returns false if we ca n't guarantee that Physreg , specified as an IR asm clobber constraint , will be preserved across the statement .


<s> bool RISCVTargetLowering :: isEligibleForTailCallOptimization ( CCState & CCInfo , CallLoweringInfo & CLI , MachineFunction & MF , const SmallVector < CCValAssign , 16 > & ArgLocs ) const { auto & Callee = CLI . Callee ; auto CalleeCC = CLI . CallConv ; auto & Outs = CLI . Outs ; auto & Caller = MF . getFunction ( ) ; auto CallerCC = Caller . getCallingConv ( ) ; if ( Caller . getFnAttribute ( "disable-tail-calls" ) . getValueAsString ( ) == "true" ) return false ; if ( Caller . hasFnAttribute ( "interrupt" ) ) return false ; if ( CCInfo . getNextStackOffset ( ) != 0 ) return false ; for ( auto & VA : ArgLocs ) if ( VA . getLocInfo ( ) == CCValAssign :: Indirect ) return false ; auto IsCallerStructRet = Caller . hasStructRetAttr ( ) ; auto IsCalleeStructRet = Outs . empty ( ) ? false : Outs [ 0 ] . Flags . isSRet ( ) ; if ( IsCallerStructRet || IsCalleeStructRet ) return false ; if ( GlobalAddressSDNode * G = dyn_cast < GlobalAddressSDNode > ( Callee ) ) { const GlobalValue * GV = G -> getGlobal ( ) ; if ( GV -> hasExternalWeakLinkage ( ) ) return false ; } const RISCVRegisterInfo * TRI = Subtarget . getRegisterInfo ( ) ; const uint32_t * CallerPreserved = TRI -> getCallPreservedMask ( MF , CallerCC ) ; if ( CalleeCC != CallerCC ) { const uint32_t * CalleePreserved = TRI -> getCallPreservedMask ( MF , CalleeCC ) ; if ( ! TRI -> regmaskSubsetEqual ( CallerPreserved , CalleePreserved ) ) return false ; } for ( auto & Arg : Outs ) if ( Arg . Flags . isByVal ( ) ) return false ; return true ; } </s>

Returns true if the call can be lowered as a tail call .


<s> static bool riscv_valid_base_register_p ( rtx x , machine_mode mode , bool strict_p ) { if ( ! strict_p && GET_CODE ( x ) == SUBREG ) x = SUBREG_REG ( x ) ; return ( REG_P ( x ) && riscv_regno_mode_ok_for_base_p ( REGNO ( x ) , mode , strict_p ) ) ; } </s>

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


<s> bool RISCVCleanupVSETVLI :: runOnMachineFunction ( MachineFunction & MF ) { if ( skipFunction ( MF . getFunction ( ) ) ) return false ; const RISCVSubtarget & ST = MF . getSubtarget < RISCVSubtarget > ( ) ; if ( ! ST . hasStdExtV ( ) ) return false ; bool Changed = false ; for ( MachineBasicBlock & MBB : MF ) Changed |= runOnMachineBasicBlock ( MBB ) ; return Changed ; } </s>

runOnMachineFunction - Emit the function body .


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


"Unexpected combination of stack realignment and varsized objects"

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


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


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

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


<s> void riscv_d_target_versions ( void ) { if ( TARGET_64BIT ) d_add_builtin_version ( "RISCV64" ) ; else d_add_builtin_version ( "RISCV32" ) ; if ( TARGET_HARD_FLOAT ) d_add_builtin_version ( "D_HardFloat" ) ; else d_add_builtin_version ( "D_SoftFloat" ) ; } </s>

Implement TARGET_D_CPU_VERSIONS for RISC-V targets .


<s> void RISCVMCCodeEmitter :: encodeInstruction ( const MCInst & MI , raw_ostream & OS , SmallVectorImpl < MCFixup > & Fixups , const MCSubtargetInfo & STI ) const { uint32_t Bits = getBinaryCodeForInstr ( MI , Fixups , STI ) ; support :: endian :: Writer < support :: little > ( OS ) . write ( Bits ) ; ++ MCNumEmitted ; } </s>

Encode the given Inst to bytes and append to CB .

RISCV RISCV support::endian support::little


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

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


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

Return true if predication is using a real merge operand .


"The number of element should not be zero."

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


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

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


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


<s> const MCFixup * RISCVMCExpr :: getPCRelHiFixup ( const MCFragment * * DFOut ) const { MCValue AUIPCLoc ; if ( ! getSubExpr ( ) -> evaluateAsRelocatable ( AUIPCLoc , nullptr , nullptr ) ) return nullptr ; const MCSymbolRefExpr * AUIPCSRE = AUIPCLoc . getSymA ( ) ; if ( ! AUIPCSRE ) return nullptr ; const MCSymbol * AUIPCSymbol = & AUIPCSRE -> getSymbol ( ) ; const auto * DF = dyn_cast_or_null < MCDataFragment > ( AUIPCSymbol -> getFragment ( ) ) ; if ( ! DF ) return nullptr ; uint64_t Offset = AUIPCSymbol -> getOffset ( ) ; if ( DF -> getContents ( ) . size ( ) == Offset ) { DF = dyn_cast_or_null < MCDataFragment > ( DF -> getNextNode ( ) ) ; if ( ! DF ) return nullptr ; Offset = 0 ; } for ( const MCFixup & F : DF -> getFixups ( ) ) { if ( F . getOffset ( ) != Offset ) continue ; switch ( ( unsigned ) F . getKind ( ) ) { default : continue ; case RISCV :: fixup_riscv_got_hi20 : case RISCV :: fixup_riscv_tls_got_hi20 : case RISCV :: fixup_riscv_tls_gd_hi20 : case RISCV :: fixup_riscv_pcrel_hi20 : case RISCV :: fixup_riscv_captab_pcrel_hi20 : case RISCV :: fixup_riscv_tls_ie_captab_pcrel_hi20 : case RISCV :: fixup_riscv_tls_gd_captab_pcrel_hi20 : if ( DFOut ) * DFOut = DF ; return & F ; } } return nullptr ; } </s>

Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO points to , and optionally the fragment containing it .


<s> static void riscv_v_adjust_scalable_frame ( rtx target , poly_int64 offset , bool epilogue ) { rtx tmp = RISCV_PROLOGUE_TEMP ( Pmode ) ; rtx adjust_size = RISCV_PROLOGUE_TEMP2 ( Pmode ) ; rtx insn , dwarf , adjust_frame_rtx ; riscv_legitimize_poly_move ( Pmode , adjust_size , tmp , gen_int_mode ( offset , Pmode ) ) ; if ( epilogue ) insn = gen_add3_insn ( target , target , adjust_size ) ; else insn = gen_sub3_insn ( target , target , adjust_size ) ; insn = emit_insn ( insn ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; adjust_frame_rtx = gen_rtx_SET ( target , plus_constant ( Pmode , target , epilogue ? offset : - offset ) ) ; dwarf = alloc_reg_note ( REG_FRAME_RELATED_EXPR , copy_rtx ( adjust_frame_rtx ) , NULL_RTX ) ; REG_NOTES ( insn ) = dwarf ; } </s>

Adjust scalable frame of vector for prologue & & epilogue .


<s> static int riscv_extend_cost ( rtx op , bool unsigned_p ) { if ( MEM_P ( op ) ) return 0 ; if ( unsigned_p && GET_MODE ( op ) == QImode ) return COSTS_N_INSNS ( 1 ) ; if ( TARGET_ZBA && TARGET_64BIT && unsigned_p && GET_MODE ( op ) == SImode ) return COSTS_N_INSNS ( 1 ) ; if ( TARGET_ZBB ) { if ( ! unsigned_p && GET_MODE ( op ) == QImode ) return COSTS_N_INSNS ( 1 ) ; if ( GET_MODE ( op ) == HImode ) return COSTS_N_INSNS ( 1 ) ; } if ( ! unsigned_p && GET_MODE ( op ) == SImode ) return COSTS_N_INSNS ( 1 ) ; return COSTS_N_INSNS ( 2 ) ; } </s>

Return the cost of sign- or zero-extending OP .


<s>
bool
RISCVInstrInfo
::
isBranchOffsetInRange
(
unsigned
BranchOp
,
int64_t
BrOffset
)
const
{
unsigned
XLen
=
STI
.
getXLen
(
)
;
switch
(
BranchOp
)
{
default
:
llvm_unreachable
(
"Unexpected opcode!"
)
;
case
RISCV
::
BEQ
:
case
RISCV
::
BNE
:
case
RISCV
::
BLT
:
case
RISCV
::
BGE
:
case
RISCV
::
BLTU
:
case
RISCV
::
BGEU
:
case
RISCV
::
CV_BEQIMM
:
case
RISCV
::
CV_BNEIMM
:
return
isIntN
(
13
,
BrOffset
)
;
case
RISCV
::
JAL
:
case
RISCV
::
PseudoBR
:
return
isIntN
(
21
,
BrOffset
)
;
case
RISCV
::
PseudoJump
:
return
isIntN
(
32
,
SignExtend64
(
BrOffset
+
0x800
,
XLen
)
)
;
case
RISCV
::
HwlpBranch
:
return
true
;
}
}
</s>

Determine if the branch target is in range .

RISCV
RISCV
"Unexpected opcode!"
RISCV::BEQ
RISCV::BNE
RISCV::BLT
RISCV::BGE
RISCV::BLTU
RISCV::BGEU
RISCV::CV_BEQIMM
RISCV::CV_BNEIMM
13
RISCV::JAL
RISCV::PseudoBR
21
RISCV::PseudoJump
32
0x800
RISCV::HwlpBranch


<s> Value * RISCVTargetLowering :: emitMaskedAtomicRMWIntrinsic ( IRBuilder < > & Builder , AtomicRMWInst * AI , Value * AlignedAddr , Value * Incr , Value * Mask , Value * ShiftAmt , AtomicOrdering Ord ) const { Value * Ordering = Builder . getInt32 ( static_cast < uint32_t > ( AI -> getOrdering ( ) ) ) ; Type * Tys [ ] = { AlignedAddr -> getType ( ) } ; Function * LrwOpScwLoop = Intrinsic :: getDeclaration ( AI -> getModule ( ) , getIntrinsicForMaskedAtomicRMWBinOp32 ( AI -> getOperation ( ) ) , Tys ) ; if ( AI -> getOperation ( ) == AtomicRMWInst :: Min || AI -> getOperation ( ) == AtomicRMWInst :: Max ) { const DataLayout & DL = AI -> getModule ( ) -> getDataLayout ( ) ; unsigned ValWidth = DL . getTypeStoreSizeInBits ( AI -> getValOperand ( ) -> getType ( ) ) ; Value * SextShamt = Builder . CreateSub ( Builder . getInt32 ( Subtarget . getXLen ( ) - ValWidth ) , ShiftAmt ) ; return Builder . CreateCall ( LrwOpScwLoop , { AlignedAddr , Incr , Mask , SextShamt , Ordering } ) ; } return Builder . CreateCall ( LrwOpScwLoop , { AlignedAddr , Incr , Mask , Ordering } ) ; } </s>

Perform a masked atomicrmw using a target-specific intrinsic .


<s>
static
void
riscv_print_operand
(
FILE
*
file
,
rtx
op
,
int
letter
)
{
machine_mode
mode
=
GET_MODE
(
op
)
;
enum
rtx_code
code
=
GET_CODE
(
op
)
;
switch
(
letter
)
{
case
'h'
:
if
(
code
==
HIGH
)
op
=
XEXP
(
op
,
0
)
;
riscv_print_operand_reloc
(
file
,
op
,
true
)
;
break
;
case
'R'
:
riscv_print_operand_reloc
(
file
,
op
,
false
)
;
break
;
case
'C'
:
fputs
(
GET_RTX_NAME
(
code
)
,
file
)
;
break
;
case
'A'
:
if
(
riscv_memmodel_needs_amo_acquire
(
(
enum
memmodel
)
INTVAL
(
op
)
)
)
fputs
(
".aq"
,
file
)
;
break
;
case
'F'
:
if
(
riscv_memmodel_needs_release_fence
(
(
enum
memmodel
)
INTVAL
(
op
)
)
)
fputs
(
"fence iorw,ow; "
,
file
)
;
break
;
case
'i'
:
if
(
code
!=
REG
)
fputs
(
"i"
,
file
)
;
break
;
case
'S'
:
{
rtx
newop
=
GEN_INT
(
ctz_hwi
(
INTVAL
(
op
)
)
)
;
output_addr_const
(
file
,
newop
)
;
break
;
}
case
'T'
:
{
rtx
newop
=
GEN_INT
(
ctz_hwi
(
~
INTVAL
(
op
)
)
)
;
output_addr_const
(
file
,
newop
)
;
break
;
}
default
:
switch
(
code
)
{
case
REG
:
if
(
letter
&&
letter
!=
'z'
)
output_operand_lossage
(
"invalid use of '%%%c'"
,
letter
)
;
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
op
)
]
)
;
break
;
case
MEM
:
if
(
letter
&&
letter
!=
'z'
)
output_operand_lossage
(
"invalid use of '%%%c'"
,
letter
)
;
else
output_address
(
mode
,
XEXP
(
op
,
0
)
)
;
break
;
default
:
if
(
letter
==
'z'
&&
op
==
CONST0_RTX
(
GET_MODE
(
op
)
)
)
fputs
(
reg_names
[
GP_REG_FIRST
]
,
file
)
;
else
if
(
letter
&&
letter
!=
'z'
)
output_operand_lossage
(
"invalid use of '%%%c'"
,
letter
)
;
else
output_addr_const
(
file
,
riscv_strip_unspec_address
(
op
)
)
;
break
;
}
}
}
</s>

Implement TARGET_PRINT_OPERAND . The RISCV-specific operand codes are : ' h' Print the high-part relocation associated with OP , after stripping any outermost HIGH . ' R' Print the low-part relocation associated with OP . ' C' Print the integer branch condition for comparison OP . ' A' Print the atomic operation suffix for memory model OP . ' F' Print a FENCE if the memory model requires a release . ' z' Print x0 if OP is zero , otherwise print OP normally .

riscv
0
".aq"
"fence iorw,ow; "
"i"
"invalid use of '%%%c'"
"%s"
"invalid use of '%%%c'"
0
"invalid use of '%%%c'"


<s> void RISCVFrameLowering :: processFunctionBeforeFrameFinalized ( MachineFunction & MF , RegScavenger * RS ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; const TargetRegisterClass * RC = & RISCV :: GPRRegClass ; for ( int FI = MFI . getObjectIndexBegin ( ) , EFI = MFI . getObjectIndexEnd ( ) ; FI < EFI ; FI ++ ) { if ( MFI . getStackID ( FI ) == TargetStackID :: RISCVVector && ! MFI . isDeadObjectIndex ( FI ) ) RVFI -> setHasSpillVRs ( ) ; } if ( ! isInt < 11 > ( MFI . estimateStackSize ( MF ) ) ) { int RegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC ) , RegInfo -> getSpillAlign ( * RC ) , false ) ; RS -> addScavengingFrameIndex ( RegScavFI ) ; } } </s>

processFunctionBeforeFrameFinalized - This method is called immediately before the specified function 's frame layout ( MF.getFrameInfo ( ) ) is finalized .

RISCV RISCV RISCV RISCV::GPRRegClass RISCV 11


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

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


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

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


<s> static rtx riscv_legitimize_tls_address ( rtx loc ) { rtx dest , tp , tmp ; enum tls_model model = SYMBOL_REF_TLS_MODEL ( loc ) ; if ( ! flag_pic ) model = TLS_MODEL_LOCAL_EXEC ; switch ( model ) { case TLS_MODEL_LOCAL_DYNAMIC : case TLS_MODEL_GLOBAL_DYNAMIC : tmp = gen_rtx_REG ( Pmode , GP_RETURN ) ; dest = gen_reg_rtx ( Pmode ) ; emit_libcall_block ( riscv_call_tls_get_addr ( loc , tmp ) , dest , tmp , loc ) ; break ; case TLS_MODEL_INITIAL_EXEC : tp = gen_rtx_REG ( Pmode , THREAD_POINTER_REGNUM ) ; tmp = gen_reg_rtx ( Pmode ) ; emit_insn ( riscv_got_load_tls_ie ( tmp , loc ) ) ; dest = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_add3_insn ( dest , tmp , tp ) ) ; break ; case TLS_MODEL_LOCAL_EXEC : tmp = riscv_unspec_offset_high ( NULL , loc , SYMBOL_TLS_LE ) ; dest = gen_reg_rtx ( Pmode ) ; emit_insn ( riscv_tls_add_tp_le ( dest , tmp , loc ) ) ; dest = gen_rtx_LO_SUM ( Pmode , dest , riscv_unspec_address ( loc , SYMBOL_TLS_LE ) ) ; break ; default : gcc_unreachable ( ) ; } return dest ; } </s>

Generate the code to access LOC , a thread-local SYMBOL_REF , and return its address . The return value will be both a valid address and a valid SET_SRC ( either a REG or a LO_SUM ) .


<s> void RISCVTargetStreamer :: finish ( ) { finishAttributeSection ( ) ; } </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> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( ( RISCVISD :: NodeType ) Opcode ) { case RISCVISD :: FIRST_NUMBER : break ; case RISCVISD :: RET_FLAG : return "RISCVISD::RET_FLAG" ; case RISCVISD :: URET_FLAG : return "RISCVISD::URET_FLAG" ; case RISCVISD :: SRET_FLAG : return "RISCVISD::SRET_FLAG" ; case RISCVISD :: MRET_FLAG : return "RISCVISD::MRET_FLAG" ; case RISCVISD :: CALL : return "RISCVISD::CALL" ; case RISCVISD :: SELECT_CC : return "RISCVISD::SELECT_CC" ; case RISCVISD :: BuildPairF64 : return "RISCVISD::BuildPairF64" ; case RISCVISD :: SplitF64 : return "RISCVISD::SplitF64" ; case RISCVISD :: TAIL : return "RISCVISD::TAIL" ; case RISCVISD :: SETVL : return "RISCVISD::SETVL" ; case RISCVISD :: BROADCAST : return "RISCVISD::BROADCAST" ; } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific


<s> static bool riscv_legitimate_constant_p ( enum machine_mode mode ATTRIBUTE_UNUSED , rtx x ) { return riscv_const_insns ( x ) > 0 ; } </s>


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

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

RISCV RISCV ISD::OutputArg 16 0 ISD::ArgFlagsTy RISCV


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

getPassName - Return a nice clean name for a pass .


"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> static bool riscv_leaf_function_p ( void ) { if ( cfun -> machine -> is_leaf == 0 ) cfun -> machine -> is_leaf = leaf_function_p ( ) ? 1 : - 1 ; return cfun -> machine -> is_leaf > 0 ; } </s>

Return leaf_function_p ( ) and memoize the result .