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

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


"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>
void
print
(
raw_ostream
&
OS
)
const
override
{
switch
(
Kind
)
{
case
Immediate
:
OS
<<
*
getImm
(
)
;
break
;
case
Register
:
OS
<<
"<register x"
;
OS
<<
getReg
(
)
<<
">"
;
break
;
case
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
case
SystemRegister
:
OS
<<
"<sysreg: "
<<
getSysReg
(
)
<<
'>'
;
break
;
}
}
</s>

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

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


<s>
bool
RISCVSExtWRemoval
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
if
(
skipFunction
(
MF
.
getFunction
(
)
)
||
DisableSExtWRemoval
)
return
false
;
MachineRegisterInfo
&
MRI
=
MF
.
getRegInfo
(
)
;
const
RISCVSubtarget
&
ST
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
!
ST
.
is64Bit
(
)
)
return
false
;
bool
MadeChange
=
false
;
for
(
MachineBasicBlock
&
MBB
:
MF
)
{
for
(
auto
I
=
MBB
.
begin
(
)
,
IE
=
MBB
.
end
(
)
;
I
!=
IE
;
)
{
MachineInstr
*
MI
=
&
*
I
++
;
if
(
MI
->
getOpcode
(
)
!=
RISCV
::
ADDIW
||
!
MI
->
getOperand
(
2
)
.
isImm
(
)
||
MI
->
getOperand
(
2
)
.
getImm
(
)
!=
0
||
!
MI
->
getOperand
(
1
)
.
isReg
(
)
)
continue
;
Register
SrcReg
=
MI
->
getOperand
(
1
)
.
getReg
(
)
;
if
(
!
SrcReg
.
isVirtual
(
)
)
continue
;
const
MachineInstr
&
SrcMI
=
*
MRI
.
getVRegDef
(
SrcReg
)
;
if
(
!
isSignExtendedW
(
SrcMI
,
MRI
)
)
continue
;
Register
DstReg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
if
(
!
MRI
.
constrainRegClass
(
SrcReg
,
MRI
.
getRegClass
(
DstReg
)
)
)
continue
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Removing redundant sign-extension\n"
)
;
MRI
.
replaceRegWith
(
DstReg
,
SrcReg
)
;
MRI
.
clearKillFlags
(
SrcReg
)
;
MI
->
eraseFromParent
(
)
;
++
NumRemovedSExtW
;
MadeChange
=
true
;
}
}
return
MadeChange
;
}
</s>

runOnMachineFunction - Emit the function body .


<s> VSETVLIInfo intersect ( const VSETVLIInfo & Other ) const { if ( ! Other . isValid ( ) ) return * this ; if ( ! isValid ( ) ) return Other ; if ( isUnknown ( ) || Other . isUnknown ( ) ) return VSETVLIInfo :: getUnknown ( ) ; if ( * this == Other ) return * this ; if ( hasSameAVL ( Other ) && hasSameVLMAX ( Other ) ) { VSETVLIInfo MergeInfo = * this ; MergeInfo . SEWLMULRatioOnly = true ; return MergeInfo ; } return VSETVLIInfo :: getUnknown ( ) ; } </s>

Intersect this set with a temporary other set in place .


<s> enum mask_policy get_prefer_mask_policy ( ) { return MASK_ANY ; } </s>


<s> void RISCVFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const RISCVRegisterInfo * RI = STI . getRegisterInfo ( ) ; const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; for ( int ID = MFI . getObjectIndexBegin ( ) , EID = MFI . getObjectIndexEnd ( ) ; ID < EID ; ID ++ ) { if ( MFI . getStackID ( ID ) == TargetStackID :: RISCVVector && ! MFI . isDeadObjectIndex ( ID ) ) { FrameSize = alignTo ( FrameSize , TRI -> getSpillAlignment ( RISCV :: GPRRegClass ) ) ; FrameSize += TRI -> getSpillSize ( RISCV :: GPRRegClass ) ; MFI . setObjectOffset ( ID , - FrameSize ) ; } } Align StackAlign = getStackAlign ( ) ; if ( RI -> needsStackRealignment ( MF ) ) { Align MaxStackAlign = std :: max ( StackAlign , MFI . getMaxAlign ( ) ) ; FrameSize += ( MaxStackAlign . value ( ) - StackAlign . value ( ) ) ; StackAlign = MaxStackAlign ; } uint64_t MaxCallSize = alignTo ( MFI . getMaxCallFrameSize ( ) , StackAlign ) ; MFI . setMaxCallFrameSize ( MaxCallSize ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; } </s>

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

RISCV RISCV RISCV RISCV RISCV::GPRRegClass RISCV::GPRRegClass


<s> static void th_mempair_save_regs ( rtx operands [ 4 ] ) { rtx set1 = gen_rtx_SET ( operands [ 0 ] , operands [ 1 ] ) ; rtx set2 = gen_rtx_SET ( operands [ 2 ] , operands [ 3 ] ) ; rtx insn = emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , set1 , set2 ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; add_reg_note ( insn , REG_CFA_OFFSET , copy_rtx ( set1 ) ) ; add_reg_note ( insn , REG_CFA_OFFSET , copy_rtx ( set2 ) ) ; } </s>

Similar like riscv_save_reg , but saves two registers to memory and marks the resulting instruction as frame-related .


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

Returns how or if MIT should be outlined .


<s> static bool any_set_in_bb_p ( hash_set < set_info * > sets , const bb_info * bb ) { for ( const set_info * set : sets ) if ( set -> bb ( ) -> index ( ) == bb -> index ( ) ) return true ; return false ; } </s>

Return true if there is an INSN in insns staying in the block BB .


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

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


<s> static int riscv_address_cost ( rtx addr , enum machine_mode mode , addr_space_t as ATTRIBUTE_UNUSED , bool speed ATTRIBUTE_UNUSED ) { return riscv_address_insns ( addr , mode , false ) ; } </s>


"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 bool riscv_valid_lo_sum_p ( enum riscv_symbol_type sym_type , enum machine_mode mode ) { if ( riscv_symbol_insns ( sym_type ) == 0 ) return false ; if ( ! riscv_split_symbol_type ( sym_type ) ) return false ; if ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD && GET_MODE_BITSIZE ( mode ) > GET_MODE_ALIGNMENT ( mode ) ) 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 addUses ( const MachineInstr & MI , SmallVectorImpl < const MachineInstr * > & Worklist , MachineRegisterInfo & MRI ) { for ( auto & UserOp : MRI . reg_operands ( MI . getOperand ( 0 ) . getReg ( ) ) ) { const auto * User = UserOp . getParent ( ) ; if ( User == & MI ) continue ; Worklist . push_back ( User ) ; } } </s>


<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
;
}
if
(
!
Ok
)
{
ErrInfo
=
"Invalid immediate"
;
return
false
;
}
}
}
}
return
true
;
}
</s>

Perform target-specific instruction verification .


<s>
static
void
add_vector_type_attribute
(
tree
type
,
const
char
*
mangled_name
)
{
tree
mangled_name_tree
=
get_identifier
(
mangled_name
)
;
tree
value
=
tree_cons
(
NULL_TREE
,
mangled_name_tree
,
NULL_TREE
)
;
TYPE_ATTRIBUTES
(
type
)
=
tree_cons
(
get_identifier
(
"RVV type"
)
,
value
,
TYPE_ATTRIBUTES
(
type
)
)
;
}
</s>

Add type attributes to builtin type tree , currently only the mangled name .


<s> static bool riscv_verify_type_context ( location_t loc , type_context_kind context , const_tree type , bool silent_p ) { return riscv_vector :: verify_type_context ( loc , context , type , silent_p ) ; } </s>


