<s>
SDValue
RISCVTargetLowering
::
LowerFormalArguments
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
InputArg
>
&
Ins
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDValue
>
&
InVals
)
const
{
switch
(
CallConv
)
{
default
:
report_fatal_error
(
"Unsupported calling convention"
)
;
case
CallingConv
::
C
:
case
CallingConv
::
Fast
:
break
;
}
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
EVT
PtrVT
=
getPointerTy
(
DAG
.
getDataLayout
(
)
)
;
if
(
IsVarArg
)
report_fatal_error
(
"VarArg not supported"
)
;
SmallVector
<
CCValAssign
,
16
>
ArgLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
ArgLocs
,
*
DAG
.
getContext
(
)
)
;
analyzeInputArgs
(
MF
,
CCInfo
,
Ins
,
false
)
;
for
(
unsigned
i
=
0
,
e
=
ArgLocs
.
size
(
)
;
i
!=
e
;
++
i
)
{
CCValAssign
&
VA
=
ArgLocs
[
i
]
;
assert
(
VA
.
getLocVT
(
)
==
Subtarget
.
getXLenVT
(
)
&&
"Unhandled argument type"
)
;
SDValue
ArgValue
;
if
(
VA
.
isRegLoc
(
)
)
ArgValue
=
unpackFromRegLoc
(
DAG
,
Chain
,
VA
,
DL
)
;
else
ArgValue
=
unpackFromMemLoc
(
DAG
,
Chain
,
VA
,
DL
)
;
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
Indirect
)
{
InVals
.
push_back
(
DAG
.
getLoad
(
VA
.
getValVT
(
)
,
DL
,
Chain
,
ArgValue
,
MachinePointerInfo
(
)
)
)
;
unsigned
ArgIndex
=
Ins
[
i
]
.
OrigArgIndex
;
assert
(
Ins
[
i
]
.
PartOffset
==
0
)
;
while
(
i
+
1
!=
e
&&
Ins
[
i
+
1
]
.
OrigArgIndex
==
ArgIndex
)
{
CCValAssign
&
PartVA
=
ArgLocs
[
i
+
1
]
;
unsigned
PartOffset
=
Ins
[
i
+
1
]
.
PartOffset
;
SDValue
Address
=
DAG
.
getNode
(
ISD
::
ADD
,
DL
,
PtrVT
,
ArgValue
,
DAG
.
getIntPtrConstant
(
PartOffset
,
DL
)
)
;
InVals
.
push_back
(
DAG
.
getLoad
(
PartVA
.
getValVT
(
)
,
DL
,
Chain
,
Address
,
MachinePointerInfo
(
)
)
)
;
++
i
;
}
continue
;
}
InVals
.
push_back
(
ArgValue
)
;
}
return
Chain
;
}
</s>

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


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

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


<s> std :: pair < unsigned , const TargetRegisterClass * > RISCVTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'r' : return std :: make_pair ( 0U , & RISCV :: GPRRegClass ) ; default : break ; } } return TargetLowering :: getRegForInlineAsmConstraint ( TRI , Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<s> void function_builder :: append_name ( const char * name ) { obstack_grow ( & m_string_obstack , name , strlen ( name ) ) ; } </s>

Add NAME to the end of the function name being built .


<s> inline machine_mode function_checker :: arg_mode ( unsigned int argno ) const { return TYPE_MODE ( TREE_TYPE ( m_args [ argno ] ) ) ; } </s>

Return the machine_mode of the corresponding arg type .


"Can't load this register from stack slot"

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


<s> unsigned RISCVAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned Kind ) { RISCVOperand & Op = static_cast < RISCVOperand & > ( AsmOp ) ; if ( ! Op . isReg ( ) ) return Match_InvalidOperand ; unsigned Reg = Op . getReg ( ) ; bool IsRegFPR32 = RISCVMCRegisterClasses [ RISCV :: FPR32RegClassID ] . contains ( Reg ) ; bool IsRegFPR32C = RISCVMCRegisterClasses [ RISCV :: FPR32CRegClassID ] . contains ( Reg ) ; if ( ( IsRegFPR32 && Kind == MCK_FPR64 ) || ( IsRegFPR32C && Kind == MCK_FPR64C ) ) { Op . Reg . RegNum = convertFPR32ToFPR64 ( Reg ) ; return Match_Success ; } return Match_InvalidOperand ; } </s>

Allow a target to add special case operand matching for things that tblgen doesn't/ca n't handle effectively .

RISCV RISCV RISCV RISCV RISCV RISCV::FPR32RegClassID RISCV RISCV::FPR32CRegClassID


<s> static bool riscv_vector_mode_supported_p ( machine_mode mode ) { if ( TARGET_VECTOR ) return riscv_v_ext_vector_mode_p ( mode ) ; return false ; } </s>


<s> InstructionCost RISCVTTIImpl :: getMinMaxReductionCost ( VectorType * Ty , VectorType * CondTy , bool IsUnsigned , TTI :: TargetCostKind CostKind ) { if ( ! isa < FixedVectorType > ( Ty ) ) return BaseT :: getMinMaxReductionCost ( Ty , CondTy , IsUnsigned , CostKind ) ; if ( ! ST -> useRVVForFixedLengthVectors ( ) ) return BaseT :: getMinMaxReductionCost ( Ty , CondTy , IsUnsigned , CostKind ) ; if ( Ty -> getScalarSizeInBits ( ) > ST -> getELEN ( ) ) return BaseT :: getMinMaxReductionCost ( Ty , CondTy , IsUnsigned , CostKind ) ; InstructionCost BaseCost = 2 ; unsigned VL = cast < FixedVectorType > ( Ty ) -> getNumElements ( ) ; std :: pair < InstructionCost , MVT > LT = TLI -> getTypeLegalizationCost ( DL , Ty ) ; return ( LT . first - 1 ) + BaseCost + Log2_32_Ceil ( VL ) ; } </s>

Try to calculate op costs for min/max reduction operations .


