"Can't load this register from stack slot"

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


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


<s> static void riscv_save_reg ( rtx reg , rtx mem ) { riscv_emit_move ( mem , reg ) ; riscv_set_frame_expr ( riscv_frame_set ( mem , reg ) ) ; } </s>

Save register REG to MEM . Make the instruction frame-related .


<s> static int riscv_flatten_aggregate_argument ( const_tree type , riscv_aggregate_field fields [ 2 ] ) { if ( ! type || TREE_CODE ( type ) != RECORD_TYPE ) return - 1 ; return riscv_flatten_aggregate_field ( type , fields , 0 , 0 ) ; } </s>

Identify candidate aggregates for passing in floating-point registers . Candidates have at most two fields after flattening .


<s> static void riscv_extend_comparands ( rtx_code code , rtx * op0 , rtx * op1 ) { if ( GET_MODE_SIZE ( word_mode ) > GET_MODE_SIZE ( GET_MODE ( * op0 ) ) ) { if ( unsigned_condition ( code ) == code && GET_MODE ( * op0 ) == QImode ) { * op0 = gen_rtx_ZERO_EXTEND ( word_mode , * op0 ) ; if ( CONST_INT_P ( * op1 ) ) * op1 = GEN_INT ( ( uint8_t ) INTVAL ( * op1 ) ) ; else * op1 = gen_rtx_ZERO_EXTEND ( word_mode , * op1 ) ; } else { * op0 = gen_rtx_SIGN_EXTEND ( word_mode , * op0 ) ; if ( * op1 != const0_rtx ) * op1 = gen_rtx_SIGN_EXTEND ( word_mode , * op1 ) ; } } } </s>

Sign- or zero-extend OP0 and OP1 for integer comparisons .


<s>
bool
RISCVInstrInfo
::
reverseBranchCondition
(
SmallVectorImpl
<
MachineOperand
>
&
Cond
)
const
{
assert
(
(
Cond
.
size
(
)
==
3
)
&&
"Invalid branch condition!"
)
;
if
(
Cond
[
0
]
.
getImm
(
)
==
RISCV
::
LoopBranch
)
return
true
;
Cond
[
0
]
.
setImm
(
getOppositeBranchOpcode
(
Cond
[
0
]
.
getImm
(
)
)
)
;
return
false
;
}
</s>

Reverses the branch condition of the specified condition list , returning false on success and true if it can not be reversed .


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

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


<s> void riscv_init_builtins ( void ) { for ( size_t i = 0 ; i < ARRAY_SIZE ( riscv_builtins ) ; i ++ ) { const struct riscv_builtin_description * d = & riscv_builtins [ i ] ; if ( d -> avail ( ) ) { tree type = riscv_build_function_type ( d -> prototype ) ; riscv_builtin_decls [ i ] = add_builtin_function ( d -> name , type , i , BUILT_IN_MD , NULL , NULL ) ; riscv_builtin_decl_index [ d -> icode ] = i ; } } } </s>


"could not find corresponding %pcrel_hi"

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


<s> bool shouldForceRelocation ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target ) override { return STI . getFeatureBits ( ) [ RISCV :: FeatureRelax ] || ForceRelocs ; } </s>


<s> void RISCVFrameLowering :: processFunctionBeforeFrameFinalized ( MachineFunction & MF , RegScavenger * RS ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterClass * RC = & RISCV :: GPRRegClass ; if ( ! isInt < 11 > ( MFI . estimateStackSize ( MF ) ) ) { const DataLayout & DL = MF . getDataLayout ( ) ; int RegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC , DL ) , RegInfo -> getSpillAlignment ( * RC , DL ) , false ) ; RS -> addScavengingFrameIndex ( RegScavFI ) ; } } </s>

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


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

runOnMachineFunction - Emit the function body .


<s> TargetLowering :: AtomicExpansionKind RISCVTargetLowering :: shouldExpandAtomicRMWInIR ( AtomicRMWInst * AI ) const { if ( AI -> isFloatingPointOperation ( ) ) return AtomicExpansionKind :: CmpXChg ; unsigned Size = AI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; if ( ( Size == 8 || Size == 16 ) && ! RISCVABI :: isCheriPureCapABI ( Subtarget . getTargetABI ( ) ) ) return AtomicExpansionKind :: MaskedIntrinsic ; return AtomicExpansionKind :: None ; } </s>

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


<s> unsigned RISCVInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { if ( MI . isMetaInstruction ( ) ) return 0 ; unsigned Opcode = MI . getOpcode ( ) ; if ( Opcode == TargetOpcode :: INLINEASM || Opcode == 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 ( ) ) ; } 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 ( ) ; } </s>

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

RISCV RISCV 0 RISCV 0 RISCV RISCV RISCV 2