<s> static int riscv_address_cost ( rtx addr , machine_mode mode , addr_space_t as ATTRIBUTE_UNUSED , bool speed ATTRIBUTE_UNUSED ) { if ( TARGET_RVC && ! speed && riscv_mshorten_memrefs && mode == SImode && ! riscv_compressed_lw_address_p ( addr ) ) return riscv_address_insns ( addr , mode , false ) + 1 ; return riscv_address_insns ( addr , mode , false ) ; } </s>


<s> static rtx riscv_legitimize_address ( rtx x , rtx oldx ATTRIBUTE_UNUSED , enum 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 ) ) 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 ) ; 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> unsigned RISCVRegisterInfo :: getFrameRegister ( const MachineFunction & MF ) const { const TargetFrameLowering * TFI = getFrameLowering ( MF ) ; return TFI -> hasFP ( MF ) ? RISCV :: X8 : RISCV :: X2 ; } </s>


<s> bool RISCVAsmBackend :: writeNopData ( uint64_t Count , MCObjectWriter * OW ) const { if ( ( Count % 4 ) != 0 ) return false ; for ( uint64_t i = 0 ; i < Count ; i += 4 ) OW -> write32 ( 0x13 ) ; return true ; } </s>

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


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

getSubtarget - Return the subtarget for which this machine code is being compiled .


<s> static void register_builtin_types ( ) { tree int8_type_node = get_typenode_from_name ( INT8_TYPE ) ; tree uint8_type_node = get_typenode_from_name ( UINT8_TYPE ) ; tree int16_type_node = get_typenode_from_name ( INT16_TYPE ) ; tree int32_type_node = get_typenode_from_name ( INT32_TYPE ) ; tree int64_type_node = get_typenode_from_name ( INT64_TYPE ) ; machine_mode mode ; VECTOR_MODE_MIN_VLEN_32 , ARGS ... ) \ mode = TARGET_MIN_VLEN > 32 ? VECTOR_MODE ## mode \ : VECTOR_MODE_MIN_VLEN_32 ## mode ; \ register_builtin_type ( VECTOR_TYPE_ ## NAME , SCALAR_TYPE ## _type_node , mode ) ; } </s>

Register the built-in RVV ABI types , such as __rvv_int32m1_t .


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

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


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

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


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

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


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


<s> Optional < MCFixupKind > RISCVAsmBackend :: getFixupKind ( StringRef Name ) const { if ( STI . getTargetTriple ( ) . isOSBinFormatELF ( ) ) { unsigned Type ; Type = llvm :: StringSwitch < unsigned > ( Name ) . Case ( "BFD_RELOC_NONE" , ELF :: R_RISCV_NONE ) . Case ( "BFD_RELOC_32" , ELF :: R_RISCV_32 ) . Case ( "BFD_RELOC_64" , ELF :: R_RISCV_64 ) . Default ( - 1u ) ; if ( Type != - 1u ) return static_cast < MCFixupKind > ( FirstLiteralRelocationKind + Type ) ; } return None ; } </s>

getFixupKind - Get the fixup kind of this expression .


<s> static unsigned char riscv_class_max_nregs ( reg_class_t rclass , machine_mode mode ) { if ( reg_class_subset_p ( rclass , FP_REGS ) ) return riscv_hard_regno_nregs ( FP_REG_FIRST , mode ) ; if ( reg_class_subset_p ( rclass , GR_REGS ) ) return riscv_hard_regno_nregs ( GP_REG_FIRST , mode ) ; return 0 ; } </s>


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

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


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

Customize the printer according to a command line option .


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

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


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

Targets should implement this to emit instructions .


<s> bool RISCVRegisterInfo :: hasReservedSpillSlot ( const MachineFunction & MF , unsigned Reg , int & FrameIdx ) const { const auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; if ( ! RVFI -> useSaveRestoreLibCalls ( ) ) return false ; auto FII = FixedCSRFIMap . find ( Reg ) ; if ( FII == FixedCSRFIMap . end ( ) ) return false ; FrameIdx = FII -> second ; return true ; } </s>

Return true if target has reserved a spill slot in the stack frame of the given function for the specified register .


<s> bool RISCVCallLowering :: lowerReturn ( MachineIRBuilder & MIRBuilder , const Value * Val , ArrayRef < Register > VRegs ) const { MachineInstrBuilder Ret = MIRBuilder . buildInstrNoInsert ( RISCV :: PseudoRET ) ; if ( Val != nullptr ) { return false ; } MIRBuilder . insertInstr ( Ret ) ; return true ; } </s>

This hook behaves as the extended lowerReturn function , but for targets that do not support swifterror value promotion .


<s> void RISCVAsmPrinter :: emitFunctionEntryLabel ( ) { AsmPrinter :: emitFunctionEntryLabel ( ) ; RISCVTargetStreamer & RTS = static_cast < RISCVTargetStreamer & > ( * OutStreamer -> getTargetStreamer ( ) ) ; RTS . setTargetABI ( STI -> getTargetABI ( ) ) ; } </s>

EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function .


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

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


"loadRegFromStackSlot didn't insert any code!"

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


<s>
void
print
(
raw_ostream
&
OS
)
const
override
{
switch
(
Kind
)
{
case
KindTy
::
Immediate
:
OS
<<
*
getImm
(
)
;
break
;
case
KindTy
::
Register
:
OS
<<
"<register x"
;
OS
<<
getReg
(
)
<<
">"
;
break
;
case
KindTy
::
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
case
KindTy
::
SystemRegister
:
OS
<<
"<sysreg: "
<<
getSysReg
(
)
<<
'>'
;
break
;
case
KindTy
::
VectorRegister
:
OS
<<
"<vecreg: "
<<
getVecReg
(
)
<<
'>'
;
break
;
case
KindTy
::
VTypeImm
:
SmallVector
<
char
,
8
>
VTypeBuf
;
OS
<<
"<vtypei: "
<<
getVTypeImm
(
VTypeBuf
)
<<
'>'
;
break
;
}
}
</s>

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

RISCV
"<register x"
">"
"'"
"'"
"<sysreg: "
"<vecreg: "
8
"<vtypei: "


"Save/restore libcall not implemented for purecap"

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


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

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


<s> bool RISCVInstrInfo :: expandPostRAPseudo ( MachineBasicBlock :: iterator MI ) const { switch ( MI -> getOpcode ( ) ) { default : return false ; } } </s>

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


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


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

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

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

Returns the disassembly of a single instruction .


