<s>
MachineInstr
*
RISCVInstrInfo
::
commuteInstructionImpl
(
MachineInstr
&
MI
,
bool
NewMI
,
unsigned
OpIdx1
,
unsigned
OpIdx2
)
const
{
auto
cloneIfNew
=
[
NewMI
]
(
MachineInstr
&
MI
)
->
MachineInstr
&
{
if
(
NewMI
)
return
*
MI
.
getParent
(
)
->
getParent
(
)
->
CloneMachineInstr
(
&
MI
)
;
return
MI
;
}
;
switch
(
MI
.
getOpcode
(
)
)
{
case
CASE_VFMA_SPLATS
(
FMACC
)
:
case
CASE_VFMA_SPLATS
(
FMADD
)
:
case
CASE_VFMA_SPLATS
(
FMSAC
)
:
case
CASE_VFMA_SPLATS
(
FMSUB
)
:
case
CASE_VFMA_SPLATS
(
FNMACC
)
:
case
CASE_VFMA_SPLATS
(
FNMADD
)
:
case
CASE_VFMA_SPLATS
(
FNMSAC
)
:
case
CASE_VFMA_SPLATS
(
FNMSUB
)
:
case
CASE_VFMA_OPCODE_LMULS
(
FMACC
,
VV
)
:
case
CASE_VFMA_OPCODE_LMULS
(
FMSAC
,
VV
)
:
case
CASE_VFMA_OPCODE_LMULS
(
FNMACC
,
VV
)
:
case
CASE_VFMA_OPCODE_LMULS
(
FNMSAC
,
VV
)
:
{
assert
(
(
OpIdx1
==
1
||
OpIdx2
==
1
)
&&
"Unexpected opcode index"
)
;
assert
(
(
OpIdx1
==
3
||
OpIdx2
==
3
)
&&
"Unexpected opcode index"
)
;
unsigned
Opc
;
switch
(
MI
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Unexpected opcode"
)
;
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FMACC
,
FMADD
)
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FMADD
,
FMACC
)
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FMSAC
,
FMSUB
)
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FMSUB
,
FMSAC
)
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FNMACC
,
FNMADD
)
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FNMADD
,
FNMACC
)
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FNMSAC
,
FNMSUB
)
CASE_VFMA_CHANGE_OPCODE_SPLATS
(
FNMSUB
,
FNMSAC
)
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FMACC
,
FMADD
,
VV
)
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FMSAC
,
FMSUB
,
VV
)
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FNMACC
,
FNMADD
,
VV
)
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FNMSAC
,
FNMSUB
,
VV
)
}
auto
&
WorkingMI
=
cloneIfNew
(
MI
)
;
WorkingMI
.
setDesc
(
get
(
Opc
)
)
;
return
TargetInstrInfo
::
commuteInstructionImpl
(
WorkingMI
,
false
,
OpIdx1
,
OpIdx2
)
;
}
case
CASE_VFMA_OPCODE_LMULS
(
FMADD
,
VV
)
:
case
CASE_VFMA_OPCODE_LMULS
(
FMSUB
,
VV
)
:
case
CASE_VFMA_OPCODE_LMULS
(
FNMADD
,
VV
)
:
case
CASE_VFMA_OPCODE_LMULS
(
FNMSUB
,
VV
)
:
{
assert
(
(
OpIdx1
==
1
||
OpIdx2
==
1
)
&&
"Unexpected opcode index"
)
;
if
(
OpIdx1
==
3
||
OpIdx2
==
3
)
{
unsigned
Opc
;
switch
(
MI
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Unexpected opcode"
)
;
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FMADD
,
FMACC
,
VV
)
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FMSUB
,
FMSAC
,
VV
)
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FNMADD
,
FNMACC
,
VV
)
CASE_VFMA_CHANGE_OPCODE_LMULS
(
FNMSUB
,
FNMSAC
,
VV
)
}
auto
&
WorkingMI
=
cloneIfNew
(
MI
)
;
WorkingMI
.
setDesc
(
get
(
Opc
)
)
;
return
TargetInstrInfo
::
commuteInstructionImpl
(
WorkingMI
,
false
,
OpIdx1
,
OpIdx2
)
;
}
break
;
}
}
return
TargetInstrInfo
::
commuteInstructionImpl
(
MI
,
NewMI
,
OpIdx1
,
OpIdx2
)
;
}
</s>

Commutes the operands in the given instruction by changing the operands order and/or changing the instruction 's opcode and/or the immediate value operand .


<s> inline bool function_call_info :: function_returns_void_p ( ) { return TREE_TYPE ( TREE_TYPE ( fndecl ) ) == void_type_node ; } </s>

Return true if the function has no return value .


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

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


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

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


<s> void RISCVTargetStreamer :: emitTargetAttributes ( const MCSubtargetInfo & STI ) { if ( STI . hasFeature ( RISCV :: FeatureRV32E ) ) emitAttribute ( RISCVAttrs :: STACK_ALIGN , RISCVAttrs :: ALIGN_4 ) ; else emitAttribute ( RISCVAttrs :: STACK_ALIGN , RISCVAttrs :: ALIGN_16 ) ; std :: string Arch = "rv32" ; if ( STI . hasFeature ( RISCV :: Feature64Bit ) ) Arch = "rv64" ; if ( STI . hasFeature ( RISCV :: FeatureRV32E ) ) Arch += "e1p9" ; else Arch += "i2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtM ) ) Arch += "_m2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtA ) ) Arch += "_a2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtF ) ) Arch += "_f2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtD ) ) Arch += "_d2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtC ) ) Arch += "_c2p0" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtB ) ) Arch += "_b0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtV ) ) Arch += "_v0p10" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZfh ) ) Arch += "_zfh0p1" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZba ) ) Arch += "_zba0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbb ) ) Arch += "_zbb0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbc ) ) Arch += "_zbc0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbe ) ) Arch += "_zbe0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbf ) ) Arch += "_zbf0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbm ) ) Arch += "_zbm0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbp ) ) Arch += "_zbp0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbproposedc ) ) Arch += "_zbproposedc0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbr ) ) Arch += "_zbr0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbs ) ) Arch += "_zbs0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZbt ) ) Arch += "_zbt0p93" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZvamo ) ) Arch += "_zvamo0p10" ; if ( STI . hasFeature ( RISCV :: FeatureStdExtZvlsseg ) ) Arch += "_zvlsseg0p10" ; emitTextAttribute ( RISCVAttrs :: ARCH , Arch ) ; } </s>

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


<s> Value * RISCVTargetLowering :: emitMaskedAtomicCmpXchgIntrinsic ( IRBuilder < > & Builder , AtomicCmpXchgInst * CI , Value * AlignedAddr , Value * CmpVal , Value * NewVal , Value * Mask , AtomicOrdering Ord ) const { Value * Ordering = Builder . getInt32 ( static_cast < uint32_t > ( Ord ) ) ; Type * Tys [ ] = { AlignedAddr -> getType ( ) } ; Function * MaskedCmpXchg = Intrinsic :: getDeclaration ( CI -> getModule ( ) , Intrinsic :: riscv_masked_cmpxchg_i32 , Tys ) ; return Builder . CreateCall ( MaskedCmpXchg , { AlignedAddr , CmpVal , NewVal , Mask , Ordering } ) ; } </s>

Perform a masked cmpxchg using a target-specific intrinsic .

RISCV RISCV Intrinsic::getDeclaration Intrinsic::riscv_masked_cmpxchg_i32


<s> void RISCVFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; Align StackAlign = getStackAlign ( ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; const TargetRegisterInfo * TRI = STI . getRegisterInfo ( ) ; if ( RVFI -> getRVVStackSize ( ) && ( ! hasFP ( MF ) || TRI -> hasStackRealignment ( MF ) ) ) { int ScalarLocalVarSize = FrameSize - RVFI -> getCalleeSavedStackSize ( ) - RVFI -> getVarArgsSaveSize ( ) ; if ( auto RVVPadding = offsetToAlignment ( ScalarLocalVarSize , RVFI -> getRVVStackAlign ( ) ) ) RVFI -> setRVVPadding ( RVVPadding ) ; } } </s>

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


<s> bool RISCVPassConfig :: addRegBankSelect ( ) { addPass ( new RegBankSelect ( ) ) ; return false ; } </s>

This method should install a register bank selector pass , which assigns register banks to virtual registers without a register class or register banks .


<s> static unsigned addLiveIn ( MachineFunction & MF , unsigned PReg , const TargetRegisterClass * RC ) { unsigned VReg = MF . getRegInfo ( ) . createVirtualRegister ( RC ) ; MF . getRegInfo ( ) . addLiveIn ( PReg , VReg ) ; return VReg ; } </s>

addLiveIn - Add the specified register as a live-in .


<s> Value * RISCVTargetLowering :: emitMaskedAtomicRMWIntrinsic ( IRBuilder < > & Builder , AtomicRMWInst * AI , Value * AlignedAddr , Value * Incr , Value * Mask , Value * ShiftAmt , AtomicOrdering Ord ) const { unsigned XLen = Subtarget . getXLen ( ) ; Value * Ordering = Builder . getIntN ( XLen , static_cast < uint64_t > ( AI -> getOrdering ( ) ) ) ; Type * Tys [ ] = { AlignedAddr -> getType ( ) } ; Function * LrwOpScwLoop = Intrinsic :: getDeclaration ( AI -> getModule ( ) , getIntrinsicForMaskedAtomicRMWBinOp ( XLen , AI -> getOperation ( ) ) , Tys ) ; if ( XLen == 64 ) { Incr = Builder . CreateSExt ( Incr , Builder . getInt64Ty ( ) ) ; Mask = Builder . CreateSExt ( Mask , Builder . getInt64Ty ( ) ) ; ShiftAmt = Builder . CreateSExt ( ShiftAmt , Builder . getInt64Ty ( ) ) ; } Value * Result ; 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 . getIntN ( XLen , XLen - ValWidth ) , ShiftAmt ) ; Result = Builder . CreateCall ( LrwOpScwLoop , { AlignedAddr , Incr , Mask , SextShamt , Ordering } ) ; } else { Result = Builder . CreateCall ( LrwOpScwLoop , { AlignedAddr , Incr , Mask , Ordering } ) ; } if ( XLen == 64 ) Result = Builder . CreateTrunc ( Result , Builder . getInt32Ty ( ) ) ; return Result ; } </s>

Perform a masked atomicrmw using a target-specific intrinsic .


"Can't load this register from stack slot"

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