<s> RISCVSubtarget & RISCVSubtarget :: initializeSubtargetDependencies ( const Triple & TT , StringRef CPU , StringRef TuneCPU , StringRef FS , StringRef ABIName ) { bool Is64Bit = TT . isArch64Bit ( ) ; if ( CPU . empty ( ) || CPU == "generic" ) CPU = 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> static rtx riscv_legitimize_address ( rtx x , rtx oldx ATTRIBUTE_UNUSED , machine_mode mode ) { rtx addr ; if ( riscv_tls_symbol_p ( x ) ) return riscv_legitimize_tls_address ( x ) ; if ( riscv_split_symbol ( NULL , x , mode , & addr , FALSE ) ) return riscv_force_address ( addr , mode ) ; if ( GET_CODE ( x ) == PLUS && CONST_INT_P ( XEXP ( x , 1 ) ) && INTVAL ( XEXP ( x , 1 ) ) != 0 ) { rtx base = XEXP ( x , 0 ) ; HOST_WIDE_INT offset = INTVAL ( XEXP ( x , 1 ) ) ; if ( ! riscv_valid_base_register_p ( base , mode , false ) ) base = copy_to_mode_reg ( Pmode , base ) ; if ( optimize_function_for_size_p ( cfun ) && ( strcmp ( current_pass -> name , "shorten_memrefs" ) == 0 ) && mode == SImode ) addr = riscv_shorten_lw_offset ( base , offset ) ; else addr = riscv_add_offset ( NULL , base , offset ) ; return riscv_force_address ( addr , mode ) ; } return x ; } </s>

This function is used to implement LEGITIMIZE_ADDRESS . If X can be legitimized in a way that the generic machinery might not expect , return a new address , otherwise return NULL . MODE is the mode of the memory being accessed .


<s>
static
bool
isValidOffset
(
RISCVAddressingMode
::
OffRange
OffR
,
int64_t
Val
)
{
assert
(
selectOffset
(
OffR
,
Val
)
&&
"Invalid displacement"
)
;
switch
(
OffR
)
{
case
RISCVAddressingMode
::
Off12Only
:
return
true
;
}
llvm_unreachable
(
"Unhandled displacement range"
)
;
}
</s>

RISCV
RISCVAddressingMode::OffRange
"Invalid displacement"
RISCVAddressingMode::Off12Only
"Unhandled displacement range"


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

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


<s>
SDValue
RISCVTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
SDLoc
DL
,
SelectionDAG
&
DAG
)
const
{
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
SmallVector
<
CCValAssign
,
16
>
RetLocs
;
CCState
RetCCInfo
(
CallConv
,
IsVarArg
,
MF
,
RetLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
Subtarget
.
isRV64
(
)
)
RetCCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_RISCV64
)
;
else
RetCCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_RISCV32
)
;
SDValue
Glue
;
if
(
RetLocs
.
empty
(
)
)
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
Chain
)
;
SmallVector
<
SDValue
,
4
>
RetOps
;
RetOps
.
push_back
(
Chain
)
;
for
(
unsigned
I
=
0
,
E
=
RetLocs
.
size
(
)
;
I
!=
E
;
++
I
)
{
CCValAssign
&
VA
=
RetLocs
[
I
]
;
SDValue
RetValue
=
OutVals
[
I
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
RetValue
=
convertValVTToLocVT
(
DAG
,
DL
,
VA
,
RetValue
)
;
unsigned
Reg
=
VA
.
getLocReg
(
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
Reg
,
RetValue
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
Reg
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Glue
.
getNode
(
)
)
RetOps
.
push_back
(
Glue
)
;
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s> poly_int64 riscv_v_adjust_bytesize ( machine_mode mode , int scale ) { if ( riscv_v_ext_vector_mode_p ( mode ) ) { poly_uint16 mode_size = GET_MODE_SIZE ( mode ) ; if ( maybe_eq ( mode_size , ( uint16_t ) - 1 ) ) mode_size = riscv_vector_chunks * scale ; if ( known_gt ( mode_size , BYTES_PER_RISCV_VECTOR ) ) mode_size = BYTES_PER_RISCV_VECTOR ; return mode_size ; } return scale ; } </s>

Call from ADJUST_BYTESIZE in riscv-modes.def . Return the correct BYTE size for corresponding machine_mode .


<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 : { 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 = 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 ; } } </s>

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


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

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


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


<s> bool RISCVFrameLowering :: enableShrinkWrapping ( const MachineFunction & MF ) const { if ( MF . getFunction ( ) . hasOptNone ( ) ) return false ; return true ; } </s>

Returns true if the target will correctly handle shrink wrapping .


<s> bool isReg ( RegisterKind RegKind ) const { return Kind == KindReg && Reg . Kind == RegKind ; } </s>


"ReadCycleWrite is only to be used on riscv32"

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


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

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


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

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


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

Returns true if arguments should be extended in lib calls .


<s> static bool riscv_valid_lo_sum_p ( enum riscv_symbol_type sym_type , machine_mode mode , rtx x ) { int align , size ; if ( riscv_symbol_insns ( sym_type ) == 0 ) return false ; if ( ! riscv_split_symbol_type ( sym_type ) ) return false ; if ( mode == BLKmode ) { rtx offset ; split_const ( x , & x , & offset ) ; if ( ! SYMBOL_REF_P ( x ) ) return false ; align = ( SYMBOL_REF_DECL ( x ) ? DECL_ALIGN ( SYMBOL_REF_DECL ( x ) ) : 1 ) ; size = ( SYMBOL_REF_DECL ( x ) && DECL_SIZE ( SYMBOL_REF_DECL ( x ) ) ? tree_to_uhwi ( DECL_SIZE ( SYMBOL_REF_DECL ( x ) ) ) : 2 * BITS_PER_WORD ) ; } else { align = GET_MODE_ALIGNMENT ( mode ) ; size = GET_MODE_BITSIZE ( mode ) . to_constant ( ) ; } if ( size > BITS_PER_WORD && ( ! TARGET_STRICT_ALIGN || size > align ) ) return false ; return true ; } </s>

Return true if a LO_SUM can address a value of mode MODE when the LO_SUM symbol has type SYM_TYPE .


<s> static void riscv_restore_reg ( rtx reg , rtx mem ) { rtx insn = riscv_emit_move ( reg , mem ) ; rtx dwarf = NULL_RTX ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; REG_NOTES ( insn ) = dwarf ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } </s>


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

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


<s> static unsigned riscv_pass_mode_in_fpr_p ( 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 RISCVTargetLowering :: isMulAddWithConstProfitable ( SDValue AddNode , SDValue ConstNode ) const { EVT VT = AddNode . getValueType ( ) ; if ( VT . isVector ( ) ) return true ; if ( VT . getScalarSizeInBits ( ) > Subtarget . getXLen ( ) ) return true ; ConstantSDNode * C1Node = cast < ConstantSDNode > ( AddNode . getOperand ( 1 ) ) ; ConstantSDNode * C2Node = cast < ConstantSDNode > ( ConstNode ) ; const APInt & C1 = C1Node -> getAPIntValue ( ) ; const APInt & C2 = C2Node -> getAPIntValue ( ) ; if ( C1 . isSignedIntN ( 12 ) && ! ( C1 * C2 ) . isSignedIntN ( 12 ) ) return false ; return true ; } </s>

Return true if it may be profitable to transform ( mul ( add x , c1 ) , c2 ) - > ( add ( mul x , c2 ) , c1 * c2 ) .


<s> bool RISCVTargetLowering :: mayBeEmittedAsTailCall ( const CallInst * CI ) const { return CI -> isTailCall ( ) ; } </s>

Return true if the target may be able emit the call instruction as a tail call .


Generate a sequence of instructions that zero registers specified by NEED_ZEROED_HARDREGS . Return the ZEROED_HARDREGS that are actually zeroed .


<s> void RISCVTargetLowering :: LowerAsmOperandForConstraint ( SDValue Op , std :: string & Constraint , std :: vector < SDValue > & Ops , SelectionDAG & DAG ) const { if ( Constraint . length ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'I' : if ( auto * C = dyn_cast < ConstantSDNode > ( Op ) ) { uint64_t CVal = C -> getSExtValue ( ) ; if ( isInt < 12 > ( CVal ) ) Ops . push_back ( DAG . getTargetConstant ( CVal , SDLoc ( Op ) , Subtarget . getXLenVT ( ) ) ) ; } return ; case 'J' : if ( auto * C = dyn_cast < ConstantSDNode > ( Op ) ) if ( C -> getZExtValue ( ) == 0 ) Ops . push_back ( DAG . getTargetConstant ( 0 , SDLoc ( Op ) , Subtarget . getXLenVT ( ) ) ) ; return ; case 'K' : if ( auto * C = dyn_cast < ConstantSDNode > ( Op ) ) { uint64_t CVal = C -> getZExtValue ( ) ; if ( isUInt < 5 > ( CVal ) ) Ops . push_back ( DAG . getTargetConstant ( CVal , SDLoc ( Op ) , Subtarget . getXLenVT ( ) ) ) ; } return ; case 'S' : if ( const auto * GA = dyn_cast < GlobalAddressSDNode > ( Op ) ) { Ops . push_back ( DAG . getTargetGlobalAddress ( GA -> getGlobal ( ) , SDLoc ( Op ) , GA -> getValueType ( 0 ) ) ) ; } else if ( const auto * BA = dyn_cast < BlockAddressSDNode > ( Op ) ) { Ops . push_back ( DAG . getTargetBlockAddress ( BA -> getBlockAddress ( ) , BA -> getValueType ( 0 ) ) ) ; } return ; default : break ; } } TargetLowering :: LowerAsmOperandForConstraint ( Op , Constraint , Ops , DAG ) ; } </s>

Lower the specified operand into the Ops vector .


<s> void RISCVTTIImpl :: getPeelingPreferences ( Loop * L , ScalarEvolution & SE , TTI :: PeelingPreferences & PP ) { BaseT :: getPeelingPreferences ( L , SE , PP ) ; } </s>

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


<s>
void
RISCVAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
)
const
{
MCContext
&
Ctx
=
Asm
.
getContext
(
)
;
MCFixupKind
Kind
=
Fixup
.
getKind
(
)
;
unsigned
NumBytes
=
(
getFixupKindInfo
(
Kind
)
.
TargetSize
+
7
)
/
8
;
if
(
!
Value
)
return
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
Value
=
adjustFixupValue
(
Fixup
,
Value
,
Ctx
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
assert
(
Offset
+
NumBytes
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
!=
4
;
++
i
)
{
Data
[
Offset
+
i
]
|=
uint8_t
(
(
Value
>>
(
i
*
8
)
)
&
0xff
)
;
}
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 loop_basic_block_p ( const basic_block cfg_bb ) { if ( JUMP_P ( BB_END ( cfg_bb ) ) && any_condjump_p ( BB_END ( cfg_bb ) ) ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , cfg_bb -> succs ) if ( e -> dest -> index == cfg_bb -> index ) return true ; } return false ; } </s>

Return true if the block is a loop itself : local_dem __________ ____|____ | | | | |________| | |_________| reaching_out


"RegScavenger required for long branching"

"new block should be inserted for expanding unconditional branch"

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

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


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

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


<s> 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" ; } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific


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

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

Returns the disassembly of a single instruction .


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

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


<s> void RISCVMCCodeEmitter :: encodeInstruction ( const MCInst & MI , raw_ostream & OS , SmallVectorImpl < MCFixup > & Fixups , const MCSubtargetInfo & STI ) const { uint64_t Bits = getBinaryCodeForInstr ( MI , Fixups , STI ) ; unsigned Size = MCII . get ( MI . getOpcode ( ) ) . getSize ( ) ; unsigned ShiftValue = 0 ; for ( unsigned I = 0 ; I != Size ; ++ I ) { OS << uint8_t ( Bits >> ShiftValue ) ; ShiftValue += 8 ; } } </s>

Encode the given Inst to bytes and append to CB .


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


<s> static unsigned getSize ( unsigned Kind ) { switch ( Kind ) { default : return 4 ; case RISCV :: fixup_riscv_rvc_jump : case RISCV :: fixup_riscv_rvc_branch : return 2 ; } } </s>

Return the number of bytes in the encoding of this instruction , or zero if the encoding size can not be known from the opcode .


<s> void function_builder :: add_unique_function ( const function_instance & instance , const function_shape * shape , tree return_type , vec < tree > & argument_types ) { if ( ! check_required_extensions ( instance ) ) return ; char * name = shape -> get_name ( * this , instance , false ) ; tree fntype = build_function_type_array ( return_type , argument_types . length ( ) , argument_types . address ( ) ) ; tree attrs = get_attributes ( instance ) ; registered_function & rfn = add_function ( instance , name , fntype , attrs , false ) ; hashval_t hash = instance . hash ( ) ; registered_function * * rfn_slot = function_table -> find_slot_with_hash ( instance , hash , INSERT ) ; gcc_assert ( ! * rfn_slot ) ; * rfn_slot = & rfn ; char * overload_name = shape -> get_name ( * this , instance , true ) ; if ( overload_name ) { tree attrs = get_attributes ( instance ) ; bool placeholder_p = ! m_direct_overloads ; add_function ( instance , overload_name , fntype , attrs , placeholder_p ) ; } obstack_free ( & m_string_obstack , name ) ; } </s>

Add a built-in function for INSTANCE , with the argument types given by ARGUMENT_TYPES and the return type given by RETURN_TYPE . NAME is the `` full '' name for C function . OVERLOAD_NAME is the `` short '' name for C++ overloaded function . OVERLOAD_NAME can be nullptr because some instance does n't have C++ overloaded function .


<s> int RISCVFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , unsigned & FrameReg ) const { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterInfo * RI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const std :: vector < CalleeSavedInfo > & CSI = MFI . getCalleeSavedInfo ( ) ; int MinCSFI = 0 ; int MaxCSFI = - 1 ; int Offset = MFI . getObjectOffset ( FI ) - getOffsetOfLocalArea ( ) + MFI . getOffsetAdjustment ( ) ; if ( CSI . size ( ) ) { MinCSFI = CSI [ 0 ] . getFrameIdx ( ) ; MaxCSFI = CSI [ CSI . size ( ) - 1 ] . getFrameIdx ( ) ; } FrameReg = RI -> getFrameRegister ( MF ) ; if ( FI >= MinCSFI && FI <= MaxCSFI ) { FrameReg = RISCV :: X2 ; Offset += MF . getFrameInfo ( ) . getStackSize ( ) ; } return Offset ; } </s>

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


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