<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 3 ; } if ( ! riscv_v_ext_vector_mode_p ( mode ) && mode != BLKmode && might_split_p ) n += ( GET_MODE_SIZE ( mode ) . to_constant ( ) + 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>
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
{
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
SmallVector
<
CCValAssign
,
16
>
RetLocs
;
CCState
RetCCInfo
(
CallConv
,
IsVarArg
,
MF
,
RetLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
Subtarget
.
isRV64
(
)
)
RetCCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_RISCV64
)
;
else
RetCCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_RISCV32
)
;
SDValue
Glue
;
if
(
RetLocs
.
empty
(
)
)
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
Chain
)
;
SmallVector
<
SDValue
,
4
>
RetOps
;
RetOps
.
push_back
(
Chain
)
;
for
(
unsigned
I
=
0
,
E
=
RetLocs
.
size
(
)
;
I
!=
E
;
++
I
)
{
CCValAssign
&
VA
=
RetLocs
[
I
]
;
SDValue
RetValue
=
OutVals
[
I
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
RetValue
=
convertValVTToLocVT
(
DAG
,
DL
,
VA
,
RetValue
)
;
unsigned
Reg
=
VA
.
getLocReg
(
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
Reg
,
RetValue
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
Reg
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Glue
.
getNode
(
)
)
RetOps
.
push_back
(
Glue
)
;
return
DAG
.
getNode
(
RISCVISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

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


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

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


<s> gimple * gimple_fold_builtin ( unsigned int code , gimple_stmt_iterator * gsi , gcall * stmt ) { registered_function & rfn = * ( * registered_functions ) [ code ] ; return gimple_folder ( rfn . instance , rfn . decl , gsi , stmt ) . fold ( ) ; } </s>

Attempt to fold STMT , given that it 's a call to the SVE function with subcode CODE . Return the new statement on success and null on failure . Insert any other new statements at GSI .


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

Load VALUE into DEST . TEMP is as for riscv_force_temporary .


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

LowerOperation - Provide custom lowering hooks for some operations .


<s> unsigned int pass_shorten_memrefs :: execute ( function * fn ) { basic_block bb ; FOR_ALL_BB_FN ( bb , fn ) { regno_map * m ; if ( optimize_bb_for_speed_p ( bb ) ) continue ; m = analyze ( bb ) ; transform ( m , bb ) ; } return 0 ; } </s>


"emitEpilogue doesn't support framepointer-less functions"


<s> bool RISCVTargetMachine :: isNoopAddrSpaceCast ( unsigned SrcAS , unsigned DstAS ) const { return true ; } </s>

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


<s> unsigned RISCVAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned Kind ) { RISCVOperand & Op = static_cast < RISCVOperand & > ( AsmOp ) ; if ( ! Op . isReg ( ) ) return Match_InvalidOperand ; Register Reg = Op . getReg ( ) ; bool IsRegFPR64 = RISCVMCRegisterClasses [ RISCV :: FPR64RegClassID ] . contains ( Reg ) ; bool IsRegFPR64C = RISCVMCRegisterClasses [ RISCV :: FPR64CRegClassID ] . contains ( Reg ) ; if ( ( IsRegFPR64 && Kind == MCK_FPR32 ) || ( IsRegFPR64C && Kind == MCK_FPR32C ) ) { Op . Reg . RegNum = convertFPR64ToFPR32 ( Reg ) ; return Match_Success ; } return Match_InvalidOperand ; } </s>

RISCV RISCV RISCV RISCV RISCV RISCV::FPR64RegClassID RISCV RISCV::FPR64CRegClassID


<s> void RISCVELFTargetObjectFile :: getModuleMetadata ( Module & M ) { TargetLoweringObjectFileELF :: getModuleMetadata ( M ) ; SmallVector < Module :: ModuleFlagEntry , 8 > ModuleFlags ; M . getModuleFlagsMetadata ( ModuleFlags ) ; for ( const auto & MFE : ModuleFlags ) { StringRef Key = MFE . Key -> getString ( ) ; if ( Key == "SmallDataLimit" ) { SSThreshold = mdconst :: extract < ConstantInt > ( MFE . Val ) -> getZExtValue ( ) ; break ; } } } </s>

Get the module-level metadata that the platform cares about .


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

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


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

"READCYCLECOUNTER only has custom type legalization on riscv32"

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


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

ParseInstruction - Parse one assembly instruction .

RISCV
RISCV
RISCV
0
1
"unexpected token"


<s>
bool
RISCVInstrInfo
::
isBranch
(
const
MachineInstr
*
MI
,
SmallVectorImpl
<
MachineOperand
>
&
Cond
,
const
MachineOperand
*
&
Target
)
const
{
switch
(
MI
->
getOpcode
(
)
)
{
case
RISCV
::
J
:
case
RISCV
::
J64
:
case
RISCV
::
JAL
:
case
RISCV
::
JAL64
:
case
RISCV
::
JALR
:
case
RISCV
::
JALR64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_ANY
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BEQ
:
case
RISCV
::
BEQ64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_EQ
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BNE
:
case
RISCV
::
BNE64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_NE
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BLT
:
case
RISCV
::
BLT64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_LT
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BLTU
:
case
RISCV
::
BLTU64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_LT
|
RISCV
::
CCMASK_CMP_UO
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BGE
:
case
RISCV
::
BGE64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_GE
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BGEU
:
case
RISCV
::
BGEU64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_GE
|
RISCV
::
CCMASK_CMP_UO
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BGT
:
case
RISCV
::
BGT64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_GT
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BGTU
:
case
RISCV
::
BGTU64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_GT
|
RISCV
::
CCMASK_CMP_UO
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BLE
:
case
RISCV
::
BLE64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_LE
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
case
RISCV
::
BLEU
:
case
RISCV
::
BLEU64
:
Cond
[
0
]
.
setImm
(
RISCV
::
CCMASK_CMP_LE
|
RISCV
::
CCMASK_CMP_UO
)
;
Target
=
&
MI
->
getOperand
(
0
)
;
return
true
;
default
:
assert
(
!
MI
->
getDesc
(
)
.
isBranch
(
)
&&
"Unknown branch opcode"
)
;
return
false
;
}
}
</s>

Returns true if this is a conditional , unconditional , or indirect branch .


<s> bool RISCVCallLowering :: lowerReturn ( MachineIRBuilder & MIRBuilder , const Value * Val , ArrayRef < Register > VRegs , FunctionLoweringInfo & FLI ) 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> static inline unsigned getFormat ( uint64_t TSFlags ) { return ( TSFlags & InstFormatMask ) >> InstFormatShift ; } </s>


<s> static bool riscv_pass_by_reference ( cumulative_args_t cum_v , enum machine_mode mode , const_tree type , bool named ) { HOST_WIDE_INT size = type ? int_size_in_bytes ( type ) : GET_MODE_SIZE ( mode ) ; struct riscv_arg_info info ; CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; if ( cum != NULL ) { riscv_get_arg_info ( & info , cum , mode , type , named , false ) ; if ( info . num_fprs ) return false ; } return ! IN_RANGE ( size , 0 , 2 * UNITS_PER_WORD ) ; } </s>


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


<s> static unsigned int riscv_function_arg_boundary ( machine_mode mode , const_tree type ) { unsigned int alignment ; if ( type && ! AGGREGATE_TYPE_P ( type ) ) alignment = TYPE_ALIGN ( TYPE_MAIN_VARIANT ( type ) ) ; else alignment = type ? TYPE_ALIGN ( type ) : GET_MODE_ALIGNMENT ( mode ) ; return MIN ( PREFERRED_STACK_BOUNDARY , MAX ( PARM_BOUNDARY , alignment ) ) ; } </s>

Implement TARGET_FUNCTION_ARG_BOUNDARY . Every parameter gets at least PARM_BOUNDARY bits of alignment , but will be given anything up to STACK_BOUNDARY bits if the type requires it .


<s> bool RISCVAsmBackend :: fixupNeedsRelaxation ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout ) const { int64_t Offset = int64_t ( Value ) ; switch ( ( unsigned ) Fixup . getKind ( ) ) { default : return false ; case RISCV :: fixup_riscv_rvc_branch : return Offset > 254 || Offset < - 256 ; case RISCV :: fixup_riscv_rvc_jump : return Offset > 2046 || Offset < - 2048 ; } } </s>

Simple predicate for targets where ! Resolved implies requiring relaxation .


<s> static void riscv_set_current_function ( tree decl ) { if ( decl == NULL_TREE || current_function_decl == NULL_TREE || current_function_decl == error_mark_node || ! cfun -> machine ) return ; cfun -> machine -> naked_p = riscv_naked_function_p ( decl ) ; } </s>

Sanity cheching for above function attributes .


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


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

getTargetNodeName - This method returns the name of a target specific


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

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


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


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

Print the specified MCInst to the specified raw_ostream .


<s> bool RISCVRegisterInfo :: hasReservedSpillSlot ( const MachineFunction & MF , Register Reg , int & FrameIdx ) const { const auto * RVFI = MF . getInfo < RISCVMachineFunctionInfo > ( ) ; if ( ! RVFI -> useSaveRestoreLibCalls ( MF ) ) return false ; const auto * FII = llvm :: find_if ( FixedCSRFIMap , [ & ] ( auto P ) { return P . first == Reg ; } ) ; if ( FII == std :: end ( FixedCSRFIMap ) ) 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>
void
RISCVInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MBBI
,
const
DebugLoc
&
DL
,
MCRegister
DstReg
,
MCRegister
SrcReg
,
bool
KillSrc
)
const
{
if
(
RISCV
::
GPRRegClass
.
contains
(
DstReg
,
SrcReg
)
)
{
BuildMI
(
MBB
,
MBBI
,
DL
,
get
(
RISCV
::
ADDI
)
,
DstReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addImm
(
0
)
;
return
;
}
unsigned
Opc
;
if
(
RISCV
::
FPR32RegClass
.
contains
(
DstReg
,
SrcReg
)
)
Opc
=
RISCV
::
FSGNJ_S
;
else
if
(
RISCV
::
FPR64RegClass
.
contains
(
DstReg
,
SrcReg
)
)
Opc
=
RISCV
::
FSGNJ_D
;
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
BuildMI
(
MBB
,
MBBI
,
DL
,
get
(
Opc
)
,
DstReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
</s>


<s> Value * RISCVTargetLowering :: emitMaskedAtomicRMWIntrinsic ( IRBuilderBase & Builder , AtomicRMWInst * AI , Value * AlignedAddr , Value * Incr , Value * Mask , Value * ShiftAmt , AtomicOrdering Ord ) const { assert ( ! RISCVABI :: isCheriPureCapABI ( Subtarget . getTargetABI ( ) ) ) ; 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 .

RISCV RISCV RISCVABI::isCheriPureCapABI Intrinsic::getDeclaration 64 64


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

Encode the given Inst to bytes and append to CB .

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


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

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


<s> bool enableMachineScheduler ( ) const override { return true ; } </s>

Enable the MachineScheduler pass for all X86 subtargets .


<s> TargetLowering :: ConstraintType RISCVTargetLowering :: getConstraintType ( StringRef Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'a' : case 'd' : case 'f' : case 'r' : return C_RegisterClass ; case 'Q' : case 'R' : case 'S' : case 'T' : case 'm' : return C_Memory ; case 'I' : case 'J' : case 'K' : case 'L' : case 'M' : return C_Other ; default : break ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

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


<s> SDValue RISCVTargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { switch ( N -> getOpcode ( ) ) { default : break ; case RISCVISD :: SplitF64 : { SDValue Op0 = N -> getOperand ( 0 ) ; if ( Op0 -> getOpcode ( ) != RISCVISD :: BuildPairF64 ) break ; return DCI . CombineTo ( N , Op0 . getOperand ( 0 ) , Op0 . getOperand ( 1 ) ) ; } } return SDValue ( ) ; } </s>

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


<s> void riscv_atomic_assign_expand_fenv ( tree * hold , tree * clear , tree * update ) { if ( ! TARGET_HARD_FLOAT ) return ; tree frflags = GET_BUILTIN_DECL ( CODE_FOR_riscv_frflags ) ; tree fsflags = GET_BUILTIN_DECL ( CODE_FOR_riscv_fsflags ) ; tree old_flags = create_tmp_var_raw ( RISCV_ATYPE_USI ) ; * hold = build4 ( TARGET_EXPR , RISCV_ATYPE_USI , old_flags , build_call_expr ( frflags , 0 ) , NULL_TREE , NULL_TREE ) ; * clear = build_call_expr ( fsflags , 1 , old_flags ) ; * update = NULL_TREE ; } </s>


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

This method must be overriden to eliminate abstract frame indices from instructions which may use them .


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"RISCV RI5CY IR pass"
;
}
</s>

getPassName - Return a nice clean name for a pass .


"eliminateFrameIndex currently requires hasFP"

"Frame offsets outside of the signed 12-bit range not supported"


"RISCV DAG->DAG Pattern Instruction Selection"


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

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


<s> static bool riscv_canonicalize_int_order_test ( enum rtx_code * code , rtx * cmp1 , enum machine_mode mode ) { HOST_WIDE_INT plus_one ; if ( riscv_int_order_operand_ok_p ( * code , * cmp1 ) ) return true ; if ( CONST_INT_P ( * cmp1 ) ) switch ( * code ) { case LE : plus_one = trunc_int_for_mode ( UINTVAL ( * cmp1 ) + 1 , mode ) ; if ( INTVAL ( * cmp1 ) < plus_one ) { * code = LT ; * cmp1 = force_reg ( mode , GEN_INT ( plus_one ) ) ; return true ; } break ; case LEU : plus_one = trunc_int_for_mode ( UINTVAL ( * cmp1 ) + 1 , mode ) ; if ( plus_one != 0 ) { * code = LTU ; * cmp1 = force_reg ( mode , GEN_INT ( plus_one ) ) ; return true ; } break ; default : break ; } return false ; } </s>

Return true if * CMP1 ( of mode MODE ) is a valid second operand for integer ordering test * CODE , or if an equivalent combination can be formed by adjusting * CODE and * CMP1 . When returning true , update * CODE and * CMP1 with the chosen code and operand , otherwise leave them alone .


<s> bool shouldNormalizeToSelectSequence ( LLVMContext & , EVT ) const override { return false ; } </s>

Returns true if we should normalize select ( N0 & N1 , X , Y ) = > select ( N0 , select ( N1 , X , Y ) , Y ) and select ( N0|N1 , X , Y ) = > select ( N0 , select ( N1 , X , Y , Y ) ) if it is likely that it saves us from materializing N0 and N1 in an integer register .


<s>
bool
RISCVDAGToDAGISel
::
SelectInlineAsmMemoryOperand
(
const
SDValue
&
Op
,
unsigned
ConstraintID
,
std
::
vector
<
SDValue
>
&
OutOps
)
{
switch
(
ConstraintID
)
{
default
:
llvm_unreachable
(
"Unexpected asm memory constraint"
)
;
case
InlineAsm
::
Constraint_m
:
SDValue
Base
,
Offset
;
selectMemRegAddr
(
Op
,
Base
,
Offset
)
;
OutOps
.
push_back
(
Base
)
;
OutOps
.
push_back
(
Offset
)
;
return
false
;
}
return
false
;
}
</s>

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

RISCV
RISCV
"Unexpected asm memory constraint"


<s> bool riscv_hard_regno_rename_ok ( unsigned from_regno ATTRIBUTE_UNUSED , unsigned to_regno ) { return ! cfun -> machine -> interrupt_handler_p || df_regs_ever_live_p ( to_regno ) ; } </s>

Return nonzero if register FROM_REGNO can be renamed to register TO_REGNO .


<s> unsigned RISCVAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned Kind ) { RISCVOperand & Op = static_cast < RISCVOperand & > ( AsmOp ) ; if ( ! Op . isReg ( ) ) return Match_InvalidOperand ; MCRegister Reg = Op . getReg ( ) ; bool IsRegFPR64 = RISCVMCRegisterClasses [ RISCV :: FPR64RegClassID ] . contains ( Reg ) ; bool IsRegFPR64C = RISCVMCRegisterClasses [ RISCV :: FPR64CRegClassID ] . contains ( Reg ) ; bool IsRegVR = RISCVMCRegisterClasses [ RISCV :: VRRegClassID ] . contains ( Reg ) ; if ( ( IsRegFPR64 && Kind == MCK_FPR32 ) || ( IsRegFPR64C && Kind == MCK_FPR32C ) ) { Op . Reg . RegNum = convertFPR64ToFPR32 ( Reg ) ; return Match_Success ; } if ( IsRegFPR64 && Kind == MCK_FPR16 ) { Op . Reg . RegNum = convertFPR64ToFPR16 ( Reg ) ; return Match_Success ; } if ( IsRegVR && ( Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8 ) ) { Op . Reg . RegNum = convertVRToVRMx ( * getContext ( ) . getRegisterInfo ( ) , Reg , Kind ) ; if ( Op . Reg . RegNum == 0 ) return Match_InvalidOperand ; return Match_Success ; } return Match_InvalidOperand ; } </s>

Allow a target to add special case operand matching for things that tblgen doesn't/ca n't handle effectively .

RISCV RISCV RISCV RISCV RISCV RISCV::FPR64RegClassID RISCV RISCV::FPR64CRegClassID RISCV RISCV::VRRegClassID 0


<s> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( Opcode ) { OPCODE ( RET_FLAG ) ; OPCODE ( CALL ) ; OPCODE ( PCREL_WRAPPER ) ; OPCODE ( Hi ) ; OPCODE ( Lo ) ; OPCODE ( FENCE ) ; OPCODE ( SELECT_CC ) ; OPCODE ( SMIN ) ; OPCODE ( UMIN ) ; OPCODE ( SMAX ) ; OPCODE ( UMAX ) ; } return NULL ; } </s>

getTargetNodeName - This method returns the name of a target specific


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

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


<s> static bool riscv_valid_offset_p ( rtx x , machine_mode mode ) { if ( ! const_arith_operand ( x , Pmode ) ) return false ; if ( GET_MODE_SIZE ( mode ) . to_constant ( ) > UNITS_PER_WORD && ! SMALL_OPERAND ( INTVAL ( x ) + GET_MODE_SIZE ( mode ) . to_constant ( ) - UNITS_PER_WORD ) ) return false ; return true ; } </s>

Return true if , for every base register BASE_REG , ( plus BASE_REG X ) can address a value of mode MODE .


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

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


<s> rtx expand ( function_expander & e ) const override { machine_mode mode = GET_MODE ( e . target ) ; rtx vlenb = gen_int_mode ( BYTES_PER_RISCV_VECTOR , mode ) ; emit_move_insn ( e . target , vlenb ) ; return e . target ; } </s>


<s> bool pass_vsetvl :: need_vsetvl ( const vector_insn_info & require , const vector_insn_info & curr_info ) const { if ( ! curr_info . valid_p ( ) || curr_info . unknown_p ( ) || curr_info . uninit_p ( ) ) return true ; if ( require . compatible_p ( static_cast < const vl_vtype_info & > ( curr_info ) ) ) return false ; return true ; } </s>

Return true if a dem_info is required to transition from curr_info to require before INSN .


<s>
const
uint32_t
*
RISCVRegisterInfo
::
getCallPreservedMask
(
const
MachineFunction
&
MF
,
CallingConv
::
ID
CC
)
const
{
auto
&
Subtarget
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
CC
==
CallingConv
::
GHC
)
return
CSR_NoRegs_RegMask
;
switch
(
Subtarget
.
getTargetABI
(
)
)
{
default
:
llvm_unreachable
(
"Unrecognized ABI"
)
;
case
RISCVABI
::
ABI_ILP32
:
case
RISCVABI
::
ABI_LP64
:
return
CSR_ILP32_LP64_RegMask
;
case
RISCVABI
::
ABI_IL32PC64
:
case
RISCVABI
::
ABI_L64PC128
:
return
CSR_IL32PC64_L64PC128_RegMask
;
case
RISCVABI
::
ABI_ILP32F
:
case
RISCVABI
::
ABI_LP64F
:
return
CSR_ILP32F_LP64F_RegMask
;
case
RISCVABI
::
ABI_IL32PC64F
:
case
RISCVABI
::
ABI_L64PC128F
:
return
CSR_IL32PC64F_L64PC128F_RegMask
;
case
RISCVABI
::
ABI_ILP32D
:
case
RISCVABI
::
ABI_LP64D
:
return
CSR_ILP32D_LP64D_RegMask
;
case
RISCVABI
::
ABI_IL32PC64D
:
case
RISCVABI
::
ABI_L64PC128D
:
return
CSR_IL32PC64D_L64PC128D_RegMask
;
}
}
</s>

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


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

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


<s> 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 auto * DF = dyn_cast_or_null < MCDataFragment > ( AUIPCSRE -> findAssociatedFragment ( ) ) ; if ( ! DF ) return nullptr ; const MCSymbol * AUIPCSymbol = & AUIPCSRE -> getSymbol ( ) ; for ( const MCFixup & F : DF -> getFixups ( ) ) { if ( F . getOffset ( ) != AUIPCSymbol -> getOffset ( ) ) continue ; switch ( ( unsigned ) F . getKind ( ) ) { default : continue ; 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> tree function_builder :: get_attributes ( const function_instance & instance ) { tree attrs = NULL_TREE ; if ( ! instance . modifies_global_state_p ( ) ) { if ( instance . reads_global_state_p ( ) ) attrs = add_attribute ( "pure" , attrs ) ; else attrs = add_attribute ( "const" , attrs ) ; } if ( ! flag_non_call_exceptions || ! instance . could_trap_p ( ) ) attrs = add_attribute ( "nothrow" , attrs ) ; return add_attribute ( "leaf" , attrs ) ; } </s>

Return the appropriate function attributes for INSTANCE .


<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
)
;
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
"Unexpected node to lower"


"getIntImmCost can only estimate cost of materialising integers"

Calculate the cost of materializing a 64-bit value .


"ReadCycleWrite is only to be used on riscv32"

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


"passing %wd to argument %d of %qE, which expects"

Report that LOCATION has a call to FNDECL in which argument ARGNO has the value ACTUAL , whereas the function requires a value in the range [ MIN , MAX ] . ARGNO counts from zero .


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

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


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

IsEligibleForTailCallOptimization - Check whether the call is eligible for tail call optimization .

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


<s> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( Opcode ) { OPCODE ( RET_FLAG ) ; OPCODE ( CALL ) ; OPCODE ( PCREL_WRAPPER ) ; OPCODE ( Hi ) ; OPCODE ( Lo ) ; OPCODE ( FENCE ) ; OPCODE ( SELECT_CC ) ; } return NULL ; } </s>


<s>
bool
RISCVInstrInfo
::
reverseBranchCondition
(
SmallVectorImpl
<
MachineOperand
>
&
Cond
)
const
{
assert
(
(
Cond
.
size
(
)
==
3
)
&&
"Invalid branch condition!"
)
;
auto
CC
=
static_cast
<
RISCVCC
::
CondCode
>
(
Cond
[
0
]
.
getImm
(
)
)
;
Cond
[
0
]
.
setImm
(
getOppositeBranchCondition
(
CC
)
)
;
return
false
;
}
</s>

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


<s> 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 auto * DF = dyn_cast_or_null < MCDataFragment > ( AUIPCSRE -> findAssociatedFragment ( ) ) ; if ( ! DF ) return nullptr ; const MCSymbol * AUIPCSymbol = & AUIPCSRE -> getSymbol ( ) ; for ( const MCFixup & F : DF -> getFixups ( ) ) { if ( F . getOffset ( ) != AUIPCSymbol -> getOffset ( ) ) continue ; switch ( ( unsigned ) F . getKind ( ) ) { default : continue ; case RISCV :: fixup_riscv_got_hi20 : case RISCV :: fixup_riscv_pcrel_hi20 : return & F ; } } return nullptr ; } </s>


<s>
void
RISCVDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
SDLoc
DL
(
Node
)
;
DEBUG
(
errs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
errs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
return
;
}
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
switch
(
Opcode
)
{
case
ISD
::
FrameIndex
:
{
SDValue
imm
=
CurDAG
->
getTargetConstant
(
0
,
DL
,
Subtarget
.
isRV64
(
)
MVT
::
i64
:
MVT
::
i32
)
;
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
getTargetLowering
(
)
->
getPointerTy
(
CurDAG
->
getDataLayout
(
)
)
)
;
unsigned
Opc
=
Subtarget
.
isRV64
(
)
RISCV
::
ADDI64
:
RISCV
::
ADDI
;
EVT
VT
=
Subtarget
.
isRV64
(
)
MVT
::
i64
:
MVT
::
i32
;
if
(
Node
->
hasOneUse
(
)
)
{
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
,
imm
)
;
return
;
}
ReplaceNode
(
Node
,
CurDAG
->
getMachineNode
(
Opc
,
DL
,
VT
,
TFI
,
imm
)
)
;
return
;
}
}
SelectCode
(
Node
)
;
return
;
}
</s>