<s> bool RISCVAsmBackend :: shouldInsertFixupForCodeAlign ( MCAssembler & Asm , const MCAsmLayout & Layout , MCAlignFragment & AF ) { if ( ! STI . getFeatureBits ( ) [ RISCV :: FeatureRelax ] ) return false ; unsigned Count ; shouldInsertExtraNopBytesForCodeAlign ( AF , Count ) ; if ( 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> MCFragment * findAssociatedFragment ( ) const override { return getSubExpr ( ) -> findAssociatedFragment ( ) ; } </s>

Find the `` associated section '' for this expression , which is currently defined as the absolute section for constants , or otherwise the section associated with the first defined symbol in the expression .


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

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


<s> bool RISCVTargetLowering :: getPostIndexedAddressParts ( SDNode * N , SDNode * Op , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( ! Subtarget . hasNonStdExtPulp ( ) ) return false ; if ( Op -> getOpcode ( ) != ISD :: ADD ) return false ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { Base = LD -> getBasePtr ( ) ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { Base = ST -> 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 .


<s> unsigned RISCVRegisterInfo :: getRegisterCostTableIndex ( const MachineFunction & MF ) const { return MF . getSubtarget < RISCVSubtarget > ( ) . hasStdExtC ( ) ? 1 : 0 ; } </s>


<s>
static
void
make_type_sizeless
(
tree
type
)
{
TYPE_ATTRIBUTES
(
type
)
=
tree_cons
(
get_identifier
(
"RVV sizeless type"
)
,
NULL_TREE
,
TYPE_ATTRIBUTES
(
type
)
)
;
}
</s>


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

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


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

Main hook for targets to transform nodes into machine nodes .


<s> void RISCVPassConfig :: addPreRegAlloc ( ) { addPass ( createRISCVMergeBaseOffsetOptPass ( ) ) ; } </s>

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


<s> void pass_vsetvl :: refine_vsetvls ( void ) const { basic_block cfg_bb ; FOR_EACH_BB_FN ( cfg_bb , cfun ) { auto info = m_vector_manager -> vector_block_infos [ cfg_bb -> index ] . local_dem ; insn_info * insn = info . get_insn ( ) ; if ( ! info . valid_p ( ) ) continue ; rtx_insn * rinsn = insn -> rtl ( ) ; if ( ! can_refine_vsetvl_p ( cfg_bb , info ) ) continue ; if ( vector_config_insn_p ( rinsn ) ) { m_vector_manager -> to_refine_vsetvls . add ( rinsn ) ; continue ; } rinsn = PREV_INSN ( rinsn ) ; rtx new_pat = gen_vsetvl_pat ( VSETVL_VTYPE_CHANGE_ONLY , info , NULL_RTX ) ; change_insn ( rinsn , new_pat ) ; } } </s>

Optimize athe case like this : bb 0 : vsetvl 0 a5 , zero , e8 , mf8 insn 0 ( demand SEW + LMUL ) bb 1 : vsetvl 1 a5 , zero , e16 , mf4 insn 1 ( demand SEW + LMUL ) In this case , we should be able to refine vsetvl 1 into vsetvl zero , zero according AVIN .


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

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


<s> bool RISCVAsmBackend :: writeNopData ( raw_ostream & OS , uint64_t Count , const MCSubtargetInfo * STI ) const { bool HasStdExtC = STI -> getFeatureBits ( ) [ RISCV :: FeatureStdExtC ] ; unsigned MinNopLen = HasStdExtC ? 2 : 4 ; if ( ( Count % MinNopLen ) != 0 ) return false ; for ( ; Count >= 4 ; Count -= 4 ) OS . write ( "\x13\0\0\0" , 4 ) ; if ( Count && HasStdExtC ) OS . write ( "\x01\0" , 2 ) ; return true ; } </s>

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


<s> static void riscv_emit_epilogue_components ( sbitmap components ) { riscv_process_components ( components , false ) ; } </s>


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

Return true if the current function must save register REGNO .


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

Perform a masked atomicrmw using a target-specific intrinsic .


<s> static void build_all ( function_builder & b , const function_group_info & group ) { for ( unsigned int pred_idx = 0 ; group . preds [ pred_idx ] != NUM_PRED_TYPES ; ++ pred_idx ) for ( unsigned int vec_type_idx = 0 ; group . ops_infos . types [ vec_type_idx ] . index != NUM_VECTOR_TYPES ; ++ vec_type_idx ) build_one ( b , group , pred_idx , vec_type_idx ) ; } </s>

Add a function instance for every operand & & predicate & & args combination in GROUP . Take the function base name from GROUP & & operand suffix from operand_suffixes & & mode suffix from type_suffixes & & predication suffix from predication_suffixes . Use apply_predication to add in the predicate .


<s> static const char * getName ( ) { return DEBUG_TYPE ; } </s>

Return a string with the name of the plan and the applicable VFs and UFs .


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

getPassName - Return a nice clean name for a pass .


<s> static bool riscv_compressed_lw_offset_p ( rtx x ) { return ( CONST_INT_P ( x ) && ( INTVAL ( x ) & 3 ) == 0 && IN_RANGE ( INTVAL ( x ) , 0 , CSW_MAX_OFFSET ) ) ; } </s>

Return true if x is an unsigned 5-bit immediate scaled by 4 .


<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 ) ) ) { int RegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC ) , RegInfo -> getSpillAlign ( * RC ) , false ) ; RS -> addScavengingFrameIndex ( RegScavFI ) ; } } </s>

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


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

Return true if the target supports masked load .


"Unexpected combination of stack realignment and varsized objects"

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


<s> const RISCVMCExpr * RISCVMCExpr :: create ( const MCExpr * Expr , VariantKind Kind , MCContext & Ctx ) { return new ( Ctx ) RISCVMCExpr ( Expr , Kind ) ; } </s>


<s> bool riscv_legitimize_move ( enum machine_mode mode , rtx dest , rtx src ) { if ( ! register_operand ( dest , mode ) && ! reg_or_0_operand ( src , mode ) ) { riscv_emit_move ( dest , force_reg ( mode , src ) ) ; return true ; } if ( CONSTANT_P ( src ) && ! move_operand ( src , mode ) ) { riscv_legitimize_const_move ( mode , dest , src ) ; set_unique_reg_note ( get_last_insn ( ) , REG_EQUAL , copy_rtx ( src ) ) ; return true ; } return false ; } </s>

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


<s> const RISCVRegisterInfo * getRegisterInfo ( ) const override { return & RegInfo ; } </s>

getRegisterInfo - TargetInstrInfo is a superset of MRegister info .


<s>
SDValue
RISCVTargetLowering
::
BuildSDIVPow2
(
SDNode
*
N
,
const
APInt
&
Divisor
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDNode
*
>
&
Created
)
const
{
AttributeList
Attr
=
DAG
.
getMachineFunction
(
)
.
getFunction
(
)
.
getAttributes
(
)
;
if
(
isIntDivCheap
(
N
->
getValueType
(
0
)
,
Attr
)
)
return
SDValue
(
N
,
0
)
;
assert
(
(
Divisor
.
isPowerOf2
(
)
||
Divisor
.
isNegatedPowerOf2
(
)
)
&&
"Unexpected divisor!"
)
;
if
(
!
Subtarget
.
hasStdExtZbt
(
)
)
return
SDValue
(
)
;
unsigned
Lg2
=
Divisor
.
countTrailingZeros
(
)
;
if
(
Lg2
==
1
||
Lg2
>=
12
)
return
SDValue
(
)
;
EVT
VT
=
N
->
getValueType
(
0
)
;
if
(
VT
!=
MVT
::
i32
&&
!
(
Subtarget
.
is64Bit
(
)
&&
VT
==
MVT
::
i64
)
)
return
SDValue
(
)
;
SDLoc
DL
(
N
)
;
SDValue
N0
=
N
->
getOperand
(
0
)
;
SDValue
Zero
=
DAG
.
getConstant
(
0
,
DL
,
VT
)
;
SDValue
Pow2MinusOne
=
DAG
.
getConstant
(
(
1ULL
<<
Lg2
)
1
,
DL
,
VT
)
;
SDValue
Cmp
=
DAG
.
getSetCC
(
DL
,
VT
,
N0
,
Zero
,
ISD
::
SETLT
)
;
SDValue
Add
=
DAG
.
getNode
(
ISD
::
ADD
,
DL
,
VT
,
N0
,
Pow2MinusOne
)
;
SDValue
Sel
=
DAG
.
getNode
(
ISD
::
SELECT
,
DL
,
VT
,
Cmp
,
Add
,
N0
)
;
Created
.
push_back
(
Cmp
.
getNode
(
)
)
;
Created
.
push_back
(
Add
.
getNode
(
)
)
;
Created
.
push_back
(
Sel
.
getNode
(
)
)
;
SDValue
SRA
=
DAG
.
getNode
(
ISD
::
SRA
,
DL
,
VT
,
Sel
,
DAG
.
getConstant
(
Lg2
,
DL
,
VT
)
)
;
if
(
Divisor
.
isNonNegative
(
)
)
return
SRA
;
Created
.
push_back
(
SRA
.
getNode
(
)
)
;
return
DAG
.
getNode
(
ISD
::
SUB
,
DL
,
VT
,
DAG
.
getConstant
(
0
,
DL
,
VT
)
,
SRA
)
;
}
</s>