<s> bool RISCVMCExpr :: evaluateAsConstant ( int64_t & Res ) const { MCValue Value ; if ( Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ) 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>
SDValue
RISCVTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
report_fatal_error
(
"unimplemented operand"
)
;
case
ISD
::
GlobalAddress
:
return
lowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
lowerBlockAddress
(
Op
,
DAG
)
;
case
ISD
::
ConstantPool
:
return
lowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
SELECT
:
return
lowerSELECT
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
lowerVASTART
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
lowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
return
lowerRETURNADDR
(
Op
,
DAG
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .

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


<s> int riscv_split_const_insns ( rtx x ) { unsigned int low , high ; low = riscv_const_insns ( riscv_subword ( x , false ) ) ; high = riscv_const_insns ( riscv_subword ( x , true ) ) ; gcc_assert ( low > 0 && high > 0 ) ; return low + high ; } </s>

X is a doubleword constant that can be handled by splitting it into two words and loading each word separately . Return the number of instructions required to do this .


<s> static bool riscv_function_ok_for_sibcall ( tree decl ATTRIBUTE_UNUSED , tree exp ATTRIBUTE_UNUSED ) { if ( TARGET_SAVE_RESTORE ) return riscv_leaf_function_p ( ) ; return true ; } </s>


"-target-abi option != target-abi module flag"

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


<s> bool RISCVAsmPrinter :: PrintAsmMemoryOperand ( const MachineInstr * MI , unsigned OpNo , const char * ExtraCode , raw_ostream & OS ) { if ( ! ExtraCode ) { const MachineOperand & MO = MI -> getOperand ( OpNo ) ; if ( ! MO . isReg ( ) ) return true ; OS << "0(" << RISCVInstPrinter :: getRegisterName ( MO . getReg ( ) ) << ")" ; return false ; } return AsmPrinter :: PrintAsmMemoryOperand ( MI , OpNo , ExtraCode , OS ) ; } </s>

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


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

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


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

We choose to return true by default since most of the intrinsics use mask predication .


<s>
bool
RISCVInstrInfo
::
verifyInstruction
(
const
MachineInstr
&
MI
,
StringRef
&
ErrInfo
)
const
{
const
MCInstrInfo
*
MCII
=
STI
.
getInstrInfo
(
)
;
MCInstrDesc
const
&
Desc
=
MCII
->
get
(
MI
.
getOpcode
(
)
)
;
for
(
auto
&
OI
:
enumerate
(
Desc
.
operands
(
)
)
)
{
unsigned
OpType
=
OI
.
value
(
)
.
OperandType
;
if
(
OpType
>=
RISCVOp
::
OPERAND_FIRST_RISCV_IMM
&&
OpType
<=
RISCVOp
::
OPERAND_LAST_RISCV_IMM
)
{
const
MachineOperand
&
MO
=
MI
.
getOperand
(
OI
.
index
(
)
)
;
if
(
MO
.
isImm
(
)
)
{
int64_t
Imm
=
MO
.
getImm
(
)
;
bool
Ok
;
switch
(
OpType
)
{
default
:
llvm_unreachable
(
"Unexpected operand type"
)
;
case
RISCVOp
::
OPERAND_UIMM1
:
Ok
=
isUInt
<
1
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM4
:
Ok
=
isUInt
<
4
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM5
:
Ok
=
isUInt
<
5
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM12
:
Ok
=
isUInt
<
12
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_SIMM12
:
Ok
=
isInt
<
12
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_SIMM13_LSB0
:
Ok
=
isShiftedInt
<
12
,
1
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM20
:
Ok
=
isUInt
<
20
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_SIMM21_LSB0
:
Ok
=
isShiftedInt
<
20
,
1
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMMLOG2XLEN
:
if
(
STI
.
getTargetTriple
(
)
.
isArch64Bit
(
)
)
Ok
=
isUInt
<
6
>
(
Imm
)
;
else
Ok
=
isUInt
<
5
>
(
Imm
)
;
break
;
}
if
(
!
Ok
)
{
ErrInfo
=
"Invalid immediate"
;
return
false
;
}
}
}
}
return
true
;
}
</s>

Perform target-specific instruction verification .


<s> void RISCVAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { RISCVMCInstLower Lower ( MF -> getContext ( ) , * this ) ; MCInst LoweredMI ; Lower . lower ( MI , LoweredMI ) ; EmitToStreamer ( * OutStreamer , LoweredMI ) ; } </s>

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


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

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


<s> tree builtin_decl ( unsigned int code , bool ) { if ( code >= vec_safe_length ( registered_functions ) ) return error_mark_node ; return ( * registered_functions ) [ code ] -> decl ; } </s>

Return the function decl with RVV function subcode CODE , or error_mark_node if no such function exists .


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

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


<s>
SDValue
RISCVTargetLowering
::
getTargetNode
(
SDValue
Op
,
SelectionDAG
&
DAG
,
unsigned
Flag
)
const
{
EVT
Ty
=
getPointerTy
(
DAG
.
getDataLayout
(
)
)
;
if
(
GlobalAddressSDNode
*
N
=
dyn_cast
<
GlobalAddressSDNode
>
(
Op
)
)
return
DAG
.
getTargetGlobalAddress
(
N
->
getGlobal
(
)
,
SDLoc
(
Op
)
,
Ty
,
0
,
Flag
)
;
if
(
ExternalSymbolSDNode
*
N
=
dyn_cast
<
ExternalSymbolSDNode
>
(
Op
)
)
return
DAG
.
getTargetExternalSymbol
(
N
->
getSymbol
(
)
,
Ty
,
Flag
)
;
if
(
BlockAddressSDNode
*
N
=
dyn_cast
<
BlockAddressSDNode
>
(
Op
)
)
return
DAG
.
getTargetBlockAddress
(
N
->
getBlockAddress
(
)
,
Ty
,
0
,
Flag
)
;
if
(
JumpTableSDNode
*
N
=
dyn_cast
<
JumpTableSDNode
>
(
Op
)
)
return
DAG
.
getTargetJumpTable
(
N
->
getIndex
(
)
,
Ty
,
Flag
)
;
if
(
ConstantPoolSDNode
*
N
=
dyn_cast
<
ConstantPoolSDNode
>
(
Op
)
)
return
DAG
.
getTargetConstantPool
(
N
->
getConstVal
(
)
,
Ty
,
N
->
getAlignment
(
)
,
N
->
getOffset
(
)
,
Flag
)
;
llvm_unreachable
(
"Unexpected node type."
)
;
return
SDValue
(
)
;
}
</s>

Retrieve the target node this edge connects to .


"%qE attribute only applies to functions"

Handle an attribute requiring a FUNCTION_DECL ; arguments as in struct attribute_spec.handler .


<s> void emitValueImpl ( const MCExpr * Value , unsigned Size , SMLoc Loc ) override { const MCExpr * A , * B ; if ( ! requiresFixups ( getContext ( ) , Value , A , B ) ) return MCELFStreamer :: emitValueImpl ( Value , Size , Loc ) ; MCStreamer :: emitValueImpl ( Value , Size , Loc ) ; MCDataFragment * DF = getOrCreateDataFragment ( ) ; flushPendingLabels ( DF , DF -> getContents ( ) . size ( ) ) ; MCDwarfLineEntry :: make ( this , getCurrentSectionOnly ( ) ) ; unsigned Add , Sub ; std :: tie ( Add , Sub ) = getRelocPairForSize ( Size ) ; DF -> getFixups ( ) . push_back ( MCFixup :: create ( DF -> getContents ( ) . size ( ) , A , static_cast < MCFixupKind > ( Add ) , Loc ) ) ; DF -> getFixups ( ) . push_back ( MCFixup :: create ( DF -> getContents ( ) . size ( ) , B , static_cast < MCFixupKind > ( Sub ) , Loc ) ) ; DF -> getContents ( ) . resize ( DF -> getContents ( ) . size ( ) + Size , 0 ) ; } </s>

Overriding these functions allows us to dismiss all labels that are candidates for marking as microMIPS when .word/.long/.4byte etc directives are emitted .


"Can't load this register from stack slot"

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


<s> poly_uint64 riscv_regmode_natural_size ( machine_mode mode ) { if ( ! riscv_vector_chunks . is_constant ( ) && riscv_v_ext_vector_mode_p ( mode ) ) return BYTES_PER_RISCV_VECTOR ; return UNITS_PER_WORD ; } </s>


<s> rtx gen_scalar_move_mask ( machine_mode mode ) { rtx_vector_builder builder ( mode , 1 , 2 ) ; builder . quick_push ( const1_rtx ) ; builder . quick_push ( const0_rtx ) ; return builder . build ( ) ; } </s>


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

ParseInstruction - Parse one assembly instruction .

RISCV
RISCV
RISCV
"call"
"tail"
"unexpected token"


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


<s>
const
uint32_t
*
RISCVRegisterInfo
::
getCallPreservedMask
(
const
MachineFunction
&
MF
,
CallingConv
::
ID
)
const
{
auto
&
Subtarget
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
MF
.
getFunction
(
)
.
hasFnAttribute
(
"interrupt"
)
)
{
if
(
Subtarget
.
hasStdExtD
(
)
)
return
CSR_XLEN_F64_Interrupt_RegMask
;
if
(
Subtarget
.
hasStdExtF
(
)
)
return
CSR_XLEN_F32_Interrupt_RegMask
;
if
(
Subtarget
.
hasStdExtV
(
)
)
return
CSR_XLEN_F32_VEC_Interrupt_RegMask
;
return
CSR_Interrupt_RegMask
;
}
if
(
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
.
hasStdExtV
(
)
)
return
CSR_ILP32F_LP64F_VEC_RegMask
;
if
(
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
.
hasStdExtF
(
)
)
return
CSR_ILP32F_LP64F_RegMask
;
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> std :: pair < unsigned , const TargetRegisterClass * > RISCVTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'd' : case 'r' : if ( Subtarget . isRV64 ( ) ) return std :: make_pair ( 0U , & RISCV :: GR64BitRegClass ) ; return std :: make_pair ( 0U , & RISCV :: GR32BitRegClass ) ; case 'f' : if ( Subtarget . hasD ( ) ) return std :: make_pair ( 0U , & RISCV :: FP64BitRegClass ) ; else if ( Subtarget . hasF ( ) ) return std :: make_pair ( 0U , & RISCV :: FP32BitRegClass ) ; else if ( Subtarget . isRV64 ( ) ) return std :: make_pair ( 0U , & RISCV :: GR64BitRegClass ) ; return std :: make_pair ( 0U , & RISCV :: GR32BitRegClass ) ; } } std :: pair < unsigned , const TargetRegisterClass * > R ; R = TargetLowering :: getRegForInlineAsmConstraint ( TRI , Constraint , VT ) ; if ( ! R . second ) { R = parseRegForInlineAsmConstraint ( Constraint , VT ) ; } return R ; } </s>