Main hook for targets to transform nodes into machine nodes .


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

Returns the estimated number of registers required to represent Ty .


<s> 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 . getFeatureBits ( ) , true ) ; int ShiftedC1Cost = RISCVMatInt :: getIntMatCost ( ShiftedC1Int , Ty . getSizeInBits ( ) , Subtarget . getFeatureBits ( ) , true ) ; if ( C1Cost < ShiftedC1Cost ) return false ; } } return true ; } </s>

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


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

ParseInstruction - Parse one assembly instruction .


<s> bool RISCVCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs , FunctionLoweringInfo & FLI ) const { if ( F . arg_empty ( ) ) return true ; return false ; } </s>

This hook must be implemented to lower the incoming ( formal ) arguments , described by VRegs , for GlobalISel .


<s> const char * riscv_output_move ( rtx dest , rtx src ) { enum rtx_code dest_code , src_code ; enum machine_mode mode ; bool dbl_p ; dest_code = GET_CODE ( dest ) ; src_code = GET_CODE ( src ) ; mode = GET_MODE ( dest ) ; dbl_p = ( GET_MODE_SIZE ( mode ) == 8 ) ; if ( dbl_p && riscv_split_64bit_move_p ( dest , src ) ) return "#" ; if ( dest_code == REG && GP_REG_P ( REGNO ( dest ) ) ) { if ( src_code == REG && FP_REG_P ( REGNO ( src ) ) ) return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.s\t%0,%1" ; if ( src_code == MEM ) switch ( GET_MODE_SIZE ( mode ) ) { case 1 : return "lbu\t%0,%1" ; case 2 : return "lhu\t%0,%1" ; case 4 : return "lw\t%0,%1" ; case 8 : return "ld\t%0,%1" ; } if ( src_code == CONST_INT ) return "li\t%0,%1" ; if ( src_code == HIGH ) return "lui\t%0,%h1" ; if ( symbolic_operand ( src , VOIDmode ) ) switch ( riscv_classify_symbolic_expression ( src ) ) { case SYMBOL_GOT_DISP : return "la\t%0,%1" ; case SYMBOL_ABSOLUTE : return "lla\t%0,%1" ; case SYMBOL_PCREL : return "lla\t%0,%1" ; default : gcc_unreachable ( ) ; } } if ( ( src_code == REG && GP_REG_P ( REGNO ( src ) ) ) || ( src == CONST0_RTX ( mode ) ) ) { if ( dest_code == REG ) { if ( GP_REG_P ( REGNO ( dest ) ) ) return "mv\t%0,%z1" ; if ( FP_REG_P ( REGNO ( dest ) ) ) { if ( ! dbl_p ) return "fmv.s.x\t%0,%z1" ; if ( TARGET_64BIT ) return "fmv.d.x\t%0,%z1" ; gcc_assert ( src == CONST0_RTX ( mode ) ) ; return "fcvt.d.w\t%0,x0" ; } } if ( dest_code == MEM ) switch ( GET_MODE_SIZE ( mode ) ) { case 1 : return "sb\t%z1,%0" ; case 2 : return "sh\t%z1,%0" ; case 4 : return "sw\t%z1,%0" ; case 8 : return "sd\t%z1,%0" ; } } if ( src_code == REG && FP_REG_P ( REGNO ( src ) ) ) { if ( dest_code == REG && FP_REG_P ( REGNO ( dest ) ) ) return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1" ; if ( dest_code == MEM ) return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0" ; } if ( dest_code == REG && FP_REG_P ( REGNO ( dest ) ) ) { if ( src_code == MEM ) return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1" ; } gcc_unreachable ( ) ; } </s>