Targets may override this function to provide custom SDIV lowering for power-of-2 denominators .


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

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


<s> 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 ; Size = AF . getAlignment ( ) - MinNopLen ; return true ; } </s>

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

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


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

If TYPE is an ABI-defined RVV type , return its attribute descriptor , otherwise return null .


<s> bool RISCVRegisterInfo :: hasReservedSpillSlot ( const MachineFunction & MF , Register Reg , int & FrameIdx ) const { const auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; if ( ! RVFI -> useSaveRestoreLibCalls ( MF ) ) return false ; auto FII = FixedCSRFIMap . find ( Reg ) ; if ( FII == FixedCSRFIMap . end ( ) ) return false ; FrameIdx = FII -> second ; return true ; } </s>

Return true if target has reserved a spill slot in the stack frame of the given function for the specified register .


"insertBranch must not be told to insert a fallthrough"

"RISCV branch conditions have two components!"

Insert branch code into the end of the specified MachineBasicBlock .


<s> void RISCVInstrInfo :: adjustStackPtr ( unsigned SP , int64_t Amount , MachineBasicBlock & MBB , MachineBasicBlock :: iterator I ) const { DebugLoc DL = I != MBB . end ( ) ? I -> getDebugLoc ( ) : DebugLoc ( ) ; unsigned ADD = STI . isRV64 ( ) ? RISCV :: ADD64 : RISCV :: ADD ; unsigned ADDI = STI . isRV64 ( ) ? RISCV :: ADDI64 : RISCV :: ADDI ; if ( isInt < 12 > ( Amount ) ) BuildMI ( MBB , I , DL , get ( ADDI ) , SP ) . addReg ( SP ) . addImm ( Amount ) ; else { unsigned Reg ; loadImmediate ( MBB , I , & Reg , Amount ) ; BuildMI ( MBB , I , DL , get ( ADD ) , SP ) . addReg ( SP ) . addReg ( Reg , RegState :: Kill ) ; } } </s>


<s> SDValue RISCVSelectionDAGInfo :: EmitTargetCodeForMemmove ( SelectionDAG & DAG , const SDLoc & dl , SDValue Chain , SDValue Dst , SDValue Src , SDValue Size , Align Alignment , bool isVolatile , bool MustPreserveCheriCapabilities , MachinePointerInfo DstPtrInfo , MachinePointerInfo SrcPtrInfo ) const { return EmitTargetCodeForMemOp ( DAG , dl , Chain , Dst , Src , Size , Alignment , isVolatile , false , MustPreserveCheriCapabilities , DstPtrInfo , SrcPtrInfo , false ) ; } </s>

Emit target-specific code that performs a memmove .


<s> bool RISCVSubtarget :: enableSubRegLiveness ( ) const { return EnableSubRegLiveness ; } </s>

Enable tracking of subregister liveness in register allocator .


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

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