Given a physical register constraint ( e.g .


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

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


<s> Optional < DestSourcePair > RISCVInstrInfo :: isCopyInstrImpl ( const MachineInstr & MI ) const { if ( MI . isMoveReg ( ) ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; switch ( MI . getOpcode ( ) ) { default : break ; case RISCV :: ADDI : if ( MI . getOperand ( 1 ) . isReg ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; break ; case RISCV :: FSGNJ_D : case RISCV :: FSGNJ_S : if ( MI . getOperand ( 1 ) . isReg ( ) && MI . getOperand ( 2 ) . isReg ( ) && MI . getOperand ( 1 ) . getReg ( ) == MI . getOperand ( 2 ) . getReg ( ) ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; break ; } return None ; } </s>

If the specific machine instruction is a instruction that moves/copies value from one register to another register return destination and source registers as machine operands .


Pass or return a composite value in the FPR pair REGNO and REGNO + 1 . MODE is the mode of the composite . MODE1 and OFFSET1 are the mode and byte offset for the first value , likewise MODE2 and OFFSET2 for the second value .


<s> void RISCVPassConfig :: addIRPasses ( ) { addPass ( createAtomicExpandPass ( ) ) ; addPass ( createCheriBoundAllocasPass ( ) ) ; TargetPassConfig :: addIRPasses ( ) ; } </s>

Add common target configurable passes that perform LLVM IR to IR transforms following machine independent optimization .


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

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

Returns the disassembly of a single instruction .


<s> const RISCVInstrInfo * getInstrInfo ( ) const { return & InstrInfo ; } </s>


<s> void reset ( ) override { static_cast < RISCVTargetStreamer * > ( getTargetStreamer ( ) ) -> reset ( ) ; MCELFStreamer :: reset ( ) ; } </s>

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


<s>
bool
RISCVInstrInfo
::
verifyInstruction
(
const
MachineInstr
&
MI
,
StringRef
&
ErrInfo
)
const
{
const
MCInstrInfo
*
MCII
=
STI
.
getInstrInfo
(
)
;
MCInstrDesc
const
&
Desc
=
MCII
->
get
(
MI
.
getOpcode
(
)
)
;
for
(
auto
&
OI
:
enumerate
(
Desc
.
operands
(
)
)
)
{
unsigned
OpType
=
OI
.
value
(
)
.
OperandType
;
if
(
OpType
>=
RISCVOp
::
OPERAND_FIRST_RISCV_IMM
&&
OpType
<=
RISCVOp
::
OPERAND_LAST_RISCV_IMM
)
{
const
MachineOperand
&
MO
=
MI
.
getOperand
(
OI
.
index
(
)
)
;
if
(
MO
.
isImm
(
)
)
{
int64_t
Imm
=
MO
.
getImm
(
)
;
bool
Ok
;
switch
(
OpType
)
{
default
:
llvm_unreachable
(
"Unexpected operand type"
)
;
case
RISCVOp
::
OPERAND_UIMM2
:
Ok
=
isUInt
<
2
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM3
:
Ok
=
isUInt
<
3
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM4
:
Ok
=
isUInt
<
4
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM5
:
Ok
=
isUInt
<
5
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM7
:
Ok
=
isUInt
<
7
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM12
:
Ok
=
isUInt
<
12
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_SIMM12
:
Ok
=
isInt
<
12
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM20
:
Ok
=
isUInt
<
20
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMMLOG2XLEN
:
if
(
STI
.
getTargetTriple
(
)
.
isArch64Bit
(
)
)
Ok
=
isUInt
<
6
>
(
Imm
)
;
else
Ok
=
isUInt
<
5
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_RVKRNUM
:
Ok
=
Imm
>=
0
&&
Imm
<=
10
;
break
;
}
if
(
!
Ok
)
{
ErrInfo
=
"Invalid immediate"
;
return
false
;
}
}
}
}
return
true
;
}
</s>

Perform target-specific instruction verification .


<s> OperandMatchResultTy RISCVAsmParser :: tryParseRegister ( unsigned & RegNo , SMLoc & StartLoc , SMLoc & EndLoc ) { const AsmToken & Tok = getParser ( ) . getTok ( ) ; StartLoc = Tok . getLoc ( ) ; EndLoc = Tok . getEndLoc ( ) ; RegNo = 0 ; StringRef Name = getLexer ( ) . getTok ( ) . getIdentifier ( ) ; if ( matchRegisterNameHelper ( isRV32E ( ) , ( MCRegister & ) RegNo , Name ) ) return MatchOperand_NoMatch ; getParser ( ) . Lex ( ) ; return MatchOperand_Success ; } </s>

tryParseRegister - parse one register if possible


<s> static void insert_insn_end_basic_block ( rtx_insn * rinsn , basic_block cfg_bb ) { rtx_insn * end_rinsn = BB_END ( cfg_bb ) ; rtx_insn * new_insn ; rtx_insn * pat , * pat_end ; pat = rinsn ; gcc_assert ( pat && INSN_P ( pat ) ) ; pat_end = pat ; while ( NEXT_INSN ( pat_end ) != NULL_RTX ) pat_end = NEXT_INSN ( pat_end ) ; if ( JUMP_P ( end_rinsn ) || ( NONJUMP_INSN_P ( end_rinsn ) && ( ! single_succ_p ( cfg_bb ) || single_succ_edge ( cfg_bb ) -> flags & EDGE_ABNORMAL ) ) ) { new_insn = emit_insn_before_noloc ( pat , end_rinsn , cfg_bb ) ; } else if ( CALL_P ( end_rinsn ) && ( ! single_succ_p ( cfg_bb ) || single_succ_edge ( cfg_bb ) -> flags & EDGE_ABNORMAL ) ) { end_rinsn = find_first_parameter_load ( end_rinsn , BB_HEAD ( cfg_bb ) ) ; while ( LABEL_P ( end_rinsn ) || NOTE_INSN_BASIC_BLOCK_P ( end_rinsn ) ) end_rinsn = NEXT_INSN ( end_rinsn ) ; new_insn = emit_insn_before_noloc ( pat , end_rinsn , cfg_bb ) ; } else new_insn = emit_insn_after_noloc ( pat , end_rinsn , cfg_bb ) ; while ( 1 ) { if ( INSN_P ( pat ) ) add_label_notes ( PATTERN ( pat ) , new_insn ) ; if ( pat == pat_end ) break ; pat = NEXT_INSN ( pat ) ; } } </s>

Add EXPR to the end of basic block BB . This is used by both the PRE and code hoisting .


<s> unsigned RISCVTargetLowering :: getExceptionPointerRegister ( const Constant * PersonalityFn ) const { if ( Subtarget . isRV64 ( ) ) return RISCV :: epc_64 ; else return RISCV :: epc ; } </s>

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


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


<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
::
PseudoBR
:
return
isIntN
(
21
,
BrOffset
)
;
case
RISCV
::
PseudoJump
:
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::PseudoBR
21
RISCV::PseudoJump
32
0x800


<s> void RISCVInstPrinter :: printInst ( const MCInst * MI , raw_ostream & O , StringRef Annot , const MCSubtargetInfo & STI ) { 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 , STI , O ) ) printInstruction ( NewMI , STI , O ) ; printAnnotation ( O , Annot ) ; } </s>

Print the specified MCInst to the specified raw_ostream .


<s> Optional < DestSourcePair > RISCVInstrInfo :: isCopyInstrImpl ( const MachineInstr & MI ) const { if ( MI . isMoveReg ( ) ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; switch ( MI . getOpcode ( ) ) { default : break ; case RISCV :: ADDI : if ( MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; break ; case RISCV :: FSGNJ_D : case RISCV :: FSGNJ_S : if ( MI . getOperand ( 1 ) . isReg ( ) && MI . getOperand ( 2 ) . isReg ( ) && MI . getOperand ( 1 ) . getReg ( ) == MI . getOperand ( 2 ) . getReg ( ) ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; break ; } return None ; } </s>


<s> int RISCVFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , unsigned & FrameReg ) const { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterInfo * RI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; const std :: vector < CalleeSavedInfo > & CSI = MFI . getCalleeSavedInfo ( ) ; int MinCSFI = 0 ; int MaxCSFI = - 1 ; int Offset = MFI . getObjectOffset ( FI ) - getOffsetOfLocalArea ( ) + MFI . getOffsetAdjustment ( ) ; if ( CSI . size ( ) ) { MinCSFI = CSI [ 0 ] . getFrameIdx ( ) ; MaxCSFI = CSI [ CSI . size ( ) - 1 ] . getFrameIdx ( ) ; } if ( FI >= MinCSFI && FI <= MaxCSFI ) { FrameReg = RISCV :: X2 ; Offset += MF . getFrameInfo ( ) . getStackSize ( ) ; } else { FrameReg = RI -> getFrameRegister ( MF ) ; if ( hasFP ( MF ) ) Offset += RVFI -> getVarArgsSaveSize ( ) ; else Offset += MF . getFrameInfo ( ) . getStackSize ( ) ; } return Offset ; } </s>

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


<s> 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 :: 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 :: 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> unsigned getNumFixupKinds ( ) const override { return 1 ; } </s>

Get the number of target specific fixup kinds .


Prepare the OPERANDS array to emit a mempair instruction using the provided information . No checks are performed , the resulting array should be validated using th_mempair_operands_p ( ) .


"Can't load this register from stack slot"

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


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

Check whether the given instruction may need relaxation .


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


<s> static rtx riscv_emit_set ( rtx target , rtx src ) { emit_insn ( gen_rtx_SET ( target , src ) ) ; return target ; } </s>

Emit an instruction of the form ( set TARGET SRC ) .


<s>
bool
RISCVInstrInfo
::
verifyInstruction
(
const
MachineInstr
&
MI
,
StringRef
&
ErrInfo
)
const
{
const
MCInstrInfo
*
MCII
=
STI
.
getInstrInfo
(
)
;
MCInstrDesc
const
&
Desc
=
MCII
->
get
(
MI
.
getOpcode
(
)
)
;
for
(
auto
&
OI
:
enumerate
(
Desc
.
operands
(
)
)
)
{
unsigned
OpType
=
OI
.
value
(
)
.
OperandType
;
if
(
OpType
>=
RISCVOp
::
OPERAND_FIRST_RISCV_IMM
&&
OpType
<=
RISCVOp
::
OPERAND_LAST_RISCV_IMM
)
{
const
MachineOperand
&
MO
=
MI
.
getOperand
(
OI
.
index
(
)
)
;
if
(
MO
.
isImm
(
)
)
{
int64_t
Imm
=
MO
.
getImm
(
)
;
bool
Ok
;
switch
(
OpType
)
{
default
:
llvm_unreachable
(
"Unexpected operand type"
)
;
case
RISCVOp
::
OPERAND_UIMM4
:
Ok
=
isUInt
<
4
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM5
:
Ok
=
isUInt
<
5
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM12
:
Ok
=
isUInt
<
12
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_SIMM12
:
Ok
=
isInt
<
12
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMM20
:
Ok
=
isUInt
<
20
>
(
Imm
)
;
break
;
case
RISCVOp
::
OPERAND_UIMMLOG2XLEN
:
if
(
STI
.
getTargetTriple
(
)
.
isArch64Bit
(
)
)
Ok
=
isUInt
<
6
>
(
Imm
)
;
else
Ok
=
isUInt
<
5
>
(
Imm
)
;
break
;
}
if
(
!
Ok
)
{
ErrInfo
=
"Invalid immediate"
;
return
false
;
}
}
}
}
return
true
;
}
</s>


<s> static int riscv_register_priority ( int regno ) { if ( riscv_compressed_reg_p ( regno ) ) return 1 ; return 0 ; } </s>

Return a register priority for hard reg REGNO .


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

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


<s> static bool anticipatable_occurrence_p ( const bb_info * bb , const vector_insn_info dem ) { insn_info * insn = dem . get_insn ( ) ; if ( dem . has_avl_reg ( ) ) { if ( ! vlmax_avl_p ( dem . get_avl ( ) ) ) { set_info * set = dem . get_avl_source ( ) ; if ( ! set ) return false ; if ( real_insn_and_same_bb_p ( set -> insn ( ) , bb ) && before_p ( set -> insn ( ) , insn ) ) return false ; } } if ( vsetvl_insn_p ( insn -> rtl ( ) ) ) { rtx dest = get_vl ( insn -> rtl ( ) ) ; for ( insn_info * i = insn -> prev_nondebug_insn ( ) ; real_insn_and_same_bb_p ( i , bb ) ; i = i -> prev_nondebug_insn ( ) ) { if ( find_access ( i -> uses ( ) , REGNO ( dest ) ) ) return false ; if ( find_access ( i -> defs ( ) , REGNO ( dest ) ) ) return false ; } } return true ; } </s>

An `` anticipatable occurrence '' is one that is the first occurrence in the basic block , the operands are not modified in the basic block prior to the occurrence and the output is not used between the start of the block and the occurrence . For VSETVL instruction , we have these following formats : 1. vsetvl zero , rs1 . 2. vsetvl zero , imm . 3. vsetvl rd , rs1 . So base on these circumstances , a DEM is considered as a local anticipatable occurrence should satisfy these following conditions : 1 ) . rs1 ( avl ) are not modified in the basic block prior to the VSETVL . 2 ) . rd ( vl ) are not modified in the basic block prior to the VSETVL . 3 ) . rd ( vl ) is not used between the start of the block and the occurrence . Note : We do n't need to check VL/VTYPE here since DEM is UNKNOWN if VL/VTYPE is modified prior to the occurrence . This case is already considered as a non-local anticipatable occurrence .


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

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


<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
>
(
)
;
MachineBasicBlock
::
iterator
MBBI
=
MBB
.
begin
(
)
;
const
RISCVInstrInfo
*
TII
=
STI
.
getInstrInfo
(
)
;
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
)
;
const
std
::
vector
<
CalleeSavedInfo
>
&
CSI
=
MFI
.
getCalleeSavedInfo
(
)
;
std
::
advance
(
MBBI
,
CSI
.
size
(
)
)
;
if
(
hasFP
(
MF
)
)
adjustReg
(
MBB
,
MBBI
,
DL
,
FPReg
,
SPReg
,
StackSize
RVFI
->
getVarArgsSaveSize
(
)
,
MachineInstr
::
FrameSetup
)
;
const
MCRegisterInfo
*
MRI
=
MF
.
getMMI
(
)
.
getContext
(
)
.
getRegisterInfo
(
)
;
unsigned
CFIIndex
=
MF
.
addFrameInst
(
MCCFIInstruction
::
createDefCfaOffset
(
nullptr
,
StackSize
)
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
TII
->
get
(
TargetOpcode
::
CFI_INSTRUCTION
)
)
.
addCFIIndex
(
CFIIndex
)
.
setMIFlags
(
MachineInstr
::
FrameSetup
)
;
for
(
const
auto
&
Entry
:
CSI
)
{
unsigned
Reg
=
Entry
.
getReg
(
)
;
int
FI
=
Entry
.
getFrameIdx
(
)
;
CFIIndex
=
MF
.
addFrameInst
(
MCCFIInstruction
::
createOffset
(
nullptr
,
MRI
->
getDwarfRegNum
(
Reg
,
true
)
,
MFI
.
getObjectOffset
(
FI
)
)
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
TII
->
get
(
TargetOpcode
::
CFI_INSTRUCTION
)
)
.
addCFIIndex
(
CFIIndex
)
.
setMIFlags
(
MachineInstr
::
FrameSetup
)
;
}
}
</s>

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

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


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