Return the appropriate instructions to move SRC into DEST . Assume that SRC is operand 1 and DEST is operand 0 .


<s> bool RISCVTargetMachine :: parseMachineFunctionInfo ( const yaml :: MachineFunctionInfo & MFI , PerFunctionMIParsingState & PFS , SMDiagnostic & Error , SMRange & SourceRange ) const { const auto & YamlMFI = static_cast < const yaml :: RISCVMachineFunctionInfo & > ( MFI ) ; PFS . MF . getInfo < RISCVMachineFunctionInfo > ( ) -> initializeBaseYamlFields ( YamlMFI ) ; return false ; } </s>

Parse out the target 's MachineFunctionInfo from the YAML reprsentation .


<s> static bool valid_sew_p ( size_t sew ) { return exact_log2 ( sew ) && sew >= 8 && sew <= 64 ; } </s>

Is this a SEW value that can be encoded into the VTYPE format .


<s>
void
RISCVFrameLowering
::
emitPrologue
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
)
const
{
assert
(
&
MF
.
front
(
)
==
&
MBB
&&
"Shrink-wrapping not yet supported"
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
auto
*
RVFI
=
MF
.
getInfo
<
RISCVMachineFunctionInfo
>
(
)
;
MachineBasicBlock
::
iterator
MBBI
=
MBB
.
begin
(
)
;
unsigned
FPReg
=
getFPReg
(
STI
)
;
unsigned
SPReg
=
getSPReg
(
STI
)
;
DebugLoc
DL
;
if
(
shouldEnableVectorUnit
(
MF
)
)
{
BuildMI
(
MBB
,
MBBI
,
DL
,
STI
.
getInstrInfo
(
)
->
get
(
RISCV
::
VCONFIG
)
)
.
addImm
(
0x60
)
;
}
determineFrameLayout
(
MF
)
;
uint64_t
StackSize
=
MFI
.
getStackSize
(
)
;
if
(
StackSize
==
0
&&
!
MFI
.
adjustsStack
(
)
)
return
;
adjustReg
(
MBB
,
MBBI
,
DL
,
SPReg
,
SPReg
,
StackSize
,
MachineInstr
::
FrameSetup
)
;
const
std
::
vector
<
CalleeSavedInfo
>
&
CSI
=
MFI
.
getCalleeSavedInfo
(
)
;
std
::
advance
(
MBBI
,
CSI
.
size
(
)
)
;
if
(
hasFP
(
MF
)
)
adjustReg
(
MBB
,
MBBI
,
DL
,
FPReg
,
SPReg
,
StackSize
RVFI
->
getVarArgsSaveSize
(
)
,
MachineInstr
::
FrameSetup
)
;
}
</s>

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

RISCV
RISCV
"Shrink-wrapping not yet supported"
RISCV
RISCV::VCONFIG
0x60
0


"Trying to obtain non-reserved register \""

Return the register ID of the name passed in .


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

getTargetNodeName - This method returns the name of a target specific


<s> static void riscv_disqualify_components ( sbitmap , edge , sbitmap , bool ) { } </s>


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

runOnMachineFunction - Emit the function body .


<s> opt_machine_mode get_vector_mode ( scalar_mode inner_mode , poly_uint64 nunits ) { enum mode_class mclass ; if ( inner_mode == E_BImode ) mclass = MODE_VECTOR_BOOL ; else if ( FLOAT_MODE_P ( inner_mode ) ) mclass = MODE_VECTOR_FLOAT ; else mclass = MODE_VECTOR_INT ; machine_mode mode ; FOR_EACH_MODE_IN_CLASS ( mode , mclass ) if ( inner_mode == GET_MODE_INNER ( mode ) && known_eq ( nunits , GET_MODE_NUNITS ( mode ) ) && riscv_v_ext_vector_mode_p ( mode ) ) return mode ; return opt_machine_mode ( ) ; } </s>

Return the RVV vector mode that has NUNITS elements of mode INNER_MODE . This function is not only used by builtins , but also will be used by auto-vectorization in the future .


<s> void init_builtins ( ) { rvv_switcher rvv ; if ( ! TARGET_VECTOR ) return ; register_builtin_types ( ) ; if ( in_lto_p ) handle_pragma_vector ( ) ; } </s>

Initialize all compiler built-ins related to RVV that should be defined at start-up .


<s> void riscv_expand_conditional_move ( rtx dest , rtx cons , rtx alt , rtx_code code , rtx op0 , rtx op1 ) { riscv_emit_int_compare ( & code , & op0 , & op1 ) ; rtx cond = gen_rtx_fmt_ee ( code , GET_MODE ( op0 ) , op0 , op1 ) ; emit_insn ( gen_rtx_SET ( dest , gen_rtx_IF_THEN_ELSE ( GET_MODE ( dest ) , cond , cons , alt ) ) ) ; } </s>

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


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


<s> bool isReg ( ) const override { return Kind == Register ; } </s>


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


<s> poly_int64 riscv_v_adjust_precision ( machine_mode mode , int scale ) { if ( riscv_v_ext_vector_mode_p ( mode ) ) return riscv_vector_chunks * scale ; return scale ; } </s>

Call from ADJUST_PRECISION in riscv-modes.def . Return the correct PRECISION size for corresponding machine_mode .


<s> static poly_uint16 riscv_convert_vector_bits ( void ) { if ( TARGET_MIN_VLEN > 32 ) { riscv_bytes_per_vector_chunk = 8 ; } else { riscv_bytes_per_vector_chunk = 4 ; } return TARGET_VECTOR ? poly_uint16 ( 1 , 1 ) : 1 ; } </s>

Return the VLEN value associated with -march . TODO : So far we only support length-agnostic value .


<s> bool RISCVRegisterInfo :: isConstantPhysReg ( MCRegister PhysReg ) const { return PhysReg == RISCV :: X0 ; } </s>

Returns true if PhysReg is unallocatable and constant throughout the function .


<s> void add_vundef_operand ( machine_mode mode ) { add_input_operand ( RVV_VUNDEF ( mode ) , mode ) ; } </s>

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


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


<s> bool RISCVAsmBackend :: writeNopData ( raw_ostream & OS , uint64_t Count ) 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> tree riscv_builtin_decl ( unsigned int code , bool initialize_p ATTRIBUTE_UNUSED ) { unsigned int subcode = code >> RISCV_BUILTIN_SHIFT ; switch ( code & RISCV_BUILTIN_CLASS ) { case RISCV_BUILTIN_GENERAL : if ( subcode >= ARRAY_SIZE ( riscv_builtins ) ) return error_mark_node ; return riscv_builtin_decls [ subcode ] ; case RISCV_BUILTIN_VECTOR : return riscv_vector :: builtin_decl ( subcode , initialize_p ) ; } return error_mark_node ; } </s>


<s> bool RISCVCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs ) const { if ( F . arg_empty ( ) ) return true ; return false ; } </s>