<s> rtx function_expander :: use_widen_ternop_insn ( insn_code icode ) { int arg_offset = 0 ; if ( use_real_mask_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_all_one_mask_operand ( mask_mode ( ) ) ; for ( int argno = arg_offset ; argno < call_expr_nargs ( exp ) ; argno ++ ) add_input_operand ( argno ) ; add_input_operand ( Pmode , get_tail_policy_for_pred ( pred ) ) ; add_input_operand ( Pmode , get_mask_policy_for_pred ( pred ) ) ; add_input_operand ( Pmode , get_avl_type_rtx ( avl_type :: NONVLMAX ) ) ; return generate_insn ( icode ) ; } </s>

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


<s> bool isMem ( RegisterKind RegKind , bool HasIndex ) const { return ( Kind == KindMem && Mem . RegKind == RegKind && ( HasIndex || ! Mem . Index ) ) ; } </s>


<s> inline machine_mode function_expander :: vector_mode ( void ) const { return TYPE_MODE ( builtin_types [ type . index ] . vector ) ; } </s>

Return the machine_mode of the corresponding vector type .


<s>
bool
RISCVInstrInfo
::
areMemAccessesTriviallyDisjoint
(
const
MachineInstr
&
MIa
,
const
MachineInstr
&
MIb
)
const
{
assert
(
MIa
.
mayLoadOrStore
(
)
&&
"MIa must be a load or store."
)
;
assert
(
MIb
.
mayLoadOrStore
(
)
&&
"MIb must be a load or store."
)
;
if
(
MIa
.
hasUnmodeledSideEffects
(
)
||
MIb
.
hasUnmodeledSideEffects
(
)
||
MIa
.
hasOrderedMemoryRef
(
)
||
MIb
.
hasOrderedMemoryRef
(
)
)
return
false
;
const
TargetRegisterInfo
*
TRI
=
STI
.
getRegisterInfo
(
)
;
const
MachineOperand
*
BaseOpA
=
nullptr
,
*
BaseOpB
=
nullptr
;
int64_t
OffsetA
=
0
,
OffsetB
=
0
;
unsigned
int
WidthA
=
0
,
WidthB
=
0
;
if
(
getMemOperandWithOffsetWidth
(
MIa
,
BaseOpA
,
OffsetA
,
WidthA
,
TRI
)
&&
getMemOperandWithOffsetWidth
(
MIb
,
BaseOpB
,
OffsetB
,
WidthB
,
TRI
)
)
{
if
(
BaseOpA
->
isIdenticalTo
(
*
BaseOpB
)
)
{
int
LowOffset
=
std
::
min
(
OffsetA
,
OffsetB
)
;
int
HighOffset
=
std
::
max
(
OffsetA
,
OffsetB
)
;
int
LowWidth
=
(
LowOffset
==
OffsetA
)
WidthA
:
WidthB
;
if
(
LowOffset
+
LowWidth
<=
HighOffset
)
return
true
;
}
}
return
false
;
}
</s>

Sometimes , it is possible for the target to tell , even without aliasing information , that two MIs access different memory addresses .


<s> unsigned RISCVTargetLowering :: getExceptionSelectorRegister ( const Constant * PersonalityFn ) const { return RISCV :: X11 ; } </s>

If a physical register , this returns the register that receives the exception typeid on entry to a landing pad .


<s> const uint32_t * RISCVRegisterInfo :: getCallPreservedMask ( const MachineFunction & MF , CallingConv :: ID ) const { if ( Subtarget . isRV64 ( ) ) if ( Subtarget . hasD ( ) ) return CSR_RV64D_RegMask ; else if ( Subtarget . hasF ( ) ) return CSR_RV64F_RegMask ; else return CSR_RV64_RegMask ; else if ( Subtarget . hasD ( ) ) return CSR_RV32D_RegMask ; else if ( Subtarget . hasF ( ) ) return CSR_RV32F_RegMask ; else return CSR_RV32_RegMask ; } </s>

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


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

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

RISCV RISCV RISCV RISCV RISCV::GPRRegClass RISCV RISCV RISCV 11 0 0 0


<s> bool RISCVAsmPrinter :: PrintAsmMemoryOperand ( const MachineInstr * MI , unsigned OpNo , unsigned AsmVariant , const char * ExtraCode , raw_ostream & OS ) { RISCVInstPrinter :: printAddress ( MI -> getOperand ( OpNo ) . getReg ( ) , MI -> getOperand ( OpNo + 1 ) . getImm ( ) , OS ) ; return false ; } </s>

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


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

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


"\nThe total VSETVL expression num = %d\n"

Assemble the candidates expressions for LCM .


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

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


<s> static rtx get_tail_policy_for_pred ( enum predication_type_index pred ) { if ( pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu ) return gen_int_mode ( TAIL_UNDISTURBED , Pmode ) ; return gen_int_mode ( get_prefer_tail_policy ( ) , Pmode ) ; } </s>

Get TAIL policy for predication . If predication indicates TU , return the TU . Otherwise , return the prefer default configuration .


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

Get a TargetTransformInfo implementation for the target .


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

getPassName - Return a nice clean name for a pass .


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

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


"frame pointer should not have been eliminated"


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

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


<s> bool RISCVTargetLowering :: getTgtMemIntrinsic ( IntrinsicInfo & Info , const CallInst & I , MachineFunction & MF , unsigned Intrinsic ) const { auto & DL = I . getModule ( ) -> getDataLayout ( ) ; switch ( Intrinsic ) { default : return false ; case Intrinsic :: riscv_masked_atomicrmw_xchg_i32 : case Intrinsic :: riscv_masked_atomicrmw_add_i32 : case Intrinsic :: riscv_masked_atomicrmw_sub_i32 : case Intrinsic :: riscv_masked_atomicrmw_nand_i32 : case Intrinsic :: riscv_masked_atomicrmw_max_i32 : case Intrinsic :: riscv_masked_atomicrmw_min_i32 : case Intrinsic :: riscv_masked_atomicrmw_umax_i32 : case Intrinsic :: riscv_masked_atomicrmw_umin_i32 : case Intrinsic :: riscv_masked_cmpxchg_i32 : Info . opc = ISD :: INTRINSIC_W_CHAIN ; Info . memVT = MVT :: i32 ; Info . ptrVal = I . getArgOperand ( 0 ) ; Info . offset = 0 ; Info . align = Align ( 4 ) ; Info . flags = MachineMemOperand :: MOLoad | MachineMemOperand :: MOStore | MachineMemOperand :: MOVolatile ; return true ; case Intrinsic :: riscv_masked_strided_load : Info . opc = ISD :: INTRINSIC_W_CHAIN ; Info . ptrVal = I . getArgOperand ( 1 ) ; Info . memVT = getValueType ( DL , I . getType ( ) -> getScalarType ( ) ) ; Info . align = Align ( DL . getTypeSizeInBits ( I . getType ( ) -> getScalarType ( ) ) / 8 ) ; Info . size = MemoryLocation :: UnknownSize ; Info . flags |= MachineMemOperand :: MOLoad ; return true ; case Intrinsic :: riscv_masked_strided_store : Info . opc = ISD :: INTRINSIC_VOID ; Info . ptrVal = I . getArgOperand ( 1 ) ; Info . memVT = getValueType ( DL , I . getArgOperand ( 0 ) -> getType ( ) -> getScalarType ( ) ) ; Info . align = Align ( DL . getTypeSizeInBits ( I . getArgOperand ( 0 ) -> getType ( ) -> getScalarType ( ) ) / 8 ) ; Info . size = MemoryLocation :: UnknownSize ; Info . flags |= MachineMemOperand :: MOStore ; return true ; } } </s>

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


<s>
void
RISCVAsmBackend
::
relaxInstruction
(
MCInst
&
Inst
,
const
MCSubtargetInfo
&
STI
)
const
{
MCInst
Res
;
bool
IsCapMode
=
STI
.
getFeatureBits
(
)
[
RISCV
::
FeatureCapMode
]
;
switch
(
Inst
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Opcode not expected!"
)
;
case
RISCV
::
C_BEQZ
:
Res
.
setOpcode
(
RISCV
::
BEQ
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
RISCV
::
C_BNEZ
:
Res
.
setOpcode
(
RISCV
::
BNE
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
RISCV
::
C_J
:
Res
.
setOpcode
(
IsCapMode
RISCV
::
CJAL
:
RISCV
::
JAL
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
IsCapMode
RISCV
::
C0
:
RISCV
::
X0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
break
;
case
RISCV
::
C_JAL
:
Res
.
setOpcode
(
RISCV
::
JAL
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X1
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
break
;
case
RISCV
::
C_CJAL
:
Res
.
setOpcode
(
RISCV
::
CJAL
)
;
Res
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
C1
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
break
;
}
Inst
=
std
::
move
(
Res
)
;
}
</s>


<s> int riscv_address_insns ( rtx x , machine_mode mode , bool might_split_p ) { struct riscv_address_info addr ; int n = 1 ; if ( ! riscv_classify_address ( & addr , x , mode , false ) ) return 0 ; if ( mode != BLKmode && might_split_p ) n += ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; if ( addr . type == ADDRESS_LO_SUM ) n += riscv_symbol_insns ( addr . symbol_type ) - 1 ; return n ; } </s>

Return the number of instructions needed to load or store a value of mode MODE at address X . Return 0 if X is n't valid for MODE . Assume that multiword moves may need to be split into word moves if MIGHT_SPLIT_P , otherwise assume that a single load or store is enough .


<s> bool RISCVTargetLowering :: isCheapToSpeculateCttz ( ) const { return Subtarget . hasStdExtZbb ( ) ; } </s>

Return true if it is cheap to speculate a call to intrinsic cttz .


<s>
bool
RISCVSExtWRemoval
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
if
(
skipFunction
(
MF
.
getFunction
(
)
)
||
DisableSExtWRemoval
)
return
false
;
MachineRegisterInfo
&
MRI
=
MF
.
getRegInfo
(
)
;
const
RISCVSubtarget
&
ST
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
!
ST
.
is64Bit
(
)
)
return
false
;
SmallPtrSet
<
MachineInstr
*
,
4
>
SExtWRemovalCands
;
for
(
MachineBasicBlock
&
MBB
:
MF
)
{
for
(
auto
I
=
MBB
.
begin
(
)
,
IE
=
MBB
.
end
(
)
;
I
!=
IE
;
)
{
MachineInstr
*
MI
=
&
*
I
++
;
if
(
MI
->
getOpcode
(
)
!=
RISCV
::
ADDIW
||
!
MI
->
getOperand
(
2
)
.
isImm
(
)
||
MI
->
getOperand
(
2
)
.
getImm
(
)
!=
0
||
!
MI
->
getOperand
(
1
)
.
isReg
(
)
)
continue
;
Register
SrcReg
=
MI
->
getOperand
(
1
)
.
getReg
(
)
;
if
(
!
SrcReg
.
isVirtual
(
)
)
continue
;
SExtWRemovalCands
.
insert
(
MI
)
;
}
}
bool
MadeChange
=
false
;
for
(
auto
MI
:
SExtWRemovalCands
)
{
SmallPtrSet
<
MachineInstr
*
,
4
>
FixableDef
;
Register
SrcReg
=
MI
->
getOperand
(
1
)
.
getReg
(
)
;
MachineInstr
&
SrcMI
=
*
MRI
.
getVRegDef
(
SrcReg
)
;
if
(
!
isSignExtendedW
(
SrcMI
,
MRI
,
FixableDef
)
)
continue
;
Register
DstReg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
if
(
!
MRI
.
constrainRegClass
(
SrcReg
,
MRI
.
getRegClass
(
DstReg
)
)
)
continue
;
for
(
MachineInstr
*
Fixable
:
FixableDef
)
{
MachineBasicBlock
&
MBB
=
*
Fixable
->
getParent
(
)
;
const
DebugLoc
&
DL
=
Fixable
->
getDebugLoc
(
)
;
unsigned
Code
=
getWOp
(
Fixable
->
getOpcode
(
)
)
;
MachineInstrBuilder
Replacement
=
BuildMI
(
MBB
,
Fixable
,
DL
,
ST
.
getInstrInfo
(
)
->
get
(
Code
)
)
;
for
(
auto
Op
:
Fixable
->
operands
(
)
)
Replacement
.
add
(
Op
)
;
for
(
auto
Op
:
Fixable
->
memoperands
(
)
)
Replacement
.
addMemOperand
(
Op
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Replacing "
<<
*
Fixable
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"     with "
<<
*
Replacement
)
;
Fixable
->
eraseFromParent
(
)
;
++
NumTransformedToWInstrs
;
}
LLVM_DEBUG
(
dbgs
(
)
<<
"Removing redundant sign-extension\n"
)
;
MRI
.
replaceRegWith
(
DstReg
,
SrcReg
)
;
MRI
.
clearKillFlags
(
SrcReg
)
;
MI
->
eraseFromParent
(
)
;
++
NumRemovedSExtW
;
MadeChange
=
true
;
}
return
MadeChange
;
}
</s>

runOnMachineFunction - Emit the function body .


<s> bool mayNeedRelaxation ( const MCInst & Inst ) const override { return false ; } </s>

Check whether the given instruction may need relaxation .


<s> static bool riscv_naked_function_p ( tree func ) { tree func_decl = func ; if ( func == NULL_TREE ) func_decl = current_function_decl ; return NULL_TREE != lookup_attribute ( "naked" , DECL_ATTRIBUTES ( func_decl ) ) ; } </s>

Return true if func is a naked function .


"ReadCycleWrite is only to be used on riscv32"

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


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


<s> bool runOnMachineFunction ( MachineFunction & MF ) override { Subtarget = & MF . getSubtarget < RISCVSubtarget > ( ) ; return SelectionDAGISel :: runOnMachineFunction ( MF ) ; } </s>


<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
(
)
)
;
analyzeOutputArgs
(
DAG
.
getMachineFunction
(
)
,
CCInfo
,
Outs
,
true
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
RVLocs
.
size
(
)
;
i
<
e
;
++
i
)
{
SDValue
Val
=
OutVals
[
i
]
;
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
assert
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
Full
&&
"Unexpected CCValAssign::LocInfo"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
Val
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

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


"this operation requires the RVV ISA extension"

"you can enable RVV using the command-line"

" option %<-march%>, or by using the %<target%>"

Report when we try to do something that requires vector when vector is disabled . This is an error of last resort and is n't very high-quality . It usually involves attempts to measure the vector length in some way .


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

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


<s> static rtx gen_vsetvl_pat ( rtx_insn * rinsn , const vector_insn_info & info ) { rtx new_pat ; vl_vtype_info new_info = info ; if ( info . get_insn ( ) && info . get_insn ( ) -> rtl ( ) && fault_first_load_p ( info . get_insn ( ) -> rtl ( ) ) ) new_info . set_avl_info ( avl_info ( get_avl ( info . get_insn ( ) -> rtl ( ) ) , nullptr ) ) ; if ( vsetvl_insn_p ( rinsn ) || vlmax_avl_p ( info . get_avl ( ) ) ) { rtx dest = get_vl ( rinsn ) ; new_pat = gen_vsetvl_pat ( VSETVL_NORMAL , new_info , dest ) ; } else if ( INSN_CODE ( rinsn ) == CODE_FOR_vsetvl_vtype_change_only ) new_pat = gen_vsetvl_pat ( VSETVL_VTYPE_CHANGE_ONLY , new_info , NULL_RTX ) ; else new_pat = gen_vsetvl_pat ( VSETVL_DISCARD_RESULT , new_info , NULL_RTX ) ; return new_pat ; } </s>


<s>
void
addExpr
(
MCInst
&
Inst
,
const
MCExpr
*
Expr
)
const
{
assert
(
Expr
&&
"Expr shouldn't be null!"
)
;
int64_t
Imm
=
0
;
bool
IsConstant
=
false
;
if
(
auto
*
RE
=
dyn_cast
<
RISCVMCExpr
>
(
Expr
)
)
{
IsConstant
=
RE
->
evaluateAsConstant
(
Imm
)
;
}
else
if
(
auto
*
CE
=
dyn_cast
<
MCConstantExpr
>
(
Expr
)
)
{
IsConstant
=
true
;
Imm
=
CE
->
getValue
(
)
;
}
if
(
IsConstant
)
Inst
.
addOperand
(
MCOperand
::
createImm
(
Imm
)
)
;
else
Inst
.
addOperand
(
MCOperand
::
createExpr
(
Expr
)
)
;
}
</s>


<s> static int riscv_integer_cost ( HOST_WIDE_INT val ) { struct riscv_integer_op codes [ RISCV_MAX_INTEGER_OPS ] ; return MIN ( riscv_build_integer ( codes , val , VOIDmode ) , riscv_split_integer_cost ( val ) ) ; } </s>

Return the cost of constructing the integer constant VAL .


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

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


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

Insert a custom frame for outlined functions .


<s> const RISCVSubtarget * RISCVTargetMachine :: getSubtargetImpl ( const Function & F ) const { Attribute CPUAttr = F . getFnAttribute ( "target-cpu" ) ; Attribute FSAttr = F . getFnAttribute ( "target-features" ) ; std :: string CPU = ! CPUAttr . hasAttribute ( Attribute :: None ) ? CPUAttr . getValueAsString ( ) . str ( ) : TargetCPU ; std :: string FS = ! FSAttr . hasAttribute ( Attribute :: None ) ? FSAttr . getValueAsString ( ) . str ( ) : TargetFS ; std :: string Key = CPU + FS ; auto & I = SubtargetMap [ Key ] ; if ( ! I ) { resetTargetOptions ( F ) ; I = std :: make_unique < RISCVSubtarget > ( TargetTriple , CPU , FS , Options . MCOptions . getABIName ( ) , * this ) ; } return I . get ( ) ; } </s>

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

RISCV RISCV RISCV "target-cpu" "target-features" RISCV


<s> static section * riscv_select_section ( tree decl , int reloc , unsigned HOST_WIDE_INT align ) { switch ( categorize_decl_for_section ( decl , reloc ) ) { case SECCAT_SRODATA : return get_named_section ( decl , ".srodata" , reloc ) ; default : return default_elf_select_section ( decl , reloc , align ) ; } } </s>

Switch to the appropriate section for output of DECL .


Return a register that is zero iff CMP0 and CMP1 are equal . The register will have the same mode as CMP0 .


<s>
SDValue
RISCVTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
case
ISD
::
RETURNADDR
:
return
lowerRETURNADDR
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
lowerSELECT_CC
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
lowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
lowerGlobalTLSAddress
(
cast
<
GlobalAddressSDNode
>
(
Op
)
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
lowerBlockAddress
(
cast
<
BlockAddressSDNode
>
(
Op
)
,
DAG
)
;
case
ISD
::
JumpTable
:
return
lowerJumpTable
(
cast
<
JumpTableSDNode
>
(
Op
)
,
DAG
)
;
case
ISD
::
ConstantPool
:
return
lowerConstantPool
(
cast
<
ConstantPoolSDNode
>
(
Op
)
,
DAG
)
;
case
ISD
::
VASTART
:
return
lowerVASTART
(
Op
,
DAG
)
;
case
ISD
::
VAARG
:
return
lowerVAARG
(
Op
,
DAG
)
;
case
ISD
::
ATOMIC_FENCE
:
return
lowerATOMIC_FENCE
(
Op
,
DAG
)
;
case
ISD
::
STACKSAVE
:
return
lowerSTACKSAVE
(
Op
,
DAG
)
;
case
ISD
::
STACKRESTORE
:
return
lowerSTACKRESTORE
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
lowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
ADD
:
return
lowerADD
(
Op
,
DAG
)
;
default
:
llvm_unreachable
(
"Unexpected node to lower"
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .

RISCV
RISCV
ISD::RETURNADDR
ISD::SELECT_CC
ISD::GlobalAddress
ISD::GlobalTLSAddress
ISD::BlockAddress
ISD::JumpTable
ISD::ConstantPool
ISD::VASTART
ISD::VAARG
ISD::ATOMIC_FENCE
ISD::STACKSAVE
ISD::STACKRESTORE
ISD::FRAMEADDR
ISD::ADD
"Unexpected node to lower"


<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 ) ; auto ParseResult = RISCVFeatures :: parseFeatureBits ( STI . hasFeature ( RISCV :: Feature64Bit ) , STI . getFeatureBits ( ) ) ; if ( ! ParseResult ) { report_fatal_error ( ParseResult . takeError ( ) ) ; } else { auto & ISAInfo = * ParseResult ; emitTextAttribute ( RISCVAttrs :: ARCH , ISAInfo -> toString ( ) ) ; } } </s>

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


<s> void pass_vsetvl :: emit_local_forward_vsetvls ( const bb_info * bb ) { auto & block_info = m_vector_manager -> vector_block_infos [ bb -> index ( ) ] ; if ( block_info . local_dem . empty_p ( ) ) return ; vector_insn_info curr_info ; for ( insn_info * insn : bb -> real_nondebug_insns ( ) ) { const vector_insn_info prev_info = curr_info ; enum vsetvl_type type = NUM_VSETVL_TYPE ; transfer_before ( curr_info , insn ) ; if ( has_vtype_op ( insn -> rtl ( ) ) ) { if ( static_cast < const vl_vtype_info & > ( prev_info ) != static_cast < const vl_vtype_info & > ( curr_info ) ) { const auto require = m_vector_manager -> vector_insn_infos [ insn -> uid ( ) ] ; if ( ! require . compatible_p ( static_cast < const vl_vtype_info & > ( prev_info ) ) ) type = insert_vsetvl ( EMIT_BEFORE , insn -> rtl ( ) , require , prev_info ) ; } } if ( type == VSETVL_VTYPE_CHANGE_ONLY ) { curr_info . set_avl_info ( prev_info . get_avl_info ( ) ) ; } transfer_after ( curr_info , insn ) ; } block_info . reaching_out = curr_info ; } </s>

Emit vsetvl within each block by forward data-flow analysis .


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

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


<s> 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_FUNCTION_CODE ( fndecl ) ; const struct riscv_builtin_description * d = & riscv_builtins [ fcode ] ; switch ( d -> builtin_type ) { case RISCV_BUILTIN_DIRECT : return riscv_expand_builtin_direct ( d -> icode , target , exp , true ) ; case RISCV_BUILTIN_DIRECT_NO_TARGET : return riscv_expand_builtin_direct ( d -> icode , target , exp , false ) ; } gcc_unreachable ( ) ; } </s>


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

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


<s> void RISCVFrameLowering :: emitPrologue ( MachineFunction & MF , MachineBasicBlock & MBB ) const { } </s>

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


<s> inline machine_mode function_checker :: ret_mode ( ) const { return TYPE_MODE ( TREE_TYPE ( TREE_TYPE ( fndecl ) ) ) ; } </s>

Return the machine_mode of the corresponding return type .


Given the pattern ( X & ( C l > > / < < Y ) ) ==/ ! = 0 return true if it should be transformed into : ( ( X < < /l > > Y ) & C ) ==/ ! = 0 WARNING : if ' X ' is a constant , the fold may deadlock ! FIXME : we could avoid passing XC , but we ca n't use isConstOrConstSplat ( ) here because it can end up being not linked in .


<s>
const
MCPhysReg
*
RISCVRegisterInfo
::
getCalleeSavedRegs
(
const
MachineFunction
*
MF
)
const
{
auto
&
Subtarget
=
MF
->
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
MF
->
getFunction
(
)
.
hasFnAttribute
(
"interrupt"
)
)
{
if
(
Subtarget
.
hasStdExtD
(
)
)
return
CSR_XLEN_F64_Interrupt_SaveList
;
if
(
Subtarget
.
hasStdExtF
(
)
)
return
CSR_XLEN_F32_Interrupt_SaveList
;
return
CSR_Interrupt_SaveList
;
if
(
Subtarget
.
hasStdExtV
(
)
)
return
CSR_XLEN_F32_VEC_Interrupt_SaveList
;
return
CSR_Interrupt_SaveList
;
}
if
(
MF
->
getSubtarget
<
RISCVSubtarget
>
(
)
.
hasStdExtV
(
)
)
return
CSR_ILP32F_LP64F_VEC_SaveList
;
switch
(
Subtarget
.
getTargetABI
(
)
)
{
default
:
llvm_unreachable
(
"Unrecognized ABI"
)
;
case
RISCVABI
::
ABI_ILP32
:
case
RISCVABI
::
ABI_LP64
:
return
CSR_ILP32_LP64_SaveList
;
case
RISCVABI
::
ABI_ILP32F
:
case
RISCVABI
::
ABI_LP64F
:
return
CSR_ILP32F_LP64F_SaveList
;
case
RISCVABI
::
ABI_ILP32D
:
case
RISCVABI
::
ABI_LP64D
:
return
CSR_ILP32D_LP64D_SaveList
;
}
}
</s>


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

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


