void addGlobalInstructionSelect ( RISCV , RISCV ) { PassManager pm ; TargetMachine * tm = RISCV ; GlobalISelPass * gis = tm -> createGlobalISelPass ( ) ; pm . addPass ( gis ) ; pm . run ( RISCV ) ; }


void addIRPasses ( RISCVTargetMachine & TM , PassManagerBase & PM ) { PM . add ( createCFGSimplificationPass ( ) ) ; PM . add ( createLowerAtomicPass ( ) ) ; PM . add ( createPromoteMemoryToRegisterPass ( ) ) ; PM . add ( createGlobalDCEPass ( ) ) ; PM . add ( createConstantPropagationPass ( ) ) ; PM . add ( createDeadArgEliminationPass ( ) ) ; PM . add ( createDeadCodeEliminationPass ( ) ) ; PM . add ( createDeadStoreEliminationPass ( ) ) ; PM . add ( createDeadInstEliminationPass ( ) ) ; PM . add ( createDeadCodeEliminationPass ( ) ) ; PM . add ( createCFGSimplificationPass ( ) ) ; PM . add ( createMergedLoadStoreMotionPass ( ) ) ; PM . add ( createMemCpyOptPass ( ) ) ; PM . add ( createLoopSimplifyPass ( ) ) ; PM . add ( createIndVarSimplifyPass ( ) ) ; PM . add ( createLICMPass ( ) ) ; PM . add ( createLoopUnrollPass ( ) ) ; PM . add ( createLoopRotatePass ( ) ) ; PM . add ( createLoopDistributionPass ( ) ) ; PM . add ( createRISCVISelDag ( TM , TM . getOptLevel ( ) ) ) ; PM . add ( createRISCVExpandPseudoPass ( ) ) ; PM . add ( createRISCVFrameLoweringPass ( ) ) ; PM . add ( createRISCVOptimizeShadowSOEPPass ( ) ) ; PM . add ( createRISCVExpandAtomicPass ( ) ) ; PM . add ( createRISCVOptimizeMIRPPass ( ) ) ; PM . add ( createRISCVConstantFoldingPass ( ) ) ; PM . add ( createRISCVReduceComplexityPass ( ) ) ; PM . add ( createRISCVExpandPredicatesPass ( ) ) ; PM . add ( createRISCVExpandAssemblerPass ( ) ) ; PM . add ( createRISCVOptimizeTailsPass ( ) ) ; PM . add ( createRISCVLoopUnrollingPass ( ) ) ; PM . add ( createRISCVExpandGeneralPatternsPass ( ) ) ; }


void addIRTranslator ( Module & M ) { RISCVTargetMachine TM ( ... ) ; Pass * IRTranslator = TM . createIRTranslator ( ) ; M . addPass ( IRTranslator ) ; }


TargetLibraryInfo * TLI , TargetIRAnalysis * CAM ) { if ( ! MF . getFunction ( ) . getAttributes ( ) . hasAttribute ( AttributeList :: FunctionIndex , Attribute :: OptimizeNone ) ) { return false ; } if ( ! ILP && ! MF . getSubtarget < MaxisSubtarget > ( ) . allUsesMustUseS12 ( ) && ! MF . getSubtarget < MaxisSubtarget > ( ) . allUsesMustUseS12 ( ) ) { return false ; } MF . getProperties ( ) . set ( MachineFunctionProperties :: Property :: SSA ) ; MF . getProperties ( ) . set ( MachineFunctionProperties :: Property :: NoVRegAlloc ) ; MF . getProperties ( ) . set ( MachineFunctionProperties :: Property :: GDNUPatterns ) ; return true ; }


RegisterClassInfo & RCI ) { } The addPostRegAlloc function can be implemented to perform any target - specific optimizations or transformations that are required after the register allocation pass pipeline . This could include optimizing specific instructions , manipulating register allocations , or performing code generation for target - specific instructions . The RISCV target - specific values , RISCV , RISCV , and RISCV , can be accessed through the MachineFunction object . These values can be used to identify the specific RISCV registers used by the target and to optimize the code accordingly . void RISCVTargetMachine :: addPostRegAlloc ( const RISCVTargetMachine & TM , MachineFunction & MF , RegisterClassInfo & RCI ) { const RISCVTargetLowering * TLI = TM . getSubtargetImpl ( ) -> getTargetLowering ( ) ; const RISCVRegisterInfo * RI = TM . getSubtargetImpl ( ) -> getRegisterInfo ( ) ; unsigned FrameReg = RI -> getFrameRegister ( MF ) ; }


void RISCVTargetMachine :: addPreRegAlloc ( PassManagerBase & PM ) { PM . add ( createRISCVExpandPseudoPass ( ) ) ; PM . add ( createRISCVISelDag ( RISCVReserveX8 ) ) ; PM . add ( createRISCVLoadStoreOptimizationPass ( ) ) ; PM . add ( createRISCVRenameRegisterPass ( ) ) ; }