This hook must be implemented to lower the incoming ( formal ) arguments , described by VRegs , for GlobalISel .


<s> bool RISCVFrameLowering :: canUseAsPrologue ( const MachineBasicBlock & MBB ) const { MachineBasicBlock * TmpMBB = const_cast < MachineBasicBlock * > ( & MBB ) ; const MachineFunction * MF = MBB . getParent ( ) ; const auto * RVFI = MF -> getInfo < RISCVMachineFunctionInfo > ( ) ; if ( ! RVFI -> useSaveRestoreLibCalls ( * MF ) ) return true ; RegScavenger RS ; RS . enterBasicBlock ( * TmpMBB ) ; return ! RS . isRegUsed ( RISCV :: X5 ) ; } </s>

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


<s> char * function_builder :: finish_name ( ) { obstack_1grow ( & m_string_obstack , 0 ) ; return ( char * ) obstack_finish ( & m_string_obstack ) ; } </s>

Zero-terminate and complete the function name being built .


<s> bool RISCVPassConfig :: addPreISel ( ) { if ( TM -> getOptLevel ( ) != CodeGenOpt :: None ) { addPass ( createHardwareLoopsPass ( ) ) ; } return false ; } </s>


<s> static section * riscv_elf_select_rtx_section ( enum machine_mode mode , rtx x , unsigned HOST_WIDE_INT align ) { section * s = default_elf_select_rtx_section ( mode , x , align ) ; if ( riscv_size_ok_for_small_data_p ( GET_MODE_SIZE ( mode ) ) ) { if ( strncmp ( s -> named . name , ".rodata.cst" , strlen ( ".rodata.cst" ) ) == 0 ) { char * name = ( char * ) alloca ( strlen ( s -> named . name ) + 2 ) ; sprintf ( name , ".s%s" , s -> named . name + 1 ) ; return get_section ( name , s -> named . common . flags , NULL ) ; } if ( s == data_section ) return sdata_section ; } return s ; } </s>

Return a section for X , handling small data .


<s> TargetStackID :: Value RISCVFrameLowering :: getStackIDForScalableVectors ( ) const { return TargetStackID :: ScalableVector ; } </s>

Returns the StackID that scalable vectors should be associated with .


<s> static bool riscv_memmodel_needs_release_fence ( enum memmodel model ) { switch ( model ) { case MEMMODEL_ACQ_REL : case MEMMODEL_SEQ_CST : case MEMMODEL_SYNC_SEQ_CST : case MEMMODEL_RELEASE : case MEMMODEL_SYNC_RELEASE : return true ; case MEMMODEL_ACQUIRE : case MEMMODEL_CONSUME : case MEMMODEL_SYNC_ACQUIRE : case MEMMODEL_RELAXED : return false ; default : gcc_unreachable ( ) ; } } </s>

Return true if a FENCE should be emitted to before a memory access to implement the release portion of memory model MODEL .


<s> bool RISCVTargetLowering :: shouldSignExtendTypeInLibCall ( EVT Type , bool IsSigned ) const { if ( Subtarget . is64Bit ( ) && Type == MVT :: i32 ) return true ; return IsSigned ; } </s>

Returns true if arguments should be sign-extended in lib calls .


<s> inline void function_expander :: add_input_operand ( machine_mode mode , rtx op ) { create_input_operand ( & m_ops [ opno ++ ] , op , mode ) ; } </s>

Create op and add it into M_OPS and increase OPNO .


<s> static void riscv_legitimize_poly_move ( machine_mode mode , rtx dest , rtx tmp , rtx src ) { poly_int64 value = rtx_to_poly_int64 ( src ) ; int offset = value . coeffs [ 0 ] ; int factor = value . coeffs [ 1 ] ; int vlenb = BYTES_PER_RISCV_VECTOR . coeffs [ 1 ] ; int div_factor = 0 ; emit_move_insn ( tmp , gen_int_mode ( BYTES_PER_RISCV_VECTOR , mode ) ) ; if ( BYTES_PER_RISCV_VECTOR . is_constant ( ) ) { gcc_assert ( value . is_constant ( ) ) ; riscv_emit_move ( dest , GEN_INT ( value . to_constant ( ) ) ) ; return ; } else if ( ( factor % vlenb ) == 0 ) div_factor = 1 ; else if ( ( factor % ( vlenb / 2 ) ) == 0 ) div_factor = 2 ; else if ( ( factor % ( vlenb / 4 ) ) == 0 ) div_factor = 4 ; else if ( ( factor % ( vlenb / 8 ) ) == 0 ) div_factor = 8 ; else gcc_unreachable ( ) ; if ( div_factor != 1 ) riscv_expand_op ( LSHIFTRT , mode , tmp , tmp , gen_int_mode ( exact_log2 ( div_factor ) , QImode ) ) ; riscv_expand_mult_with_const_int ( mode , dest , tmp , factor / ( vlenb / div_factor ) ) ; HOST_WIDE_INT constant = offset - factor ; if ( constant == 0 ) return ; else if ( SMALL_OPERAND ( constant ) ) riscv_expand_op ( PLUS , mode , dest , dest , gen_int_mode ( constant , mode ) ) ; else { rtx high ; high = gen_int_mode ( CONST_HIGH_PART ( constant ) , mode ) ; constant = CONST_LOW_PART ( constant ) ; riscv_emit_move ( tmp , high ) ; riscv_expand_op ( PLUS , mode , dest , tmp , dest ) ; riscv_expand_op ( PLUS , mode , dest , dest , gen_int_mode ( constant , mode ) ) ; } } </s>