"function attributes %qs and %qs are mutually exclusive"

Sanity cheching for above function attributes .


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

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


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

RISCV RISCV RISCV "riscv-call" "riscv-plt" "riscv-lo" "riscv-hi" "riscv-pcrel-lo" "riscv-pcrel-hi" "riscv-got-hi" "riscv-tprel-lo" "riscv-tprel-hi" "riscv-tprel-add" "riscv-tls-got-hi" "riscv-tls-gd-hi"


"instruction use requires an option to be enabled"

"immediate must be a multiple of 2 bytes in the range"

"operand must be formed of letters selected in-order from 'iorw'"

MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst and emit it to the specified MCStreamer .


<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 ) ; } 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 .


"Can't store this register to stack slot"

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


<s> static bool classof ( const RISCVMCExpr * ) { return true ; } </s>

Methods for support type inquiry through isa , cast , and dyn_cast :


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

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


<s> bool RISCVTargetLowering :: allowsMisalignedMemoryAccesses ( EVT VT , unsigned AddrSpace , Align Alignment , MachineMemOperand :: Flags Flags , bool * Fast ) const { if ( ! VT . isVector ( ) ) { if ( Fast ) * Fast = false ; return Subtarget . enableUnalignedScalarMem ( ) ; } 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>
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"
;
}
}
</s>

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

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