<s> void riscv_cpu_cpp_builtins ( cpp_reader * pfile ) { builtin_define ( "__riscv" ) ; if ( TARGET_RVC ) builtin_define ( "__riscv_compressed" ) ; if ( TARGET_RVE ) builtin_define ( "__riscv_32e" ) ; if ( TARGET_ATOMIC ) builtin_define ( "__riscv_atomic" ) ; if ( TARGET_MUL ) builtin_define ( "__riscv_mul" ) ; if ( TARGET_DIV ) builtin_define ( "__riscv_div" ) ; if ( TARGET_DIV && TARGET_MUL ) builtin_define ( "__riscv_muldiv" ) ; builtin_define_with_int_value ( "__riscv_xlen" , UNITS_PER_WORD * 8 ) ; if ( TARGET_HARD_FLOAT ) builtin_define_with_int_value ( "__riscv_flen" , UNITS_PER_FP_REG * 8 ) ; if ( TARGET_HARD_FLOAT && TARGET_FDIV ) { builtin_define ( "__riscv_fdiv" ) ; builtin_define ( "__riscv_fsqrt" ) ; } switch ( riscv_abi ) { case ABI_ILP32E : builtin_define ( "__riscv_abi_rve" ) ; gcc_fallthrough ( ) ; case ABI_ILP32 : case ABI_LP64 : builtin_define ( "__riscv_float_abi_soft" ) ; break ; case ABI_ILP32F : case ABI_LP64F : builtin_define ( "__riscv_float_abi_single" ) ; break ; case ABI_ILP32D : case ABI_LP64D : builtin_define ( "__riscv_float_abi_double" ) ; break ; } switch ( riscv_cmodel ) { case CM_MEDLOW : builtin_define ( "__riscv_cmodel_medlow" ) ; break ; case CM_PIC : builtin_define ( "__riscv_cmodel_pic" ) ; case CM_MEDANY : builtin_define ( "__riscv_cmodel_medany" ) ; break ; } if ( TARGET_MIN_VLEN != 0 ) builtin_define_with_int_value ( "__riscv_v_min_vlen" , TARGET_MIN_VLEN ) ; if ( TARGET_VECTOR_ELEN_64 ) builtin_define_with_int_value ( "__riscv_v_elen" , 64 ) ; else if ( TARGET_VECTOR_ELEN_32 ) builtin_define_with_int_value ( "__riscv_v_elen" , 32 ) ; if ( TARGET_VECTOR_ELEN_FP_64 ) builtin_define_with_int_value ( "__riscv_v_elen_fp" , 64 ) ; else if ( TARGET_VECTOR_ELEN_FP_32 ) builtin_define_with_int_value ( "__riscv_v_elen_fp" , 32 ) ; else if ( TARGET_MIN_VLEN != 0 ) builtin_define_with_int_value ( "__riscv_v_elen_fp" , 0 ) ; if ( TARGET_MIN_VLEN ) builtin_define ( "__riscv_vector" ) ; builtin_define_with_int_value ( "__riscv_arch_test" , 1 ) ; const riscv_subset_list * subset_list = riscv_current_subset_list ( ) ; if ( ! subset_list ) return ; size_t max_ext_len = 0 ; for ( const riscv_subset_t * subset = subset_list -> begin ( ) ; subset != subset_list -> end ( ) ; subset = subset -> next ) max_ext_len = MAX ( max_ext_len , subset -> name . length ( ) ) ; char * buf = ( char * ) alloca ( max_ext_len + 10 ) ; for ( const riscv_subset_t * subset = subset_list -> begin ( ) ; subset != subset_list -> end ( ) ; subset = subset -> next ) { int version_value = ( subset -> major_version * 1000000 ) + ( subset -> minor_version * 1000 ) ; if ( ( subset -> name == "zicsr" || subset -> name == "zifencei" ) && version_value == 0 ) version_value = 2000000 ; sprintf ( buf , "__riscv_%s" , subset -> name . c_str ( ) ) ; builtin_define_with_int_value ( buf , version_value ) ; } } </s>


<s> bool RISCVTargetLowering :: isTruncateFree ( EVT SrcVT , EVT DstVT ) const { if ( Subtarget . is64Bit ( ) || SrcVT . isVector ( ) || DstVT . isVector ( ) || ! SrcVT . isInteger ( ) || ! DstVT . isInteger ( ) ) return false ; unsigned SrcBits = SrcVT . getSizeInBits ( ) ; unsigned DestBits = DstVT . getSizeInBits ( ) ; return ( SrcBits == 64 && DestBits == 32 ) ; } </s>

Return true if it 's free to truncate a value of type Ty1 to type Ty2 .


<s> rtx riscv_subword ( rtx op , bool high_p ) { unsigned int byte = high_p ? UNITS_PER_WORD : 0 ; enum machine_mode mode = GET_MODE ( op ) ; if ( mode == VOIDmode ) mode = TARGET_64BIT ? TImode : DImode ; if ( MEM_P ( op ) ) return adjust_address ( op , word_mode , byte ) ; if ( REG_P ( op ) ) gcc_assert ( ! FP_REG_RTX_P ( op ) ) ; return simplify_gen_subreg ( word_mode , op , mode , byte ) ; } </s>

Return one word of double-word value OP . HIGH_P is true to select the high part or false to select the low part .


<s> static int riscv_build_integer ( struct riscv_integer_op * codes , HOST_WIDE_INT value , enum machine_mode mode ) { int cost = riscv_build_integer_1 ( codes , value , mode ) ; if ( value > 0 && cost > 2 ) { struct riscv_integer_op alt_codes [ RISCV_MAX_INTEGER_OPS ] ; int alt_cost , shift = clz_hwi ( value ) ; HOST_WIDE_INT shifted_val ; shifted_val = ( value << shift ) | ( ( ( ( HOST_WIDE_INT ) 1 ) << shift ) - 1 ) ; alt_cost = 1 + riscv_build_integer_1 ( alt_codes , shifted_val , mode ) ; if ( alt_cost < cost ) { alt_codes [ alt_cost - 1 ] . code = LSHIFTRT ; alt_codes [ alt_cost - 1 ] . value = shift ; memcpy ( codes , alt_codes , sizeof ( alt_codes ) ) ; cost = alt_cost ; } shifted_val = value << shift ; alt_cost = 1 + riscv_build_integer_1 ( alt_codes , shifted_val , mode ) ; if ( alt_cost < cost ) { alt_codes [ alt_cost - 1 ] . code = LSHIFTRT ; alt_codes [ alt_cost - 1 ] . value = shift ; memcpy ( codes , alt_codes , sizeof ( alt_codes ) ) ; cost = alt_cost ; } } return cost ; } </s>

Fill CODES with a sequence of rtl operations to load VALUE . Return the number of operations needed .


<s>
static
void
riscv_file_start
(
void
)
{
default_file_start
(
)
;
fprintf
(
asm_out_file
,
"\t.option %spic\n"
,
(
flag_pic
""
:
"no"
)
)
;
if
(
!
riscv_mrelax
)
fprintf
(
asm_out_file
,
"\t.option norelax\n"
)
;
}
</s>

riscv
"\t.option %spic\n"
""
"no"
"\t.option norelax\n"


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

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


<s> static void riscv_conditional_register_usage ( void ) { if ( TARGET_RVE ) { for ( int r = 16 ; r <= 31 ; r ++ ) fixed_regs [ r ] = 1 ; } if ( riscv_abi == ABI_ILP32E ) { for ( int r = 16 ; r <= 31 ; r ++ ) call_used_regs [ r ] = 1 ; } if ( ! TARGET_HARD_FLOAT ) { for ( int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) fixed_regs [ regno ] = call_used_regs [ regno ] = 1 ; } if ( UNITS_PER_FP_ARG == 0 ) { for ( int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) call_used_regs [ regno ] = 1 ; } } </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 = Align ( 4 ) ; Info . flags = MachineMemOperand :: MOLoad | MachineMemOperand :: MOStore | MachineMemOperand :: MOVolatile ; return true ; } case Intrinsic :: riscv_masked_strided_load : Info . opc = ISD :: INTRINSIC_W_CHAIN ; Info . ptrVal = I . getArgOperand ( 1 ) ; Info . memVT = MVT :: getVT ( I . getType ( ) -> getScalarType ( ) ) ; Info . align = Align ( I . getType ( ) -> getScalarSizeInBits ( ) / 8 ) ; Info . size = MemoryLocation :: UnknownSize ; Info . flags |= MachineMemOperand :: MOLoad ; return true ; case Intrinsic :: riscv_masked_strided_store : Info . opc = ISD :: INTRINSIC_VOID ; Info . ptrVal = I . getArgOperand ( 1 ) ; Info . memVT = MVT :: getVT ( I . getArgOperand ( 0 ) -> getType ( ) -> getScalarType ( ) ) ; Info . align = Align ( I . getArgOperand ( 0 ) -> getType ( ) -> getScalarSizeInBits ( ) / 8 ) ; Info . size = MemoryLocation :: UnknownSize ; Info . flags |= MachineMemOperand :: MOStore ; return true ; } } </s>

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


<s> void RISCVInstPrinter :: printInst ( const MCInst * MI , raw_ostream & O , StringRef Annot , const MCSubtargetInfo & STI ) { printInstruction ( MI , O ) ; printAnnotation ( O , Annot ) ; } </s>

Print the specified MCInst to the specified raw_ostream .