Analyze src and emit const_poly_int mov sequence .


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

ParseInstruction - Parse one assembly instruction .

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


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


<s> bool RISCVTTIImpl :: isLoweredToCall ( const Function * F ) { if ( F -> getName ( ) . startswith ( "llvm.riscv.cv" ) ) return false ; return BaseT :: isLoweredToCall ( F ) ; } </s>

Test whether calls to a function lower to actual program function calls .


<s> void function_expander :: add_vundef_operand ( machine_mode mode ) { add_input_operand ( mode , RVV_VUNDEF ( mode ) ) ; } </s>


<s> static bool support_relaxed_compatible_p ( const vector_insn_info & info1 , const vector_insn_info & info2 ) { if ( fault_first_load_p ( info1 . get_insn ( ) -> rtl ( ) ) && info2 . demand_p ( DEMAND_AVL ) && info2 . has_avl_reg ( ) && info2 . get_avl_source ( ) && info2 . get_avl_source ( ) -> insn ( ) -> is_phi ( ) ) { hash_set < set_info * > sets = get_all_sets ( info2 . get_avl_source ( ) , true , false , false ) ; for ( set_info * set : sets ) { if ( read_vl_insn_p ( set -> insn ( ) -> rtl ( ) ) ) { const insn_info * insn = get_backward_fault_first_load_insn ( set -> insn ( ) ) ; if ( insn == info1 . get_insn ( ) ) return info2 . compatible_vtype_p ( info1 ) ; } } } return false ; } </s>

Return true if the instruction support relaxed compatible check .


"Can't store this register to stack slot"

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


<s> const char * riscv_output_move ( rtx dest , rtx src ) { enum rtx_code dest_code , src_code ; machine_mode mode ; bool dbl_p ; dest_code = GET_CODE ( dest ) ; src_code = GET_CODE ( src ) ; mode = GET_MODE ( dest ) ; dbl_p = ( GET_MODE_SIZE ( mode ) == 8 ) ; if ( dbl_p && riscv_split_64bit_move_p ( dest , src ) ) return "#" ; if ( dest_code == REG && GP_REG_P ( REGNO ( dest ) ) ) { if ( src_code == REG && FP_REG_P ( REGNO ( src ) ) ) return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.w\t%0,%1" ; if ( src_code == MEM ) switch ( GET_MODE_SIZE ( mode ) ) { case 1 : return "lbu\t%0,%1" ; case 2 : return "lhu\t%0,%1" ; case 4 : return "lw\t%0,%1" ; case 8 : return "ld\t%0,%1" ; } if ( src_code == CONST_INT ) { if ( SMALL_OPERAND ( INTVAL ( src ) ) || LUI_OPERAND ( INTVAL ( src ) ) ) return "li\t%0,%1" ; if ( TARGET_ZBS && SINGLE_BIT_MASK_OPERAND ( INTVAL ( src ) ) ) return "bseti\t%0,zero,%S1" ; abort ( ) ; } if ( src_code == HIGH ) return "lui\t%0,%h1" ; if ( symbolic_operand ( src , VOIDmode ) ) switch ( riscv_classify_symbolic_expression ( src ) ) { case SYMBOL_GOT_DISP : return "la\t%0,%1" ; case SYMBOL_ABSOLUTE : return "lla\t%0,%1" ; case SYMBOL_PCREL : return "lla\t%0,%1" ; default : gcc_unreachable ( ) ; } } if ( ( src_code == REG && GP_REG_P ( REGNO ( src ) ) ) || ( src == CONST0_RTX ( mode ) ) ) { if ( dest_code == REG ) { if ( GP_REG_P ( REGNO ( dest ) ) ) return "mv\t%0,%z1" ; if ( FP_REG_P ( REGNO ( dest ) ) ) { if ( ! dbl_p ) return "fmv.w.x\t%0,%z1" ; if ( TARGET_64BIT ) return "fmv.d.x\t%0,%z1" ; gcc_assert ( src == CONST0_RTX ( mode ) ) ; return "fcvt.d.w\t%0,x0" ; } } if ( dest_code == MEM ) switch ( GET_MODE_SIZE ( mode ) ) { case 1 : return "sb\t%z1,%0" ; case 2 : return "sh\t%z1,%0" ; case 4 : return "sw\t%z1,%0" ; case 8 : return "sd\t%z1,%0" ; } } if ( src_code == REG && FP_REG_P ( REGNO ( src ) ) ) { if ( dest_code == REG && FP_REG_P ( REGNO ( dest ) ) ) return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1" ; if ( dest_code == MEM ) return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0" ; } if ( dest_code == REG && FP_REG_P ( REGNO ( dest ) ) ) { if ( src_code == MEM ) return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1" ; } gcc_unreachable ( ) ; } </s>

Return the appropriate instructions to move SRC into DEST . Assume that SRC is operand 1 and DEST is operand 0 .


<s> void th_mempair_order_operands ( rtx operands [ 4 ] , bool load_p , machine_mode mode ) { int mem_op = load_p ? 1 : 0 ; bool reversed = false ; if ( ! th_mempair_check_consecutive_mems ( mode , operands + mem_op , operands + mem_op + 2 , & reversed ) ) gcc_unreachable ( ) ; if ( reversed ) { std :: swap ( operands [ 0 ] , operands [ 2 ] ) ; std :: swap ( operands [ 1 ] , operands [ 3 ] ) ; } } </s>

Given OPERANDS of consecutive load/store that can be merged , swap them if they are not in ascending order . Return true if swap was performed .


"READCYCLECOUNTER only has custom type legalization on riscv32"

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