Insert a call to an outlined function into the program .


<s> bool get_ma ( ) const { return m_ma ; } </s>

Get ma according to operand [ mask_op_idx ] .


<s> MVT RISCVTargetLowering :: getRegisterTypeForCallingConv ( LLVMContext & Context , CallingConv :: ID CC , EVT VT ) const { if ( VT == MVT :: f16 && Subtarget . hasStdExtF ( ) && ! Subtarget . hasStdExtZfh ( ) ) return MVT :: f32 ; return TargetLowering :: getRegisterTypeForCallingConv ( Context , CC , VT ) ; } </s>

Certain combinations of ABIs , Targets and features require that types are legal for some operations and not for other operations .


<s> Optional < MCFixupKind > RISCVAsmBackend :: getFixupKind ( StringRef Name ) const { if ( STI . getTargetTriple ( ) . isOSBinFormatELF ( ) ) { unsigned Type ; Type = llvm :: StringSwitch < unsigned > ( Name ) . Default ( - 1u ) ; if ( Type != - 1u ) return static_cast < MCFixupKind > ( FirstLiteralRelocationKind + Type ) ; } return None ; } </s>

getFixupKind - Get the fixup kind of this expression .


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


<s>
bool
RISCVMakeCompressibleOpt
::
runOnMachineFunction
(
MachineFunction
&
Fn
)
{
if
(
skipFunction
(
Fn
.
getFunction
(
)
)
||
!
Fn
.
getFunction
(
)
.
hasMinSize
(
)
)
return
false
;
const
RISCVSubtarget
&
STI
=
Fn
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
const
RISCVInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
!
STI
.
hasStdExtC
(
)
)
return
false
;
for
(
MachineBasicBlock
&
MBB
:
Fn
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"MBB: "
<<
MBB
.
getName
(
)
<<
"\n"
)
;
for
(
MachineInstr
&
MI
:
MBB
)
{
RegImmPair
RegImm
=
getRegImmPairPreventingCompression
(
MI
)
;
if
(
!
RegImm
.
Reg
&&
RegImm
.
Imm
==
0
)
continue
;
SmallVector
<
MachineInstr
*
,
8
>
MIs
;
Register
NewReg
=
analyzeCompressibleUses
(
MI
,
RegImm
,
MIs
)
;
if
(
!
NewReg
)
continue
;
if
(
RISCV
::
GPRRegClass
.
contains
(
RegImm
.
Reg
)
)
{
assert
(
isInt
<
12
>
(
RegImm
.
Imm
)
)
;
BuildMI
(
MBB
,
MI
,
MI
.
getDebugLoc
(
)
,
TII
.
get
(
RISCV
::
ADDI
)
,
NewReg
)
.
addReg
(
RegImm
.
Reg
)
.
addImm
(
RegImm
.
Imm
)
;
}
else
{
assert
(
RegImm
.
Imm
==
0
)
;
unsigned
Opcode
=
RISCV
::
FPR32RegClass
.
contains
(
RegImm
.
Reg
)
RISCV
::
FSGNJ_S
:
RISCV
::
FSGNJ_D
;
BuildMI
(
MBB
,
MI
,
MI
.
getDebugLoc
(
)
,
TII
.
get
(
Opcode
)
,
NewReg
)
.
addReg
(
RegImm
.
Reg
)
.
addReg
(
RegImm
.
Reg
)
;
}
for
(
MachineInstr
*
UpdateMI
:
MIs
)
updateOperands
(
*
UpdateMI
,
RegImm
,
NewReg
)
;
}
}
return
true
;
}
</s>