Implement TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P - return TRUE if MODE is HFmode , and punt to the generic implementation otherwise .


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

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


<s> bool riscv_store_data_bypass_p ( rtx_insn * out_insn , rtx_insn * in_insn ) { rtx out_set , in_set ; rtx out_pat , in_pat ; rtx out_exp , in_exp ; int i , j ; in_set = single_set ( in_insn ) ; if ( in_set ) { if ( MEM_P ( SET_DEST ( in_set ) ) ) { out_set = single_set ( out_insn ) ; if ( ! out_set ) { out_pat = PATTERN ( out_insn ) ; if ( GET_CODE ( out_pat ) == PARALLEL ) { for ( i = 0 ; i < XVECLEN ( out_pat , 0 ) ; i ++ ) { out_exp = XVECEXP ( out_pat , 0 , i ) ; if ( ( GET_CODE ( out_exp ) == CLOBBER ) || ( GET_CODE ( out_exp ) == USE ) ) continue ; else if ( GET_CODE ( out_exp ) != SET ) return false ; } } } } } else { in_pat = PATTERN ( in_insn ) ; if ( GET_CODE ( in_pat ) != PARALLEL ) return false ; for ( i = 0 ; i < XVECLEN ( in_pat , 0 ) ; i ++ ) { in_exp = XVECEXP ( in_pat , 0 , i ) ; if ( ( GET_CODE ( in_exp ) == CLOBBER ) || ( GET_CODE ( in_exp ) == USE ) ) continue ; else if ( GET_CODE ( in_exp ) != SET ) return false ; if ( MEM_P ( SET_DEST ( in_exp ) ) ) { out_set = single_set ( out_insn ) ; if ( ! out_set ) { out_pat = PATTERN ( out_insn ) ; if ( GET_CODE ( out_pat ) != PARALLEL ) return false ; for ( j = 0 ; j < XVECLEN ( out_pat , 0 ) ; j ++ ) { out_exp = XVECEXP ( out_pat , 0 , j ) ; if ( ( GET_CODE ( out_exp ) == CLOBBER ) || ( GET_CODE ( out_exp ) == USE ) ) continue ; else if ( GET_CODE ( out_exp ) != SET ) return false ; } } } } } return store_data_bypass_p ( out_insn , in_insn ) ; } </s>