<s> outliner :: OutlinedFunction RISCVInstrInfo :: getOutliningCandidateInfo ( std :: vector < outliner :: Candidate > & RepeatedSequenceLocs ) const { auto CannotInsertCall = [ ] ( outliner :: Candidate & C ) { const TargetRegisterInfo * TRI = C . getMF ( ) -> getSubtarget ( ) . getRegisterInfo ( ) ; C . initLRU ( * TRI ) ; LiveRegUnits LRU = C . LRU ; return ! LRU . available ( RISCV :: X5 ) ; } ; 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> Optional < DestSourcePair > RISCVInstrInfo :: isCopyInstrImpl ( const MachineInstr & MI ) const { if ( MI . isMoveReg ( ) ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; switch ( MI . getOpcode ( ) ) { default : break ; case RISCV :: ADDI : if ( MI . getOperand ( 1 ) . isReg ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; break ; case RISCV :: FSGNJ_D : case RISCV :: FSGNJ_S : case RISCV :: FSGNJ_H : if ( MI . getOperand ( 1 ) . isReg ( ) && MI . getOperand ( 2 ) . isReg ( ) && MI . getOperand ( 1 ) . getReg ( ) == MI . getOperand ( 2 ) . getReg ( ) ) return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; break ; } return None ; } </s>

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


<s> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { case RISCVISD :: NODE : \ return "RISCVISD::" # NODE ; switch ( ( RISCVISD :: NodeType ) Opcode ) { case RISCVISD :: FIRST_NUMBER : break ; NODE_NAME_CASE ( RET_FLAG ) NODE_NAME_CASE ( URET_FLAG ) NODE_NAME_CASE ( SRET_FLAG ) NODE_NAME_CASE ( MRET_FLAG ) NODE_NAME_CASE ( CALL ) NODE_NAME_CASE ( SELECT_CC ) NODE_NAME_CASE ( BuildPairF64 ) NODE_NAME_CASE ( SplitF64 ) NODE_NAME_CASE ( TAIL ) NODE_NAME_CASE ( SLLW ) NODE_NAME_CASE ( SRAW ) NODE_NAME_CASE ( SRLW ) NODE_NAME_CASE ( DIVW ) NODE_NAME_CASE ( DIVUW ) NODE_NAME_CASE ( REMUW ) NODE_NAME_CASE ( ROLW ) NODE_NAME_CASE ( RORW ) NODE_NAME_CASE ( FSLW ) NODE_NAME_CASE ( FSRW ) NODE_NAME_CASE ( FMV_H_X ) NODE_NAME_CASE ( FMV_X_ANYEXTH ) NODE_NAME_CASE ( FMV_W_X_RV64 ) NODE_NAME_CASE ( FMV_X_ANYEXTW_RV64 ) NODE_NAME_CASE ( READ_CYCLE_WIDE ) NODE_NAME_CASE ( GREVI ) NODE_NAME_CASE ( GREVIW ) NODE_NAME_CASE ( GORCI ) NODE_NAME_CASE ( GORCIW ) NODE_NAME_CASE ( VMV_X_S ) NODE_NAME_CASE ( SPLAT_VECTOR_I64 ) } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific

RISCV RISCV RISCVISD::NODE "RISCVISD::" RISCVISD::NodeType RISCVISD::FIRST_NUMBER


<s> void RISCVMCInstLower :: lower ( const MachineInstr * MI , MCInst & OutMI ) const { unsigned Opcode = MI -> getOpcode ( ) ; if ( ! AsmPrinter . OutStreamer -> hasRawTextSupport ( ) ) Opcode = getShortenedInstr ( Opcode ) ; OutMI . setOpcode ( Opcode ) ; for ( unsigned I = 0 , E = MI -> getNumOperands ( ) ; I != E ; ++ I ) { const MachineOperand & MO = MI -> getOperand ( I ) ; MCOperand MCOp = lowerOperand ( MO ) ; if ( MCOp . isValid ( ) ) OutMI . addOperand ( MCOp ) ; } } </s>


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


"%<#pragma riscv intrinsic%> requires a string parameter"

"%<#pragma riscv intrinsic%> option %qs needs 'V' extension "

"unknown %<#pragma riscv intrinsic%> option %qs"

Implement `` # pragma riscv intrinsic '' .


<s> EVT RISCVTargetLowering :: getSetCCResultType ( const DataLayout & DL , LLVMContext & Context , EVT VT ) const { if ( ! VT . isVector ( ) ) return getPointerTy ( DL ) ; if ( Subtarget . hasVInstructions ( ) && ( 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> static void riscv_va_start ( tree valist , rtx nextarg ) { nextarg = plus_constant ( Pmode , nextarg , - cfun -> machine -> varargs_size ) ; std_expand_builtin_va_start ( valist , nextarg ) ; } </s>


<s> static rtx riscv_legitimize_address ( rtx x , rtx oldx ATTRIBUTE_UNUSED , machine_mode mode ) { rtx addr ; if ( riscv_tls_symbol_p ( x ) ) return riscv_legitimize_tls_address ( x ) ; if ( riscv_split_symbol ( NULL , x , mode , & addr ) ) 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> bool RISCVPulpHWLoops :: runOnMachineFunction ( MachineFunction & MF ) { if ( ! MF . getSubtarget < RISCVSubtarget > ( ) . hasNonStdExtPulp ( ) ) { return false ; } TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; MachineDominatorTree * MDT = & getAnalysis < MachineDominatorTree > ( ) ; FindInstrPairs ( MDT -> getRootNode ( ) , nullptr , nullptr ) ; assert ( Setups . size ( ) == Branches . size ( ) && Setups . size ( ) == LoopNums . size ( ) ) ; if ( Setups . empty ( ) ) return false ; while ( ! Setups . empty ( ) ) { ProcessHardwareLoop ( Setups . pop_back_val ( ) , Branches . pop_back_val ( ) , LoopNums . pop_back_val ( ) , MF ) ; } return true ; } </s>

runOnMachineFunction - Emit the function body .


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

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


"Not all fixup kinds added to Infos array"


<s> void expand ( enum insn_code icode , bool temporary_volatile_p = false ) { if ( temporary_volatile_p ) { temporary_volatile_ok v ( true ) ; expand_insn ( icode , m_opno , m_ops ) ; } else expand_insn ( icode , m_opno , m_ops ) ; } </s>


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

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


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

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


<s> rtx riscv_function_value ( const_tree type , const_tree func , enum machine_mode mode ) { struct riscv_arg_info info ; CUMULATIVE_ARGS args ; if ( type ) { int unsigned_p = TYPE_UNSIGNED ( type ) ; mode = TYPE_MODE ( type ) ; mode = promote_function_mode ( type , mode , & unsigned_p , func , 1 ) ; } memset ( & args , 0 , sizeof args ) ; return riscv_get_arg_info ( & info , & args , mode , type , true , true ) ; } </s>

Implement FUNCTION_VALUE and LIBCALL_VALUE . For normal calls , VALTYPE is the return type and MODE is VOIDmode . For libcalls , VALTYPE is null and MODE is the mode of the return value .


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

Returns true if the target requires ( and can make use of ) the register scavenger .


<s> BitVector RISCVRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { const TargetFrameLowering * 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 ) ; 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 .


"Trying RV32Zdinx table (Double in Integer and"

"Trying RVZfinx table (Float in Integer):\n"

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

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

Returns the disassembly of a single instruction .


"Can't load this register from stack slot"

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


<s> bool isUnknown ( ) const { return State == Unknown ; } </s>

Tests if this MemDepResult represents a query which can not and/or will not be computed .


<s>
void
RISCVRegisterInfo
::
eliminateFrameIndex
(
MachineBasicBlock
::
iterator
II
,
int
SPAdj
,
unsigned
FIOperandNum
,
RegScavenger
*
RS
)
const
{
MachineInstr
&
MI
=
*
II
;
MachineFunction
&
MF
=
*
MI
.
getParent
(
)
->
getParent
(
)
;
DEBUG
(
errs
(
)
<<
"\nFunction : "
<<
MF
.
getName
(
)
<<
"\n"
;
errs
(
)
<<
"<--------->\n"
<<
MI
)
;
int
FrameIndex
=
MI
.
getOperand
(
FIOperandNum
)
.
getIndex
(
)
;
uint64_t
stackSize
=
MF
.
getFrameInfo
(
)
->
getStackSize
(
)
;
int64_t
spOffset
=
MF
.
getFrameInfo
(
)
->
getObjectOffset
(
FrameIndex
)
;
DEBUG
(
errs
(
)
<<
"FrameIndex : "
<<
FrameIndex
<<
"\n"
<<
"spOffset   : "
<<
spOffset
<<
"\n"
<<
"stackSize  : "
<<
stackSize
<<
"\n"
)
;
eliminateFI
(
MI
,
FIOperandNum
,
FrameIndex
,
stackSize
,
spOffset
)
;
}
</s>

This method must be overriden to eliminate abstract frame indices from instructions which may use them .

RISCV
RISCV
"\nFunction : "
"\n"
"<--------->\n"
"FrameIndex : "
"\n"
"spOffset   : "
"\n"
"stackSize  : "
"\n"


<s> static bool has_vector_insn ( function * fn ) { basic_block cfg_bb ; rtx_insn * rinsn ; FOR_ALL_BB_FN ( cfg_bb , fn ) FOR_BB_INSNS ( cfg_bb , rinsn ) if ( NONDEBUG_INSN_P ( rinsn ) && has_vtype_op ( rinsn ) ) return true ; return false ; } </s>

Return true if FN has a vector instruction that use VL/VTYPE .


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

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


<s>
bool
RISCVInstrInfo
::
getMemOperandWithOffsetWidth
(
const
MachineInstr
&
LdSt
,
const
MachineOperand
*
&
BaseReg
,
int64_t
&
Offset
,
unsigned
&
Width
,
const
TargetRegisterInfo
*
TRI
)
const
{
assert
(
LdSt
.
mayLoadOrStore
(
)
&&
"Expected a memory operation."
)
;
if
(
LdSt
.
getNumExplicitOperands
(
)
!=
3
)
return
false
;
if
(
!
LdSt
.
getOperand
(
1
)
.
isReg
(
)
||
!
LdSt
.
getOperand
(
2
)
.
isImm
(
)
)
return
false
;
if
(
!
LdSt
.
hasOneMemOperand
(
)
)
return
false
;
Width
=
(
*
LdSt
.
memoperands_begin
(
)
)
->
getSize
(
)
;
BaseReg
=
&
LdSt
.
getOperand
(
1
)
;
Offset
=
LdSt
.
getOperand
(
2
)
.
getImm
(
)
;
return
true
;
}
</s>

Return true if get the base operand , byte offset of an instruction and the memory width .


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

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


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

Emit target-specific code that performs a memcpy .


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

getMachineOpValue - Return binary encoding of operand .


<s> void RISCVFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; if ( hasFP ( MF ) ) { SavedRegs . set ( RISCV :: X1 ) ; SavedRegs . set ( RISCV :: X8 ) ; } } </s>

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


<s> const char * RISCVTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { case RISCVISD :: NODE : \ return "RISCVISD::" # NODE ; switch ( ( RISCVISD :: NodeType ) Opcode ) { case RISCVISD :: FIRST_NUMBER : break ; NODE_NAME_CASE ( RET_FLAG ) NODE_NAME_CASE ( URET_FLAG ) NODE_NAME_CASE ( SRET_FLAG ) NODE_NAME_CASE ( MRET_FLAG ) NODE_NAME_CASE ( CALL ) NODE_NAME_CASE ( SELECT_CC ) NODE_NAME_CASE ( BuildPairF64 ) NODE_NAME_CASE ( SplitF64 ) NODE_NAME_CASE ( TAIL ) NODE_NAME_CASE ( SLLW ) NODE_NAME_CASE ( SRAW ) NODE_NAME_CASE ( SRLW ) NODE_NAME_CASE ( DIVW ) NODE_NAME_CASE ( DIVUW ) NODE_NAME_CASE ( REMUW ) NODE_NAME_CASE ( ROLW ) NODE_NAME_CASE ( RORW ) NODE_NAME_CASE ( FSLW ) NODE_NAME_CASE ( FSRW ) NODE_NAME_CASE ( FMV_H_X ) NODE_NAME_CASE ( FMV_X_ANYEXTH ) NODE_NAME_CASE ( FMV_W_X_RV64 ) NODE_NAME_CASE ( FMV_X_ANYEXTW_RV64 ) NODE_NAME_CASE ( READ_CYCLE_WIDE ) NODE_NAME_CASE ( GREVI ) NODE_NAME_CASE ( GREVIW ) NODE_NAME_CASE ( GORCI ) NODE_NAME_CASE ( GORCIW ) } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific


<s>
const
char
*
getPassName
(
)
const
override
{
return
"RISCV Assembly Printer"
;
}
</s>

getPassName - Return a nice clean name for a pass .


<s> rtx function_expander :: use_compare_insn ( rtx_code rcode , insn_code icode ) { machine_mode mode = TYPE_MODE ( builtin_types [ type . index ] . vector ) ; machine_mode mask_mode = TYPE_MODE ( TREE_TYPE ( exp ) ) ; int arg_offset = 0 ; if ( use_real_mask_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_all_one_mask_operand ( mask_mode ) ; if ( use_real_merge_p ( pred ) ) add_input_operand ( arg_offset ++ ) ; else add_vundef_operand ( mask_mode ) ; rtx op1 = expand_normal ( CALL_EXPR_ARG ( exp , arg_offset ++ ) ) ; rtx op2 = expand_normal ( CALL_EXPR_ARG ( exp , arg_offset ++ ) ) ; if ( ! insn_operand_matches ( icode , opno + 1 , op1 ) ) op1 = force_reg ( mode , op1 ) ; if ( ! insn_operand_matches ( icode , opno + 2 , op2 ) ) { if ( VECTOR_MODE_P ( GET_MODE ( op2 ) ) ) op2 = force_reg ( mode , op2 ) ; else op2 = force_reg ( GET_MODE_INNER ( mode ) , op2 ) ; } rtx comparison = gen_rtx_fmt_ee ( rcode , mask_mode , op1 , op2 ) ; if ( ! VECTOR_MODE_P ( GET_MODE ( op2 ) ) ) comparison = gen_rtx_fmt_ee ( rcode , mask_mode , op1 , gen_rtx_VEC_DUPLICATE ( mode , op2 ) ) ; add_fixed_operand ( comparison ) ; add_fixed_operand ( op1 ) ; if ( CONST_INT_P ( op2 ) ) add_integer_operand ( op2 ) ; else add_fixed_operand ( op2 ) ; for ( int argno = arg_offset ; argno < call_expr_nargs ( exp ) ; argno ++ ) add_input_operand ( argno ) ; 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>
rtx
function_expander
::
generate_insn
(
insn_code
icode
)
{
gcc_assert
(
opno
==
insn_data
[
icode
]
.
n_generator_args
)
;
if
(
!
maybe_expand_insn
(
icode
,
opno
,
m_ops
)
)
{
error
(
"invalid argument to built-in function"
)
;
return
NULL_RTX
;
}
return
function_returns_void_p
(
)
const0_rtx
:
m_ops
[
0
]
.
value
;
}
</s>

Generate instruction ICODE , given that its operands have already been added to M_OPS . Return the value of the first operand .

riscv
"invalid argument to built-in function"
0


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

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


<s> static bool riscv_canonicalize_int_order_test ( enum rtx_code * code , rtx * cmp1 , machine_mode mode ) { HOST_WIDE_INT plus_one ; if ( riscv_int_order_operand_ok_p ( * code , * cmp1 ) ) return true ; if ( CONST_INT_P ( * cmp1 ) ) switch ( * code ) { case LE : plus_one = trunc_int_for_mode ( UINTVAL ( * cmp1 ) + 1 , mode ) ; if ( INTVAL ( * cmp1 ) < plus_one ) { * code = LT ; * cmp1 = force_reg ( mode , GEN_INT ( plus_one ) ) ; return true ; } break ; case LEU : plus_one = trunc_int_for_mode ( UINTVAL ( * cmp1 ) + 1 , mode ) ; if ( plus_one != 0 ) { * code = LTU ; * cmp1 = force_reg ( mode , GEN_INT ( plus_one ) ) ; return true ; } break ; default : break ; } return false ; } </s>

Return true if * CMP1 ( of mode MODE ) is a valid second operand for integer ordering test * CODE , or if an equivalent combination can be formed by adjusting * CODE and * CMP1 . When returning true , update * CODE and * CMP1 with the chosen code and operand , otherwise leave them alone .


<s>
void
RISCVMCCodeEmitter
::
encodeInstruction
(
const
MCInst
&
MI
,
raw_ostream
&
OS
,
SmallVectorImpl
<
MCFixup
>
&
Fixups
,
const
MCSubtargetInfo
&
STI
)
const
{
const
MCInstrDesc
&
Desc
=
MCII
.
get
(
MI
.
getOpcode
(
)
)
;
unsigned
Size
=
Desc
.
getSize
(
)
;
if
(
MI
.
getOpcode
(
)
==
RISCV
::
PseudoCALL
||
MI
.
getOpcode
(
)
==
RISCV
::
PseudoTAIL
)
{
expandFunctionCall
(
MI
,
OS
,
Fixups
,
STI
)
;
MCNumEmitted
+=
2
;
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::PseudoCALL
RISCV::PseudoTAIL
2
"Unhandled encodeInstruction length!"
2
support::endian
support::little
4
support::endian
support::little


<s> static rtx riscv_unspec_offset_high ( rtx temp , rtx addr , enum riscv_symbol_type symbol_type ) { addr = gen_rtx_HIGH ( Pmode , riscv_unspec_address ( addr , symbol_type ) ) ; return riscv_force_temporary ( temp , addr ) ; } </s>

If riscv_unspec_address ( ADDR , SYMBOL_TYPE ) is a 32-bit value , add the high part to BASE and return the result . Just return BASE otherwise . TEMP is as for riscv_force_temporary . The returned expression can be used as the first operand to a LO_SUM .


<s>
bool
RISCVInsertVSETVLI
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
const
RISCVSubtarget
&
ST
=
MF
.
getSubtarget
<
RISCVSubtarget
>
(
)
;
if
(
!
ST
.
hasStdExtV
(
)
)
return
false
;
TII
=
ST
.
getInstrInfo
(
)
;
MRI
=
&
MF
.
getRegInfo
(
)
;
assert
(
BlockInfo
.
empty
(
)
&&
"Expect empty block infos"
)
;
BlockInfo
.
resize
(
MF
.
getNumBlockIDs
(
)
)
;
bool
HaveVectorOp
=
false
;
for
(
const
MachineBasicBlock
&
MBB
:
MF
)
HaveVectorOp
|=
computeVLVTYPEChanges
(
MBB
)
;
if
(
HaveVectorOp
)
{
for
(
const
MachineBasicBlock
&
MBB
:
MF
)
{
WorkList
.
push
(
&
MBB
)
;
BlockInfo
[
MBB
.
getNumber
(
)
]
.
InQueue
=
true
;
}
while
(
!
WorkList
.
empty
(
)
)
{
const
MachineBasicBlock
&
MBB
=
*
WorkList
.
front
(
)
;
WorkList
.
pop
(
)
;
computeIncomingVLVTYPE
(
MBB
)
;
}
for
(
MachineBasicBlock
&
MBB
:
MF
)
emitVSETVLIs
(
MBB
)
;
}
BlockInfo
.
clear
(
)
;
return
HaveVectorOp
;
}
</s>

runOnMachineFunction - Emit the function body .

RISCV
RISCV
RISCV
RISCV
"Expect empty block infos"


<s> bool RISCVAsmParser :: ParseDirective ( AsmToken DirectiveID ) { return true ; } </s>

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


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


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


<s> Register RISCVTargetLowering :: getExceptionPointerRegister ( const Constant * PersonalityFn ) const { return RISCV :: X10 ; } </s>

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


<s> bool RISCVTargetLowering :: hasAndNot ( SDValue Y ) const { EVT VT = Y . getValueType ( ) ; if ( VT . isVector ( ) ) return false ; return Subtarget . hasStdExtZbb ( ) && ! isa < ConstantSDNode > ( Y ) ; } </s>

Return true if the target has a bitwise and-not operation : X = ~A & B This can be used to simplify select or other instructions .


<s> static unsigned HOST_WIDE_INT riscv_asan_shadow_offset ( void ) { return TARGET_64BIT ? ( HOST_WIDE_INT_1 << 29 ) : 0 ; } </s>


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


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

Print the specified MCInst to the specified raw_ostream .


<s> static bool riscv_print_operand_punct_valid_p ( unsigned char code ) { return ( code == '~' ) ; } </s>


<s> unsigned RISCVTargetLowering :: ComputeNumSignBitsForTargetNode ( SDValue Op , const APInt & DemandedElts , const SelectionDAG & DAG , unsigned Depth ) const { switch ( Op . getOpcode ( ) ) { default : break ; case RISCVISD :: SLLW : case RISCVISD :: SRAW : case RISCVISD :: SRLW : case RISCVISD :: DIVW : case RISCVISD :: DIVUW : case RISCVISD :: REMUW : case RISCVISD :: ROLW : case RISCVISD :: RORW : case RISCVISD :: GREVIW : case RISCVISD :: GORCIW : case RISCVISD :: FSLW : case RISCVISD :: FSRW : return 33 ; case RISCVISD :: VMV_X_S : if ( Op . getOperand ( 0 ) . getScalarValueSizeInBits ( ) > Subtarget . getXLen ( ) ) return 1 ; return Subtarget . getXLen ( ) - Op . getOperand ( 0 ) . getScalarValueSizeInBits ( ) + 1 ; } return 1 ; } </s>

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

RISCV RISCV RISCVISD::SLLW RISCVISD::SRAW RISCVISD::SRLW RISCVISD::DIVW RISCVISD::DIVUW RISCVISD::REMUW RISCVISD::ROLW RISCVISD::RORW RISCVISD::GREVIW RISCVISD::GORCIW RISCVISD::FSLW RISCVISD::FSRW 33 RISCVISD::VMV_X_S 0 1 0 1 1


<s> void copyPhysReg ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MBBI , const DebugLoc & DL , MCRegister DstReg , MCRegister SrcReg , bool KillSrc ) const override { copyPhysReg ( MBB , MBBI , DL , DstReg , SrcReg , KillSrc , MachineInstr :: NoFlags ) ; } </s>