runOnMachineFunction - Emit the function body .


<s> static int riscv_arg_partial_bytes ( cumulative_args_t cum , enum machine_mode mode , tree type , bool named ) { struct riscv_arg_info arg ; riscv_get_arg_info ( & arg , get_cumulative_args ( cum ) , mode , type , named , false ) ; return arg . stack_p ? arg . num_gprs * UNITS_PER_WORD : 0 ; } </s>


<s> bool RISCVTargetLowering :: getPostIndexedAddressParts ( SDNode * N , SDNode * Op , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( ! Subtarget . hasExtXCoreVMem ( ) ) return false ; if ( Op -> getOpcode ( ) != ISD :: ADD ) return false ; if ( LSBaseSDNode * LS = dyn_cast < LSBaseSDNode > ( N ) ) { Base = LS -> getBasePtr ( ) ; } else { return false ; } if ( Base == Op -> getOperand ( 0 ) ) { Offset = Op -> getOperand ( 1 ) ; } else if ( Base == Op -> getOperand ( 1 ) ) { Offset = Op -> getOperand ( 0 ) ; } else { return false ; } AM = ISD :: POST_INC ; return true ; } </s>

Returns true by value , base pointer and offset pointer and addressing mode by reference if this node can be combined with a load / store to form a post-indexed load / store .