Given that there exists at least one variable that is set ( produced ) by OUT_INSN and read ( consumed ) by IN_INSN , return true iff IN_INSN represents one or more memory store operations and none of the variables set by OUT_INSN is used by IN_INSN as the address of a store operation . If either IN_INSN or OUT_INSN does not represent a `` single '' RTL SET expression ( as loosely defined by the implementation of the single_set function ) or a PARALLEL with only SETs , CLOBBERs , and USEs inside , this function returns false . Borrowed from rs6000 , riscv_store_data_bypass_p checks for certain conditions that result in assertion failures in the generic store_data_bypass_p function and returns FALSE in such cases . This is required to make -msave-restore work with the sifive-7 pipeline description .


Implement TARGET_MODES_TIEABLE_P . Do n't allow floating-point modes to be tied , since type punning of single-precision and double-precision is implementation defined .


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


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

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


<s> bool RISCVTargetLowering :: isFMAFasterThanFMulAndFAdd ( const MachineFunction & MF , EVT VT ) const { VT = VT . getScalarType ( ) ; if ( ! VT . isSimple ( ) ) return false ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { case MVT :: f16 : return Subtarget . hasStdExtZfh ( ) ; case MVT :: f32 : return Subtarget . hasStdExtF ( ) ; case MVT :: f64 : return Subtarget . hasStdExtD ( ) ; default : break ; } return false ; } </s>

Return true if an FMA operation is faster than a pair of fmul and fadd instructions .


<s> bool RISCVTargetLowering :: isCheapToSpeculateCtlz ( ) const { return Subtarget . hasStdExtZbb ( ) ; } </s>

Return true if it is cheap to speculate a call to intrinsic ctlz .


<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
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCCALLReg
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCCALL
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCTAIL
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCJump
)
{
expandFunctionCall
(
MI
,
OS
,
Fixups
,
STI
)
;
MCNumEmitted
+=
2
;
return
;
}
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoAddTPRel
)
{
expandAddTPRel
(
MI
,
OS
,
Fixups
,
STI
)
;
MCNumEmitted
+=
1
;
return
;
}
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCIncOffsetTPRel
)
{
expandCIncOffsetTPRel
(
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
RISCV::PseudoCCALLReg
RISCV::PseudoCCALL
RISCV::PseudoCTAIL
RISCV::PseudoCJump
2
RISCV::PseudoAddTPRel
1
RISCV::PseudoCIncOffsetTPRel
1
"Unhandled encodeInstruction length!"
2
support::endian
support::little
4
support::endian
support::little


<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 ) ; if ( epilogue_cfa_sp_offset && REGNO ( reg ) == HARD_FRAME_POINTER_REGNUM ) { rtx cfa_adjust_rtx = gen_rtx_PLUS ( Pmode , stack_pointer_rtx , GEN_INT ( epilogue_cfa_sp_offset ) ) ; dwarf = alloc_reg_note ( REG_CFA_DEF_CFA , cfa_adjust_rtx , dwarf ) ; } REG_NOTES ( insn ) = dwarf ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } </s>


"The number of element should not be zero."

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


<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 ) ) ) { int RegScavFI = MFI . CreateStackObject ( RegInfo -> getSpillSize ( * RC ) , RegInfo -> getSpillAlignment ( * RC ) , false ) ; RS -> addScavengingFrameIndex ( RegScavFI ) ; } } </s>

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


<s> bool RISCVTargetLowering :: isSExtCheaperThanZExt ( EVT SrcVT , EVT DstVT ) const { return Subtarget . is64Bit ( ) && SrcVT == MVT :: i32 && DstVT == MVT :: i64 ; } </s>

Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension .


<s> bool get_ta ( ) const { return m_ta ; } </s>

Get ta according to operand [ tail_op_idx ] .


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


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

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


"ABI for flattened struct with zero-length "

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


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

Returns how or if MIT should be outlined .


<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 :: BFPW : case RISCVISD :: FCVT_W_RV64 : case RISCVISD :: FCVT_WU_RV64 : case RISCVISD :: STRICT_FCVT_W_RV64 : case RISCVISD :: STRICT_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 : { unsigned XLen = Subtarget . getXLen ( ) ; unsigned EltBits = Op . getOperand ( 0 ) . getScalarValueSizeInBits ( ) ; if ( EltBits <= XLen ) return XLen - EltBits + 1 ; break ; } } return 1 ; } </s>

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


<s> static unsigned get_sew ( machine_mode mode ) { unsigned int sew = GET_MODE_CLASS ( mode ) == MODE_VECTOR_BOOL ? 8 : GET_MODE_BITSIZE ( GET_MODE_INNER ( mode ) ) ; return sew ; } </s>

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


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

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


<s> static inline VConstraintType getConstraint ( uint64_t TSFlags ) { return static_cast < VConstraintType > ( ( TSFlags & ConstraintMask ) >> ConstraintShift ) ; } </s>

Fetch condition in the form of PredicateConstraint , if possible .


<s> static int riscv_immediate_operand_p ( int code , HOST_WIDE_INT x ) { switch ( code ) { case ASHIFT : case ASHIFTRT : case LSHIFTRT : return true ; case AND : case IOR : case XOR : case PLUS : case LT : case LTU : return SMALL_OPERAND ( x ) ; case LE : return SMALL_OPERAND ( x + 1 ) ; case LEU : return SMALL_OPERAND ( x + 1 ) && x + 1 != 0 ; case GE : case GEU : return x == 1 ; default : return x == 0 ; } } </s>

Return true if there is an instruction that implements CODE and accepts X as an immediate operand .


"could not find corresponding %pcrel_hi"


"Can't store this register to stack slot"

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


<s> static SDValue getAllOnesMask ( MVT VecVT , SDValue VL , SDLoc DL , SelectionDAG & DAG ) { MVT MaskVT = getMaskTypeFor ( VecVT ) ; return DAG . getNode ( RISCVISD :: VMSET_VL , DL , MaskVT , VL ) ; } </s>

Return an all true boolean vector ( mask ) with NumElts lanes .


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

This method should install an IR translator pass , which converts from LLVM code to machine instructions with possibly generic opcodes .


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

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