<s> rtx function_expander :: use_exact_insn ( insn_code icode ) { machine_mode mode = TYPE_MODE ( TREE_TYPE ( exp ) ) ; int arg_offset = 0 ; if ( base -> use_mask_predication_p ( ) ) { if ( use_real_mask_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_all_one_mask_operand ( mask_mode ( ) ) ; } if ( ! function_returns_void_p ( ) && base -> has_merge_operand_p ( ) ) { if ( use_real_merge_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_vundef_operand ( mode ) ; } for ( int argno = arg_offset ; argno < call_expr_nargs ( exp ) ; argno ++ ) add_input_operand ( argno ) ; if ( base -> apply_tail_policy_p ( ) ) add_input_operand ( Pmode , get_tail_policy_for_pred ( pred ) ) ; if ( base -> apply_mask_policy_p ( ) ) add_input_operand ( Pmode , get_mask_policy_for_pred ( pred ) ) ; if ( base -> apply_vl_p ( ) ) add_input_operand ( Pmode , get_avl_type_rtx ( avl_type :: NONVLMAX ) ) ; return generate_insn ( icode ) ; } </s>

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


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

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


"Can't store this register to stack slot"

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


<s>
StringRef
getPassName
(
)
const
override
{
return
"RISCV Redundant Copy Elimination"
;
}
</s>

getPassName - Return a nice clean name for a pass .

RISCV
"RISCV Redundant Copy Elimination"


<s> void emit_hard_vlmax_vsetvl ( machine_mode vmode , rtx vl ) { unsigned int sew = get_sew ( vmode ) ; emit_insn ( gen_vsetvl ( Pmode , vl , RVV_VLMAX , gen_int_mode ( sew , Pmode ) , gen_int_mode ( get_vlmul ( vmode ) , Pmode ) , const0_rtx , const0_rtx ) ) ; } </s>

Emit a vlmax vsetvl instruction . This should only be used when optimization is disabled or after vsetvl insertion pass .


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

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


<s> bool RISCVTargetLowering :: decomposeMulByConstant ( LLVMContext & Context , EVT VT , SDValue C ) const { if ( VT . isScalarInteger ( ) ) { if ( Subtarget . hasStdExtM ( ) && VT . getSizeInBits ( ) > Subtarget . getXLen ( ) ) return false ; if ( auto * ConstNode = dyn_cast < ConstantSDNode > ( C . getNode ( ) ) ) { const APInt & Imm = ConstNode -> getAPIntValue ( ) ; if ( ( Imm + 1 ) . isPowerOf2 ( ) || ( Imm - 1 ) . isPowerOf2 ( ) || ( 1 - Imm ) . isPowerOf2 ( ) || ( - 1 - Imm ) . isPowerOf2 ( ) ) return true ; if ( Subtarget . hasStdExtZba ( ) && ! Imm . isSignedIntN ( 12 ) && ( ( Imm - 2 ) . isPowerOf2 ( ) || ( Imm - 4 ) . isPowerOf2 ( ) || ( Imm - 8 ) . isPowerOf2 ( ) ) ) return true ; if ( Subtarget . hasStdExtM ( ) && VT . getSizeInBits ( ) >= Subtarget . getXLen ( ) ) return false ; if ( ! Imm . isSignedIntN ( 12 ) && Imm . countTrailingZeros ( ) < 12 ) { APInt ImmS = Imm . ashr ( Imm . countTrailingZeros ( ) ) ; if ( ( ImmS + 1 ) . isPowerOf2 ( ) || ( ImmS - 1 ) . isPowerOf2 ( ) || ( 1 - ImmS ) . isPowerOf2 ( ) ) return true ; } } } return false ; } </s>

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


"Should use MaskedValueIsZero if you don't know whether Op"

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


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

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


<s> static rtx riscv_force_temporary ( rtx dest , rtx value ) { if ( can_create_pseudo_p ( ) ) return force_reg ( Pmode , value ) ; else { riscv_emit_move ( dest , value ) ; return dest ; } } </s>

Copy VALUE to a register and return that register . If new pseudos are allowed , copy it into a new register , otherwise use DEST .


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


<s> bool riscv_hard_regno_mode_ok_p ( unsigned int regno , enum machine_mode mode ) { unsigned int nregs = riscv_hard_regno_nregs ( regno , mode ) ; if ( GP_REG_P ( regno ) ) { if ( ! GP_REG_P ( regno + nregs - 1 ) ) return false ; } else if ( FP_REG_P ( regno ) ) { if ( ! FP_REG_P ( regno + nregs - 1 ) ) return false ; if ( GET_MODE_CLASS ( mode ) != MODE_FLOAT && GET_MODE_CLASS ( mode ) != MODE_COMPLEX_FLOAT ) return false ; if ( GET_MODE_UNIT_SIZE ( mode ) > UNITS_PER_FP_REG || ( ! call_used_regs [ regno ] && GET_MODE_UNIT_SIZE ( mode ) > UNITS_PER_FP_ARG ) ) return false ; } else return false ; for ( unsigned i = 1 ; i < nregs ; i ++ ) if ( call_used_regs [ regno ] != call_used_regs [ regno + i ] ) return false ; return true ; } </s>

Return true if register REGNO can store a value of mode MODE .


<s> static rtx riscv_force_binary ( machine_mode mode , enum rtx_code code , rtx x , rtx y ) { return riscv_emit_binary ( code , gen_reg_rtx ( mode ) , x , y ) ; } </s>

Compute ( CODE X Y ) and store the result in a new register of mode MODE . Return that new register .


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

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


<s> void RISCVELFTargetObjectFile :: Initialize ( MCContext & Ctx , const TargetMachine & TM ) { TargetLoweringObjectFileELF :: Initialize ( Ctx , TM ) ; SmallDataSection = getContext ( ) . getELFSection ( ".sdata" , ELF :: SHT_PROGBITS , ELF :: SHF_WRITE | ELF :: SHF_ALLOC ) ; SmallBSSSection = getContext ( ) . getELFSection ( ".sbss" , ELF :: SHT_NOBITS , ELF :: SHF_WRITE | ELF :: SHF_ALLOC ) ; } </s>

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


<s> static bool riscv_pass_aggregate_in_fpr_and_gpr_p ( const_tree type , riscv_aggregate_field fields [ 2 ] ) { unsigned num_int = 0 , num_float = 0 ; int n = riscv_flatten_aggregate_argument ( type , fields ) ; for ( int i = 0 ; i < n ; i ++ ) { num_float += SCALAR_FLOAT_TYPE_P ( fields [ i ] . type ) ; num_int += INTEGRAL_TYPE_P ( fields [ i ] . type ) ; } return num_int == 1 && num_float == 1 ; } </s>

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


<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 ; I -> eraseFromParent ( ) ; if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; I = MBB . end ( ) ; if ( I == MBB . begin ( ) ) return 1 ; -- I ; if ( ! I -> getDesc ( ) . isConditionalBranch ( ) ) return 1 ; I -> eraseFromParent ( ) ; if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; return 2 ; } </s>

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


<s> bool RISCVAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { MCSubtargetInfo & NewSTI = OutStreamer -> getContext ( ) . getSubtargetCopy ( * TM . getMCSubtargetInfo ( ) ) ; NewSTI . setFeatureBits ( MF . getSubtarget ( ) . getFeatureBits ( ) ) ; STI = & NewSTI ; SetupMachineFunction ( MF ) ; emitFunctionBody ( ) ; return false ; } </s>

runOnMachineFunction - Emit the function body .


<s> static void riscv_block_move_loop ( rtx dest , rtx src , unsigned HOST_WIDE_INT length , unsigned HOST_WIDE_INT bytes_per_iter ) { rtx label , src_reg , dest_reg , final_src , test ; unsigned HOST_WIDE_INT leftover ; leftover = length % bytes_per_iter ; length -= leftover ; riscv_adjust_block_mem ( src , bytes_per_iter , & src_reg , & src ) ; riscv_adjust_block_mem ( dest , bytes_per_iter , & dest_reg , & dest ) ; final_src = expand_simple_binop ( Pmode , PLUS , src_reg , GEN_INT ( length ) , 0 , 0 , OPTAB_WIDEN ) ; label = gen_label_rtx ( ) ; emit_label ( label ) ; riscv_block_move_straight ( dest , src , bytes_per_iter ) ; riscv_emit_move ( src_reg , plus_constant ( Pmode , src_reg , bytes_per_iter ) ) ; riscv_emit_move ( dest_reg , plus_constant ( Pmode , dest_reg , bytes_per_iter ) ) ; test = gen_rtx_NE ( VOIDmode , src_reg , final_src ) ; if ( Pmode == DImode ) emit_jump_insn ( gen_cbranchdi4 ( test , src_reg , final_src , label ) ) ; else emit_jump_insn ( gen_cbranchsi4 ( test , src_reg , final_src , label ) ) ; if ( leftover ) riscv_block_move_straight ( dest , src , leftover ) ; else emit_insn ( gen_nop ( ) ) ; } </s>

Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER bytes at a time . LENGTH must be at least BYTES_PER_ITER . Assume that the memory regions do not overlap .


<s>
RISCVSubtarget
&
RISCVSubtarget
::
initializeSubtargetDependencies
(
const
Triple
&
TT
,
StringRef
CPU
,
StringRef
TuneCPU
,
StringRef
FS
,
StringRef
ABIName
)
{
bool
Is64Bit
=
TT
.
isArch64Bit
(
)
;
if
(
CPU
.
empty
(
)
)
CPU
=
Is64Bit
"generic-rv64"
:
"generic-rv32"
;
if
(
CPU
==
"generic"
)
report_fatal_error
(
Twine
(
"CPU 'generic' is not supported. Use "
)
+
(
Is64Bit
"generic-rv64"
:
"generic-rv32"
)
)
;
if
(
TuneCPU
.
empty
(
)
)
TuneCPU
=
CPU
;
ParseSubtargetFeatures
(
CPU
,
TuneCPU
,
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>
InstructionCost
RISCVTTIImpl
::
getArithmeticReductionCost
(
unsigned
Opcode
,
VectorType
*
VTy
,
Optional
<
FastMathFlags
>
FMF
,
TTI
::
TargetCostKind
CostKind
)
{
if
(
!
isa
<
FixedVectorType
>
(
VTy
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
if
(
VTy
->
getElementType
(
)
->
isIntegerTy
(
1
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
if
(
!
ST
->
useRVVForFixedLengthVectors
(
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
if
(
VTy
->
getScalarSizeInBits
(
)
>
ST
->
getELEN
(
)
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
int
ISD
=
TLI
->
InstructionOpcodeToISD
(
Opcode
)
;
assert
(
ISD
&&
"Invalid opcode"
)
;
if
(
ISD
!=
ISD
::
ADD
&&
ISD
!=
ISD
::
OR
&&
ISD
!=
ISD
::
XOR
&&
ISD
!=
ISD
::
AND
&&
ISD
!=
ISD
::
FADD
)
return
BaseT
::
getArithmeticReductionCost
(
Opcode
,
VTy
,
FMF
,
CostKind
)
;
InstructionCost
BaseCost
=
2
;
unsigned
VL
=
cast
<
FixedVectorType
>
(
VTy
)
->
getNumElements
(
)
;
std
::
pair
<
InstructionCost
,
MVT
>
LT
=
TLI
->
getTypeLegalizationCost
(
DL
,
VTy
)
;
if
(
TTI
::
requiresOrderedReduction
(
FMF
)
)
return
(
LT
.
first
1
)
+
BaseCost
+
VL
;
return
(
LT
.
first
1
)
+
BaseCost
+
Log2_32_Ceil
(
VL
)
;
}
</s>

Calculate the cost of vector reduction intrinsics .

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


<s> EVT getSetCCResultType ( const DataLayout & , LLVMContext & , EVT VT ) const override { return MVT :: i32 ; } </s>

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


<s> bool RISCVTargetLowering :: getTgtMemIntrinsic ( IntrinsicInfo & Info , const CallInst & I , MachineFunction & MF , unsigned Intrinsic ) const { auto & DL = I . getModule ( ) -> getDataLayout ( ) ; 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 : Info . opc = ISD :: INTRINSIC_W_CHAIN ; Info . memVT = MVT :: i32 ; Info . ptrVal = I . getArgOperand ( 0 ) ; Info . offset = 0 ; Info . align = Align ( 4 ) ; Info . flags = MachineMemOperand :: MOLoad | MachineMemOperand :: MOStore | MachineMemOperand :: MOVolatile ; return true ; case Intrinsic :: riscv_masked_strided_load : Info . opc = ISD :: INTRINSIC_W_CHAIN ; Info . ptrVal = I . getArgOperand ( 1 ) ; Info . memVT = getValueType ( DL , I . getType ( ) -> getScalarType ( ) ) ; Info . align = Align ( DL . getTypeSizeInBits ( I . getType ( ) -> getScalarType ( ) ) / 8 ) ; Info . size = MemoryLocation :: UnknownSize ; Info . flags |= MachineMemOperand :: MOLoad ; return true ; case Intrinsic :: riscv_masked_strided_store : Info . opc = ISD :: INTRINSIC_VOID ; Info . ptrVal = I . getArgOperand ( 1 ) ; Info . memVT = getValueType ( DL , I . getArgOperand ( 0 ) -> getType ( ) -> getScalarType ( ) ) ; Info . align = Align ( DL . getTypeSizeInBits ( I . getArgOperand ( 0 ) -> getType ( ) -> getScalarType ( ) ) / 8 ) ; Info . size = MemoryLocation :: UnknownSize ; Info . flags |= MachineMemOperand :: MOStore ; return true ; case Intrinsic :: riscv_seg2_load : case Intrinsic :: riscv_seg3_load : case Intrinsic :: riscv_seg4_load : case Intrinsic :: riscv_seg5_load : case Intrinsic :: riscv_seg6_load : case Intrinsic :: riscv_seg7_load : case Intrinsic :: riscv_seg8_load : Info . opc = ISD :: INTRINSIC_W_CHAIN ; Info . ptrVal = I . getArgOperand ( 0 ) ; Info . memVT = getValueType ( DL , I . getType ( ) -> getStructElementType ( 0 ) -> getScalarType ( ) ) ; Info . align = Align ( DL . getTypeSizeInBits ( I . getType ( ) -> getStructElementType ( 0 ) -> getScalarType ( ) ) / 8 ) ; Info . size = MemoryLocation :: UnknownSize ; Info . flags |= MachineMemOperand :: MOLoad ; return true ; } } </s>

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


<s> void RISCVTargetStreamer :: reset ( ) { } </s>

Reset an existing scalar value for Def and a given Instance .


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


<s> int riscv_const_insns ( rtx x ) { enum riscv_symbol_type symbol_type ; rtx offset ; switch ( GET_CODE ( x ) ) { case HIGH : if ( ! riscv_symbolic_constant_p ( XEXP ( x , 0 ) , & symbol_type ) || ! riscv_split_symbol_type ( symbol_type ) ) return 0 ; return 1 ; case CONST_INT : { int cost = riscv_integer_cost ( INTVAL ( x ) ) ; return cost < 4 ? cost : 0 ; } case CONST_DOUBLE : case CONST_VECTOR : return x == CONST0_RTX ( GET_MODE ( x ) ) ? 1 : 0 ; case CONST : if ( riscv_symbolic_constant_p ( x , & symbol_type ) ) return riscv_symbol_insns ( symbol_type ) ; split_const ( x , & x , & offset ) ; if ( offset != 0 ) { int n = riscv_const_insns ( x ) ; if ( n != 0 ) return n + riscv_integer_cost ( INTVAL ( offset ) ) ; } return 0 ; case SYMBOL_REF : case LABEL_REF : return riscv_symbol_insns ( riscv_classify_symbol ( x ) ) ; default : return 0 ; } } </s>

Return the number of instructions needed to load constant X . Return 0 if X is n't a valid constant .


<s> std :: pair < unsigned , unsigned > RISCVInstrInfo :: decomposeMachineOperandsTargetFlags ( unsigned TF ) const { const unsigned Mask = RISCVII :: MO_DIRECT_FLAG_MASK ; return std :: make_pair ( TF & Mask , TF & ~ Mask ) ; } </s>

Decompose the machine operand 's target flags into two values - the direct target flag value and any of bit flags that are applied .


<s> bool RISCVPassConfig :: addLegalizeMachineIR ( ) { addPass ( new Legalizer ( ) ) ; return false ; } </s>

This method should install a legalize pass , which converts the instruction sequence into one that can be selected by the target .


<s> RISCVSubtarget & RISCVSubtarget :: initializeSubtargetDependencies ( StringRef CPU , StringRef FS ) { std :: string CPUName = CPU ; if ( CPUName . empty ( ) ) { CPUName = "" ; } ParseSubtargetFeatures ( CPUName , FS ) ; return * this ; } </s>


"  Found lowered global address with one use: "


<s> SMLoc getLoc ( ) const { return getParser ( ) . getTok ( ) . getLoc ( ) ; } </s>

Get the source location of the point where the field was defined .


<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 : case TargetOpcode :: INLINEASM_BR : { const MachineFunction & MF = * MI . getParent ( ) -> getParent ( ) ; const auto & TM = static_cast < const RISCVTargetMachine & > ( MF . getTarget ( ) ) ; return getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>

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


<s> bool function_instance :: modifies_global_state_p ( ) const { unsigned int flags = call_properties ( ) ; if ( flags & CP_RAISE_FP_EXCEPTIONS ) return true ; return flags & ( CP_WRITE_MEMORY | CP_WRITE_CSR ) ; } </s>

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


"loadRegFromStackSlot didn't insert any code!"

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


<s> static void riscv_function_arg_advance ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; struct riscv_arg_info info ; riscv_get_arg_info ( & info , cum , arg . mode , arg . type , arg . named , false ) ; cum -> num_fprs = info . fpr_offset + info . num_fprs ; cum -> num_gprs = info . gpr_offset + info . num_gprs ; } </s>


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


<s>
unsigned
getReg
(
)
const
override
{
assert
(
Kind
==
KindTy
::
Register
&&
"Invalid type access!"
)
;
return
Reg
.
RegNum
.
id
(
)
;
}
</s>

Returns the register associated with this edge .


<s> const RISCVRegisterInfo * getRegisterInfo ( ) const { return & InstrInfo . getRegisterInfo ( ) ; } </s>

getRegisterInfo - TargetInstrInfo is a superset of MRegister info .


<s> const RISCVSubtarget * getSubtargetImpl ( ) const { return & Subtarget ; } </s>

Virtual method implemented by subclasses that returns a reference to that target 's TargetSubtargetInfo-derived member variable .


<s> static unsigned riscv_pass_mode_in_fpr_p ( enum machine_mode mode ) { if ( GET_MODE_UNIT_SIZE ( mode ) <= UNITS_PER_FP_ARG ) { if ( GET_MODE_CLASS ( mode ) == MODE_FLOAT ) return 1 ; if ( GET_MODE_CLASS ( mode ) == MODE_COMPLEX_FLOAT ) return 2 ; } return 0 ; } </s>

If MODE represents an argument that can be passed or returned in floating-point registers , return the number of registers , else 0 .


<s> bool RISCVFrameLowering :: hasFP ( const MachineFunction & MF ) const { return true ; } </s>

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


<s> unsigned RISCVInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { default : { if ( MI . getParent ( ) && MI . getParent ( ) -> getParent ( ) ) { const auto MF = MI . getMF ( ) ; const auto & TM = static_cast < const RISCVTargetMachine & > ( MF -> getTarget ( ) ) ; const MCRegisterInfo & MRI = * TM . getMCRegisterInfo ( ) ; const MCSubtargetInfo & STI = * TM . getMCSubtargetInfo ( ) ; const RISCVSubtarget & ST = MF -> getSubtarget < RISCVSubtarget > ( ) ; if ( isCompressibleInst ( MI , & ST , MRI , STI ) ) return 2 ; } return get ( Opcode ) . getSize ( ) ; } case TargetOpcode :: EH_LABEL : case TargetOpcode :: IMPLICIT_DEF : case TargetOpcode :: KILL : case TargetOpcode :: DBG_VALUE : return 0 ; case RISCV :: PseudoCALLReg : case RISCV :: PseudoCALL : case RISCV :: PseudoJump : case RISCV :: PseudoTAIL : case RISCV :: PseudoLLA : case RISCV :: PseudoLA : case RISCV :: PseudoLA_TLS_IE : case RISCV :: PseudoLA_TLS_GD : return 8 ; case TargetOpcode :: INLINEASM : case TargetOpcode :: INLINEASM_BR : { const MachineFunction & MF = * MI . getParent ( ) -> getParent ( ) ; const auto & TM = static_cast < const RISCVTargetMachine & > ( MF . getTarget ( ) ) ; return getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>

RISCV RISCV RISCV RISCV RISCV 2 0 RISCV::PseudoCALLReg RISCV::PseudoCALL RISCV::PseudoJump RISCV::PseudoTAIL RISCV::PseudoLLA RISCV::PseudoLA RISCV::PseudoLA_TLS_IE RISCV::PseudoLA_TLS_GD 8 RISCV 0


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

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


<s> bool evaluateBranch ( const MCInst & Inst , uint64_t Addr , uint64_t Size , uint64_t & Target ) const override { if ( isConditionalBranch ( Inst ) ) { int64_t Imm ; if ( Size == 2 ) Imm = Inst . getOperand ( 1 ) . getImm ( ) ; else Imm = Inst . getOperand ( 2 ) . getImm ( ) ; Target = Addr + Imm ; return true ; } if ( Inst . getOpcode ( ) == RISCV :: C_JAL || Inst . getOpcode ( ) == RISCV :: C_J || Inst . getOpcode ( ) == RISCV :: C_CJAL ) { Target = Addr + Inst . getOperand ( 0 ) . getImm ( ) ; return true ; } if ( Inst . getOpcode ( ) == RISCV :: JAL || Inst . getOpcode ( ) == RISCV :: CJAL ) { Target = Addr + Inst . getOperand ( 1 ) . getImm ( ) ; return true ; } return false ; } </s>

Given a branch instruction try to get the address the branch targets .


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

Return true if it is a vsetvl instruction .


"could not find corresponding %pcrel_hi"

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


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

Perform a masked cmpxchg using a target-specific intrinsic .


<s> static bool riscv_is_eh_return_data_register ( unsigned int regno ) { unsigned int i , regnum ; if ( ! crtl -> calls_eh_return ) return false ; for ( i = 0 ; ( regnum = EH_RETURN_DATA_REGNO ( i ) ) != INVALID_REGNUM ; i ++ ) if ( regno == regnum ) { return true ; } return false ; } </s>

Return TRUE if provided REGNO is eh return data register .


<s> void RISCVInstPrinter :: printInst ( const MCInst * MI , uint64_t Address , StringRef Annot , const MCSubtargetInfo & STI , raw_ostream & O ) { bool Res = false ; const MCInst * NewMI = MI ; MCInst UncompressedMI ; if ( ! NoAliases ) Res = uncompressInst ( UncompressedMI , * MI , MRI , STI ) ; if ( Res ) NewMI = const_cast < MCInst * > ( & UncompressedMI ) ; if ( NoAliases || ! printAliasInstr ( NewMI , Address , STI , O ) ) printInstruction ( NewMI , Address , STI , O ) ; printAnnotation ( O , Annot ) ; } </s>

Print the specified MCInst to the specified raw_ostream .


<s> rtx riscv_return_addr ( int count , rtx frame ATTRIBUTE_UNUSED ) { if ( count != 0 ) return const0_rtx ; return get_hard_reg_initial_val ( Pmode , RETURN_ADDR_REGNUM ) ; } </s>

Implement RETURN_ADDR_RTX . We do not support moving back to a previous frame .


<s> static void riscv_for_each_saved_reg ( HOST_WIDE_INT sp_offset , riscv_save_restore_fn fn ) { HOST_WIDE_INT offset ; offset = cfun -> machine -> frame . gp_sp_offset - sp_offset ; for ( int regno = GP_REG_FIRST ; regno <= GP_REG_LAST - 1 ; regno ++ ) if ( BITSET_P ( cfun -> machine -> frame . mask , regno - GP_REG_FIRST ) ) { riscv_save_restore_reg ( word_mode , regno , offset , fn ) ; offset -= UNITS_PER_WORD ; } offset = cfun -> machine -> frame . fp_sp_offset - sp_offset ; for ( int regno = FP_REG_FIRST ; regno <= FP_REG_LAST ; regno ++ ) if ( BITSET_P ( cfun -> machine -> frame . fmask , regno - FP_REG_FIRST ) ) { enum 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>
static
void
riscv_file_start
(
void
)
{
default_file_start
(
)
;
fprintf
(
asm_out_file
,
"\t.option %spic\n"
,
(
flag_pic
""
:
"no"
)
)
;
}
</s>


<s> unsigned RISCVInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { default : { if ( MI . getParent ( ) && MI . getParent ( ) -> getParent ( ) ) { const auto MF = MI . getMF ( ) ; const auto & TM = static_cast < const RISCVTargetMachine & > ( MF -> getTarget ( ) ) ; const MCRegisterInfo & MRI = * TM . getMCRegisterInfo ( ) ; const MCSubtargetInfo & STI = * TM . getMCSubtargetInfo ( ) ; const RISCVSubtarget & ST = MF -> getSubtarget < RISCVSubtarget > ( ) ; if ( isCompressibleInst ( MI , & ST , MRI , STI ) ) return 2 ; } return get ( Opcode ) . getSize ( ) ; } case TargetOpcode :: EH_LABEL : case TargetOpcode :: IMPLICIT_DEF : case TargetOpcode :: KILL : case TargetOpcode :: DBG_VALUE : return 0 ; case RISCV :: PseudoCALLReg : case RISCV :: PseudoCALL : case RISCV :: PseudoJump : case RISCV :: PseudoTAIL : case RISCV :: PseudoLLA : case RISCV :: PseudoLA : case RISCV :: PseudoLA_TLS_IE : case RISCV :: PseudoLA_TLS_GD : return 8 ; case RISCV :: PseudoAtomicLoadNand32 : case RISCV :: PseudoAtomicLoadNand64 : return 20 ; case RISCV :: PseudoMaskedAtomicSwap32 : case RISCV :: PseudoMaskedAtomicLoadAdd32 : case RISCV :: PseudoMaskedAtomicLoadSub32 : return 28 ; case RISCV :: PseudoMaskedAtomicLoadNand32 : return 32 ; case RISCV :: PseudoMaskedAtomicLoadMax32 : case RISCV :: PseudoMaskedAtomicLoadMin32 : return 44 ; case RISCV :: PseudoMaskedAtomicLoadUMax32 : case RISCV :: PseudoMaskedAtomicLoadUMin32 : return 36 ; case RISCV :: PseudoCmpXchg32 : case RISCV :: PseudoCmpXchg64 : return 16 ; case RISCV :: PseudoMaskedCmpXchg32 : return 32 ; case TargetOpcode :: INLINEASM : case TargetOpcode :: INLINEASM_BR : { const MachineFunction & MF = * MI . getParent ( ) -> getParent ( ) ; const auto & TM = static_cast < const RISCVTargetMachine & > ( MF . getTarget ( ) ) ; return getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>

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


<s> void RISCVFrameLowering :: processFunctionBeforeFrameFinalized ( MachineFunction & MF , RegScavenger * RS ) const { const RISCVRegisterInfo * RegInfo = MF . getSubtarget < RISCVSubtarget > ( ) . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterClass * RC ; if ( RISCVABI :: isCheriPureCapABI ( STI . getTargetABI ( ) ) ) RC = & RISCV :: GPCRRegClass ; else 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 RISCVInstrInfo :: analyzeBranch ( MachineBasicBlock & MBB , MachineBasicBlock * & TBB , MachineBasicBlock * & FBB , SmallVectorImpl < MachineOperand > & Cond , bool AllowModify ) const { TBB = FBB = nullptr ; Cond . clear ( ) ; auto * RVFI = MBB . getParent ( ) -> getInfo < RISCVMachineFunctionInfo > ( ) ; MachineBasicBlock :: iterator I = MBB . getLastNonDebugInstr ( ) ; if ( I == MBB . end ( ) || ! isUnpredicatedTerminator ( * I ) ) return RVFI -> isHwlpBasicBlock ( MBB . getNextNode ( ) ) ; MachineBasicBlock :: iterator FirstUncondOrIndirectBr = MBB . end ( ) ; int NumTerminators = 0 ; for ( auto J = I . getReverse ( ) ; J != MBB . rend ( ) && isUnpredicatedTerminator ( * J ) ; J ++ ) { NumTerminators ++ ; if ( J -> getDesc ( ) . isUnconditionalBranch ( ) || J -> getDesc ( ) . isIndirectBranch ( ) ) { FirstUncondOrIndirectBr = J . getReverse ( ) ; } } if ( AllowModify && FirstUncondOrIndirectBr != MBB . end ( ) ) { while ( std :: next ( FirstUncondOrIndirectBr ) != MBB . end ( ) ) { std :: next ( FirstUncondOrIndirectBr ) -> eraseFromParent ( ) ; NumTerminators -- ; } I = FirstUncondOrIndirectBr ; } if ( I -> getDesc ( ) . isIndirectBranch ( ) ) return true ; if ( NumTerminators > 2 ) return true ; if ( NumTerminators == 1 && I -> getDesc ( ) . isUnconditionalBranch ( ) ) { TBB = getBranchDestBlock ( * I ) ; return false ; } if ( NumTerminators == 1 && I -> getDesc ( ) . isConditionalBranch ( ) ) { parseCondBranch ( * I , TBB , Cond ) ; return false ; } if ( NumTerminators == 2 && std :: prev ( I ) -> getDesc ( ) . isConditionalBranch ( ) && I -> getDesc ( ) . isUnconditionalBranch ( ) ) { parseCondBranch ( * std :: prev ( I ) , TBB , Cond ) ; FBB = getBranchDestBlock ( * I ) ; return false ; } return true ; } </s>

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


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

Return the riscv_cpu_info entry for the given name string .


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

Main hook for targets to transform nodes into machine nodes .


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

getTargetNodeName - This method returns the name of a target specific


<s>
bool
RISCVInstrInfo
::
isBranchOffsetInRange
(
unsigned
BranchOp
,
int64_t
BrOffset
)
const
{
switch
(
BranchOp
)
{
default
:
llvm_unreachable
(
"Unexpected opcode!"
)
;
case
RISCV
::
BEQ
:
case
RISCV
::
BNE
:
case
RISCV
::
BLT
:
case
RISCV
::
BGE
:
case
RISCV
::
BLTU
:
case
RISCV
::
BGEU
:
case
RISCV
::
P_BEQIMM
:
case
RISCV
::
P_BNEIMM
:
return
isIntN
(
13
,
BrOffset
)
;
case
RISCV
::
JAL
:
case
RISCV
::
PseudoBR
:
return
isIntN
(
21
,
BrOffset
)
;
case
RISCV
::
LoopBranch
:
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::P_BEQIMM
RISCV::P_BNEIMM
13
RISCV::JAL
RISCV::PseudoBR
21
RISCV::LoopBranch


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

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


<s> bool trackLivenessAfterRegAlloc ( const MachineFunction & ) const override { return true ; } </s>

Returns true if the live-ins should be tracked after register allocation .


"Prologue matched, checking for no-return epilogue.\n"

"Prologue call to riscv_save_0 followed by noreturn call, "


"Can't store this register to stack slot"

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


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

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


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

getPassName - Return a nice clean name for a pass .


<s> void riscv_set_return_address ( rtx address , rtx scratch ) { rtx slot_address ; gcc_assert ( BITSET_P ( cfun -> machine -> frame . mask , RETURN_ADDR_REGNUM ) ) ; slot_address = riscv_add_offset ( scratch , stack_pointer_rtx , cfun -> machine -> frame . gp_sp_offset ) ; riscv_emit_move ( gen_frame_mem ( GET_MODE ( address ) , slot_address ) , address ) ; } </s>

Emit code to change the current function 's return address to ADDRESS . SCRATCH is available as a scratch register , if needed . ADDRESS and SCRATCH are both word-mode GPRs .


<s> static unsigned int riscv_min_arithmetic_precision ( void ) { return 32 ; } </s>


<s>
void
RISCVFrameLowering
::
emitPrologue
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
)
const
{
assert
(
&
MF
.
front
(
)
==
&
MBB
&&
"Shrink-wrapping not yet supported"
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
auto
*
RVFI
=
MF
.
getInfo
<
RISCVMachineFunctionInfo
>
(
)
;
const
RISCVRegisterInfo
*
RI
=
STI
.
getRegisterInfo
(
)
;
const
RISCVInstrInfo
*
TII
=
STI
.
getInstrInfo
(
)
;
MachineBasicBlock
::
iterator
MBBI
=
MBB
.
begin
(
)
;
unsigned
FPReg
=
getFPReg
(
STI
)
;
unsigned
SPReg
=
getSPReg
(
STI
)
;
DebugLoc
DL
;
determineFrameLayout
(
MF
)
;
uint64_t
StackSize
=
MFI
.
getStackSize
(
)
;
if
(
StackSize
==
0
&&
!
MFI
.
adjustsStack
(
)
)
return
;
adjustReg
(
MBB
,
MBBI
,
DL
,
SPReg
,
SPReg
,
StackSize
,
MachineInstr
::
FrameSetup
)
;
unsigned
CFIIndex
=
MF
.
addFrameInst
(
MCCFIInstruction
::
createDefCfaOffset
(
nullptr
,
StackSize
)
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
TII
->
get
(
TargetOpcode
::
CFI_INSTRUCTION
)
)
.
addCFIIndex
(
CFIIndex
)
;
const
std
::
vector
<
CalleeSavedInfo
>
&
CSI
=
MFI
.
getCalleeSavedInfo
(
)
;
std
::
advance
(
MBBI
,
CSI
.
size
(
)
)
;
for
(
const
auto
&
Entry
:
CSI
)
{
int64_t
Offset
=
MFI
.
getObjectOffset
(
Entry
.
getFrameIdx
(
)
)
;
unsigned
Reg
=
Entry
.
getReg
(
)
;
unsigned
CFIIndex
=
MF
.
addFrameInst
(
MCCFIInstruction
::
createOffset
(
nullptr
,
RI
->
getDwarfRegNum
(
Reg
,
true
)
,
Offset
)
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
TII
->
get
(
TargetOpcode
::
CFI_INSTRUCTION
)
)
.
addCFIIndex
(
CFIIndex
)
;
}
if
(
hasFP
(
MF
)
)
{
adjustReg
(
MBB
,
MBBI
,
DL
,
FPReg
,
SPReg
,
StackSize
RVFI
->
getVarArgsSaveSize
(
)
,
MachineInstr
::
FrameSetup
)
;
unsigned
CFIIndex
=
MF
.
addFrameInst
(
MCCFIInstruction
::
createDefCfa
(
nullptr
,
RI
->
getDwarfRegNum
(
FPReg
,
true
)
,
0
)
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
TII
->
get
(
TargetOpcode
::
CFI_INSTRUCTION
)
)
.
addCFIIndex
(
CFIIndex
)
;
}
}
</s>

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

RISCV
RISCV
"Shrink-wrapping not yet supported"
RISCV
RISCV
RISCV
0
0


<s> bool RISCVTargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT ) const { return Imm . isPosZero ( ) ; } </s>

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


<s> static unsigned int riscv_next_saved_reg ( unsigned int regno , unsigned int limit , HOST_WIDE_INT * offset , bool inc = true ) { if ( inc ) regno ++ ; while ( regno <= limit ) { if ( BITSET_P ( cfun -> machine -> frame . mask , regno - GP_REG_FIRST ) ) { * offset = * offset - UNITS_PER_WORD ; return regno ; } regno ++ ; } return INVALID_REGNUM ; } </s>

Return the next register up from REGNO up to LIMIT for the callee to save or restore . OFFSET will be adjusted accordingly . If INC is set , then REGNO will be incremented first . Returns INVALID_REGNUM if there is no such next register .


<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 -> needsStackRealignment ( MF ) || MFI . hasVarSizedObjects ( ) || MFI . isFrameAddressTaken ( ) ; } </s>

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


<s> bool check ( function_checker & c ) const override { poly_int64 outer_size = GET_MODE_SIZE ( c . arg_mode ( 0 ) ) ; poly_int64 inner_size = GET_MODE_SIZE ( c . ret_mode ( ) ) ; unsigned int nvecs = exact_div ( outer_size , inner_size ) . to_constant ( ) ; return c . require_immediate ( 1 , 0 , nvecs - 1 ) ; } </s>

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


<s> static bool riscv_cannot_copy_insn_p ( rtx_insn * insn ) { return recog_memoized ( insn ) >= 0 && get_attr_cannot_copy ( insn ) ; } </s>


<s> void RISCVPassConfig :: addMachineSSAOptimization ( ) { TargetPassConfig :: addMachineSSAOptimization ( ) ; if ( TM -> getTargetTriple ( ) . getArch ( ) == Triple :: riscv64 ) addPass ( createRISCVSExtWRemovalPass ( ) ) ; } </s>

Methods with trivial inline returns are convenient points in the common codegen pass pipeline where targets may insert passes .


<s> RISCVSubtarget & RISCVSubtarget :: initializeSubtargetDependencies ( const Triple & TT , StringRef CPU , StringRef FS , StringRef ABIName ) { bool Is64Bit = TT . isArch64Bit ( ) ; std :: string CPUName = CPU ; if ( CPUName . empty ( ) ) CPUName = Is64Bit ? "generic-rv64" : "generic-rv32" ; ParseSubtargetFeatures ( CPUName , 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> TargetStackID :: Value getStackIDForScalableVectors ( ) const override { return TargetStackID :: RISCVVector ; } </s>

Returns the StackID that scalable vectors should be associated with .


<s>
void
RISCVDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
if
(
Node
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
Node
->
setNodeId
(
1
)
;
return
;
}
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
MVT
XLenVT
=
Subtarget
->
getXLenVT
(
)
;
SDLoc
DL
(
Node
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
switch
(
Opcode
)
{
case
ISD
::
Constant
:
{
auto
ConstNode
=
cast
<
ConstantSDNode
>
(
Node
)
;
if
(
VT
==
XLenVT
&&
ConstNode
->
isNullValue
(
)
)
{
SDValue
New
=
CurDAG
->
getCopyFromReg
(
CurDAG
->
getEntryNode
(
)
,
SDLoc
(
Node
)
,
RISCV
::
X0
,
XLenVT
)
;
ReplaceNode
(
Node
,
New
.
getNode
(
)
)
;
return
;
}
int64_t
Imm
=
ConstNode
->
getSExtValue
(
)
;
if
(
XLenVT
==
MVT
::
i64
)
{
ReplaceNode
(
Node
,
selectImm
(
CurDAG
,
SDLoc
(
Node
)
,
Imm
,
XLenVT
)
)
;
return
;
}
break
;
}
case
ISD
::
FrameIndex
:
{
SDValue
Imm
=
CurDAG
->
getTargetConstant
(
0
,
DL
,
XLenVT
)
;
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
ReplaceNode
(
Node
,
CurDAG
->
getMachineNode
(
RISCV
::
ADDI
,
DL
,
VT
,
TFI
,
Imm
)
)
;
return
;
}
case
ISD
::
SRL
:
{
if
(
!
Subtarget
->
is64Bit
(
)
)
break
;
SDValue
Op0
=
Node
->
getOperand
(
0
)
;
SDValue
Op1
=
Node
->
getOperand
(
1
)
;
uint64_t
Mask
;
if
(
Op1
.
getOpcode
(
)
==
ISD
::
Constant
&&
isConstantMask
(
Op0
.
getNode
(
)
,
Mask
)
)
{
uint64_t
ShAmt
=
cast
<
ConstantSDNode
>
(
Op1
.
getNode
(
)
)
->
getZExtValue
(
)
;
if
(
(
Mask
|
maskTrailingOnes
<
uint64_t
>
(
ShAmt
)
)
==
0xffffffff
)
{
SDValue
ShAmtVal
=
CurDAG
->
getTargetConstant
(
ShAmt
,
SDLoc
(
Node
)
,
XLenVT
)
;
CurDAG
->
SelectNodeTo
(
Node
,
RISCV
::
SRLIW
,
XLenVT
,
Op0
.
getOperand
(
0
)
,
ShAmtVal
)
;
return
;
}
}
}
}
SelectCode
(
Node
)
;
}
</s>

Main hook for targets to transform nodes into machine nodes .


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


<s> bool RISCVTargetLowering :: isShuffleMaskLegal ( ArrayRef < int > M , EVT VT ) const { if ( ShuffleVectorSDNode :: isSplatMask ( M . data ( ) , VT ) ) return true ; return false ; } </s>

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


<s> Register RISCVTargetLowering :: getExceptionPointerRegister ( const Constant * PersonalityFn ) const { return RISCVABI :: isCheriPureCapABI ( Subtarget . getTargetABI ( ) ) ? RISCV :: C10 : RISCV :: X10 ; } </s>

If a physical register , this returns the register that receives the exception address on entry to an EH pad .


<s> virtual gimple * fold ( gimple_folder & ) const { return NULL ; } </s>

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


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

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

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


<s> static tree riscv_build_function_type ( enum riscv_function_type type ) { static tree types [ ( int ) RISCV_MAX_FTYPE_MAX ] ; if ( types [ ( int ) type ] == NULL_TREE ) switch ( type ) { case RISCV_FTYPE_NAME ## NUM ARGS : \ types [ ( int ) type ] \ = build_function_type_list ( RISCV_FTYPE_ATYPES ## NUM ARGS , \ NULL_TREE ) ; \ break ; default : gcc_unreachable ( ) ; } return types [ ( int ) type ] ; } </s>

Return the function type associated with function prototype TYPE .


<s> static int riscv_register_move_cost ( machine_mode mode , reg_class_t from , reg_class_t to ) { if ( ( from == FP_REGS && to == GR_REGS ) || ( from == GR_REGS && to == FP_REGS ) ) return tune_param -> fmv_cost ; return riscv_secondary_memory_needed ( mode , from , to ) ? 8 : 2 ; } </s>


<s>
const
uint32_t
*
RISCVRegisterInfo
::
getCallPreservedMask
(
const
MachineFunction
&
MF
,
CallingConv
::
ID
)
const
{
auto
&
Subtarget
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
switch
(
Subtarget
.
getTargetABI
(
)
)
{
default
:
llvm_unreachable
(
"Unrecognized ABI"
)
;
case
RISCVABI
::
ABI_ILP32
:
case
RISCVABI
::
ABI_LP64
:
return
CSR_ILP32_LP64_RegMask
;
case
RISCVABI
::
ABI_ILP32F
:
case
RISCVABI
::
ABI_LP64F
:
return
CSR_ILP32F_LP64F_RegMask
;
case
RISCVABI
::
ABI_ILP32D
:
case
RISCVABI
::
ABI_LP64D
:
return
CSR_ILP32D_LP64D_RegMask
;
}
}
</s>

Return a mask of call-preserved registers for the given calling convention on the current function .


<s> rtx riscv_unspec_address ( rtx address , enum riscv_symbol_type symbol_type ) { rtx base , offset ; split_const ( address , & base , & offset ) ; return riscv_unspec_address_offset ( base , offset , symbol_type ) ; } </s>

Return an UNSPEC address with underlying address ADDRESS and symbol type SYMBOL_TYPE .


<s> static machine_mode riscv_promote_function_mode ( const_tree type ATTRIBUTE_UNUSED , machine_mode mode , int * punsignedp ATTRIBUTE_UNUSED , const_tree fntype ATTRIBUTE_UNUSED , int for_return ATTRIBUTE_UNUSED ) { int unsignedp ; if ( type != NULL_TREE ) return promote_mode ( type , mode , punsignedp ) ; unsignedp = * punsignedp ; PROMOTE_MODE ( mode , unsignedp , type ) ; * punsignedp = unsignedp ; return mode ; } </s>


<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 :: PseudoCALLReg : case RISCV :: PseudoCALL : case RISCV :: PseudoTAIL : case RISCV :: PseudoLLA : case RISCV :: PseudoLA : case RISCV :: PseudoLA_TLS_IE : case RISCV :: PseudoLA_TLS_GD : return 8 ; case TargetOpcode :: INLINEASM : case TargetOpcode :: INLINEASM_BR : { const MachineFunction & MF = * MI . getParent ( ) -> getParent ( ) ; const auto & TM = static_cast < const RISCVTargetMachine & > ( MF . getTarget ( ) ) ; return getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>

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


<s> RISCVSubtarget & RISCVSubtarget :: initializeSubtargetDependencies ( StringRef CPU , StringRef FS , bool Is64Bit ) { std :: string CPUName = CPU ; if ( CPUName . empty ( ) ) CPUName = Is64Bit ? "generic-rv64" : "generic-rv32" ; ParseSubtargetFeatures ( CPUName , FS ) ; if ( Is64Bit ) { XLenVT = MVT :: i64 ; XLen = 64 ; } return * this ; } </s>


<s> rtx function_expander :: use_contiguous_load_insn ( insn_code icode ) { gcc_assert ( call_expr_nargs ( exp ) > 0 ) ; machine_mode mode = TYPE_MODE ( TREE_TYPE ( exp ) ) ; int arg_offset = 0 ; if ( use_real_mask_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_all_one_mask_operand ( mask_mode ( ) ) ; if ( use_real_merge_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_vundef_operand ( mode ) ; add_mem_operand ( mode , arg_offset ++ ) ; for ( int argno = arg_offset ; argno < call_expr_nargs ( exp ) ; argno ++ ) add_input_operand ( argno ) ; if ( GET_MODE_CLASS ( mode ) != MODE_VECTOR_BOOL ) { add_input_operand ( Pmode , get_tail_policy_for_pred ( pred ) ) ; add_input_operand ( Pmode , get_mask_policy_for_pred ( pred ) ) ; } if ( opno != insn_data [ icode ] . n_generator_args ) add_input_operand ( Pmode , get_avl_type_rtx ( avl_type :: NONVLMAX ) ) ; return generate_insn ( icode ) ; } </s>


<s> bool RISCVTargetLowering :: hasBitTest ( SDValue X , SDValue Y ) const { auto * C = dyn_cast < ConstantSDNode > ( Y ) ; return C && C -> getAPIntValue ( ) . ule ( 10 ) ; } </s>

Return true if the target has a bit-test instruction : ( X & ( 1 < < Y ) ) ==/ ! = 0 This knowledge can be used to prevent breaking the pattern , or creating it if it could be recognized .


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

getPassName - Return a nice clean name for a pass .


<s> const char * mangle_builtin_type ( const_tree type ) { if ( TYPE_NAME ( type ) && TREE_CODE ( TYPE_NAME ( type ) ) == TYPE_DECL ) type = TREE_TYPE ( TYPE_NAME ( type ) ) ; if ( tree attr = lookup_vector_type_attribute ( type ) ) if ( tree id = TREE_VALUE ( chain_index ( 0 , TREE_VALUE ( attr ) ) ) ) return IDENTIFIER_POINTER ( id ) ; return NULL ; } </s>

If TYPE is a built-in type defined by the RVV ABI , return the mangled name , otherwise return NULL .


<s> bool RISCVELFTargetObjectFile :: isGlobalInSmallSection ( const GlobalObject * GO , const TargetMachine & TM ) const { const GlobalVariable * GVA = dyn_cast < GlobalVariable > ( GO ) ; if ( ! GVA ) return false ; if ( GVA -> hasSection ( ) ) { StringRef Section = GVA -> getSection ( ) ; if ( Section == ".sdata" || Section == ".sbss" ) return true ; return false ; } if ( ( ( GVA -> hasExternalLinkage ( ) && GVA -> isDeclaration ( ) ) || GVA -> hasCommonLinkage ( ) ) ) return false ; Type * Ty = GVA -> getValueType ( ) ; if ( ! Ty -> isSized ( ) ) return false ; return isInSmallSection ( GVA -> getParent ( ) -> getDataLayout ( ) . getTypeAllocSize ( Ty ) ) ; } </s>

Return true if this global address should be placed into small data/bss section .


<s> bool RISCVFrameLowering :: canUseAsEpilogue ( const MachineBasicBlock & MBB ) const { MachineBasicBlock * TmpMBB = const_cast < MachineBasicBlock * > ( & MBB ) ; const auto * RVFI = MBB . getParent ( ) -> getInfo < RISCVMachineFunctionInfo > ( ) ; if ( ! RVFI -> useSaveRestoreLibCalls ( ) ) return true ; if ( MBB . succ_size ( ) > 1 ) return false ; MachineBasicBlock * SuccMBB = MBB . succ_empty ( ) ? TmpMBB -> getFallThrough ( ) : * MBB . succ_begin ( ) ; if ( ! SuccMBB ) return true ; return SuccMBB -> isReturnBlock ( ) && SuccMBB -> size ( ) == 1 ; } </s>

Check whether or not the given MBB can be used as a epilogue for the target .


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


"Can only merge with a valid VSETVLInfo"


<s> const CallLowering * RISCVSubtarget :: getCallLowering ( ) const { return CallLoweringInfo . get ( ) ; } </s>


<s> void RISCVAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved ) const { return ; } </s>

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


<s> static bool vsetvl_insn_p ( rtx_insn * rinsn ) { if ( ! vector_config_insn_p ( rinsn ) ) return false ; return ( INSN_CODE ( rinsn ) == CODE_FOR_vsetvldi || INSN_CODE ( rinsn ) == CODE_FOR_vsetvlsi ) ; } </s>

Return true if it is vsetvldi or vsetvlsi .


<s> static void riscv_setup_incoming_varargs ( cumulative_args_t cum , const function_arg_info & arg , int * pretend_size ATTRIBUTE_UNUSED , int no_rtl ) { CUMULATIVE_ARGS local_cum ; int gp_saved ; local_cum = * get_cumulative_args ( cum ) ; riscv_function_arg_advance ( pack_cumulative_args ( & local_cum ) , arg ) ; gp_saved = MAX_ARGS_IN_REGISTERS - local_cum . num_gprs ; if ( ! no_rtl && gp_saved > 0 ) { rtx ptr = plus_constant ( Pmode , virtual_incoming_args_rtx , REG_PARM_STACK_SPACE ( cfun -> decl ) - gp_saved * UNITS_PER_WORD ) ; rtx mem = gen_frame_mem ( BLKmode , ptr ) ; set_mem_alias_set ( mem , get_varargs_alias_set ( ) ) ; move_block_from_reg ( local_cum . num_gprs + GP_ARG_FIRST , mem , gp_saved ) ; } if ( REG_PARM_STACK_SPACE ( cfun -> decl ) == 0 ) cfun -> machine -> varargs_size = gp_saved * UNITS_PER_WORD ; } </s>


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

runOnMachineFunction - Emit the function body .


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

Evaluates the fixup as a constant value .


<s> static tree riscv_d_handle_target_float_abi ( void ) { const char * abi ; switch ( riscv_abi ) { case ABI_ILP32E : case ABI_ILP32 : case ABI_LP64 : abi = "soft" ; break ; case ABI_ILP32F : case ABI_LP64F : abi = "single" ; break ; case ABI_ILP32D : case ABI_LP64D : abi = "double" ; break ; default : abi = "" ; break ; } return build_string_literal ( strlen ( abi ) + 1 , abi ) ; } </s>

Handle a call to ` __traits ( getTargetInfo , `` floatAbi '' ) ' .


<s> bool pass_vsetvl :: cleanup_illegal_dirty_blocks ( void ) { bool changed_p = false ; for ( const bb_info * bb : crtl -> ssa -> bbs ( ) ) { basic_block cfg_bb = bb -> cfg_bb ( ) ; const auto & prop = m_vector_manager -> vector_block_infos [ cfg_bb -> index ] . reaching_out ; if ( ! prop . valid_or_dirty_p ( ) ) continue ; if ( hard_empty_block_p ( bb , prop ) ) { m_vector_manager -> vector_block_infos [ cfg_bb -> index ] . local_dem = vector_insn_info :: get_hard_empty ( ) ; m_vector_manager -> vector_block_infos [ cfg_bb -> index ] . reaching_out = vector_insn_info :: get_hard_empty ( ) ; changed_p = true ; continue ; } } return changed_p ; } </s>


<s> static bool riscv_allocate_stack_slots_for_args ( ) { return ! riscv_naked_function_p ( current_function_decl ) ; } </s>


<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 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>


"frame pointer should not have been eliminated"


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

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


<s> static HOST_WIDE_INT riscv_constant_alignment ( const_tree exp , HOST_WIDE_INT align ) { if ( ( TREE_CODE ( exp ) == STRING_CST || TREE_CODE ( exp ) == CONSTRUCTOR ) && ( riscv_align_data_type == riscv_align_data_type_xlen ) ) return MAX ( align , BITS_PER_WORD ) ; return align ; } </s>


<s> static rtx riscv_pass_fpr_single ( machine_mode type_mode , unsigned regno , machine_mode value_mode , HOST_WIDE_INT offset ) { rtx x = gen_rtx_REG ( value_mode , regno ) ; if ( type_mode != value_mode ) { x = gen_rtx_EXPR_LIST ( VOIDmode , x , GEN_INT ( offset ) ) ; x = gen_rtx_PARALLEL ( type_mode , gen_rtvec ( 1 , x ) ) ; } return x ; } </s>

Return the representation of an argument passed or returned in an FPR when the value has mode VALUE_MODE and the type has TYPE_MODE . The two modes may be different for structures like : struct __attribute__ ( ( packed ) ) foo { float f ; } where the SFmode value `` f '' is passed in REGNO but the struct itself has mode BLKmode .


<s> bool RISCVInstPrinter :: applyTargetSpecificCLOption ( StringRef Opt ) { if ( Opt == "no-aliases" ) { NoAliases = true ; return true ; } if ( Opt == "numeric" ) { ArchRegNames = true ; return true ; } return false ; } </s>

Customize the printer according to a command line option .


<s> bool isLegalMaskedStore ( Type * DataType , Align Alignment ) { return isLegalMaskedLoadStore ( DataType , Alignment ) ; } </s>

Return true if the target supports masked store .


<s> static bool riscv_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { unsigned int nregs = riscv_hard_regno_nregs ( regno , mode ) ; if ( GP_REG_P ( regno ) ) { if ( ! GP_REG_P ( regno + nregs - 1 ) ) return false ; } else if ( FP_REG_P ( regno ) ) { if ( ! FP_REG_P ( regno + nregs - 1 ) ) return false ; if ( GET_MODE_CLASS ( mode ) != MODE_FLOAT && GET_MODE_CLASS ( mode ) != MODE_COMPLEX_FLOAT ) return false ; if ( GET_MODE_UNIT_SIZE ( mode ) > UNITS_PER_FP_REG || ( ! call_used_or_fixed_reg_p ( regno ) && GET_MODE_UNIT_SIZE ( mode ) > UNITS_PER_FP_ARG ) ) return false ; } else return false ; for ( unsigned i = 1 ; i < nregs ; i ++ ) if ( call_used_or_fixed_reg_p ( regno ) != call_used_or_fixed_reg_p ( regno + i ) ) return false ; return true ; } </s>


<s> static rtx get_vl_x2_rtx ( rtx avl , machine_mode mode , machine_mode demote_mode ) { rtx i32vl = NULL_RTX ; if ( CONST_INT_P ( avl ) ) { unsigned elt_size = GET_MODE_BITSIZE ( GET_MODE_INNER ( mode ) ) ; unsigned min_size = get_unknown_min_value ( mode ) ; unsigned vlen_max = RVV_65536 ; unsigned vlmax_max = compute_vlmax ( vlen_max , elt_size , min_size ) ; unsigned vlen_min = TARGET_MIN_VLEN ; unsigned vlmax_min = compute_vlmax ( vlen_min , elt_size , min_size ) ; unsigned HOST_WIDE_INT avl_int = INTVAL ( avl ) ; if ( avl_int <= vlmax_min ) i32vl = gen_int_mode ( 2 * avl_int , Pmode ) ; else if ( avl_int >= 2 * vlmax_max ) { i32vl = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_no_side_effects_vsetvl_rtx ( demote_mode , i32vl , RVV_VLMAX ) ) ; } else { } } if ( ! i32vl ) { rtx i64vl = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_no_side_effects_vsetvl_rtx ( mode , i64vl , force_reg ( Pmode , avl ) ) ) ; i32vl = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_rtx_SET ( i32vl , gen_rtx_ASHIFT ( Pmode , i64vl , const1_rtx ) ) ) ; } return force_vector_length_operand ( i32vl ) ; } </s>


<s>
EVT
RISCVTargetLowering
::
getOptimalMemOpType
(
const
MemOp
&
Op
,
const
AttributeList
&
FuncAttributes
)
const
{
bool
IsNonZeroMemset
=
Op
.
isMemset
(
)
&&
!
Op
.
isZeroMemset
(
)
;
if
(
Subtarget
.
hasCheri
(
)
&&
!
IsNonZeroMemset
)
{
unsigned
CapSize
=
Subtarget
.
typeForCapabilities
(
)
.
getSizeInBits
(
)
/
8
;
if
(
Op
.
size
(
)
>=
CapSize
)
{
Align
CapAlign
(
CapSize
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
__func__
<<
" Size="
<<
Op
.
size
(
)
<<
" DstAlign="
<<
(
Op
.
isFixedDstAlign
(
)
Op
.
getDstAlign
(
)
.
value
(
)
:
0
)
<<
" SrcAlign="
<<
(
Op
.
isMemset
(
)
0
:
Op
.
getSrcAlign
(
)
.
value
(
)
)
<<
" CapSize="
<<
CapSize
<<
"\n"
)
;
if
(
Op
.
isAligned
(
CapAlign
)
)
{
return
CapType
;
}
else
if
(
!
Op
.
isMemset
(
)
)
{
return
MVT
::
isVoid
;
}
}
}
return
TargetLowering
::
getOptimalMemOpType
(
Op
,
FuncAttributes
)
;
}
</s>

It returns EVT : :Other if the type should be determined using generic target-independent logic .

RISCV
RISCV
8
" Size="
" DstAlign="
0
" SrcAlign="
0
" CapSize="
"\n"
MVT::isVoid


<s> static bool riscv_save_reg_p ( unsigned int regno ) { bool call_saved = ! global_regs [ regno ] && ! call_used_regs [ 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 ; return false ; } </s>

Return true if the current function must save register REGNO .


<s> void function_builder :: append_base_name ( const char * name ) { append_name ( "__riscv_" ) ; append_name ( name ) ; } </s>


<s> bool evaluateBranch ( const MCInst & Inst , uint64_t Addr , uint64_t Size , uint64_t & Target ) const override { if ( isConditionalBranch ( Inst ) ) { int64_t Imm ; if ( Size == 2 ) Imm = Inst . getOperand ( 1 ) . getImm ( ) ; else Imm = Inst . getOperand ( 2 ) . getImm ( ) ; Target = Addr + Imm ; return true ; } if ( Inst . getOpcode ( ) == RISCV :: C_JAL || Inst . getOpcode ( ) == RISCV :: C_J ) { Target = Addr + Inst . getOperand ( 0 ) . getImm ( ) ; return true ; } if ( Inst . getOpcode ( ) == RISCV :: JAL ) { Target = Addr + Inst . getOperand ( 1 ) . getImm ( ) ; return true ; } return false ; } </s>

Given a branch instruction try to get the address the branch targets .


<s> HOST_WIDE_INT riscv_initial_elimination_offset ( int from , int to ) { HOST_WIDE_INT src , dest ; riscv_compute_frame_info ( ) ; if ( to == HARD_FRAME_POINTER_REGNUM ) dest = cfun -> machine -> frame . hard_frame_pointer_offset ; else if ( to == STACK_POINTER_REGNUM ) dest = 0 ; else gcc_unreachable ( ) ; if ( from == FRAME_POINTER_REGNUM ) src = cfun -> machine -> frame . frame_pointer_offset ; else if ( from == ARG_POINTER_REGNUM ) src = cfun -> machine -> frame . arg_pointer_offset ; else gcc_unreachable ( ) ; return src - dest ; } </s>

Implement INITIAL_ELIMINATION_OFFSET . FROM is either the frame pointer or argument pointer . TO is either the stack pointer or hard frame pointer .


<s> RISCVTargetLowering :: ConstraintType RISCVTargetLowering :: getConstraintType ( StringRef Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'A' : return C_Memory ; default : break ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>


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


<s> unsigned RISCVInstrInfo :: isLoadFromStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : return 0 ; case RISCV :: LB : case RISCV :: LBU : case RISCV :: LH : case RISCV :: LHU : case RISCV :: FLH : case RISCV :: LW : case RISCV :: FLW : case RISCV :: LWU : case RISCV :: LD : case RISCV :: FLD : case RISCV :: LC_64 : case RISCV :: LC_128 : case RISCV :: CLB : case RISCV :: CLBU : case RISCV :: CLH : case RISCV :: CLHU : case RISCV :: CLW : case RISCV :: CFLW : case RISCV :: CLWU : case RISCV :: CLD : case RISCV :: CFLD : case RISCV :: CLC_64 : case RISCV :: CLC_128 : break ; } if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } return 0 ; } </s>

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


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

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

RISCV RISCV RISCV 0 RISCV RISCV::X0 RISCV::X2 RISCV::X3 RISCV::X4 RISCV::X8 RISCVABI::getBPReg RISCV::VL RISCV::VTYPE RISCV::VXSAT RISCV::VXRM RISCV::FRM RISCV::FFLAGS RISCV::FCSR


<s> void RISCVAsmPrinter :: emitStartOfAsmFile ( Module & M ) { if ( TM . getTargetTriple ( ) . isOSBinFormatELF ( ) ) emitAttributes ( ) ; } </s>

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


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


<s>
void
RISCVRegisterInfo
::
getOffsetOpcodes
(
const
StackOffset
&
Offset
,
SmallVectorImpl
<
uint64_t
>
&
Ops
)
const
{
assert
(
Offset
.
getScalable
(
)
%
8
==
0
&&
"Invalid frame offset"
)
;
DIExpression
::
appendOffset
(
Ops
,
Offset
.
getFixed
(
)
)
;
unsigned
VLENB
=
getDwarfRegNum
(
RISCV
::
VLENB
,
true
)
;
int64_t
VLENBSized
=
Offset
.
getScalable
(
)
/
8
;
if
(
VLENBSized
>
0
)
{
Ops
.
push_back
(
dwarf
::
DW_OP_constu
)
;
Ops
.
push_back
(
VLENBSized
)
;
Ops
.
append
(
{
dwarf
::
DW_OP_bregx
,
VLENB
,
0ULL
}
)
;
Ops
.
push_back
(
dwarf
::
DW_OP_mul
)
;
Ops
.
push_back
(
dwarf
::
DW_OP_plus
)
;
}
else
if
(
VLENBSized
<
0
)
{
Ops
.
push_back
(
dwarf
::
DW_OP_constu
)
;
Ops
.
push_back
(
VLENBSized
)
;
Ops
.
append
(
{
dwarf
::
DW_OP_bregx
,
VLENB
,
0ULL
}
)
;
Ops
.
push_back
(
dwarf
::
DW_OP_mul
)
;
Ops
.
push_back
(
dwarf
::
DW_OP_minus
)
;
}
}
</s>

Gets the DWARF expression opcodes for Offset .


"Not all fixup kinds added to Infos array"


<s> bool RISCVInstrInfo :: analyzeBranch ( MachineBasicBlock & MBB , MachineBasicBlock * & TBB , MachineBasicBlock * & FBB , SmallVectorImpl < MachineOperand > & Cond , bool AllowModify ) const { MachineBasicBlock :: iterator I = MBB . end ( ) ; while ( I != MBB . begin ( ) ) { -- I ; if ( I -> isDebugValue ( ) ) continue ; if ( ! isUnpredicatedTerminator ( * I ) ) break ; SmallVector < MachineOperand , 4 > ThisCond ; ThisCond . push_back ( MachineOperand :: CreateImm ( 0 ) ) ; const MachineOperand * ThisTarget ; if ( ! isBranch ( I , ThisCond , ThisTarget ) ) return true ; if ( ! ThisTarget -> isMBB ( ) ) return true ; if ( ThisCond [ 0 ] . getImm ( ) == RISCV :: CCMASK_ANY ) { if ( ! AllowModify ) { TBB = ThisTarget -> getMBB ( ) ; continue ; } while ( std :: next ( I ) != MBB . end ( ) ) std :: next ( I ) -> eraseFromParent ( ) ; Cond . clear ( ) ; FBB = 0 ; TBB = ThisTarget -> getMBB ( ) ; continue ; } if ( Cond . empty ( ) ) { FBB = TBB ; TBB = ThisTarget -> getMBB ( ) ; Cond . push_back ( MachineOperand :: CreateImm ( ThisCond [ 0 ] . getImm ( ) ) ) ; for ( unsigned int i = 0 ; i < ( I -> getNumExplicitOperands ( ) ) ; i ++ ) Cond . push_back ( I -> getOperand ( i ) ) ; continue ; } assert ( Cond . size ( ) <= 4 ) ; assert ( TBB ) ; if ( TBB != ThisTarget -> getMBB ( ) ) return true ; unsigned OldCond = Cond [ 0 ] . getImm ( ) ; if ( OldCond == ThisCond [ 0 ] . getImm ( ) ) continue ; } return false ; } </s>

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


<s> static void riscv_setup_incoming_varargs ( cumulative_args_t cum , const function_arg_info & arg , int * pretend_size ATTRIBUTE_UNUSED , int no_rtl ) { CUMULATIVE_ARGS local_cum ; int gp_saved ; local_cum = * get_cumulative_args ( cum ) ; if ( ! TYPE_NO_NAMED_ARGS_STDARG_P ( TREE_TYPE ( current_function_decl ) ) ) riscv_function_arg_advance ( pack_cumulative_args ( & local_cum ) , arg ) ; gp_saved = MAX_ARGS_IN_REGISTERS - local_cum . num_gprs ; if ( ! no_rtl && gp_saved > 0 ) { rtx ptr = plus_constant ( Pmode , virtual_incoming_args_rtx , REG_PARM_STACK_SPACE ( cfun -> decl ) - gp_saved * UNITS_PER_WORD ) ; rtx mem = gen_frame_mem ( BLKmode , ptr ) ; set_mem_alias_set ( mem , get_varargs_alias_set ( ) ) ; move_block_from_reg ( local_cum . num_gprs + GP_ARG_FIRST , mem , gp_saved ) ; } if ( REG_PARM_STACK_SPACE ( cfun -> decl ) == 0 ) cfun -> machine -> varargs_size = gp_saved * UNITS_PER_WORD ; } </s>


<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
:
return
isIntN
(
13
,
BrOffset
)
;
case
RISCV
::
JAL
:
case
RISCV
::
CJAL
:
case
RISCV
::
PseudoBR
:
case
RISCV
::
PseudoCBR
:
return
isIntN
(
21
,
BrOffset
)
;
case
RISCV
::
PseudoJump
:
case
RISCV
::
PseudoCJump
:
return
isIntN
(
32
,
SignExtend64
(
BrOffset
+
0x800
,
XLen
)
)
;
}
}
</s>

Determine if the branch target is in range .

RISCV
RISCV
"Unexpected opcode!"
RISCV::BEQ
RISCV::BNE
RISCV::BLT
RISCV::BGE
RISCV::BLTU
RISCV::BGEU
13
RISCV::JAL
RISCV::CJAL
RISCV::PseudoBR
RISCV::PseudoCBR
21
RISCV::PseudoJump
RISCV::PseudoCJump
32
0x800


<s> bool RISCVAsmBackend :: fixupNeedsRelaxationAdvanced ( const MCFixup & Fixup , bool Resolved , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout , const bool WasForced ) const { if ( ! Resolved && ! WasForced ) return true ; int64_t Offset = int64_t ( Value ) ; switch ( Fixup . getTargetKind ( ) ) { default : return false ; case RISCV :: fixup_riscv_rvc_branch : return Offset > 254 || Offset < - 256 ; case RISCV :: fixup_riscv_rvc_jump : case RISCV :: fixup_riscv_rvc_cjump : return Offset > 2046 || Offset < - 2048 ; } } </s>

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


<s> void function_builder :: register_function_group ( const function_group_info & group ) { ( * group . shape ) -> build ( * this , group ) ; } </s>


<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
;
bool
IsScalableVector
=
false
;
if
(
RISCV
::
FPR16RegClass
.
contains
(
DstReg
,
SrcReg
)
)
Opc
=
RISCV
::
FSGNJ_H
;
else
if
(
RISCV
::
FPR32RegClass
.
contains
(
DstReg
,
SrcReg
)
)
Opc
=
RISCV
::
FSGNJ_S
;
else
if
(
RISCV
::
FPR64RegClass
.
contains
(
DstReg
,
SrcReg
)
)
Opc
=
RISCV
::
FSGNJ_D
;
else
if
(
RISCV
::
VRRegClass
.
contains
(
DstReg
,
SrcReg
)
)
{
Opc
=
RISCV
::
PseudoVMV1R_V
;
IsScalableVector
=
true
;
}
else
if
(
RISCV
::
VRM2RegClass
.
contains
(
DstReg
,
SrcReg
)
)
{
Opc
=
RISCV
::
PseudoVMV2R_V
;
IsScalableVector
=
true
;
}
else
if
(
RISCV
::
VRM4RegClass
.
contains
(
DstReg
,
SrcReg
)
)
{
Opc
=
RISCV
::
PseudoVMV4R_V
;
IsScalableVector
=
true
;
}
else
if
(
RISCV
::
VRM8RegClass
.
contains
(
DstReg
,
SrcReg
)
)
{
Opc
=
RISCV
::
PseudoVMV8R_V
;
IsScalableVector
=
true
;
}
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
if
(
IsScalableVector
)
BuildMI
(
MBB
,
MBBI
,
DL
,
get
(
Opc
)
,
DstReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
else
BuildMI
(
MBB
,
MBBI
,
DL
,
get
(
Opc
)
,
DstReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
</s>