"RISCV DAG->DAG Pattern Instruction Selection"

getPassName - Return a nice clean name for a pass .


<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 ( ) ) ; assert ( checkAllSuperRegsMarked ( Reserved ) ) ; return Reserved ; } </s>

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


<s> MVT RISCVTargetLowering :: getVPExplicitVectorLengthTy ( ) const { return Subtarget . getXLenVT ( ) ; } </s>

Returns the type to be used for the EVL/AVL operand of VP nodes : ISD : :VP_ADD , ISD : :VP_SUB , etc .


"Not all fixup kinds added to Infos array"


<s> const uint32_t * RISCVRegisterInfo :: getCallPreservedMask ( const MachineFunction & MF , CallingConv :: ID ) const { if ( MF . getFunction ( ) . hasFnAttribute ( "interrupt" ) ) { if ( MF . getSubtarget < RISCVSubtarget > ( ) . hasStdExtD ( ) ) return CSR_XLEN_F64_Interrupt_RegMask ; if ( MF . getSubtarget < RISCVSubtarget > ( ) . hasStdExtF ( ) ) return CSR_XLEN_F32_Interrupt_RegMask ; return CSR_Interrupt_RegMask ; } return CSR_RegMask ; } </s>

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


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

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


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

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


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

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


<s>
static
rtx
riscv_expand_builtin_insn
(
enum
insn_code
icode
,
unsigned
int
n_ops
,
struct
expand_operand
*
ops
,
bool
has_target_p
)
{
if
(
!
maybe_expand_insn
(
icode
,
n_ops
,
ops
)
)
{
error
(
"invalid argument to built-in function"
)
;
return
has_target_p
gen_reg_rtx
(
ops
[
0
]
.
mode
)
:
const0_rtx
;
}
return
has_target_p
ops
[
0
]
.
value
:
const0_rtx
;
}
</s>

Expand instruction ICODE as part of a built-in function sequence . Use the first NOPS elements of OPS as the instruction 's operands . HAS_TARGET_P is true if operand 0 is a target ; it is false if the instruction has no target . Return the target rtx if HAS_TARGET_P , otherwise return const0_rtx .


<s> bool convertSelectOfConstantsToMath ( EVT VT ) const override { return true ; } </s>

Return true if a select of constants ( select Cond , C1 , C2 ) should be transformed into simple math ops with the condition value .


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

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


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

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


<s> bool riscv_split_symbol ( rtx temp , rtx addr , enum 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 ( 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> 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 ( 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>


<s> inline void function_expander :: add_output_operand ( machine_mode mode , rtx target ) { create_output_operand ( & m_ops [ opno ++ ] , target , mode ) ; } </s>

Create output and add it into M_OPS and increase OPNO .


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

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


<s> 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 ) ; assert ( checkAllSuperRegsMarked ( Reserved ) ) ; return Reserved ; } </s>


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

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

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


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


<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" ; emitTextAttribute ( RISCVAttrs :: ARCH , Arch ) ; } </s>

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


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

Return true if the instruction is fault first load instruction .


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

Encode the given Inst to bytes and append to CB .

RISCV
RISCV
RISCV::PseudoCALLReg
RISCV::PseudoCALL
RISCV::PseudoTAIL
RISCV::PseudoJump
2
RISCV::PseudoAddTPRel
1
"Unhandled encodeInstruction length!"
2
support::endian
support::little
4
support::endian
support::little


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

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

RISCV RISCV 0 ISD::ADD ISD::OR 1 1 RISCVMatInt::getIntMatCost RISCVMatInt::getIntMatCost


<s> bool pass_vsetvl :: forward_demand_fusion ( 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 ( cfg_bb == ENTRY_BLOCK_PTR_FOR_FN ( cfun ) ) continue ; if ( vsetvl_insn_p ( prop . get_insn ( ) -> rtl ( ) ) ) continue ; edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , cfg_bb -> succs ) { auto & local_dem = m_vector_manager -> vector_block_infos [ e -> dest -> index ] . local_dem ; auto & reaching_out = m_vector_manager -> vector_block_infos [ e -> dest -> index ] . reaching_out ; if ( e -> dest -> index == cfg_bb -> index ) continue ; if ( e -> flags & EDGE_COMPLEX ) continue ; if ( e -> dest -> index == EXIT_BLOCK_PTR_FOR_FN ( cfun ) -> index ) continue ; if ( ! local_dem . valid_or_dirty_p ( ) ) continue ; if ( local_dem . available_p ( prop ) ) continue ; if ( ! local_dem . compatible_p ( prop ) ) continue ; if ( propagate_avl_across_demands_p ( prop , local_dem ) ) continue ; vector_insn_info new_info = local_dem . merge ( prop , GLOBAL_MERGE ) ; new_info . set_insn ( local_dem . get_insn ( ) ) ; if ( local_dem . dirty_p ( ) ) { gcc_assert ( local_dem == reaching_out ) ; new_info . set_dirty ( local_dem . dirty_with_killed_avl_p ( ) ) ; local_dem = new_info ; reaching_out = local_dem ; } else { if ( reaching_out == local_dem ) reaching_out = new_info ; local_dem = new_info ; change_vsetvl_insn ( local_dem . get_insn ( ) , new_info ) ; } auto & prob = m_vector_manager -> vector_block_infos [ e -> dest -> index ] . probability ; auto & curr_prob = m_vector_manager -> vector_block_infos [ cfg_bb -> index ] . probability ; prob = curr_prob * e -> probability ; changed_p = true ; } } return changed_p ; } </s>


<s> bool has_merge_operand_p ( ) const override { if ( UNSPEC == UNSPEC_VSLIDEUP ) return false ; return true ; } </s>

We choose to return true by default since most of the intrinsics use has merge operand .


<s> bool RISCVTargetLowering :: isLegalAddressingMode ( const DataLayout & DL , const AddrMode & AM , Type * Ty , unsigned AS , Instruction * I ) const { if ( AM . BaseGV ) return false ; if ( Subtarget . hasVInstructions ( ) && isa < VectorType > ( Ty ) ) return AM . HasBaseReg && AM . Scale == 0 && ! AM . BaseOffs ; if ( ! isInt < 12 > ( AM . BaseOffs ) ) return false ; switch ( AM . Scale ) { case 0 : break ; case 1 : if ( ! AM . HasBaseReg ) break ; return false ; default : return false ; } return true ; } </s>

isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target , for a load/store of the specified type .


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


<s> bool RISCVAsmBackend :: shouldInsertFixupForCodeAlign ( MCAssembler & Asm , const MCAsmLayout & Layout , MCAlignFragment & AF ) { const MCSubtargetInfo * STI = AF . getSubtargetInfo ( ) ; if ( ! STI -> getFeatureBits ( ) [ RISCV :: FeatureRelax ] ) return false ; unsigned Count ; if ( ! shouldInsertExtraNopBytesForCodeAlign ( AF , Count ) || ( Count == 0 ) ) return false ; MCContext & Ctx = Asm . getContext ( ) ; const MCExpr * Dummy = MCConstantExpr :: create ( 0 , Ctx ) ; MCFixup Fixup = MCFixup :: create ( 0 , Dummy , MCFixupKind ( RISCV :: fixup_riscv_align ) , SMLoc ( ) ) ; uint64_t FixedValue = 0 ; MCValue NopBytes = MCValue :: get ( Count ) ; Asm . getWriter ( ) . recordRelocation ( Asm , Layout , & AF , Fixup , NopBytes , FixedValue ) ; return true ; } </s>

Hook which indicates if the target requires a fixup to be generated when handling an align directive in an executable section .


<s> bool riscv_new_address_profitable_p ( rtx memref , rtx_insn * insn , rtx new_addr ) { addr_space_t as = MEM_ADDR_SPACE ( memref ) ; bool speed = optimize_bb_for_speed_p ( BLOCK_FOR_INSN ( insn ) ) ; int old_cost = address_cost ( XEXP ( memref , 0 ) , GET_MODE ( memref ) , as , speed ) ; int new_cost = address_cost ( new_addr , GET_MODE ( memref ) , as , speed ) ; return new_cost <= old_cost ; } </s>