void addPreSched2 ( RISCV , RISCV ) { BasicBlock * preSchedBlock = BasicBlock :: Create ( ) ; for ( Function :: iterator FI = F . begin ( ) , FE = F . end ( ) ; FI != FE ; ++ FI ) { BasicBlock * BB = & * FI ; if ( BB -> getTerminator ( ) -> getOpcode ( ) == RISCV || BB -> getTerminator ( ) -> getOpcode ( ) == RISCV ) { preSchedBlock -> getInstList ( ) . splice ( preSchedBlock -> end ( ) , BB -> getInstList ( ) , BB -> begin ( ) , BB -> end ( ) ) ; } }


void addRegBankSelect ( ) { TargetMachine * TM = getTargetMachine ( ) ; const RISCVSubtarget * ST = TM -> getSubtarget < RISCVSubtarget > ( ) ; RegisterBankSelectorPass * RBSP = new RegisterBankSelectorPass ( ST -> getRISCV ( ) ) ; TM -> addPass ( RBSP ) ; }


TargetSubtargetInfo & getSubtargetImpl ( ) { const RISCVTargetMachine & TM = static_cast < const RISCVTargetMachine & > ( getTargetMachine ( ) ) ; const Triple & TT = TM . getTargetTriple ( ) ; std :: string CPU = TM . getTargetCPU ( ) ; std :: string TuneCPU = TM . getTargetABI ( ) ; const FeatureBitset & Features = TM . getFeatureBits ( ) ; RISCVABI :: ABI ABI = RISCVABI :: getTargetABI ( TT . getArch ( ) ) ; if ( ABI == RISCVABI :: ABI_Unknown ) { ABI = TM . getModule ( ) . getDataLayout ( ) . getABIEnum ( ) ; } return * new RISCVSubtarget ( TT , CPU , TuneCPU , Features , ABI ) ; }


TargetTransformInfo getTargetTransformInfo ( const TargetMachine * TM ) { if ( ! TM -> getTargetTriple ( ) . isRISCV ( ) ) { return TargetTransformInfo ( ) ; } RISCVTargetTransformInfo TTI ; return TTI ; }


bool isNoopAddrSpaceCast ( uint32_t SrcAS , uint32_t DestAS ) { if ( SrcAS == RISCV && DestAS == RISCV ) { return true ; } return false ; }


namespace
llvm
{
class
RISCVPreEmitPass
:
public
MachineFunctionPass
{
public
:
static
char
ID
;
RISCVPreEmitPass
(
)
:
MachineFunctionPass
(
ID
)
{
}
bool
runOnMachineFunction
(
MachineFunction
&
MF
)
override
{
return
false
;
}
StringRef
getPassName
(
)
const
override
{
return
"RISCV Pre-Emit Pass"
;
}
}
;
char
RISCVPreEmitPass
::
ID
=
0
;
FunctionPass
*
createRISCVPreEmitPass
(
)
{
return
new
RISCVPreEmitPass
(
)
;
}
INITIALIZE_PASS
(
RISCVPreEmitPass
,
"addPreEmitPass"
,
"RISCV Pre-Emit Pass"
,
false
,
true
)
}
extern
"C"
void
LLVMInitializeRISCVTargetPreEmitPass
(
)
{
llvm
::
PassRegistry
&
Registry
=
*
llvm
::
PassRegistry
::
getPassRegistry
(
)
;
llvm
::
initializeRISCVPreEmitPass
(
Registry
)
;
}


llvm :: PassManager addIRPasses ( ) { llvm :: Triple TargetTriple ( llvm :: sys :: getProcessTriple ( ) ) ; TargetTriple . setArchName ( "riscv32" ) ; llvm :: TargetLibraryInfoWrapperPass * TLIWP = new llvm :: TargetLibraryInfoWrapperPass ( TargetTriple ) ; llvm :: PassManager PM ; llvm :: addTargetSpecificPasses ( PM , TargetTriple ) ; llvm :: addCommonTargetConfigPasses ( PM , TLIWP ) ; return PM ; }


bool isNoopAddrSpaceCast ( unsigned SrcAS , unsigned DestAS ) { if ( SrcAS == RISCV && DestAS == RISCV ) { return true ; } else { return false ; } }


TargetSubtargetInfo & RISCVTargetMachine :: getSubtargetImpl ( const Triple & TT , StringRef CPU , StringRef FS ) { LLVMContext & Ctx = getLLVMContext ( ) ; if ( ! Subtarget ) { if ( TT . isArch32Bit ( ) ) Subtarget = llvm :: createRISCVSubtargetImpl ( Ctx , TT . getArchName ( ) , CPU , "RISCV" , "target-cpu" , FS ) ; else Subtarget = llvm :: createRISCVSubtargetImpl ( Ctx , TT . getArchName ( ) , CPU , FS ) ; if ( ! CPU . empty ( ) ) { ParseRISCVCPUFeatures ( "+reserve-ra" , CPU , true ) ; } RISCVSubtarget * RI = cast < RISCVSubtarget > ( Subtarget ) ; RI -> setCPU ( CPU ) ; RI -> setFeatureString ( FS ) ; return * Subtarget ; }


Modules & M , MCStreamer & MCOS , AsmPrinter & AP ) { RISCV :: RISCV , RISCV :: RISCV , RISCV :: RISCV , RISCV :: RISCV , RISCV :: RISCV }


if ( TM . getTargetTriple ( ) . getArch ( ) != Triple :: riscv ) { return ; } ` ` ` Next , we need to get the MachineRegisterInfo ( MRI ) object from DAGisel , which will be used to define new virtual registers for RISCV . ` ` ` cpp MachineRegisterInfo & MRI = DAGisel . getMF ( ) -> getRegInfo ( ) ; ` ` ` Now , we can start adding the target - specific virtual registers for RISCV . For this , we will use the ` addReg ( ) ` function of MRI , which takes in two parameters , register number and allocation flags . The code for adding target - specific virtual registers would be : ` ` ` cpp for ( unsigned i = 0 ; i < 32 ; ++ i ) { MRI . addReg ( RISCV :: X0 + i , RegState :: Virtual | RegState :: Preserved ) ; } if ( STI . hasFP ( ) ) { for ( unsigned i = 0 ; i < 32 ; ++ i ) { MRI . addReg ( RISCV :: F0 + i , RegState :: Virtual | RegState :: Preserved ) ; } }


bool RISCVTargetMachine :: addPreRegAlloc ( FunctionPassManager & FPM ) { FPM . add ( new RISCVPass1 ( ) ) ; FPM . add ( new RISCVPass2 ( ) ) ; FPM . add ( new RISCVPass3 ( ) ) ; FPM . add ( new RISCVPass4 ( ) ) ; return true ; }


TargetSubtargetInfo & RISCVTargetLowering :: getSubtargetImpl ( const Function & F ) const { RISCVSubtarget STI = RISCVSubtarget ( RISCVTargetMachine & TM , const Triple & TargetTriple , StringRef CPU , StringRef FS , const TargetOptions & Options , Optional < VectorType > Features , Optional < RISCVABI :: ABI > ABIName , Optional < StringRef > ABI ) ; if ( CPU . empty ( ) ) CPU = getDefaultCPU ( Options ) ; RISCVGenSubtargetInfo :: InitSchedModel ( STI , CPU ) ; auto & Subtarget = * new RISCVSubtarget ( RISCVTargetMachine & TM , const Triple & TargetTriple , CPU , FS , Options , Features , ABIName , ABI ) ; return Subtarget ; }


void addPreEmitPass2 ( ModulePassManager & MPM , RISCVTargetMachine & TM , MachineModuleInfo & MMI ) { RISCVSubtarget & STI = TM . getSubtarget < RISCVSubtarget > ( ) ; }


void addISelPrepare ( PassManagerBase & PM , TargetMachine & TM ) { PM . add ( createEarlyCSEPass ( ) ) ; PM . add ( createJumpThreadingPass ( ) ) ; PM . add ( createBranchFolderPass ( ) ) ; PM . add ( createLICMPass ( ) ) ; PM . add ( createLoopSimplifyPass ( ) ) ; }


void addInstSelector ( TargetOptions Target ) { TargetMachine * TM = Target . createTargetMachine ( TRIPLE , CPU , FEATURES , Options , RM , CM , OA ) ; PassRegistry & Registry = * PassRegistry :: getPassRegistry ( ) ; initializeRISCVExpandPseudoPass ( Registry ) ; initializeRISCVInstrInfoPass ( Registry ) ; initializeRISCVExpandPseudoPass ( Registry ) ; initializeRISCVBranchExpansionPass ( Registry ) ; addPass ( createRISCVISelDAG ( Target , * TM ) ) ; }


void addIRPasses ( TargetMachine & TM , PassManagerBase & PM ) { if ( TM . getTargetTriple ( ) . getArch ( ) == Triple :: riscv ) { PM . add ( createInstructionCombiningPass ( ) ) ; PM . add ( createDeadCodeEliminationPass ( ) ) ; PM . add ( createCFGSimplificationPass ( ) ) ; } }


void addPreEmitPass ( RISCVTargetMachine & TM ) { StringRef TargetName = TM . getTargetTriple ( ) . getArchName ( ) ; if ( TargetName == "RISCV" ) { TM . addPass ( createRISCVSpecificPass ( ) ) ; TM . addPass ( createRISCVAnotherSpecificPass ( ) ) ; } return ; }


void RISCVTarget :: addPreRegAlloc ( PassManagerBase & PM ) { PM . add ( createGVNPass ( ) ) ; PM . add ( createDeadCodeEliminationPass ( ) ) ; PM . add ( createLoopUnrollPass ( ) ) ; }


llvm :: NamedMDNode * getModuleMetadata ( llvm :: Module & M ) { llvm :: NamedMDNode * RISCVMetadata = M . getNamedMetadata ( "RISCV" ) ; if ( ! RISCVMetadata ) { return nullptr ; } llvm :: MDNode * FirstOp = RISCVMetadata -> getOperand ( 0 ) ; if ( ! FirstOp || ! FirstOp -> isMDNode ( ) ) { return nullptr ; } llvm :: Value * SecondOp = FirstOp -> getOperand ( 1 ) ; if ( ! SecondOp || ! SecondOp -> getType ( ) -> isIntegerTy ( ) ) { return nullptr ; } int SmallDataLimit = SecondOp -> getUniqueInteger ( ) . getLimitedValue ( ) ; llvm :: NamedMDNode * RISCVSpecificMetadata = llvm :: NamedMDNode :: Create ( M . getContext ( ) , "RISCVSpecific" , RISCVMetadata ) ; llvm :: APInt Value ( 32 , SmallDataLimit ) ; llvm :: ConstantAsMetadata * MDValue = llvm :: ConstantAsMetadata :: get ( llvm :: ConstantInt :: get ( M . getContext ( ) , Value ) ) ; llvm :: MDNode * Metadata = llvm :: MDNode :: get ( M . getContext ( ) , { MDValue , MDValue } ) ; RISCVSpecificMetadata -> addOperand ( Metadata ) ; return RISCVSpecificMetadata ; }


Section * getSectionForConstant ( const Constant * C , RISCVSubtarget & STI ) { SectionKind Kind = C -> getSectionKind ( ) ; switch ( Kind ) { case SectionKind :: getText ( ) : { StringRef SectionName = ".text" ; const MCAsmInfo * MAI = STI . getMCAsmInfo ( ) ; const MCSection * S = MAI -> getNonexecutableStackSection ( STI ) ; unsigned Attributes = STI . getTargetLowering ( ) -> getStackSectionFlags ( ) ; MCContext & Context = STI . getTargetLowering ( ) -> getContext ( ) ; return Context . getELFSection ( SectionName , S , Attributes , 0 , "text" ) ; } case SectionKind :: getReadOnly ( ) : { StringRef SectionName = ".rodata" ; const MCAsmInfo * MAI = STI . getMCAsmInfo ( ) ; const MCSection * S = MAI -> getNonexecutableStackSection ( STI ) ; unsigned Attributes = STI . getTargetLowering ( ) -> getStackSectionFlags ( ) ; MCContext & Context = STI . getTargetLowering ( ) -> getContext ( ) ; return Context . getELFSection ( SectionName , S , Attributes , 0 , "rodata" ) ; } case SectionKind :: getData ( ) : { StringRef SectionName = ".data" ; const MCAsmInfo * MAI = STI . getMCAsmInfo ( ) ; const MCSection * S = MAI -> getNonexecutableStackSection ( STI ) ; unsigned Attributes = STI . getTargetLowering ( ) -> getStackSectionFlags ( ) ; MCContext & Context = STI . getTargetLowering ( ) -> getContext ( ) ; return Context . getELFSection ( SectionName , S , Attributes , 0 , "data" ) ; }


bool RISCVTargetLowering :: isConstantInSmallSection ( const Constant * C , unsigned & Size , bool HasGOT ) const { if ( isa < GlobalValue > ( C ) && ! HasGOT ) { Size = Subtarget . is64Bit ( ) ? 8 : 4 ; return true ; } if ( isa < ConstantArray > ( C ) || isa < ConstantStruct > ( C ) ) { auto * CT = cast < CompositeType > ( C -> getType ( ) ) ; Size = ( unsigned ) TD -> getTypeAllocSize ( CT ) ; return Subtarget . is64Bit ( ) ? Size <= 8 : Size <= 4 ; } if ( isa < ConstantInt > ( C ) ) { Size = Subtarget . is64Bit ( ) ? 8 : 4 ; return true ; } return false ; }


TEST
(
isGlobalInSmallSection
,
TrueResult
)
{
Module
M
(
"test"
,
getGlobalContext
(
)
)
;
Type
*
i32Type
=
IntegerType
::
get
(
getGlobalContext
(
)
,
32
)
;
GlobalVariable
*
gv
=
new
GlobalVariable
(
M
,
i32Type
,
false
,
GlobalValue
::
ExternalLinkage
,
ConstantInt
::
get
(
i32Type
,
42
,
false
)
,
"test"
)
;
Triple
TargetTriple
(
"riscv32-unknown-linux"
)
;
std
::
string
Error
;
const
Target
*
Target
=
TargetRegistry
::
lookupTarget
(
""
,
TargetTriple
,
Error
)
;
TargetOptions
opt
;
assert
(
Target
&&
"Failed to get Target"
)
;
TargetMachine
*
TM
=
Target
->
createTargetMachine
(
"riscv32"
,
""
,
""
,
opt
,
Reloc
::
Default
,
CodeModel
::
Default
)
;
EXPECT_TRUE
(
isGlobalInSmallSection
(
gv
,
*
TM
)
)
;
delete
TM
;
}


llvm :: Metadata * getModuleMetadata ( llvm :: Module & M ) { llvm :: NamedMDNode * metaNode = M . getNamedMetadata ( "llvm.module.flags" ) ; if ( ! metaNode ) { return nullptr ; } for ( llvm :: MDNode * op : metaNode -> operands ( ) ) { llvm :: MDString * idNode = llvm :: dyn_cast < llvm :: MDString > ( op -> getOperand ( 0 ) -> get ( ) ) ; if ( idNode && idNode -> getString ( ) == "RISCV" ) { llvm :: Metadata * targetValue = op -> getOperand ( 1 ) . get ( ) ; if ( llvm :: ConstantInt * CI = llvm :: dyn_cast < llvm :: ConstantInt > ( targetValue ) ) { int64_t value = CI -> getValue ( ) . getSExtValue ( ) ; if ( value == 8 ) { llvm :: Metadata * nextValue = op -> getOperand ( 2 ) . get ( ) ; if ( llvm :: MDString * nextString = llvm :: dyn_cast < llvm :: MDString > ( nextValue ) ) { if ( nextString -> getString ( ) == "SmallDataLimit" ) { return targetValue ; } } } } } } return nullptr ; }


string getSectionForConstant ( SectionKind sectionKind ) { string section ; switch ( sectionKind ) { case SectionKind :: RISCV : case SectionKind :: RISCV : section = "riscv_section" ; break ; default : section = "" ; break ; } return section ; }


RISCVTargetLoweringInfo * RISCVTargetLoweringInfo :: Initialize ( TargetMachine & TM ) { RTM . setForRISCV ( ) ; RISCVTargetLoweringInfo * TLI = new RISCVTargetLoweringInfo ( ) ; TLI -> setTargetArch ( RISCV ) ; TLI -> setTargetGlobalAddress ( RISCV ) ; return TLI ; }


void emitTargetAttributes ( ) { IRBuilder < > Builder ( BasicBlock ) ; RISCVAttrs Attrs ; Attrs . add ( RISCVAttrs :: STACK_ALIGN , 1 ) ; Attrs . add ( RISCVAttrs :: ALIGN_4 , 1 ) ; Attrs . add ( RISCVAttrs :: ALIGN_16 , 1 ) ; uint64_t FeatureBits = RISCVFeatures :: parseFeatureBits ( Builder ) ; if ( FeatureBits & RISCV :: FeatureRV32E ) Attrs . add ( RISCVAttrs :: ARCH , "rv32e" ) ; else if ( FeatureBits & RISCV :: Feature64Bit ) Attrs . add ( RISCVAttrs :: ARCH , "rv64" ) ; Builder . addAttr ( "target-features" , Attrs . get ( ) ) ; }


void finish ( RISCV & Target ) { std :: set < RISCVRegister > LiveRegisters ; for ( RISCVInstruction & I : Target . getInstructions ( ) ) { for ( RISCVRegister Reg : I . getLiveRegisters ( ) ) { if ( Reg . isPhysical ( ) ) { LiveRegisters . insert ( Reg ) ; } } } for ( RISCVRegister Reg : LiveRegisters ) { Target . createLiveRange ( Reg ) ; } for ( RISCVInstruction & I : Target . getInstructions ( ) ) { RISCVOperandVector & Operands = I . getOperands ( ) ; for ( unsigned I = 0 , E = Operands . size ( ) ; I != E ; ++ I ) { if ( Operands [ I ] . isRegister ( ) && LiveRegisters . count ( Operands [ I ] . getReg ( ) ) ) { RISCVRegister LiveReg = Target . getLiveRange ( Operands [ I ] . getReg ( ) ) ; Operands [ I ] = RISCVOperand :: createReg ( LiveReg ) ; } } } Target . setTargetSpecificValue ( "RISCV" ) ; return Target ; }


void
reset
(
Def
,
Instance
)
{
RISCV
.
reset
(
Def
,
Instance
)
;
RISCV
.
reset
(
RISCV
.
target_specific_value
)
;
}
int
main
(
)
{
RISCV
riscv
=
new
RISCV
(
)
;
int
Def
=
10
;
int
Instance
=
1
;
reset
(
Def
,
Instance
)
;
std
::
cout
<<
"Scalar value reset for Def "
<<
Def
<<
" and Instance "
<<
Instance
<<
std
::
endl
;
return
0
;
}


void emitTargetAttributes ( LLVMContext & Context , MACHInst & Inst ) { if ( Inst . getKind ( ) != MACHInst :: RISCV ) { return ; } AttributeSet Attrs = AttributeSet :: get ( Context , AttributeSet :: FunctionIndex , "target-features" ) ; Attrs = Attrs . addAttribute ( Context , "target-cpu" , "riscv" ) ; if ( RISCV :: FeatureRV32E . inRange ( Inst . getFeatureBits ( ) ) ) { Attrs = Attrs . addAttribute ( Context , "target-features" , "rv32e" ) ; } Attrs = Attrs . addAttribute ( Context , "target-align-stack" , "4" ) ; Attrs = Attrs . addAttribute ( Context , "target-align-data" , "16" ) ; if ( RISCV :: Feature64Bit . inRange ( Inst . getFeatureBits ( ) ) ) { Attrs = Attrs . addAttribute ( Context , "target-features" , "rv64i" ) ; } Attrs = Attrs . addAttribute ( Context , "target-specific" , "RISCV" ) ; Attrs = Attrs . addAttribute ( Context , "target-specific-value" , "RISCVAttrs::ARCH" ) ; Inst . addFnAttr ( Attrs ) ; }


raw_ostream
&
OS
)
{
OS
<<
"\t.arch "
<<
CPU
<<
"\n"
;
for
(
StringRef
Feature
:
Features
.
split
(
','
)
)
{
OS
<<
"\t.attribute "
<<
Feature
<<
"\n"
;
}


void emitTargetAttributes ( LLVMContext & C , RISCVAttrs & Attrs ) { const RISCVTargetMachine & TM = static_cast < const RISCVTargetMachine & > ( C . getTargetIRAnalysis ( ) . getTargetMachine ( ) ) ; Module & M = const_cast < Module & > ( * TM . getModule ( ) ) ; M . addModuleFlag ( Module :: Warning , "RISCV" , RISCVAttrs :: STACK_ALIGN ) ; M . addModuleFlag ( Module :: Warning , "RISCV" , RISCVAttrs :: ALIGN_4 ) ; M . addModuleFlag ( Module :: Warning , "RISCV" , RISCVAttrs :: STACK_ALIGN ) ; M . addModuleFlag ( Module :: Warning , "RISCV" , RISCVAttrs :: ALIGN_16 ) ; M . addModuleFlag ( Module :: Warning , "RISCV" , RISCVAttrs :: ARCH ) ; if ( TM . getTargetTriple ( ) . getArch ( ) == Triple :: riscv32 ) { M . addModuleFlag ( Module :: Warning , "RISCV" , RISCV :: FeatureRV32E ) ; M . addModuleFlag ( Module :: Warning , "RISCV" , "rv32" ) ; } if ( TM . getTargetTriple ( ) . isArch64Bit ( ) ) { M . addModuleFlag ( Module :: Warning , "RISCV" , RISCV :: Feature64Bit ) ; M . addModuleFlag ( Module :: Warning , "RISCV" , "rv64" ) ; }


function getArithmeticReductionCost ( vectorType , operationType ) { cost = 0 foreach ( element in vectorType ) { cost = cost + element } switch ( operationType ) { case ADD : cost = cost * 2 break case OR : cost = cost * 3 break case XOR : cost = cost * 4 break case AND : cost = cost * 5 break case FADD : cost = cost * 6 break } return cost }


int getIntImmCostInst ( int immediate , int type , int inst , RISCV RISCV ) { int cost = 0 ; if ( immediate >= 0xffff || immediate <= - 0xffff ) { if ( type == 1 ) { cost += 10 ; } else if ( type == 0 ) { cost += 20 ; } if ( inst == LOAD ) { cost += 5 ; } if ( immediate < 0 ) { cost += 5 ; }


int getIntrinsicInstrCost ( TargetMachine * TM , Intrinsic :: ID ID , unsigned int Opcode , Type * RetTy , ArrayRef < Type * > Args , FastMathFlags FMF , unsigned int CostKind ) { if ( TM -> getTargetTriple ( ) . getArch ( ) != Triple :: riscv ) return - 1 ; if ( ID != Intrinsic :: experimental_stepvector ) return - 2 ; if ( Args . size ( ) != 2 ) return - 3 ; if ( CostKind != 1 ) return - 4 ; Type * ArgTy = Args [ 0 ] ; if ( ! ArgTy -> isRISCVectorType ( ) ) return - 5 ; unsigned int VecSize = ( unsigned int ) ArgTy -> getVectorNumElements ( ) ; return VecSize * 2 ; }


bool getMinMaxReductionCost ( llvm :: Instruction * op , llvm :: Instruction :: BinaryOps opcode , llvm :: Type * elementType , llvm :: Type * reductionType , int & cost ) { if ( target_specific_value == "RISCV,RISCV,2,1" ) { if ( elementType == llvm :: Type :: FloatTy && reductionType == llvm :: Type :: FloatTy ) { cost = 2 ; return true ; } if ( elementType == llvm :: Type :: IntTy && reductionType == llvm :: Type :: IntTy ) { cost = 1 ; return true ; } if ( elementType -> isVectorTy ( ) && elementType -> getScalarType ( ) == llvm :: Type :: FloatTy && reductionType -> isVectorTy ( ) ) { cost = 4 ; return true ; } if ( elementType -> isVectorTy ( ) && elementType -> getScalarType ( ) == llvm :: Type :: IntTy && reductionType -> isVectorTy ( ) ) { cost = 3 ; return true ; } } return false ; }


unsigned getRegUsageForType ( const Type * Ty ) { unsigned RISCVIntRegs = 32 ; unsigned RISCVFPRegs = 32 ; unsigned RISCVRVVRegs = 0 ; if ( Ty -> isIntegerTy ( ) ) { unsigned Size = Ty -> getPrimitiveSizeInBits ( ) ; unsigned RegCount = ( Size + ( RISCVIntRegs - 1 ) ) / RISCVIntRegs ; return RegCount ; } else if ( Ty -> isFloatingPointTy ( ) ) { unsigned Size = Ty -> getPrimitiveSizeInBits ( ) ; unsigned RegCount = ( Size + ( RISCVFPRegs - 1 ) ) / RISCVFPRegs ; return RegCount ; } else if ( Ty -> isVectorTy ( ) ) { unsigned Size = Ty -> getScalarSizeInBits ( ) ; unsigned RegCount = ( Size + ( RISCVRVVRegs - 1 ) ) / RISCVRVVRegs ; return RegCount ; } return 0 ; } unsigned getRegUsageForType ( const TargetRegisterClass * RC ) { const TargetRegisterInfo * TRI = RC -> TargetInstructionInfo ; BitVector ContainedRegs = TRI -> getAllocatableSet ( * TRI -> getTargetMachine ( ) ) ; return ContainedRegs . count ( ) ; }


bool isLegalMaskedGather ( ) { if ( Target . getTargetTriple ( ) . getArch ( ) != Triple :: riscv ) { return false ; } if ( Subtarget . hasMaskedGather ( ) ) { return true ; } return false ; }


bool isLegalMaskedLoad ( const TargetMachine & TM ) { const TargetSubtargetInfo * STI = TM . getSubtargetImpl ( ) ; const RISCVSubtarget * RISCVSTI = STI ? STI -> getSubtargetImpl ( ) : nullptr ; return RISCVSTI && RISCVSTI -> hasMaskedLoad ( ) ; }


bool isLegalMaskedScatter ( const TargetMachine & TM ) { return TM . getTargetTriple ( ) . getArch ( ) == Triple :: riscv ; }


bool isLegalMaskedStore ( ) { const FeatureBitset & featureBits = Subtarget -> getFeatureBits ( ) ; if ( ! featureBits [ RISCV :: FeatureMaskedStore ] ) return false ; return true ; }


const int getIntImmCostInst ( RISCVMachineFunction * MF , Type * Ty , uint64_t Val ) { if ( ! Ty -> isIntegerTy ( ) ) { return 0 ; } if ( Val == 0 ) { return 0 ; } return RISCV :: getIntImmCost ( ( RISCVSize ) Ty -> getPrimitiveSizeInBits ( ) , Val , 0 , 0 , MF -> getSubtarget ( ) . getRISCVIntImmCostKind ( ) ) ; }


int getIntImmCost ( uint64_t Value ) { if ( Value == 0 ) { return TargetCostConstants :: TCC_Free ; } return TargetCostConstants :: TCC_Basic ; }


uint32_t getNumberOfRegisters ( uint32_t Register ) { switch ( Register ) { case RISCV : return 32 ; case 1 : return 1 ; case 32 : return 0 ; case 31 : return 31 ; default : return 0 ; } }


int getIntImmCost ( RISCV :: Intrinsic :: ID TargetID , RISCV :: RISCV TargetRISCV , uint64_t Value ) { int maxCost = 0 ; switch ( TargetID ) { case RISCV :: Intrinsic :: ID :: RISCV_LUI : maxCost = 2 ; break ; case RISCV :: Intrinsic :: ID :: RISCV_ADDI : maxCost = 1 ; break ; case RISCV :: Intrinsic :: ID :: RISCV_ADDIW : maxCost = 2 ; break ; default : return - 1 ; } int cost = 0 ; if ( isInt < 12 > ( Value ) && isInt < 12 > ( Value , false ) ) { cost = 1 + ( TargetRISCV . hasBExtension ( ) ? 1 : 0 ) ; uint64_t extendedValue = SignExtend64 < 12 > ( Value ) ; if ( extendedValue != Value ) { cost += 1 ; } }


bool isHardwareLoopProfitable ( Loop * L ) { LLVMContext & Context = L -> getHeader ( ) -> getModule ( ) -> getContext ( ) ; if ( MDNode * MD = L -> getLoopID ( ) ) { for ( unsigned i = 0 , ie = MD -> getNumOperands ( ) ; i < ie ; ++ i ) { const MDOperand & Op = MD -> getOperand ( i ) ; if ( GlobalVariable * GV = dyn_cast < GlobalVariable > ( Op ) ) { if ( GV -> getName ( ) . equals ( "llvm.loop.set_loop_iterations" ) ) { unsigned Iterations = cast < ConstantInt > ( GV -> getInitializer ( ) -> getOperand ( 0 ) ) -> getZExtValue ( ) ; if ( Iterations > 0 ) { return getContext ( ) . getTargetInfo ( ) . isHardwareLoopsOptEnabled ( ) && getContext ( ) . getTargetInfo ( ) . isHardwareLoopProfitable ( getTarget ( ) , getTargetTriple ( ) , true , true , Iterations ) ; } } } } } return false ; }


bool isLoweredToCall ( Function * F ) { Triple TargetTriple ( F -> getParent ( ) -> getTargetTriple ( ) ) ; if ( TargetTriple . getArch ( ) != Triple :: riscv && TargetTriple . getVendor ( ) == "llvm" && TargetTriple . getOS ( ) == "riscv" && TargetTriple . getObjectFormat ( ) == "llvm.riscv.pulp" ) { return false ; } for ( BasicBlock & BB : * F ) { for ( Instruction & I : BB ) { if ( CallInst * CI = dyn_cast < CallInst > ( & I ) ) { Function * Callee = CI -> getCalledFunction ( ) ; if ( ! Callee || Callee -> isIntrinsic ( ) ) { return false ; } } } } return true ; }


llvm :: TargetTransformInfo :: UnrollingPreferences getUnrollingPreferences ( ) { llvm :: TargetTransformInfo :: UnrollingPreferences preferences ; preferences . SetUsePeeling ( false ) ; preferences . Partial = preferences . RuntimeOptimization = false ; preferences . Threshold = 60 ; preferences . PercentForLoopUnrolling = 0 ; preferences . DefaultUnrollRuntimeCount = 4 ; preferences . DefaultFullUnrollRuntimeCount = 12 ; preferences . AggressiveThresholdPercent = 0 ; preferences . MinPercentForWithAndIfBranchProbability = 0 ; preferences . LoopCharacteristics . push_back ( llvm :: TargetTransformInfo :: TCK_InstructionLatency ) ; preferences . LoopCharacteristics . push_back ( llvm :: TargetTransformInfo :: TCK_CodeSize ) ; preferences . InstructionCost = 2 ; preferences . LoopsInterleaveCount = 0 ; preferences . InterleaveCount = 0 ; preferences . Reciprocals = 0 ; preferences . VectorizationFactor = 4 ; preferences . SetHardwareLoopInfo ( llvm :: TargetTransformInfo :: HardwareLoopInfo ( 2 , true , false , false ) ) ; preferences . AdditionalInfo . setVectorization ( ) ; return preferences ; }


int getIntImmCost ( int64_t Value ) { int Cost = 0 ; if ( isInt < 12 > ( Value ) ) { Cost = 0 ; } else { int64_t HighBits = Value >> 32 ; if ( isInt < 12 > ( HighBits ) ) { Cost += 1 ; } else { Cost += RISCVMatInt :: getIntMatCost ( Instruction :: Load ) ; } int64_t LowBits = Value & 0xFFFFFFFF ; if ( isInt < 12 > ( LowBits ) ) { Cost += 1 ; } else { Cost += RISCVMatInt :: getIntMatCost ( Instruction :: Load ) ; } } return Cost ; }


define i32 @ getIntImmCostInst ( i32 % imm ) { entry : % imm_cost = call i32 @ llvm . riscv . getIntImmCost ( i32 % imm , i32 0 , i32 0 , i1 false , i1 true ) ret i32 % imm_cost }


bool isLoweredToCall ( const Function * F ) { std :: string target = Triple ( F -> getParent ( ) -> getTargetTriple ( ) ) . getArch ( ) ; if ( target == "riscv" ) { StringRef FName = F -> getName ( ) ; if ( FName . find ( "llvm.riscv.cv" ) != StringRef :: npos ) { return false ; } return true ; } return false ; }


Type * Ty ) { if ( ! Subtarget -> isRISCV ( ) ) return 0 ; if ( Ty -> getIntegerBitWidth ( ) != 64 ) return 0 ; unsigned NumBits = Val . getActiveBits ( ) - 64 ; return 1 << NumBits ; }


unsigned int getRegUsageForType ( Type * Ty , RISCV :: RVVBitsPerBlock ) { ... } ` ` ` The function name is getRegUsageForType , the return type is unsigned int , and the two parameters are Ty and RISCV :: RVVBitsPerBlock . Step 2 : Initialize the Register Count The function will calculate the estimated number of registers required to represent the given type . To start , we will initialize a variable named RegCount to 0 as follows : ` ` ` unsigned int getRegUsageForType ( Type * Ty , RISCV :: RVVBitsPerBlock ) { unsigned int RegCount = 0 ; ... } ` ` ` Step 3 : Check if the given type is a vector type The RISC - V Vector Extension ( RVV ) supports vector data types that have a fixed number of elements . Therefore , the first step in calculating the register usage for a type is to check if it is a vector type . ` ` ` unsigned int getRegUsageForType ( Type * Ty , RISCV :: RVVBitsPerBlock ) { unsigned int RegCount = 0 ; if ( Ty -> isVectorTy ( ) ) { ... } return RegCount ; } ` ` ` Step 4 : Get the Vector Element Type If the given type is a vector type , we need to calculate the register usage for the vector element type . We can use the function getVectorElementType to get the element type of the vector type as follows : ` ` ` if ( Ty -> isVectorTy ( ) ) { Type * ElemTy = dyn_cast < VectorType > ( Ty ) -> getElementType ( ) ; ... } ` ` ` Step 5 : Calculate the Number of Elements To get the estimated number of registers required for the vector type , we need to calculate the number of elements in the vector . We can use the getVectorNumElements function to get this value as follows : ` ` ` if ( Ty -> isVectorTy ( ) ) { Type * ElemTy = dyn_cast < VectorType > ( Ty ) -> getElementType ( ) ; unsigned int NumElements = dyn_cast < VectorType > ( Ty ) -> getNumElements ( ) ; ... }


llvm
::
UnrollingPreferences
getUnrollingPreferences
(
)
{
llvm
::
UnrollingPreferences
preferences
;
preferences
.
Opcode
=
RISCV
::
INSTS
;
preferences
.
ConsecutiveDepCheck
=
true
;
preferences
.
MaxLoopSize
=
0
;
preferences
.
Partial
=
0
;
preferences
.
RuntimeChunkSize
=
4
;
preferences
.
AllowPartial
=
0
;
preferences
.
Prefix
=
"Loop has:\n"
;
preferences
.
CountS
=
"Blocks: "
;
preferences
.
BodyS
=
"\n"
;
preferences
.
ExitS
=
"Exit blocks: "
;
preferences
.
Width
=
2
;
preferences
.
UnrollStyle
=
4
;
preferences
.
VectorizeFlag
=
"llvm.loop.isvectorized"
;
preferences
.
VectorizeWidth
=
0
;
preferences
.
VectorizeCost
=
"Cost of loop: "
;
preferences
.
PrimitiveCost
=
60
;
preferences
.
DuplicateFactor
=
12
;
return
preferences
;
}


unsigned int getIntImmCost ( const RISCVInstrInfo & InstInfo , unsigned int Opcode , int64_t Value , unsigned int Idx , const RISCVSubtarget & ) { if ( Opcode == RISCV :: ADDI || Opcode == RISCV :: ADDI64 ) { return 1 ; } return 0 ; }


function getGatherScatterOpCost ( Target , DstTy , NumIndices ) { if ( Target != RISCV ) { return 0 ; } Size = getTypeSizeInBytes ( DstTy ) ; Cost = Size * NumIndices ; return Cost ; }


int RISCVTargetLowering :: getIntImmCost ( const APInt & Imm , Type * Ty , TLIContext & Ctx ) const { return 64 ; }


int getIntImmCostInst ( uint8_t OpType , uint64_t Immediate ) { int Cost = 0 ; if ( OpType != RISCV ) return Cost ; if ( Immediate > 0xFFFFFFFF ) return Cost ; if ( Immediate <= 0xFF ) { Cost = 1 ; } else if ( Immediate <= 0xFFFF ) { Cost = 2 ; } else if ( Immediate <= 0xFFFFFF ) { Cost = 3 ; } else if ( Immediate <= 0xFFFFFFFF ) { Cost = 4 ; } return Cost ; }


llvm :: TargetLowering * getTLI ( llvm :: RISCVModule & Input ) { return ( new llvm :: RISCVTargetLowering ( Input . getInfo ( ) ) ) . getTLI ( ) ; }


void workaround_arc_anomaly ( ) { set_target ( "arc" ) ; arc_hazard ( ) ; compute_branch_shortening ( NOP_SIZE ) ; set_target ( "default" ) ; }