"could not find corresponding %pcrel_hi"

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


<s> unsigned RISCVRegisterInfo :: getFrameRegister ( const MachineFunction & MF ) const { const TargetFrameLowering * TFI = MF . getSubtarget ( ) . getFrameLowering ( ) ; return TFI -> hasFP ( MF ) ? ( Subtarget . isRV64 ( ) ? RISCV :: fp_64 : RISCV :: fp ) : ( Subtarget . isRV64 ( ) ? RISCV :: sp_64 : RISCV :: sp ) ; } </s>

RISCV RISCV RISCV::fp_64 RISCV::fp RISCV::sp_64 RISCV::sp


"-target-abi option != target-abi module flag"

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


<s> static hash_set < basic_block > get_all_predecessors ( basic_block cfg_bb ) { hash_set < basic_block > blocks ; auto_vec < basic_block > work_list ; hash_set < basic_block > visited_list ; work_list . safe_push ( cfg_bb ) ; while ( ! work_list . is_empty ( ) ) { basic_block new_cfg_bb = work_list . pop ( ) ; visited_list . add ( new_cfg_bb ) ; edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , new_cfg_bb -> preds ) { if ( ! visited_list . contains ( e -> src ) ) work_list . safe_push ( e -> src ) ; blocks . add ( e -> src ) ; } } return blocks ; } </s>

Recursively find all predecessor blocks for cfg_bb .


"Can't load this register from stack slot"

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


<s> static enum riscv_privilege_levels riscv_get_interrupt_type ( tree decl ) { gcc_assert ( decl != NULL_TREE ) ; if ( ( TREE_CODE ( decl ) != FUNCTION_DECL ) || ( ! riscv_interrupt_type_p ( TREE_TYPE ( decl ) ) ) ) return UNKNOWN_MODE ; tree attr_args = TREE_VALUE ( lookup_attribute ( "interrupt" , TYPE_ATTRIBUTES ( TREE_TYPE ( decl ) ) ) ) ; if ( attr_args && TREE_CODE ( TREE_VALUE ( attr_args ) ) != VOID_TYPE ) { const char * string = TREE_STRING_POINTER ( TREE_VALUE ( attr_args ) ) ; if ( ! strcmp ( string , "user" ) ) return USER_MODE ; else if ( ! strcmp ( string , "supervisor" ) ) return SUPERVISOR_MODE ; else return MACHINE_MODE ; } else return MACHINE_MODE ; } </s>

Get the interrupt type , return UNKNOWN_MODE if it 's not interrupt function .


<s> TargetLowering :: ConstraintWeight RISCVTargetLowering :: getSingleConstraintMatchWeight ( AsmOperandInfo & info , const char * constraint ) const { ConstraintWeight weight = CW_Invalid ; Value * CallOperandVal = info . CallOperandVal ; if ( CallOperandVal == NULL ) return CW_Default ; Type * type = CallOperandVal -> getType ( ) ; switch ( * constraint ) { default : weight = TargetLowering :: getSingleConstraintMatchWeight ( info , constraint ) ; break ; case 'a' : case 'd' : case 'r' : if ( CallOperandVal -> getType ( ) -> isIntegerTy ( ) ) weight = CW_Register ; break ; case 'f' : if ( type -> isFloatingPointTy ( ) ) weight = CW_Register ; break ; case 'I' : if ( ConstantInt * C = dyn_cast < ConstantInt > ( CallOperandVal ) ) if ( isUInt < 8 > ( C -> getZExtValue ( ) ) ) weight = CW_Constant ; break ; case 'J' : if ( ConstantInt * C = dyn_cast < ConstantInt > ( CallOperandVal ) ) if ( isUInt < 12 > ( C -> getZExtValue ( ) ) ) weight = CW_Constant ; break ; case 'K' : if ( ConstantInt * C = dyn_cast < ConstantInt > ( CallOperandVal ) ) if ( isInt < 16 > ( C -> getSExtValue ( ) ) ) weight = CW_Constant ; break ; case 'L' : if ( ConstantInt * C = dyn_cast < ConstantInt > ( CallOperandVal ) ) if ( isInt < 20 > ( C -> getSExtValue ( ) ) ) weight = CW_Constant ; break ; case 'M' : if ( ConstantInt * C = dyn_cast < ConstantInt > ( CallOperandVal ) ) if ( C -> getZExtValue ( ) == 0x7fffffff ) weight = CW_Constant ; break ; } return weight ; } </s>

Examine constraint string and operand type and determine a weight value .


<s>
SDValue
RISCVTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
report_fatal_error
(
"unimplemented operand"
)
;
case
ISD
::
GlobalAddress
:
return
lowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
lowerBlockAddress
(
Op
,
DAG
)
;
case
ISD
::
ConstantPool
:
return
lowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
SELECT
:
return
lowerSELECT
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
lowerVASTART
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
lowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
return
lowerRETURNADDR
(
Op
,
DAG
)
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
lowerINTRINSIC_WO_CHAIN
(
Op
,
DAG
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .

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


<s> static bool riscv_scalar_mode_supported_p ( scalar_mode mode ) { if ( mode == HFmode ) return true ; else return default_scalar_mode_supported_p ( mode ) ; } </s>


<s> static void riscv_print_operand_reloc ( FILE * file , rtx op , bool hi_reloc ) { const char * reloc ; switch ( riscv_classify_symbolic_expression ( op ) ) { case SYMBOL_ABSOLUTE : reloc = hi_reloc ? "%hi" : "%lo" ; break ; case SYMBOL_PCREL : reloc = hi_reloc ? "%pcrel_hi" : "%pcrel_lo" ; break ; case SYMBOL_TLS_LE : reloc = hi_reloc ? "%tprel_hi" : "%tprel_lo" ; break ; default : gcc_unreachable ( ) ; } fprintf ( file , "%s(" , reloc ) ; output_addr_const ( file , riscv_strip_unspec_address ( op ) ) ; fputc ( ')' , file ) ; } </s>

Print symbolic operand OP , which is part of a HIGH or LO_SUM in context CONTEXT . HI_RELOC indicates a high-part reloc .


<s> static rtx riscv_shorten_lw_offset ( rtx base , HOST_WIDE_INT offset ) { rtx addr , high ; high = GEN_INT ( offset & ~ CSW_MAX_OFFSET ) ; offset &= CSW_MAX_OFFSET ; if ( ! SMALL_OPERAND ( INTVAL ( high ) ) ) high = force_reg ( Pmode , high ) ; base = force_reg ( Pmode , gen_rtx_PLUS ( Pmode , high , base ) ) ; addr = plus_constant ( Pmode , base , offset ) ; return addr ; } </s>

Modify base + offset so that offset fits within a compressed load/store insn and the excess is added to base .


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


<s> static bool ignore_vlmul_insn_p ( rtx_insn * rinsn ) { return get_attr_type ( rinsn ) == TYPE_VIMOVVX || get_attr_type ( rinsn ) == TYPE_VFMOVVF || get_attr_type ( rinsn ) == TYPE_VIMOVXV || get_attr_type ( rinsn ) == TYPE_VFMOVFV ; } </s>

Return true if the instruction ignores VLMUL field of VTYPE .


<s> static tree add_attribute ( const char * name , tree attrs ) { return tree_cons ( get_identifier ( name ) , NULL_TREE , attrs ) ; } </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 ; } } } </s>

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


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


<s> yaml :: MachineFunctionInfo * RISCVTargetMachine :: createDefaultFuncInfoYAML ( ) const { return new yaml :: RISCVMachineFunctionInfo ( ) ; } </s>

Allocate and return a default initialized instance of the YAML representation for the MachineFunctionInfo .


<s> inline hashval_t registered_function_hasher :: hash ( value_type value ) { return value -> instance . hash ( ) ; } </s>

Hash function for builtin functions with up to 3 arguments and a return type .


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

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

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


<s> bool RISCVExpandPseudo :: runOnMachineFunction ( MachineFunction & MF ) { TII = static_cast < const RISCVInstrInfo * > ( MF . getSubtarget ( ) . getInstrInfo ( ) ) ; bool Modified = false ; for ( auto & MBB : MF ) Modified |= expandMBB ( MBB ) ; return Modified ; } </s>

runOnMachineFunction - Emit the function body .