void runOnMachineFunction ( MachineFunction & MF ) { const TargetSubtargetInfo & STI = MF . getSubtarget ( ) ; const TargetInstrInfo & TII = * STI . getInstrInfo ( ) ; const NVPTXInstrInfo * NVPTXII = static_cast < const NVPTXInstrInfo * > ( TII ) ; const NVPTXFrameLowering * NVPTXFL = STI . getFrameLowering ( ) ; MachineModuleInfo * MMI = MF . getMMI ( ) ; const MachineFunction & MF = MMI -> getMachineFunction ( ) ; MachineBasicBlock & EntryMBB = MF . CreateMachineBasicBlock ( ) ; MF . insert ( MF . begin ( ) , & EntryMBB ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; MachineConstantPool * MCP = MMI -> getConstantPool ( ) ; MachineJumpTableInfo * MJTI = MMI -> getJumpTableInfo ( ) ; MachineDominatorTree * MDT = nullptr ; if ( MF . shouldKeepCFG ( ) ) { MDT = new MachineDominatorTree ( MF ) ; } MachineLoopInfo * MLI = nullptr ; if ( MF . shouldKeepCFG ( ) ) { MLI = new MachineLoopInfo ( * MDT ) ; } MachineBranchProbabilityInfo * MBPI = nullptr ; if ( MF . shouldTrackBranchProbability ( ) ) { MBPI = new MachineBranchProbabilityInfo ( MF ) ; } MachinePostDominatorTree * MPDT = nullptr ; if ( MF . shouldKeepCFG ( ) && MF . shouldDoPostMISched ( ) ) { MPDT = new MachinePostDominatorTree ( ) ; MPDT -> runOnMachineFunction ( MF ) ; }


bool
runOnMachineFunction
(
MachineFunction
&
MF
)
{
const
NVPTXSubtarget
&
ST
=
MF
.
getSubtarget
<
NVPTXSubtarget
>
(
)
;
MachineBasicBlock
&
MBB
=
MF
.
front
(
)
;
NVPTXMachineFunctionInfo
*
MFI
=
MF
.
getInfo
<
NVPTXMachineFunctionInfo
>
(
)
;
MFI
->
setTargetSpecificValue
(
NVPTX
,
NVPTX
,
0
,
0
)
;
for
(
auto
&
MI
:
MBB
)
{
unsigned
Opcode
=
MI
.
getOpcode
(
)
;
if
(
Opcode
==
NVPTX
::
RET
)
{
Outs
<<
'\t'
<<
"return"
;
unsigned
NumOperands
=
MI
.
getNumOperands
(
)
;
if
(
NumOperands
>
0
)
{
unsigned
RetValReg
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
Outs
<<
' '
<<
getRegisterName
(
RetValReg
)
;
}
Outs
<<
'\n'
;
}


void runOnMachineFunction ( MachineFunction & MF ) { MF . setSubtarget ( NVPTX :: NVPTXSubtarget :: NVPTX , NVPTX :: NVPTXSubtarget :: NVPTX , 0 , 0 ) ; }


"Frame indices can only appear as the first operand of a DBG_VALUE machine instruction"


void runOnMachineFunction ( MachineFunction & MF ) { if ( MF . getTarget ( ) . getTargetTriple ( ) != "NVPTX-NVPTX-0-0" ) { return ; } MachineBasicBlock & MBB = MF . front ( ) ; for ( MachineBasicBlock :: iterator MI = MBB . begin ( ) , E = MBB . end ( ) ; MI != E ; ++ MI ) { MachineInstr & I = * MI ; if ( ! isTargetSpecific ( I ) ) { continue ; } emitTargetInstruction ( I ) ; } if ( needsAdditionalCodeGen ( MF ) ) { handleAdditionalCodeGen ( MF ) ; } return ; }


bool
runOnMachineFunction
(
MachineFunction
&
MF
)
{
MachineModuleInfo
&
MMI
=
MF
.
getMMI
(
)
;
const
Module
*
M
=
MMI
.
getModule
(
)
;
MachineModuleInfoNVPTX
&
MMINVPTX
=
MMI
.
getObjFileInfo
<
MachineModuleInfoNVPTX
>
(
)
;
const
NVPTXTargetStreamer
&
Stream
=
MMI
.
getObjFileInfo
<
NVPTXTargetStreamer
>
(
)
;
const
ModuleManager
&
MM
=
Stream
.
getModuleManager
(
)
;
const
MachineFunctionInfo
*
MFI
=
MF
.
getInfo
<
MachineFunctionInfo
>
(
)
;
MachineFunctionInfoNVPTX
*
MFInfo
=
MF
.
getInfo
<
MachineFunctionInfoNVPTX
>
(
)
;
MFInfo
->
init
(
)
;
const
NVPTXRegisterInfo
*
TRI
=
static_cast
<
const
NVPTXRegisterInfo
*
>
(
MF
.
getTarget
(
)
.
getRegisterInfo
(
)
)
;
MachineRegisterInfo
&
MRI
=
MF
.
getRegInfo
(
)
;
const
Function
*
F
=
MF
.
getFunction
(
)
;
bool
isKernel
=
F
->
hasFnAttribute
(
"nvvm-kernel"
)
;
MMI
.
beginFunction
(
&
MF
,
isKernel
)
;
const
FunctionType
*
FTy
=
F
->
getFunctionType
(
)
;
const
SmallVector
<
RegisterInfo
*
,
8
>
&
ReservedRegs
=
TRI
->
getReservedRegs
(
)
;
for
(
unsigned
i
=
0
,
e
=
FTy
->
getNumParams
(
)
;
i
!=
e
;
++
i
)
{
Register
ArgReg
=
MRI
.
createGenericVirtualRegister
(
ReservedRegs
[
i
]
)
;
ArgReg
.
SubRegs
=
isKernel
TRI
->
getSubRegs
(
ArgReg
.
Reg
)
:
;
MRI
.
addLiveIn
(
ReservedRegs
[
i
]
,
ArgReg
)
;
}
MMI
.
beginFunction
(
&
MFINFPTX
)
;
LLVM_DEBUG
(
errs
(
)
<<
"Machine Function["
<<
MF
.
getFunctionNumber
(
)
<<
"] emitted\n"
)
;
return
true
;
}


bool runOnMachineFunction ( MachineFunction & MF ) { const Triple & TT = MF . getTarget ( ) . getTargetTriple ( ) ; if ( ! TT . isNVPTX ( ) ) return false ; MF . getTarget ( ) . setTargetSpecificOption ( "nvptx" , "nvptx" ) ; MF . getTarget ( ) . setTargetSpecificOption ( "nvptx-float-mode" , "0" ) ; MF . getTarget ( ) . setTargetSpecificOption ( "nvptx-long-double-size" , "0" ) ; return true ; }


bool runOnMachineFunction ( MachineFunction & MF ) { const TargetInstrInfo * TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const TargetFrameLowering * TFI = MF . getSubtarget ( ) . getFrameLowering ( ) ; const uint32_t TargetID = NVPTX ; const uint32_t FeatureBits = NVPTX ; MachineModuleInfo MMI ( MF . getFunction ( ) . getParent ( ) ) ; MachineIRBuilder MIRBuilder ( MF ) ; const MCInstrDesc & PrologueDesc = TII -> get ( NVPTX :: PROLOG_LABEL ) ; MachineInstrBuilder MIB = MIRBuilder . buildInstr ( PrologueDesc ) ; MIB . addImm ( TargetID ) ; MIB . addImm ( FeatureBits ) ; const MCInstrDesc & EpilogueDesc = TII -> get ( NVPTX :: EPILOG_LABEL ) ; MIB = MIRBuilder . buildInstr ( EpilogueDesc ) ; MIB . addImm ( TargetID ) ; MIB . addImm ( FeatureBits ) ; MIRBuilder . finalize ( MF ) ; return true ; }


"Frame indices can only appear as the first "

"operand of a DBG_VALUE machine instruction"


void runOnMachineFunction ( MachineFunction & MF ) { }


void runOnMachineFunction ( MachineFunction & MF ) { const TargetLowering * TLI = MF . getTarget ( ) . getTargetLowering ( ) ; const NVPTXTargetLowering * NVTX_TLI = static_cast < const NVPTXTargetLowering * > ( TLI ) ; const NVPTXMachineFunctionInfo * NVPTX_MFI = MF . getInfo < NVPTXMachineFunctionInfo > ( ) ; for ( MachineBasicBlock & MBB : MF ) { for ( MachineInstr & MI : MBB ) { unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { case NVPTX :: NVPTX_CAT : case NVPTX :: NVPTX_SMEET : default : NVTX_TLI -> emitInstruction ( & MBB , & MI ) ; break ; } } } MF . getRegInfo ( ) . setMapping ( NVPTX :: NVPTX , NVTX_TLI -> getRegisterInfo ( MF ) ) ; MF . getRegInfo ( ) . setMapping ( NVPTX :: NVPTX_MEM , NVTX_TLI -> getMemoryInfo ( MF ) ) ; MF . getRegInfo ( ) . setMapping ( NVPTX :: NVPTX_ZERO , NVTX_TLI -> getZeroReg ( MF ) ) ; MF . getRegInfo ( ) . setMapping ( NVPTX :: NVPTX_ONE , NVTX_TLI -> getOneReg ( MF ) ) ; NVPTX_MFI -> setNumHWRegs ( TLI -> getNumRegs ( ) ) ; NVPTX_MFI -> setScratchSize ( TLI -> getScratchMemSize ( & MF ) ) ; NVPTX_MFI -> setMaxBRegs ( NVPTX_MFI -> useAllBRegs ( ) ? TLI -> getMaxBRegs ( ) : NVPTX_MFI -> getNumBRegs ( ) ) ; NVPTX_MFI -> finalizeLowering ( ) ; }


"NVPTX Proxy Register Instruction Erasure"


void runOnMachineFunction ( MachineFunction & MF ) { MachineBasicBlock & MBB = MF . front ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; const TargetRegisterClass * I1RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegI1 ) ; const TargetRegisterClass * I16RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegI16 ) ; const TargetRegisterClass * I32RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegI32 ) ; const TargetRegisterClass * I64RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegI64 ) ; const TargetRegisterClass * F16RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegF16 ) ; const TargetRegisterClass * F16x2RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegF16x2 ) ; const TargetRegisterClass * F32RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegF32 ) ; const TargetRegisterClass * F64RC = MRI . getTargetRegisterInfo ( ) -> getRegClass ( NVPTX :: ProxyRegF64 ) ; for ( MachineBasicBlock :: iterator I = MBB . begin ( ) , E = MBB . end ( ) ; I != E ; ++ I ) { MachineInstr & MI = * I ; for ( unsigned i = 0 , e = MI . getNumOperands ( ) ; i != e ; ++ i ) { MachineOperand & MO = MI . getOperand ( i ) ; if ( MO . isReg ( ) ) { unsigned Reg = MO . getReg ( ) ; if ( NVPTX :: ProxyRegI1 . contains ( Reg ) ) { MO . setReg ( MRI . createVirtualRegister ( I1RC ) ) ; } else if ( NVPTX :: ProxyRegI16 . contains ( Reg ) ) { MO . setReg ( MRI . createVirtualRegister ( I16RC ) ) ; }


std
::
string
getName
(
const
llvm
::
Function
&
F
,
llvm
::
StringRef
TargetID
)
{
if
(
TargetID
!=
"NVPTX"
)
{
return
""
;
}
llvm
::
BasicBlock
&
BB
=
F
.
getEntryBlock
(
)
;
llvm
::
LoopInfoEx
&
LI
=
llvm
::
getAnalysis
<
llvm
::
LoopInfoEx
>
(
F
)
;
const
llvm
::
DenseMap
<
llvm
::
Loop
*
,
llvm
::
VectorShape
::
Shape
>
*
VFMap
=
LI
.
getVectorizationFactor
(
)
;
const
llvm
::
DenseMap
<
llvm
::
Loop
*
,
llvm
::
VectorShape
::
Shape
>
*
UFMap
=
LI
.
getUnrollFactor
(
)
;
std
::
vector
<
llvm
::
VectorShape
::
Shape
>
VFList
;
std
::
vector
<
llvm
::
VectorShape
::
Shape
>
UFList
;
for
(
llvm
::
Loop
*
L
:
LI
)
{
auto
VFIt
=
VFMap
->
find
(
L
)
;
auto
UFIt
=
UFMap
->
find
(
L
)
;
if
(
VFIt
!=
VFMap
->
end
(
)
)
{
VFList
.
push_back
(
VFIt
->
second
)
;
}
if
(
UFIt
!=
UFMap
->
end
(
)
)
{
UFList
.
push_back
(
UFIt
->
second
)
;
}
}
std
::
string
OutputStr
=
"Plan name: "
+
F
.
getName
(
)
.
str
(
)
+
" | VFs: "
;
for
(
auto
VF
:
VFList
)
{
OutputStr
+=
std
::
to_string
(
VF
)
+
" "
;
}
OutputStr
+=
"| UFs: "
;
for
(
auto
UF
:
UFList
)
{
OutputStr
+=
std
::
to_string
(
UF
)
+
" "
;
}
return
OutputStr
;
}


bool & ChangesMade ) { const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; unsigned FrameReg = TRI -> getFrameRegister ( MF ) ; MachineBasicBlock & MBB = MF . front ( ) ; MachineBasicBlock :: iterator I = MBB . begin ( ) , E = MBB . end ( ) ; while ( I != E ) { MachineInstr & MI = * I ; bool IsCall = MI . isCall ( ) ; bool IsStore = MI . getOpcode ( ) == NVPTX :: ST ; int FrameNDXOperand = MI . findRegisterUseOperandIdx ( FrameReg , false ) ; if ( FrameNDXOperand != - 1 ) { MachineOperand & FrameNDX = MI . getOperand ( FrameNDXOperand ) ; FrameNDX . ChangeToImmediate ( 0 ) ; if ( IsCall ) { MachineOperand & MNCC = MI . getOperand ( FrameNDXOperand - 1 ) ; if ( MNCC . isFI ( ) ) { MNCC . ChangeToImmediate ( 0 ) ; } } if ( IsStore ) { MachineOperand & StoreOperand = MI . getOperand ( FrameNDXOperand + 1 ) ; if ( StoreOperand . isFI ( ) ) { StoreOperand . ChangeToImmediate ( 0 ) ; } } } ++ I ; } ChangesMade = true ; }


BitVector getReservedRegs ( ) { BitVector ReservedRegs ( NVPTX :: NUM_TARGET_REGS ) ; ReservedRegs . set ( NVPTX :: ENVREG0 ) ; ReservedRegs . set ( NVPTX :: ENVREG31 ) ; ReservedRegs . set ( NVPTX :: VRFrame32 ) ; ReservedRegs . set ( NVPTX :: VRFrameLocal32 ) ; ReservedRegs . set ( NVPTX :: VRFrame64 ) ; ReservedRegs . set ( NVPTX :: VRFrameLocal64 ) ; ReservedRegs . set ( NVPTX :: VRDepot ) ; return ReservedRegs ; }


void getCalleeSavedRegs ( const MachineFunction & MF , BitVector & SavedRegs , const TargetRegisterInfo * TRI ) { const TargetMachine & TM = MF . getTarget ( ) ; const uint32_t CalleeSavedRegs [ ] = { NVPTX :: NVPTX , NVPTX :: NVPTX , 0 } ; const uint32_t * CalleeSavedRegsBegin = CalleeSavedRegs ; const uint32_t * CalleeSavedRegsEnd = CalleeSavedRegs + array_lengthof ( CalleeSavedRegs ) ; for ( uint32_t RegNum : make_range ( CalleeSavedRegsBegin , CalleeSavedRegsEnd ) ) { SavedRegs . set ( RegNum ) ; } }


"Dwarf register number for NVPTX register 10 is %d\n"


Register getRARegister ( void ) const { Register RAReg = NVPTX :: VR0 ; return RAReg ; }


MachineBasicBlock :: iterator MI ) const { for ( MachineBasicBlock :: iterator I = MBB . begin ( ) , E = MBB . end ( ) ; I != E ; ) { MachineInstr & MI = * I ; if ( MI . getOpcode ( ) == NVPTX :: VRFrame ) { unsigned FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; MI . setDesc ( TII -> get ( NVPTX :: IMPLICIT_DEF ) ) ; MI . RemoveOperand ( 1 ) ; MI . addReg ( 0 ) ; MI . getOperand ( 1 ) . setImm ( FrameIndex ) ; } ++ I ; } }


std :: vector < MCPhysReg > getCalleeSavedRegs ( NVPTXTarget const & target , int target_specific_value ) { if ( target_specific_value != NVPTX , NVPTX , 0 ) { return { } ; } std :: vector < MCPhysReg > callee_saved_regs ; for ( MCPhysReg reg : target . getRegisters ( ) ) { if ( isCalleeSaved ( reg , target ) ) { callee_saved_regs . push_back ( reg ) ; } } return callee_saved_regs ; } bool isCalleeSaved ( MCPhysReg reg , NVPTXTarget const & target ) { return ! isReturnReg ( reg , target ) && ! isCallerModified ( reg , target ) ; }


void eliminateFrameIndex ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) { if ( ! MF . getTarget ( ) . isNVPTX ( ) ) return ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; DebugLoc DL = MI -> getDebugLoc ( ) ; for ( MachineBasicBlock :: iterator MII = MBB . begin ( ) , MIE = MBB . end ( ) ; MII != MIE ; ++ MII ) { if ( MII -> isTargetSpecific ( ) && MII -> getOpcode ( ) == NVPTX :: VRFrame ) { unsigned FrameIdx = MII -> getOperand ( 0 ) . getIndex ( ) ; if ( MFI . isFrameIndexUsed ( FrameIdx ) ) { int FIdx = MFI . getObjectIndexBegin ( ) + FrameIdx ; MFI . replaceFrameIndex ( FrameIdx , FIdx ) ; MII -> eraseFromParent ( ) ; } } } }


"Instr doesn't have FrameIndex operand!"


MachineBasicBlock :: iterator MI ) override { for ( MachineBasicBlock :: iterator I = MBB . begin ( ) , E = MBB . end ( ) ; I != E ; ++ I ) { MachineInstr & Inst = * I ; if ( Inst . hasTargetMemoryOpcode ( ) && Inst . getNumOperands ( ) > 0 && Inst . getOperand ( 0 ) . isFI ( ) ) { unsigned FrameIndexOpIdx = Inst . getOperand ( 0 ) . getOperandNo ( ) ; Register Reg = getRegForFrameIndex ( FrameIndexOpIdx , MF ) ; Inst . getOperand ( 0 ) . ChangeToRegister ( Reg , false ) ; } } MachineBasicBlock :: eliminateFrameIndex ( MF , MBB , MI ) ; }


void dummyFunction ( ) { llvm :: Register frameReg = getFrameRegister ( this ) ; frameReg . dump ( ) ; }


llvm :: BitVector llvm :: NVPTXRegisterInfo :: getReservedRegs ( const llvm :: TargetRegisterInfo * TRI , const llvm :: MachineFunction & MF ) { unsigned NumRegs = TRI -> getNumRegs ( ) ; llvm :: BitVector ReservedRegs ( NumRegs ) ; for ( int Reg = 0 ; Reg < NumRegs ; Reg ++ ) { if ( TRI -> isReserved ( Reg ) ) { ReservedRegs . set ( Reg ) ; } } return ReservedRegs ; }


StringRef
getPassName
(
)
{
StringRef
target
=
"NVPTX Replace Image Handles"
;
return
target
;
}


string
getPassName
(
)
{
return
"NVPTX Replace Image Handles"
;
}


bool isVirtualSection ( Section section ) { TargetSpecificValue targetSpecific = section . getTargetSpecificValue ( NVPTX ) ; if ( targetSpecific . hasObjectFileContent ( ) ) { return false ; } else { return true ; } }


void getAnalysisUsage ( AnalysisUsage & Info ) const override { LLVMTargetMachine :: getAnalysisUsage ( Info ) ; Info . addRequired < PTXInfo > ( ) ; Info . addPreserved < PTXInfo > ( ) ; Info . addRequired < NVPTXTargetTransformInfo > ( ) ; Info . addRequired < TargetLibraryInfoWrapperPass > ( ) ; Info . addRequired < NVPTXLowerKernelArgsPass > ( ) ; }


std
::
string
getPassName
(
)
{
return
"Split basic blocks at barrier"
;
}


bool runOnFunction ( Function * F , PassManager & PM ) { bool modified = false ; for ( BasicBlock & BB : * F ) { for ( Instruction & I : BB ) { if ( auto * CI = dyn_cast < CallInst > ( & I ) ) { if ( CI -> getCalledFunction ( ) -> getName ( ) == "bar_split" ) { auto * bar = CallInst :: CreateIntrinsic ( Intrinsic :: nvvm_bar_syncscope0_smem , None , { CI } ) ; BB . getInstList ( ) . insertAfter ( CI , bar ) ; BB . splitBasicBlock ( bar -> getIterator ( ) ) ; modified = true ; } if ( CI -> getCalledFunction ( ) -> getName ( ) == "NVPTX.barrier" ) { CI -> eraseFromParent ( ) ; modified = true ; } } } } if ( modified ) { PM . markFunctionAsModified ( F ) ; } return modified ; }


void
initializeSubtargetDependencies
(
CPU
c
,
TuneCPU
t
,
std
::
string
feature
)
{
const
llvm
::
SubtargetFeatures
featureList
{
feature
}
;
const
llvm
::
Target
*
parent
=
llvm
::
TargetRegistry
::
lookupTarget
(
"NVPTX"
)
;
assert
(
parent
&&
"NVPTX target not found"
)
;
llvm
::
TargetOptions
options
=
getDefaultTargetOptions
(
)
;
llvm
::
TargetMachine
*
tm
=
parent
->
createTargetMachine
(
"sm_20"
,
""
,
""
,
options
,
llvm
::
Reloc
::
Model
::
Static
)
;
tm
->
createPassConfig
(
llvm
::
CodeGenOpt
::
Level
::
Aggressive
)
;
llvm
::
CodeModel
::
Model
CM
=
llvm
::
CodeModel
::
Model
::
Small
;
llvm
::
SubtargetFeatures
subtargetFeatures
(
featureList
.
getString
(
)
)
;
const
NVPTXSubtarget
subtarget
=
parent
->
createSubtargetImpl
(
NVPTX_MC
::
getFeatureBits
(
"sm_20"
,
0
,
32
)
,
feature
,
subtargetFeatures
,
*
tm
,
""
,
CM
)
;
subtarget
.
initializeSubtargetDependencies
(
c
,
t
,
feature
)
;
}


void NVPTXSubtarget ( LLVMModule * M ) { NVPTXSubtargetData = { NVPTX , NVPTX , NVPTX , NVPTX , NVPTX , 0 , 20 } ; M -> addTargetSubtargetInfo ( NVPTXCreateTargetSubtargetInfo ( NVPTX , NVPTXSubtargetData ) ) ; }


TargetInstrInfo * getInstrInfo ( const NVPTXTargetMachine & TM , NVPTXSubtarget & STI ) { TargetInstrInfo * TII = new TargetInstrInfo ( TM ) ; TII -> setNVPTX ( STI ) ; return TII ; }


TargetInstrInfo * getRegisterInfo ( const Target & T , const Pass & P ) { if ( T . getArch ( ) != NVPTX :: Arch ) return nullptr ; const TargetRegisterInfo * TRI = T . getRegisterInfo ( ) ; const TargetInstrInfo * TII = T . getInstrInfo ( ) ; NVPTX :: TargetInstrInfo * TargetInfo = new NVPTX :: TargetInstrInfo ( TRI ) ; TargetInfo -> TII = TII ; return TargetInfo ; }


void initializeSubtargetDependencies ( NVPTXSubtarget & ST , const NVPTXTargetMachine & TM , StringRef CPU , StringRef TuneCPU , StringRef FeatureStr ) { ST . setCPU ( CPU ) ; ST . setTuneCPU ( TuneCPU ) ; ST . setFeatureString ( FeatureStr ) ; ST . setTargetID ( NVPTX :: NVPTX ) ; ST . setFeatureString ( "" ) ; ST . setTargetSpecificFlag ( TargetInfo :: CF_NVIDIATARGET ) ; ST . setTargetSpecificFlag ( FeatureBitset ( NVPTX :: FeatureSet_SM_20 ) ) ; ST . dataSectionAlignment = 32 ; ST . toplevelSchedulingPreference = Sched :: Source ; }


void NVPTXSubtarget ( Module * M ) { NVPTXSubtarget * NVPTXTarget = new NVPTXSubtarget ( ) ; NVPTXTarget -> setNVPTXVersion ( "NVPTX" ) ; NVPTXTarget -> setTargetID ( "NVPTX" ) ; NVPTXTarget -> setFeatureString ( "NVPTX,NVPTX,NVPTX,NVPTX,NVPTX,0,20" ) ; M -> setSubtarget ( NVPTXTarget ) ; return NVPTXTarget ; }


"nvptx;nvptx;nvvm;0;10;sm_10;we are not using FeatureStr;0;31"


NVPTXSubtarget NVPTXSubtarget ( Module & M ) { TargetOptions Options ; NVPTXSubtarget Subtarget ( M , std :: string ( M . getTargetTriple ( ) . getArchName ( ) ) , std :: string ( M . getTargetTriple ( ) . getTriple ( ) ) ) ; Subtarget . is64Bit ( ) = ( M . getDataLayout ( ) . getPointerSize ( 0 ) == 8 ) ; Subtarget . hasDRISC ( ) = strcmp ( M . getTargetTriple ( ) . getArchName ( ) , "NVPTX64" ) == 0 || strcmp ( M . getTargetTriple ( ) . getArchName ( ) , "NVPTX" ) == 0 ; Subtarget . hasImageHandles ( ) = true ; Subtarget . hasAtomics ( ) = true ; Subtarget . hasFMA ( ) = true ; Subtarget . hasLDG ( ) = true ; Subtarget . hasSM75 ( ) = false ; Subtarget . GVAlignInBits = 128 ; Subtarget . SharedAlignInBits = 32 ; Subtarget . LocalAlignInBits = 32 ; Subtarget . GenericAlignInBits = 32 ; Subtarget . StackAlignment = 256 ; Subtarget . FunctionAlignment = 1 ; Subtarget . enableExtPipes ( ) = true ; Subtarget . enableMemoryPredication ( ) = true ; Subtarget . features ( ) . AddFeature ( "ptx50" ) ; Subtarget . features ( ) . AddFeature ( "width64" ) ; Subtarget . features ( ) . AddFeature ( "stride128" ) ; Subtarget . sm_version = 75 ; Subtarget . setTargetAEmm ( Subtarget . hasSM50 ( ) , Subtarget . hasSM61 ( ) , Subtarget . hasSM70 ( ) , Subtarget . hasSM75 ( ) , 0 , 20 ) ; return Subtarget ; }


void initializeSubtargetDependencies ( CPU , TuneCPU , FeatureString ) { Subtarget -> setTargetArch ( NVPTX ) ; Subtarget -> setCPU ( TuneCPU ) ; Subtarget -> ToggleFeature ( "sm_20" , true ) ; Subtarget -> setTargetVersion ( 0 ) ; Subtarget -> setTargetAddressSpace ( 32 ) ; }


InstrItins ( NVPTXInstrItineraryData ) { std :: string CPUName = CPU ; if ( CPUName . empty ( ) ) CPUName = "sm_10" ; ParseSubtargetFeatures ( CPUName , FS ) ; } void NVPTXSubtarget :: ParseSubtargetFeatures ( StringRef CPUName , StringRef FS ) { if ( FS . empty ( ) ) FS = "+ptx20,+ptx30,+ptx40" ; std :: string TargetFS = "ptx20,ptx30,ptx40" ; if ( CPUName == "ptx" ) { if ( ! FeatureStr . empty ( ) ) TargetFS = "+" + TargetFS ; ParseSubtargetFeatures ( TargetFS , "" ) ; return ; } if ( CPUName == "ptx20" ) InstrInfo = & NVPTXInstrInfo :: ptx20InstrInfo ; else if ( CPUName == "ptx30" ) InstrInfo = & NVPTXInstrInfo :: ptx30InstrInfo ; else InstrInfo = & NVPTXInstrInfo :: ptx40InstrInfo ; InitCPUSchedModel ( CPUName ) ; ParseSubtargetFeatures ( TargetFS , FS ) ; }


void initializeSubtargetDependencies ( CPU , TuneCPU , featureStr ) { LLVMInitializeNVPTXTargetInfo ( ) ; LLVMInitializeNVPTXTarget ( ) ; LLVMInitializeNVPTXTargetMC ( ) ; StringRef CPU ( CPU ) ; StringRef TuneCPU ( TuneCPU ) ; StringRef featureStr ( featureStr ) ; NVPTX :: initializeSubtargetDependencies ( CPU , TuneCPU , featureStr ) ; }


void
NVPTXSubtarget
(
Module
*
M
)
{
NVPTXTargetMachine
TM
;
NVPTXSubtarget
STI
;
M
->
setTargetTriple
(
"nvptx64-nvidia-cuda"
)
;
STI
.
NVPTX
::
PTXVersion
=
NVPTX
::
PTX20
;
STI
.
NVPTX
::
PTXFeatureVersion
=
0
;
STI
.
NVPTX
::
TargetCPU
=
NVPTX
::
SM_20
;
STI
.
NVPTX
::
TargetABI
=
NVPTX
::
NVCL
;
STI
.
NVPTX
::
TargetType
=
NVPTX
::
CUDA
;
TM
.
initTargetMachine
(
)
;
M
->
setTargetMachine
(
TM
)
;
llvm
::
errs
(
)
<<
"PTXVersion: "
<<
STI
.
NVPTX
::
PTXVersion
<<
"\n"
;
llvm
::
errs
(
)
<<
"PTXFeatureVersion: "
<<
STI
.
NVPTX
::
PTXFeatureVersion
<<
"\n"
;
llvm
::
errs
(
)
<<
"TargetCPU: "
<<
STI
.
NVPTX
::
TargetCPU
<<
"\n"
;
llvm
::
errs
(
)
<<
"TargetABI: "
<<
STI
.
NVPTX
::
TargetABI
<<
"\n"
;
llvm
::
errs
(
)
<<
"TargetType: "
<<
STI
.
NVPTX
::
TargetType
<<
"\n"
;
}


function NVPTXSubtarget ( module ) { this . NVPTX = module this . NVPTX = module this . NVPTX = module this . NVPTX = module this . NVPTX = module this . NVPTX = 0 this . NVPTX = 20 }


GPU ( M . getTargetTriple ( ) . isOSBinFormatMachO ( ) ? NVPTX :: NVCL : NVPTX :: CUDA ) { ... }


DataLayout getDataLayout ( Module & M , const TargetOptions & Options ) { Triple TargetTriple = Triple ( M . getTargetTriple ( ) ) ; std :: string DataLayoutString = createNVPTXDataLayoutString ( TargetTriple ) ; return DataLayout ( DataLayoutString ) ; }


TargetInstrInfo & getInstrInfo ( ) const { return static_cast < TargetInstrInfo & > ( * this -> SubtargetInfoT :: getInstrInfo ( ) ) ; } ` ` ` The function should take in the NVPTX backend as a parameter , and return a reference to the TargetInstrInfo for that backend . This function can be defined as a member function of the NVPTX TargetMachine class , or a standalone function in the NVPTXTargetMachine . cpp file . The purpose of this function is to provide access to the TargetInstrInfo for any code generation tasks related to the NVPTX backend . This includes retrieving information about individual instructions , as well as generating new instructions for the backend . The function should first cast the NVPTX backend to a TargetMachine class , and then use its getInstrInfo ( ) function to retrieve the TargetInstrInfo for the NVPTX backend . This TargetInstrInfo object should then be returned by reference . In summary , the getInstrInfo function for NVPTX backend should have the following structure : ` ` ` TargetInstrInfo & getInstrInfo ( NVPTXTargetMachine & TM ) const { return static_cast < TargetInstrInfo & > ( * TM . getSubtargetImpl ( ) -> getInstrInfo ( ) ) ; }


TargetInstrInfo * getRegisterInfo ( TargetMachine & TM ) { return new NVPTXInstrInfo ( NVPTX :: getRegisterInfo ( ) , TM ) ; }


NVPTXSubtarget * NVPTXSubtarget ( Module & M , NVPTX :: TargetISA ISA ) { NVPTXSubtarget * Subtarget = new NVPTXSubtarget ( ) ; initializeSubtargetDependencies ( * Subtarget , M , ISA ) ; Subtarget -> setVersion ( NVPTX :: NVPTX ) ; Subtarget -> setTarget ( NVPTX :: NVPTX ) ; Subtarget -> setFeatureBits ( 0 ) ; Subtarget -> setAlignementBits ( 20 ) ; Subtarget -> setGPUType ( NVPTX :: NVCL ) ; Subtarget -> setArch ( NVPTX :: CUDA ) ; return Subtarget ; }


void addFastRegAlloc ( NVPTX & Target ) { Target . addPass ( createTargetTransformInfoWrapperPass ( Target . getTM < TargetMachine > ( ) ) ) ; Target . addPass ( createAlwaysInlinerLegacyPass ( ) ) ; Target . addPass ( createNVVMReflectPass ( ) ) ; }


void addOptimizedRegAlloc ( TargetMachine & TM , PassManagerBase & PM ) { const NVPTXSubtarget & ST = TM . getSubtarget < NVPTXSubtarget > ( ) ; PM . add ( createNVPTXRegAllocPass ( & ST ) ) ; PM . add ( createMachineSchedulerPass ( ) ) ; PM . add ( createStackSlotColoringPass ( ) ) ; PM . add ( createNVPTXPostRAPass ( & ST ) ) ; }


const NVPTXTargetMachine & TM ) { PM . add ( createNVPTXTargetTransformInfoPass ( TM ) ) ; PM . add ( createNVPTXPostRAPass ( ) ) ; PM . add ( createNVPTXPrologEpilogPass ( TM ) ) ; PM . add ( createNVPTXInsertChecksPass ( TM ) ) ; PM . add ( createNVPTXInsertNVVMIntrinsicsPass ( TM ) ) ; PM . add ( createNVPTXWrapNVVMIntrinsicsPass ( TM ) ) ; PM . add ( new NVPTXTargetMachine ( TM ) ) ; }


void addPreRegAlloc ( llvm :: FunctionPassManager & FPM , llvm :: TargetMachine & TM , llvm :: TargetIRAnalysis & TIRA ) { llvm :: FunctionPass * CustomPass = createCustomPass ( ) ; FPM . add ( CustomPass ) ; }


void addRegAssignAndRewriteFast ( ) { MachineFunction & MF = getMachineFunction ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; const NVPTXSubtarget & ST = MF . getSubtarget < NVPTXSubtarget > ( ) ; MF . addPass ( createNVPTXAssignRegistersPass ( & NVPTX :: Main_64RegClass ) ) ; MF . addPass ( createNVPTXSimpleRegisterRewriter ( ST ) ) ; if ( ST . isCPURewriteEnabled ( ) ) MF . addPass ( createNVPTXRegisterCopyPropagationPass ( ) ) ; if ( ST . isCSEEnabled ( ) ) MF . addPass ( createNVPTXRegisterCSEPass ( ) ) ; MF . addPass ( createNVPTXScavengerPass ( ) ) ; MF . addPass ( createNVPTXCSRPass ( ) ) ; MF . addPass ( createNVPTXLiveRegisterInfo ( ST ) ) ; return MF ; }


TargetPassConfig * createPassConfig ( const TargetMachine & TM , PassManagerBase & PM ) { TargetPassConfig * TPC = new TargetPassConfig ( TM , PM ) ; TPC -> addPass ( createNVPTXISelDag ( TM ) ) ; TPC -> addPass ( createNVPTXExpandPseudoPass ( TM ) ) ; TPC -> addPass ( createNVPTXLowerAggrCopiesPass ( TM ) ) ; TPC -> setOpt ( & TM . getOptLevel ( ) ) ; return TPC ; }


void registerPassBuilderCallbacks ( ) { PassBuilder & PB = getPassBuilder ( ) ; PB . registerPipelineParsingCallback ( [ ] ( StringRef Name , ModulePassManager & MPM , ArrayRef < PassBuilder :: PipelineElement > ) { if ( Name == "nvptx" ) { MPM . addPass ( createMyNVPTXPass ( ) ) ; return true ; } return false ; } ) ; PB . registerPipelineParsingCallback ( [ ] ( StringRef Name , ModulePassManager & MPM , ArrayRef < PassBuilder :: PipelineElement > ) { if ( Name == "nvvm-reflect" ) { MPM . addPass ( createNVVMReflectPass ( ) ) ; return true ; } return false ; } ) ; PB . registerPipelineParsingCallback ( [ ] ( StringRef Name , ModulePassManager & MPM , ArrayRef < PassBuilder :: PipelineElement > ) { if ( Name == "nvvm-intr-range" ) { MPM . addPass ( createNVVMIntrinsicRangePass ( ) ) ; return true ; } return false ; } ) ; PB . registerLoopAnalyses ( [ & PB ] ( const PassBuilder :: LoopAnalysesTy & LAM ) { PB . registerLoopAnalysis ( NVPTXTargetMachine :: AM , LAM ) ; PB . registerLoopAnalysis ( NVVMTargetMachine :: AM , LAM ) ; } ) ; }


void
addFastRegAlloc
(
)
{
StringRef
TargetID
=
"NVPTX"
;
StringRef
Arch
=
"NVPTX"
;
StringRef
Message
=
"NVPTX uses no regalloc!"
;
addPass
(
TargetID
,
Arch
,
Message
)
;
}


"Instruction Selector Pass for NVPTX has been successfully installed.\n"


void addIRPasses ( ) { addMachineIndependentOptimizationPass ( ) ; addNVPTXOptimizationPass ( ) ; addNVPTXCodeGenerationPass ( ) ; addNVPTXVectorizationPass ( ) ; addNVPTXBarrierRemovalPass ( ) ; addNVPTXLoopUnrollingPass ( ) ; addNVPTXIntrinsicOptimizerPass ( ) ; addNVPTXFloatingPointOptimizationPass ( ) ; addNVPTXSoftwarePipeliningPass ( ) ; }


void addOptimizedRegAlloc ( TargetPassConfig & PassConfig ) { PassConfig -> addPass ( new NVPTXTargetMachineSignature ( ) ) ; PassConfig -> addPass ( createNVPTXFixupLivenessPass ( ) ) ; PassConfig -> addPass ( createNVPTXLowerLoadStorePass ( ) ) ; PassConfig -> addPass ( createNoRegAllocPass ( ) ) ; PassConfig -> addPass ( createStackSlotColoringPass ( ) ) ; }


void addPostRegAlloc ( llvm :: PassManager & PM ) { llvm :: FunctionPass * NVPTXP1 = new llvm :: SomeNVPTXP1Pass ( ) ; llvm :: FunctionPass * NVPTXP2 = new llvm :: SomeNVPTXP2Pass ( ) ; llvm :: FunctionPass * NVPTXP3 = new llvm :: SomeNVPTXP3Pass ( ) ; llvm :: FunctionPass * NVPTXP4 = new llvm :: SomeNVPTXP4Pass ( ) ; PM . add ( NVPTXP1 ) ; PM . add ( NVPTXP2 ) ; PM . add ( NVPTXP3 ) ; PM . add ( NVPTXP4 ) ; PM . run ( * M ) ; }


PassConfig * createPassConfig ( TargetMachine & TM ) { auto * Conf = new PassConfig ( TM ) ; Conf -> addPass ( createNVPTXISelDag ( Conf ) ) ; Conf -> addPass ( createNVPTXPeephole ( Conf ) ) ; MCAsmInfo * MAI = new NVTMCAsmInfo ( TM . getTargetTriple ( ) ) ; Conf -> setMCAsmInfo ( MAI ) ; Conf -> addMachinePasses ( createNVPTXLowerThreadPrivate ( Conf ) ) ; return Conf ; }


RegisterRegAlloc * createTargetRegisterAllocator ( Module * M , TargetMachine & TM , PassManagerBase & PM ) { NVPTXTargetMachine & NVPTXTM = static_cast < NVPTXTargetMachine & > ( TM ) ; const NVPTXSubtarget & ST = NVPTXTM . getSubtarget < NVPTXSubtarget > ( * M ) ; return new NVPTXRegisterAllocator ( ST , M -> getDataLayout ( ) ) ; }


TargetIRAnalysis * getTargetIRAnalysis ( const TargetMachine & TM , const TargetLibraryInfo & TLI ) { if ( ! TM . getTargetTriple ( ) . isNVPTX ( ) ) { return nullptr ; } LLVMContext & Context = TM . getContext ( ) ; TargetIRAnalysis * TIA = new TargetIRAnalysis ( Context ) ; TIA -> setTargetMachine ( & TM ) ; TIA -> setTargetLibraryInfo ( & TLI ) ; TIA -> setRelocationModel ( TM . getRelocationModel ( ) ) ; TIA -> setCodeModel ( TM . getCodeModel ( ) ) ; return TIA ; }


void addInstSelector ( Module & M ) { TargetMachine * TM = nullptr ; std :: string Err ; const Target * TheTarget = TargetRegistry :: lookupTarget ( "nvptx64-nvidia-cuda" , Err ) ; TM = TheTarget -> createTargetMachine ( "sm_XX" , "" , "" , TargetOptions ( ) , None ) ; PassRegistry * Registry = PassRegistry :: getPassRegistry ( ) ; initializeTargetPassConfig ( * Registry ) ; TargetLibraryInfoWrapperPass * TLIWP = new TargetLibraryInfoWrapperPass ( ) ; TargetLibraryInfo * TLI = & TLIWP -> getTLI ( TM -> getTargetTriple ( ) ) ; PassManagerBuilder Builder ; Builder . LibraryInfo = TLI ; Builder . Inliner = createFunctionInliningPass ( ) ; Builder . addExtension ( PassManagerBuilder :: EP_ModuleOptimizerEarly , addOptimizationPasses ) ; MachinePassRegistry * MPR = MachinePassRegistry :: getPassRegistry ( ) ; const MCAsmInfo * MAI = TM -> getMCAsmInfo ( ) ; const MCInstrInfo * MCII = TM -> getMCInstrInfo ( ) ; const MCRegisterInfo * MRI = TM -> getMCRegisterInfo ( ) ; const MCSubtargetInfo * STI = TM -> getMCSubtargetInfo ( ) ; const MCCodeGenInfo * CGI = TM -> getMCCodeGenInfo ( ) ; MCContext * Ctx = new MCContext ( MAI , MRI , nullptr ) ; MCTargetOptions MCOptions ; MCOptions . AsmVerbose = false ; MCOptions . MCInstPrintOpersMem = false ; std :: unique_ptr < MCStreamer > Str ; if ( CGI -> ReverseAsmComments ) { Str . reset ( TM -> getTarget ( ) . createAsmStreamer ( * Ctx , Out , true , false , false ) ) ; } else { Str . reset ( TM -> getTarget ( ) . createCivilianStreamer ( * Ctx , Out , false , true ) ) ; }


NVPTXObjFileLowering getObjFileLowering ( const TargetMachine & TM ) { NVPTXObjFileLowering TLO ; TLO . targetDataSize = TM . getDataLayout ( ) . getPointerSize ( ) ; TLO . targetAlign = TM . getDataLayout ( ) . getPointerABIAlignment ( 0 ) ; TLO . isLittleEndian = TM . getDataLayout ( ) . isLittleEndian ( ) ; TLO . hasIdentDirective = true ; TLO . canRelaxRelocations = true ; return TLO ; }


NVPTXTargetMachine :: getSubtargetImpl ( const Function & F ) const { return * this ; }


void addIRPasses ( TargetPassConfig & PassConfig , bool IsOptimize ) { PassConfig . addPass ( createNVPTXIRLoweringPass ( ) ) ; PassConfig . addPass ( createNVPTXTargetLibraryInfoPass ( ) ) ; PassConfig . addPass ( createNVPTXDAGToDAGISelPass ( ) ) ; PassConfig . addPass ( createNVPTXCodeGenPreparePass ( ) ) ; PassConfig . addPass ( createNVPTXISelDag ( PassConfig ) ) ; PassConfig . addPass ( createNVPTXRegBankSelectPass ( ) ) ; PassConfig . addPass ( createNVPTXILPInserter ( ) ) ; if ( IsOptimize ) { PassConfig . addPass ( createNVPTXMCCodeEmitterPass ( ) ) ; } }


"Error: This function is only meant for NVPTX backend.\n"


"Target machine does not support emission of this file type."


std :: string getDataLayout ( ) { if ( Module -> getTargetTriple ( ) . find ( "nvptx" ) == std :: string :: npos ) { return "" ; } const llvm :: DataLayout & DL = Module -> getDataLayout ( ) ; std :: string DLString = DL . getStringRepresentation ( ) ; DLString += "-nvptx" ; if ( DL . isBigEndian ( ) ) { DLString += "-eb" ; } else { DLString += "-el" ; } return DLString ; }


int TargetInstrInfo * getInstrInfo ( ) { TargetInstrInfo * NVPTXInstrInfo = new TargetInstrInfo ( ) ; NVPTXInstrInfo -> setTarget ( Triple ( "nvptx" ) ) ; return NVPTXInstrInfo ; }


"target does not have NVPTX as a target specific value"


const TargetSubtargetInfo & getSubtargetImpl ( ) const override { return Subtarget ; }


bool DisableVerify = true ) { const NVPTXTargetMachine & NTM = static_cast < const NVPTXTargetMachine & > ( TM ) ; NVPTXPassConfig * TPC = new NVPTXPassConfig ( NTM ) ; MCStreamer * Streamer = 0 ; if ( NTM . getTargetTriple ( ) . getArch ( ) == Triple :: nvptx64 ) { Streamer = llvm :: createNVPTXSTMCStreamer ( PM , OutContext , OutStream ) ; } else { Streamer = llvm :: createNVPTXAsmStreamer ( PM , OutContext , OutStream ) ; } TPC -> setMCStreamer ( Streamer ) ; PM . add ( TPC -> createNVPTXISelDag ( NTM ) ) ; PM . add ( TPC -> createNVPTXLowerKernelArgsPass ( NTM ) ) ; PM . add ( TPC -> createNVPTXCopyKernelArgsPass ( NTM ) ) ; PM . add ( TPC -> createNVPTXFrameLoweringPass ( NTM ) ) ; PM . add ( TPC -> createNVPTXAsmPrinterPass ( NTM , OutStream ) ) ; PM . add ( TPC -> createNVPTXIPRARegAllocPass ( NTM ) ) ; PM . add ( TPC -> createNVPTXCodeGenPreparePass ( NTM ) ) ; PM . add ( TPC -> createNVPTXWarpSizePass ( NTM ) ) ; if ( ! DisableVerify ) PM . add ( createVerifierPass ( ) ) ; PM . add ( createCFGSimplificationPass ( ) ) ; PM . add ( createPromoteMemoryToRegisterPass ( ) ) ; PM . add ( createMachineCodeEmissionPass ( Streamer , DisableVerify ) ) ; }


llvm :: PassConfig createPassConfig ( ) { llvm :: PassConfig passConfig ; passConfig . addTargetPasses ( NVPTX , NVPTX , NVPTX ) ; return passConfig ; }


bool isMachineVerifierClean ( ) { if ( Target . getID ( ) == NVPTX ) { return true ; } return false ; }


void addIRPasses ( TargetPassConfig * TargetPassConfig ) { TargetMachine * TM = & TargetPassConfig -> getTM < TargetMachine > ( ) ; Triple TargetTriple = TM -> getTargetTriple ( ) ; if ( TargetTriple . getArch ( ) != Triple :: nvptx ) { return ; } PassBuilder & PB = TargetPassConfig -> getOptPipeline ( ) ; LoopAnalysisManager & LAM = TargetPassConfig -> getLAM ( ) ; FunctionAnalysisManager & FAM = TargetPassConfig -> getFAM ( ) ; FunctionPassManager FPM ; FPM . addPass ( LoopSimplifyPass ( ) ) ; FPM . addPass ( LICMPass ( ) ) ; FPM . addPass ( NewGVNPass ( ) ) ; FPM . addPass ( LazyValueInfoCacheAnalysis ( ) ) ; FPM . addPass ( TwoAddressInstructionPass ( ) ) ; FPM . addPass ( LateSimplifyPass ( ) ) ; PB . addExtensionsToPM ( FPM ) ; TargetPassConfig -> addISelPrepare ( ) ; PB . addIRPasses ( ) ; TargetPassConfig -> addPassesToHandleExceptions ( ) ; TargetPassConfig -> addEarlyAsPossiblePasses ( ) ; FPM . addPass ( FunctionPassManager ( ) ) ; TargetPassConfig -> addMachinePasses ( ) ; TargetPassConfig -> addISelFinalize ( ) ; TargetPassConfig -> addMachineLateOptimization ( ) ; PB . addMachinePasses ( ) ; FPM . run ( * TargetPassConfig -> getFunctionPassManager ( ) , * TargetPassConfig -> getAnalysisManager ( ) ) ; }


TargetIRAnalysis * getTargetIRAnalysis ( StringRef nvptx1 , StringRef nvptx2 , StringRef nvptx3 ) { if ( ! TargetMachine :: isNVPTX ( TargetTriple ) ) return nullptr ; return new TargetIRAnalysis ( nvptx1 , nvptx2 , nvptx3 ) ; }


void getRegisterInfo ( const TargetInstrInfo * TII ) { TII -> setTargetSpecificValue ( NVPTX ) ; const MRegisterInfo * MRI = TII -> getRegisterInfo ( ) ; TII -> setRegisterInfo ( NVPTX , MRI ) ; }


void addInstSelector ( FunctionPassManager & FPM , const TargetMachine & TM ) { FPM . add ( createNVPTXInstructionSelectorPass ( TM ) ) ; TargetLibraryInfoImpl TLII ( TM . getTargetTriple ( ) ) ; FPM . add ( new TargetLibraryInfoWrapperPass ( TLII ) ) ; FPM . add ( createBarrierNoopPass ( ) ) ; }


void addIRPasses ( Target * target ) { target -> addPass ( NVPTXAddressSpaceTransformPass ( ) ) ; target -> addPass ( NVPTXStructLayoutTransformPass ( ) ) ; target -> addPass ( NVPTXVectorizationPass ( ) ) ; target -> addPass ( NVPTXInstructionCombiningPass ( ) ) ; target -> addPass ( NVPTXHighOrderTransformPass ( ) ) ; }


"Add Post Register-Allocation Pass for NVPTX"


"Warning: NVPTX should not be used as target specific value!"


void addIRPasses ( Module & M , NVPTX nvptx , NVPTX nvptx , NVPTX nvptx , NVPTX nvptx , NVPTX nvptx ) { PassManagerBuilder PMBuilder ; PMBuilder . DisableTailCalls = true ; PMBuilder . Inliner = createNVPTXFatbinInliningPass ( ) ; PMBuilder . VerifyInput = true ; PMBuilder . VerifyOutput = true ; PMBuilder . populateModulePassManager ( MPM ) ; PMBuilder . populateFunctionPassManager ( FPM ) ; PMBuilder . populateLTOPassManager ( LPM ) ; MPM . run ( M ) ; FPM . doInitialization ( ) ; for ( Function & F : M ) if ( ! F . isDeclaration ( ) ) FPM . run ( F ) ; FPM . doFinalization ( ) ; LPM . run ( * M . getModule ( ) ) ; PMBuilder . OptLevel = 3 ; PMBuilder . populateFunctionPassManager ( FPM ) ; FPM . doInitialization ( ) ; for ( Function & F : M ) if ( ! F . isDeclaration ( ) ) FPM . run ( F ) ; FPM . doFinalization ( ) ; }


void addIRPasses ( ) { FunctionPassManager PM = FunctionPassManager ( Module ) ; PM . add ( createNVPTXIRTransform1 ( ) ) ; PM . add ( createNVPTXIRTransform2 ( ) ) ; PM . add ( createNVPTXIRTransform3 ( ) ) ; PM . add ( createNVPTXIRTransform4 ( ) ) ; PM . add ( createNVPTXIRTransform5 ( ) ) ; PM . add ( createNVPTXIRTransform6 ( ) ) ; PM . add ( createNVPTXIRTransform7 ( ) ) ; PM . add ( createNVPTXIRTransform8 ( ) ) ; PM . run ( ) ; PassManager PM2 = PassManager ( ) ; PM2 . add ( createNVPTXPass1 ( ) ) ; PM2 . add ( createNVPTXPass2 ( ) ) ; PM2 . add ( createNVPTXPass3 ( ) ) ; PM2 . add ( createNVPTXPass4 ( ) ) ; PM2 . add ( createNVPTXPass5 ( ) ) ; PM2 . add ( createNVPTXPass6 ( ) ) ; PM2 . add ( createNVPTXPass7 ( ) ) ; PM2 . add ( createNVPTXPass8 ( ) ) ; PM . run ( * Module ) ; }


TargetTransformInfo
*
getTargetTransformInfo
(
const
Triple
&
TT
)
{
if
(
TT
.
isNVPTX
(
)
)
{
NVPTXTargetMachine
*
TM
=
(
NVPTXTargetMachine
*
)
TM
;
return
new
NVPTXTargetTransformInfo
(
TM
->
getSubtargetImpl
(
)
)
;
}
return
;
}
TargetTransformInfo
*
TTI
=
getTargetTransformInfo
(
Triple
(
"nvptx--nvidia-cuda"
)
)
;
if
(
!
TTI
)
{
errs
(
)
<<
"Target is not NVPTX\n"
;
return
1
;
}


TargetIRAnalysis
getTargetIRAnalysis
(
Target
&
target
,
uint64_t
nvptxTargetValue
,
Triple
nvptxTargetTriple
)
{
if
(
nvptxTargetTriple
.
getArch
(
)
!=
Triple
::
nvptx
)
{
report_fatal_error
(
"Invalid target triple!"
)
;
}
return
NVPTXIRAnalysis
(
target
,
nvptxTargetValue
)
;
}


void registerPassBuilderCallbacks ( ) { LLVMAddTargetSpecificNVPTXCallbacks ( getNVPTXPassBuilderCallbacks , "NVPTX" , "NVPTX" , "nvvm-reflect" , "nvvm-intr-range" ) ; } The function above is named "registerPassBuilderCallbacks" . It calls the LLVMAddTargetSpecificNVPTXCallbacks function which takes in the callback function called "getNVPTXPassBuilderCallbacks" as its first argument and the target specific values as the remaining arguments . In this case , the target specific values are "NVPTX" , "NVPTX" , "nvvm-reflect" , "nvvm-intr-range" . The NVPTX callback function "getNVPTXPassBuilderCallbacks" can be defined as follows : void getNVPTXPassBuilderCallbacks ( void * PassBuilder ) { auto * PPBCB = static_cast < PassBuilderCallbackManager * > ( PassBuilder ) ; PPBCB -> registerCallback ( "nvvm-reflect" , & registerNVVMReflectPass ) ; PPBCB -> registerCallback ( "nvvm-intr-range" , & registerNVVMIntrRangePass ) ; }


class AddOptimizedRegAllocPass : public llvm :: PassInfoMixin < AddOptimizedRegAllocPass > { public : AddOptimizedRegAllocPass ( ) = default ; llvm :: PreservedAnalyses run ( llvm :: Function & F , llvm :: FunctionAnalysisManager & FAM ) { llvm :: TargetMachine & TM = FAM . getResult < llvm :: TargetIRAnalysis > ( F ) ; if ( ! TM . getTargetTriple ( ) . isNVPTX ( ) ) { return llvm :: PreservedAnalyses :: all ( ) ; }


bool createTargetRegisterAllocator ( const Target & T , MachineFunction & MF , LiveIntervals & LIS ) { if ( T . getID ( ) != TargetMachine :: TM_NVPTX ) { return false ; } if ( MF . getFunction ( ) -> getAttributes ( ) . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: OptimizeNone ) ) { return false ; } unsigned AllocNo = 0 ; MF . addPass ( createNVPTXAssignRegistersPass ( AllocNo ) ) ; LIS = getAnalysis < LiveIntervals > ( ) ; LIS -> computeRegUnitSets ( ) ; return true ; }


function < TargetPassConfig * ( ) > GetTPC ) { PMBuilder -> addExtension ( PassManagerBuilder :: EP_EarlyAsPossible , [ & ] ( const PassManagerBuilder & Builder , PassManagerBase & PM ) { if ( Builder . LibraryInfo ) { PM . add ( createTargetTransformInfoWrapperPass ( GetTPC ( ) ) ) ; } PM . add ( createCorrelatedValuePropagationPass ( ) ) ; return true ; } ) ; GetTPC ( ) -> addIRPass ( createNVPTXExpandVCETestPass ( ) ) ; }


void addIRPasses ( llvm :: Module * M ) { llvm :: PassManagerBuilder PMBuilder ; PMBuilder . OptLevel = 2 ; PMBuilder . populateModulePassManager ( * M ) ; llvm :: Triple TT = M -> getTargetTriple ( ) ; if ( TT . getArch ( ) == llvm :: Triple :: nvptx ) { llvm :: PassManagerBuilder :: addNVPTXPasses ( PMBuilder ) ; M -> setDataLayout ( "e-i64:64-v16:16-n16:32:64" ) ; M -> addModuleFlag ( llvm :: Module :: Warning , "nvvm-reflect-list" , 1 ) ; } }


void addIRPasses ( LLVMContext & C , PassManagerBase & PM , TargetMachine & TM ) { NVPTXTargetMachine & PTM = static_cast < NVPTXTargetMachine & > ( TM ) ; PM . add ( createTargetTransformInfoWrapperPass ( PTM . getTargetIRAnalysis ( ) ) ) ; PM . add ( createConstantMergePass ( ) ) ; PM . add ( createCFGSimplificationPass ( ) ) ; PM . add ( createDeadCodeEliminationPass ( ) ) ; PM . add ( createLowerSwitchPass ( ) ) ; PM . add ( createNVPTXISelDag ( PTM ) ) ; PM . add ( createNVPTXRemoveBarriersPass ( ) ) ; PM . add ( new NVPTXExtractAddrSpaceCast ( PTM . getDataLayout ( ) ) ) ; PM . add ( new NVPTXLowerAggrCopies ( ) ) ; PM . add ( createNVPTXAssignValidGlobalIdsPass ( PTM ) ) ; PM . add ( new NVPTXFavorNonGenericAddrSpaces ( PTM . getDataLayout ( ) ) ) ; PM . add ( createNVPTXAssignComputeThreadIdsPass ( ) ) ; PM . add ( new LowerPtrIntrinsics ( PTM . getDataLayout ( ) ) ) ; PM . add ( new LowerAtomicPass ( PTM . getDataLayout ( ) ) ) ; PM . add ( createNVPTXVectorLowering ( PTM ) ) ; PM . add ( new LowerFieldInits ( ) ) ; PM . add ( createNVPTXLateLoweringPass ( ) ) ; PM . add ( new NVPTXPropagateWideningArithmetic ( ) ) ; PM . add ( new LowerStructArgs ( ) ) ; }


void addIRPasses ( LLVMPassManager & PM , const TargetMachine & TM ) { PM . add ( createPromoteMemoryToRegisterPass ( ) ) ; PM . add ( createInstructionCombiningPass ( ) ) ; PM . add ( createCFGSimplificationPass ( ) ) ; PM . add ( createJumpThreadingPass ( ) ) ; PM . add ( createCFGSimplificationPass ( ) ) ; PM . add ( createReassociatePass ( ) ) ; PM . add ( createLoopRotatePass ( ) ) ; PM . add ( createLICMPass ( ) ) ; PM . add ( createLoopUnswitchPass ( false , false ) ) ; PM . add ( createLoopDeletionPass ( ) ) ; PM . add ( createSimpleLoopUnrollPass ( ) ) ; PM . add ( createLateCSEPass ( ) ) ; PM . add ( createMemCpyOptPass ( ) ) ; PM . add ( createGVNPass ( ) ) ; PM . add ( createSCCPPass ( ) ) ; PM . add ( createInstructionCombiningPass ( ) ) ; PM . add ( createStripDeadPrototypesPass ( ) ) ; PM . add ( createConstantPropagationPass ( ) ) ; if ( TM . getTargetTriple ( ) . getArch ( ) == Triple :: nvptx || TM . getTargetTriple ( ) . getArch ( ) == Triple :: nvptx64 ) { PM . add ( createNVPTXLowerAllocaPass ( ) ) ; PM . add ( createNVPTXISelLoweringPass ( ) ) ; PM . add ( createNVPTXPreAllocLoweringPass ( ) ) ; PM . add ( createLowerInvokePass ( TM ) ) ; PM . add ( createTailCallEliminationPass ( ) ) ; PM . add ( createNVPTXReplaceImageHandlesPass ( ) ) ; PM . add ( createNVPTXInstrInfoPass ( ) ) ; PM . add ( createNVPTXTargetTransformInfoPass ( ) ) ; } switch ( TM . getTargetTriple ( ) . getArch ( ) ) { case Triple :: nvptx : PM . add ( createNVPTXISelDAGToDAGPass ( ) ) ; PM . add ( createNVPTXFrameToArgsOffsetPass ( ) ) ; break ; case Triple :: nvptx64 : PM . add ( createNVPTX64ISelDAGToDAGPass ( ) ) ; PM . add ( createNVPTX64FrameToArgsOffsetPass ( ) ) ; break ; } }


<
return
type
>
addIRPasses
(
llvm
::
PassManagerBase
*
PM
,
<
target
specific
type
>
Target
)
{
switch
(
Target
)
{
case
NVPTX
:
break
;
default
:
llvm_unreachable
(
"Unsupported target for NVPTX backend"
)
;
}
}


void addIRPasses ( Module * M ) { auto TM = M -> getDataLayout ( ) . getTargetMachine ( ) ; TargetPassConfig * TPC = TM -> createPassConfig ( PM ) ; TPC -> addTargetPassesToEmitFile ( PM , OS ) ; PM . add ( TPC ) ; }


void addIRPasses ( TargetMachine TM , PassManagerBase & PM ) { PM . add ( createSimpleInlinerPass ( ) ) ; PM . add ( createGVNPass ( ) ) ; PM . add ( createCFGSimplificationPass ( ) ) ; PM . add ( createNVPTXLowerAllocaPass ( ) ) ; PM . add ( createNVPTXISelDag ( TM ) ) ; PM . add ( createNVPTXCFGOptPass ( ) ) ; PM . add ( createNVPTXAssignValidGlobalNamesPass ( ) ) ; PM . add ( createNVVMReflectPass ( ) ) ; PM . add ( createNVVMReflectOnVectorPass ( ) ) ; PM . add ( createNVVMDWARFTransformPass ( ) ) ; PM . add ( createNVPTXImageOptimizerPass ( ) ) ; }


"Unable to create target for module's target triple"


if ( ! TM . isNVPTX ( ) ) { return nullptr ; } Next , we create a TargetInstrInfo object specifically for NVPTX target using the createNVPTXInstrInfo function from the TargetInstrInfo class : TargetInstrInfo * TII = TM . getSubtargetImpl ( ) -> createNVPTXInstrInfo ( ) ; The createNVPTXInstrInfo function takes in the NVPTX target specific values and populates the TargetInstrInfo object with necessary information . We can then return this object after type casting it to the const pointer type : return static_cast < const TargetInstrInfo * > ( TII ) ; The final getInstrInfo function will look something like this : const TargetInstrInfo * getInstrInfo ( const TargetMachine & TM , NVPTXTargetLowering * TLI ) { if ( ! TM . isNVPTX ( ) ) { return nullptr ; } TargetInstrInfo * TII = TM . getSubtargetImpl ( ) -> createNVPTXInstrInfo ( ) ; return static_cast < const TargetInstrInfo * > ( TII ) ; }


TargetInstrInfoNVPTX & getRegisterInfo ( ) { static TargetInstrInfoNVPTX NVPTXInstrInfo ; return NVPTXInstrInfo ; }


const TargetSubtargetInfo & getSubtargetImpl ( const Class & target ) { return target . NVPTX ; }


string
getExplicitSectionGlobal
(
string
Name
,
GlobalValue
*
D
)
{
const
Triple
&
T
=
TM
.
getTargetTriple
(
)
;
switch
(
T
.
getArch
(
)
)
{
default
:
llvmUnreachable
(
"Unexpected target!"
)
;
case
Triple
::
nvptx
:
{
const
GlobalVariable
*
GV
=
dyn_cast
<
GlobalVariable
>
(
D
)
;
if
(
!
GV
||
GV
->
hasSection
(
)
)
return
StringRef
(
""
)
;
if
(
Name
==
"__cuda_libdevice_comat_table"
)
{
return
StringRef
(
"__nv_%cudart"
,
MAI
->
getFileFormatName
(
)
)
;
}
else
{
assert
(
Name
.
startswith
(
"__cuda_"
)
)
;
return
StringRef
(
"__nv_%s"
,
Name
.
substr
(
7
)
)
;
}
}
}
}


const char * getSectionForConstant ( Constant * constant , SectionKind kind ) { if ( constant -> getTargetSpecificValue ( ) == "NVPTX" ) { if ( kind == SectionKind :: ReadOnly ) { return ".nv.constant" ; } else if ( kind == SectionKind :: Data ) { return ".nv.data" ; } else if ( kind == SectionKind :: Text ) { return ".nv.exec" ; } else { return nullptr ; } } return nullptr ; }


std :: string getSectionForConstant ( Constant * C , StringRef TargetSpecificType ) { SectionKind Kind = C -> getSectionKind ( ) ; if ( TargetSpecificType == "NVPTX" ) { if ( Kind . isText ( ) ) return "nvvm.kernel" ; else if ( Kind . isBSS ( ) ) return "nvvm.bss" ; else if ( Kind . isReadOnly ( ) ) return "nvvm.const" ; else return "nvvm.global" ; } return "" ; }


"Unsupported section kind for constant!"


void NVPTXTargetMachine :: Initialize ( const Target & T ) { InitNVPTXLowering ( T ) ; Attributes = CreateTargetMachineAttributes ( T , getTargetTriple ( ) ) ; InstructionSelector = createNVPTXInstructionSelector ( * this , getSubtargetImpl ( ) , getCodeInfo ( ) ) ; CodeGenOpts . MCOptions . AsmVerbose = true ; CodeGenOpts . MCOptions . MCUseDwarfDirectory = true ; setSubtargetForCodeGen ( * getSubtargetImpl ( ) ) ; GlobalISel . reset ( createNVPTXGISel ( ) ) ; RegisterPassManagerBuilder buildForNVPTX ( * this ) ; addPassesToEmitFile ( * PM , * MFM , nullptr , CODEGEN_FILETY , CodeGenOpts . EmitCodeView , CodeGenOpts . EmitCodeViewReloc ) ; }


String getSectionForConstant ( SectionKind Kind ) { if ( Kind . isThreadLocal ( ) || Kind . isGlobal ( ) ) { return ".data" ; } else if ( Kind . isText ( ) ) { return ".text" ; } else if ( Kind . isReadOnly ( ) ) { return ".const" ; } return "" ; }


"This function is for NVPTX backend only!"


void Initialize ( ) { NVPTX :: InitGlobalISel ( ) ; NVPTX :: InitLowerIncompatibleDefaultOperations ( ) ; NVPTX :: InitGlobalAddressLowering ( ) ; NVPTX :: InitFunctionLowering ( ) ; NVPTX :: InitStackPointerAndFrameLowering ( ) ; NVPTX :: InitInstrInfo ( ) ; NVPTX :: InitTargetLowering ( ) ; NVPTX :: InitRegisterInfo ( ) ; NVPTX :: InitLowerThreadLocalMetadata ( ) ; NVPTX :: InitTargetMachine ( ) ; NVPTX :: InitPasses ( ) ; NVPTX :: InitAsmPrinter ( ) ; NVPTX :: InitAsmParser ( ) ; NVPTX :: InitMIRParser ( ) ; NVPTX :: InitMCCodeGenInfo ( ) ; NVPTX :: InitMCInstrAnalysis ( ) ; }


Section * getSectionForConstant ( Constant * C , SectionKind Kind ) { LLVMContext & Cxt = C -> getContext ( ) ; const TargetMachine & TM = getTargetMachine ( ) ; const Triple & TT = TM . getTargetTriple ( ) ; if ( TT . getArch ( ) == Triple :: nvptx || TT . getArch ( ) == Triple :: nvptx64 ) { switch ( Kind ) { case SectionKind :: Data : return Cxt . getOrCreateSection ( ".nv.data" , SectionKind :: Data , 0 , SectionFlags :: Writeable ) ; case SectionKind :: ReadOnly : return Cxt . getOrCreateSection ( ".nv.constant" , SectionKind :: ReadOnly , 0 , SectionFlags :: None ) ; case SectionKind :: BSS : return Cxt . getOrCreateSection ( ".nv.bss" , SectionKind :: BSS , 0 , SectionFlags :: Writeable ) ; case SectionKind :: Text : return Cxt . getOrCreateSection ( ".nv.text" , SectionKind :: Text , 0 , SectionFlags :: Executable ) ; default : return nullptr ; } } return Cxt . getOrCreateSection ( "" , Kind , 0 , SectionFlags :: None ) ; }


void Initialize ( ) { TargetOptions Options ; Options . GPUArch = NVPTX ; Options . UseFastMath = true ; TargetMachine * TM = Triple ( TheTriple ) . createTargetMachine ( TheTriple , "" , "" , Options , None , None , CodeGenOpt :: Aggressive ) ; PassRegistry * Registry = PassRegistry :: getPassRegistry ( ) ; initializeCore ( * Registry ) ; initializeCodeGen ( * Registry ) ; initializeLowerIntrinsicsPass ( * Registry ) ; initializePeepholeOptimizerPass ( * Registry ) ; initializeInstructionCombiningPass ( * Registry ) ; initializeScalarOpts ( * Registry ) ; initializeVectorization ( * Registry ) ; initializeIROptimization ( * Registry ) ; initializeLoopStrengthReducePass ( * Registry ) ; initializeUnreachableBlockElimPass ( * Registry ) ; initializeConstantHoistingPass ( * Registry ) ; initializeScalarizeMaskedMemIntrinPass ( * Registry ) ; initializeExpandMemCmpPass ( * Registry ) ; initializeCodeGenPreparePass ( * Registry ) ; initilaizeNvptxLowerAggrCopiesPass ( * Registry ) ; }


Section getSectionForConstant ( SectionKind sectionKind , const TargetMachine & TM , bool isFromGlobal ) { if ( sectionKind == TextSection ) { return Section ( ".text" , SectionKind :: Text ) ; } else if ( sectionKind == ReadOnlyDataSection ) { return Section ( ".rodata" , SectionKind :: ReadOnlyData ) ; } if ( isFromGlobal ) { if ( sectionKind == TextSection ) { return Section ( ".global" , SectionKind :: Data ) ; } else if ( sectionKind == ReadOnlyDataSection ) { return Section ( ".global_const" , SectionKind :: ReadOnly ) ; } } else { if ( sectionKind == TextSection ) { return Section ( ".local" , SectionKind :: Data ) ; } else if ( sectionKind == ReadOnlyDataSection ) { return Section ( ".local_const" , SectionKind :: ReadOnly ) ; }


SmallVectorImpl < char > & Out ) { if ( TT . getArch ( ) != Triple :: nvptx ) { return ; } if ( const auto * Attr = GV -> getSection ( ) ) { StringRef Section = Attr -> getString ( ) . drop_back ( ) ; Out . push_back ( '.' ) ; Out . append ( Section . begin ( ) , Section . end ( ) ) ; Out . push_back ( '.' ) ; } }


SectionKind getSectionForConstant ( const Constant * C ) { if ( const GlobalValue * GV = dyn_cast < GlobalValue > ( C ) ) { if ( GV -> hasSection ( ) && GV -> getSection ( ) == ".nv_fatbin" ) { return SectionKind :: getMetadata ( ) ; } else if ( GV -> hasSection ( ) && GV -> getSection ( ) == ".nv_constant" ) { return SectionKind :: getReadOnly ( ) ; } } else if ( const MetadataAsValue * MD = dyn_cast < MetadataAsValue > ( C ) ) { if ( MD -> hasMetadata ( ) && MD -> getMetadata ( ) -> getSection ( ) == ".nv_fatbin" ) { return SectionKind :: getMetadata ( ) ; } } return SectionKind :: getReadOnly ( ) ; }


void
Initialize
(
)
{
TargetRegistry
::
RegisterTarget
(
TheNVPTXTarget
,
"nvptx"
,
"NVPTX (NVIDIA PTX 32-bit)"
,
PTXTargetMachine
::
Create
)
;
}
`
`
`
This
function
registers
the
NVPTX
target
and
sets
it
to
be
the
default
target
.
It
also
creates
a
target
machine
for
NVPTX
called
PTXTargetMachine
.
Next
,
the
function
initializes
the
TargetOptions
for
NVPTX
.
This
includes
setting
the
target
specific
values
:
`
`
`
class
NVPTXTargetOptions
{
NVPTX
::
TargetFeatures
Features
;
public
:
NVPTXTargetOptions
(
)
=
default
;
const
NVPTX
::
TargetFeatures
&
getFeatures
(
)
const
{
return
Features
;
}
NVPTX
::
TargetFeatures
&
getFeatures
(
)
{
return
Features
;
}
}
;
`
`
`
The
TargetOptions
class
contains
a
field
called
Features
,
which
is
a
struct
that
holds
all
the
target
specific
values
for
NVPTX
.
In
this
case
,
it
is
of
type
NVPTX
::
TargetFeatures
.
Lastly
,
the
function
sets
the
target
specific
values
for
NVPTX
.
These
values
can
be
changed
as
needed
for
different
targets
.
`
`
`
void
Initialize
(
)
{
TargetRegistry
::
RegisterTarget
(
TheNVPTXTarget
,
"nvptx"
,
"NVPTX (NVIDIA PTX 32-bit)"
,
PTXTargetMachine
::
Create
)
;
NVPTXTargetOptions
Options
;
Options
.
getFeatures
(
)
.
setFeature
(
NVPTX
::
Feature1
,
true
)
;
Options
.
getFeatures
(
)
.
setFeature
(
NVPTX
::
Feature2
,
false
)
;
...
Options
.
getFeatures
(
)
.
setFeature
(
NVPTX
::
FeatureN
,
true
)
;
setTargetOptions
(
Options
)
;
}


void emitRawBytes ( std :: vector < uint8_t > Data ) { for ( int i = 0 ; i < Data . size ( ) ; i ++ ) { outs ( ) << format ( "%0*X" , 2 , Data [ i ] ) ; } outs ( ) << "," ; }


void outputDwarfFileDirectives ( raw_ostream & stream , const MCAsmInfo & MAI , const MCSubtargetInfo & STI ) { for ( const std :: string & File : MAI . getDwarfFileDirectivePrefix ( ) ) { stream << "\t.file\t" << File << '\n' ; } stream << "\t.target\tNVPTX,NVPTX\n" ; }


void
changeSection
(
)
{
TargetStreamer
*
Streamer
=
static_cast
<
TargetStreamer
*
>
(
OutStreamer
->
getTargetStreamer
(
)
)
;
if
(
!
Streamer
)
return
;
Streamer
->
changeSection
(
"NVPTX"
,
"NVPTX"
,
"SubSection is not null!"
,
"//\t}\n"
,
"//\t.section"
,
"//\t{\n"
)
;
}


void changeSection ( NVPTX , SubSection , openingBracket , closingBracket ) { streamer << NVPTX << "," ; if ( SubSection != null ) { streamer << NVPTX << "," ; } streamer << openingBracket << "\n" ; if ( SubSection != null ) { streamer << "\t" << SubSection << "\n" ; } streamer << closingBracket << "\n" ; }


void closeLastSection ( ) { MachineFunction & MF = MF ; if ( MF . getTarget ( ) . getTargetTriple ( ) . getArch ( ) != Triple :: nvptx ) { return ; } std :: string NVPTXClosingString ( "\t}" ) ; MachineBasicBlock * CloseBB = MF . CreateMachineBasicBlock ( ) ; MachineFunction :: iterator endBB = MF . end ( ) ; if ( endBB == MF . begin ( ) ) { return ; } -- endBB ; MF . insert ( endBB , CloseBB ) ; MachineInstr * closingInst = MF . CreateMachineInstr ( NVPTX :: NVPTX , * CloseBB , MF . CreateTempVirtualRegister ( MVT :: Other ) ) ; closingInst -> addOperand ( MachineOperand :: CreateImm ( NVPTXClosingString ) ) ; CloseBB -> insert ( CloseBB -> end ( ) , closingInst ) ; }


void changeSection ( ) { MCStreamer & Streamer = getStreamer ( ) ; if ( SubSection != NULL ) { Streamer . EmitRawText ( StringRef ( "\t}\n" ) ) ; Streamer . EmitRawText ( StringRef ( "\t.section\t{\n" ) ) ; } }


void
outputDwarfFileDirectives
(
StreamWriter
&
streamer
)
{
streamer
<<
".file "
<<
"NVPTX,NVPTX\n"
;
streamer
.
flush
(
)
;
}


"Error: Section value cannot be null!\n"


void closeLastSection ( ) { const std :: string NVPTX = "NVPTX" ; const std :: string NVPTX_CLOSE = "\t}" ; outs ( ) << NVPTX << NVPTX_CLOSE << "\n" ; }


void emitRawBytes ( char * Data ) { MachineBasicBlock & MBB = * MF -> CreateMachineBasicBlock ( MBB -> getBasicBlock ( ) ) ; MachineFunction :: iterator InsertPos = MBB . begin ( ) ; DebugLoc DL ; MachineInstr * MI = BuildMI ( MF , DL , TII -> get ( NVPTX :: DATA ) , "NvPTXData" ) ; MI -> addImm ( NVPTX ) ; MI -> addImm ( NVPTX ) ; MI -> addImm ( 40 ) ; MI -> addImm ( 1 ) ; MI -> addImm ( 1 ) ; MI -> addImm ( 0 ) ; MI -> addImm ( 128 ) ; MI -> addImm ( 1 ) ; MI -> addImm ( 1 ) ; MI -> addImm ( "," ) ; MI -> addMBB ( NvPTXData ) ; MBB . insert ( InsertPos , MI ) ; ++ InsertPos ; }


void
outputDwarfFileDirectives
(
raw_ostream
&
OS
,
const
TargetMachine
&
TM
)
{
OS
<<
'\n'
;
OS
<<
"  .section   .debug_info\n\n"
;
OS
<<
"  .file     1"
;
OS
<<
'"'
<<
"dummy_c_source"
<<
'"'
;
OS
<<
'"'
<<
'"'
<<
'\n'
;
OS
<<
'\n'
;
OS
<<
'\n'
;
}


's target-specific properties. 2. If the given instruction is a floating-point operation (isFP is true), multiply the reciprocal throughput by 2 as floating-point operations are typically slower on NVPTX backend. 3. Adjust the throughput based on the number of operands and preferred operand type. If the instruction prefers constant operands (preferConst is true), the throughput should be increased by 1. If the instruction has more than 2 operands (NumOps > 2), the throughput should be divided by 2. 4. Return the adjusted calculation as the instruction cost. The final implementation for the function will look as follows: ``` unsigned int getArithmeticInstrCost(unsigned Opcode, MVT VT, MVT ? ST, unsigned NumOps, bool preferConst, bool isFP) {     unsigned int throughput = getTargetRecipThruput(Opcode, VT);     if (isFP) {         throughput *= 2;     }     if (preferConst) {         throughput += 1;     }     if (NumOps > 2) {         throughput /= 2;     }     return throughput; }


llvm :: TargetLowering * getTLI ( llvm :: TargetMachine * TM ) { return TM -> getTargetLowering ( ) ; }


static TargetTransformInfo :: UnrollingPreferences getUnrollingPreferences ( ) { TargetTransformInfo :: UnrollingPreferences UP ; UP . AllowsUnroll = true ; UP . Interleave = true ; UP . Vectorize = false ; UP . Partial = TargetTransformInfo :: UnrollingPreferences :: UF_NVPTX ; UP . Runtime = TargetTransformInfo :: UnrollingPreferences :: UR_NVPTX ; UP . Vector = 4 ; UP . FavorSmallSize = true ; return UP ; }


bool hasBranchDivergence ( const MachineFunction & MF ) { const TargetSubtargetInfo & ST = MF . getSubtarget < TargetSubtargetInfo > ( ) ; if ( ! ST . isNVPTX ( ) ) return false ; for ( const MachineBasicBlock & MBB : MF ) { const MachineInstr * BranchInst = MBB . getFirstTerminator ( ) ; if ( BranchInst && BranchInst -> isConditionalBranch ( ) ) { const MachineOperand & Op1 = BranchInst -> getOperand ( 0 ) ; const MachineOperand & Op2 = BranchInst -> getOperand ( 1 ) ; if ( Op1 . getReg ( ) != Op2 . getReg ( ) ) { return true ; } } } return false ; }


bool isSourceOfDivergence ( Value * V ) { if ( ! V -> getType ( ) -> isPointerTy ( ) ) return false ; Type * Ty = V -> getType ( ) -> getPointerElementType ( ) ; if ( ! Ty -> isVectorTy ( ) ) return false ; unsigned VecSize = Ty -> getVectorNumElements ( ) ; if ( VecSize == 1 ) return false ; const TargetLibraryInfo * TLI = & getAnalysis < TargetLibraryInfoWrapperPass > ( ) . getTLI ( ) ; TargetSpecificInfo TSInfo ( TLI ) ; if ( TSInfo . getScalarTargetSpecificValue ( V ) != "NVPTX" ) return false ; Value * Mask = TSInfo . getVectorMask ( V ) ; if ( Mask != nullptr ) return true ; return false ; }


"This instruction is not supported on NVPTX backend."


struct PeelingPrefs getPeelingPreferences ( NVPTX , LVPTX ) { struct PeelingPrefs preferences ; preferences . peelingFactor = 2 ; return preferences ; }


llvm :: UnrollingPreferences getUnrollingPreferences ( const llvm :: TargetOptions & Options , StringRef TargetCPU , StringRef TargetFeature , unsigned UnrollingCount ) { llvm :: UnrollingPreferences prefs ; prefs . Count = UnrollingCount ; if ( Options . hasAtomics ( ) ) { prefs . TargetUnrollPreferences = llvm :: TargetTransformInfo :: UnrollingPreferences :: UP_NVPTX ; } return prefs ; }


Function * instCombineIntrinsic ( IntrinsicInst * inst , LLVMContext & ctx , IRBuilder < > & builder ) { Value * nvptx = builder . getInt32 ( NVPTX ) ; Value * nvptx = builder . getInt32 ( NVPTX ) ; switch ( nvptx ) { case NVPTX : { Value * add = builder . CreateAdd ( nvptx , nvptx ) ; add -> setOperand ( 0 , inst -> getArgOperand ( 0 ) ) ; return add ; }


unsigned int getArithmeticInstrCost ( unsigned int Opcode , Type * Ty , TargetCostKind CostKind , InstructionCost & Cost ) { if ( CostKind != TargetCostKind :: RecipThroughput ) { return 1 ; } if ( Ty != MVT :: i64 ) { return 1 ; } switch ( Opcode ) { case ISD :: ADD : Cost = 2 ; break ; case ISD :: MUL : Cost = 2 ; break ; case ISD :: XOR : Cost = 2 ; break ; case ISD :: OR : Cost = 2 ; break ; case ISD :: AND : Cost = 2 ; break ; default : Cost = 0 ; break ; } return Cost * 2 ; }


unsigned int getArithmeticInstrCost ( const TargetTransformInfo & TTI , TTI :: TargetCostKind CostKind , Type * Ty1 , Type * Ty2 ) { if ( TTI . getSubtarget < TargetSubtargetInfo > ( ) . getTargetTriple ( ) . getArch ( ) != Triple :: nvptx ) return 0 ; if ( CostKind != TTI :: TCK_RecipThroughput ) return 0 ; if ( Ty1 -> getPrimitiveSizeInBits ( ) != 64 || Ty2 -> getPrimitiveSizeInBits ( ) != 64 ) return 0 ; unsigned int Cost = TTI . getIntrinsicCost ( Intrinsic :: nvptx_add_i64 , Ty1 ) + TTI . getIntrinsicCost ( Intrinsic :: nvptx_mul_i64 , Ty1 ) + TTI . getIntrinsicCost ( Intrinsic :: nvptx_xor_i64 , Ty1 ) + TTI . getIntrinsicCost ( Intrinsic :: nvptx_or_i64 , Ty1 ) + TTI . getIntrinsicCost ( Intrinsic :: nvptx_and_i64 , Ty1 ) ; return Cost ; }


void getAnalysisUsage ( AnalysisUsage & AU ) const override { MachineFunctionPass :: getAnalysisUsage ( AU ) ; AU . addRequired < NVPTXTargetMachine > ( ) ; AU . addRequired < TargetTransformInfoWrapperPass > ( ) ; AU . addRequired < MachineRegisterInfo > ( ) ; AU . addPreserved < MachineFunctionAnalysis > ( ) ; }


unsigned getArithmeticInstrCost ( TargetOpcode Opcode , MVT VT ) { switch ( Opcode ) { case NVPTX :: ADD : case NVPTX :: MUL : case NVPTX :: XOR : case NVPTX :: OR : case NVPTX :: AND : if ( VT == MVT :: i64 ) { return 2 ; } break ; } return 1 ; }


bool hasBranchDivergence ( const llvm :: Function * F ) { const llvm :: TargetMachine * TM = F -> getParent ( ) -> getTargetMachine ( ) ; const llvm :: TargetSubtargetInfo * STI = TM -> getSubtargetImpl ( F ) ; const llvm :: NVPTXSubtarget * ST = static_cast < const llvm :: NVPTXSubtarget * > ( STI ) ; return ST -> getGenLoops ( ) && ST -> getCapBranchDivergence ( ) ; }


llvm :: ImmutablePass * initializePass ( ) { llvm :: Value * nvptxValue = return new llvm :: ImmutablePass ( nvptxValue ) ; }


int getArithmeticInstrCost ( NVPTXTargetLowerInfo & TLInfo , TTI :: InstructionRemark & Remark , TargetTransformInfo :: TargetCostKind CostKind , EVT VT , unsigned NumOperands ) { if ( ! TLInfo . isArithmeticInstr ( VT ) || ! TLInfo . isLegalArithType ( VT ) ) return - 1 ; if ( VT == MVT :: i64 ) { switch ( NumOperands ) { case 2 : return 14 ; case 1 : return 14 ; default : return - 1 ; } } else { return - 1 ; } }


unsigned int getArithmeticInstrCost ( OpCode op , ValueType type , int numOps , int latency ) { if ( op != ISD :: ADD && op != ISD :: MUL && op != ISD :: XOR && op != ISD :: OR && op != ISD :: AND ) { return 0 ; } if ( type != MVT :: i64 ) { return 0 ; } if ( numOps != 2 ) { return 0 ; } unsigned int throughput = 0 ; switch ( op ) { case ISD :: ADD : case ISD :: MUL : throughput = 1 ; break ; case ISD :: XOR : case ISD :: OR : case ISD :: AND : throughput = 0.5 ; break ; } unsigned int cost = throughput * latency ; return cost ; }


int getNumberOfRegisters ( ) { llvm :: TargetMachine * targetMachine = llvm :: EngineBuilder ( ) . selectTarget ( ) ; if ( ! targetMachine || targetMachine -> getTargetTriple ( ) . getArch ( ) != llvm :: Triple :: nvptx ) { return 0 ; } const llvm :: TargetSubtargetInfo * subtargetInfo = targetMachine -> getSubtargetImpl ( llvm :: StringRef ( "nvptx" ) ) ; int numRegs = subtargetInfo -> getRegInfo ( ) . getNumRegs ( ) ; return numRegs ; }


llvm :: UnrollingPreferences getUnrollingPreferences ( ) { llvm :: UnrollingPreferences preferences ; preferences . setTargetUnrollingPreferences ( "NVPTX" , 4 ) ; return preferences ; }


bool hasVolatileVariant ( Instruction * I ) { if ( I -> mayReadOrWriteMemory ( ) ) { Triple Target = I -> getModule ( ) -> getTargetTriple ( ) ; if ( Target . getArch ( ) == Triple :: nvptx ) { Instruction * VI = I -> getVolatileVariant ( ) ; if ( VI != nullptr ) { return true ; } } } return false ; }


unsigned int getAlign ( Instruction * inst ) { if ( inst -> isLoad ( ) || inst -> isStore ( ) ) { Value * ptrOperand = inst -> getPointerOperand ( ) ; if ( PointerType * ptrType = dyn_cast < PointerType > ( ptrOperand -> getType ( ) ) ) { unsigned int ptrAlign = ptrType -> getAlignment ( ) ; if ( ptrAlign != 0 ) { return min ( ptrAlign , 16 ) ; } else { return 16 ; } } } return 16 ; }


unsigned MaxKnownAlignment , unsigned DefaultAssumedAlignment ) { if ( TargetTriple == "NVPTX" ) { if ( Name == "callalign" ) { return MinKnownAlignment ; } } return DefaultAssumedAlignment ; }


Instruction * getInst ( Instruction * instruction ) { if ( instruction -> getTargetSpecificValue ( ) == "NVPTX,0,0,0,0" ) { return instruction -> getDependentInst ( ) ; } else { return nullptr ; } }


unsigned getAlign ( const Value * V ) { if ( const AlignedAttr * AA = V -> getFnAttr ( "align" ) ) { unsigned Align = AA -> getAlignment ( ) ; if ( Align > 0 ) { return Align ; } } unsigned TargetAlign = V -> getFnAttr ( "nvptx" ) -> getValueAsInt ( ) ; return TargetAlign & TargetAlignMask ; }


int getAlign ( void * base , int offset , char * dereference ) { if ( strcmp ( dereference , "load" ) == 0 || strcmp ( dereference , "store" ) == 0 ) { return 16 ; } else { int addr = ( int ) base + offset ; return addr & 16 ; } }


unsigned getAlign ( ) { unsigned callalign = NVPTX_CALLALIGN ; unsigned minalign = NVPTX_MINALIGN ; unsigned maxalign = NVPTX_MAXALIGN ; if ( callalign != 0 ) { return callalign ; } if ( minalign >= maxalign || minalign < NVPTX_DEFAULT_ALIGN ) { return NVPTX_DEFAULT_ALIGN ; } return minalign ; }


Instruction * getInst ( Dependency * dep ) { Function * F = dep -> getUser ( ) -> getParent ( ) ; if ( F -> getCallingConv ( ) == CallingConv :: NVPTX ) { Value * depVal = dep -> getDepValue ( ) ; if ( depVal -> getValueID ( ) == Value :: TargetSpecificConstant && depVal -> getOperand ( 0 ) == ( Value * ) CallingConv :: NVPTX ) { ConstantInt * instID = cast < ConstantInt > ( depVal -> getOperand ( 1 ) ) ; Instruction * inst = dyn_cast < Instruction > ( F -> getInstruction ( instID -> getZExtValue ( ) ) ) ; return inst ; } } return nullptr ; }


namespace { # define NVPTX "nvptx" class NVPTXPass : public FunctionPass { public : static char ID ; NVPTXPass ( ) : FunctionPass ( ID ) { } bool runOnFunction ( Function & F ) override { auto & FAM = getAnalysisManager < FunctionAnalysisManager > ( ) ; auto * PDT = & FAM . getResult < PostDominatorTreeAnalysis > ( F ) ; PDT -> printAsDOT ( F . getParent ( ) -> getModuleIdentifier ( ) + "." + F . getName ( ) , dbgs ( ) ) ; return false ; } void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . addRequired < PostDominatorTreeAnalysis > ( ) ; AU . setPreservesAll ( ) ; AU . addRequired < TargetLibraryInfoWrapperPass > ( ) ; AU . addRequired < DominatorTreeWrapperPass > ( ) ; }


bool runOnFunction ( Function & F ) override { const Target * target = F . getParent ( ) -> getTarget ( ) ; if ( ! target || target -> getTargetTriple ( ) . isNVPTX ( ) ) return false ; return true ; }


"_reflect function should not have a body"

"_reflect's return type should be integer"

"Wrong number of operands to _reflect function"

"Format of _reflect function not recognized"


"Only one operand expected for _reflect function"


void getAnalysisUsage ( AnalysisUsage & au ) const override { au . addRequired < NVPTXTargetTransformInfo > ( ) ; au . addPreserved < NVPTXTargetTransformInfo > ( ) ; au . setPreservesCFG ( ) ; }


DominatorTree * run ( Function & F ) { TargetMachine * TM = get NVPTXTargetMachine ( ) ; LLVMContext & C = F . getContext ( ) ; LegacyPassManager PM ; PM . add ( createTargetTransformInfoWrapperPass ( TM -> getTargetIRAnalysis ( ) ) ) ; DominatorTree * DT = new DominatorTree ( ) ; DT -> recalculate ( F ) ; PM . add ( createDomTreePrinterPass ( ) ) ; PM . run ( F ) ; return DT ; }


void NVPTXTargetMachine :: runOnFunction ( Function & F ) { NVPTXTargetLowering & TLI = * getSubtargetImpl ( F ) -> getTargetLowering ( ) ; TLI . runOnFunction ( F ) ; } void NVPTXTargetLowering :: runOnFunction ( Function & F ) { AttributeSet attrs = F . getAttributes ( ) ; attrs . addAttribute ( F . getContext ( ) , "nvvmir" , "1.0" ) ; F . setAttributes ( attrs ) ; }


bool runOnFunction ( Function & Func , TargetLibraryInfo & TLI ) { Triple TargetTriple ( Func . getParent ( ) -> getTargetTriple ( ) ) ; if ( TargetTriple . getArch ( ) != Triple :: nvptx || ! ( TargetTriple . getVendor ( ) == Triple :: NVIDIA && TargetTriple . getOS ( ) == Triple :: Cuda ) ) { return false ; }


"Expected a const-to-gen conversion for _reflect function"

"Only a call instruction can use _reflect"


void NVPTXTargetMachine :: getAnalysisUsage ( AnalysisUsage & AU ) const { TargetMachine :: getAnalysisUsage ( AU ) ; AU . addRequired < NVPTXTargetTransformInfo > ( ) ; }


void runOnModule ( Module & M ) override { Type * Int32Ty = Type :: getInt32Ty ( M . getContext ( ) ) ; Function * Func = M . getFunction ( "myFunction" ) ; BasicBlock * BB = & Func -> getEntryBlock ( ) ; Instruction * InsertionPt = & * BB -> getFirstInsertionPt ( ) ; Value * NewInst = BinaryOperator :: Create ( Instruction :: Add , ConstantInt :: get ( Int32Ty , 5 ) , ConstantInt :: get ( Int32Ty , 10 ) , "newInst" ) ; InsertionPt -> insertBefore ( NewInst ) ; }


std
::
string
getPassName
(
const
void
*
Pass
)
{
if
(
Pass
==
&
llvm
::
NVPTX
::
ConvertVectorTypesPass
::
ID
)
return
"NVPTX Convert Vector Types"
;
else
return
""
;
}


"Should be handled target independently"


void runOnMachineFunction ( MachineFunction & MF ) { TargetMachine & TM = MF . getTarget ( ) ; TM . setARCTargetSpecificValue ( 4 ) ; MF . emitARCBodyInstructions ( ) ; TM . setARCTargetSpecificValue ( ARC ) ; }


void
emitInstruction
(
ARCMachineFunction
&
MF
,
MCInst
&
Inst
)
{
ARCODMCInst
&
ARCInst
=
static_cast
<
ARCODMCInst
&
>
(
Inst
)
;
switch
(
ARCInst
.
getOpcode
(
)
)
{
case
ARC
::
DBG_VALUE
:
{
MF
.
emitInstruction
(
ARCInst
.
getOpcode
(
)
,
ARCInst
.
getOperands
(
)
,
ARC
::
TARGET
)
;
break
;
}
default
:
llvm_unreachable
(
"Unexpected instruction type!"
)
;
}
}


string
getPassName
(
)
{
return
"ARC Assembly Printer"
;
}


void runOnMachineFunction ( MachineFunction & MF ) { ARCTargetMachine & TM = static_cast < ARCTargetMachine & > ( MF . getTarget ( ) ) ; unsigned int TargetSpecificValue = TM . getTargetSpecificValue ( ) ; ARCInstrInfo & TII = * TM . getInstrInfo ( ) ; MachineBasicBlock * MBB = MF . CreateMachineBasicBlock ( ) ; MF . push_back ( MBB ) ; MachineBasicBlock :: iterator I = MBB -> begin ( ) ; BuildMI ( * MBB , I , DebugLoc ( ) , TII . get ( ARC :: ARC_ADD_imm ) , ARC :: ARC ) . addReg ( ARC :: ARC ) . addImm ( TargetSpecificValue ) ; BuildMI ( * MBB , std :: next ( I ) , DebugLoc ( ) , TII . get ( ARC :: ARC_RET ) ) ; }


void
runOnMachineFunction
(
MachineFunction
&
MF
)
{
ARCFunctionInfo
*
AFI
=
MF
.
getInfo
<
ARCFunctionInfo
>
(
)
;
EmitARCBranchFinalize
(
MF
)
;
dbgs
(
)
<<
"Running ARC Branch Finalize on "
<<
MF
.
getName
(
)
.
str
(
)
<<
"\n"
;
dbgs
(
)
<<
"Estimated function size for "
<<
MF
.
getName
(
)
.
str
(
)
<<
": "
;
if
(
!
AFI
)
{
dbgs
(
)
<<
"Unknown (or size 0) size for: "
;
}
else
{
dbgs
(
)
<<
AFI
->
getSize
(
)
<<
": "
;
}
dbgs
(
)
<<
MF
.
getName
(
)
.
str
(
)
<<
"\n"
;
generateMachineCode
(
MF
)
;
}


MachineFrameInfo & MFI , StackMapLayout & SM , TargetLoweringBase * TLI ) { MF -> runFunctionBegin ( ) ; MF -> runARCFinalize ( ) ; for ( auto & BB : MF -> getBasicBlocks ( ) ) { emitBasicBlock ( BB , MBB , MFI , SM , TLI ) ; BB -> runOnMachineFunction ( ) ; }


std
::
string
getPassName
(
)
{
return
"ARC Branch Finalization Pass"
;
}


void
runOnMachineFunction
(
const
MachineFunction
&
MF
)
{
O
<<
"Running ARC Branch Finalize on "
<<
MF
.
getName
(
)
<<
"\n"
;
O
<<
"#define ARC 1"
<<
" // Set ARC specific value\n"
;
O
<<
"#define ARC 0"
<<
"\n"
;
O
<<
"Running ARC Branch Finalize on "
<<
"\n"
;
O
<<
"#define ARC 0"
<<
"\n"
;
unsigned
int
FuncSize
=
getFunctionSize
(
MF
)
;
O
<<
"Unknown (or size 0) size for: "
<<
MF
.
getName
(
)
<<
"\n"
;
O
<<
"Estimated function size for "
<<
MF
.
getName
(
)
<<
": \n"
;
O
<<
"\n"
;
EmitARCSpecificInstructions
(
MF
)
;
FuncSize
+=
getTargetSpecificValue
(
)
;
O
<<
"Estimated function size for "
<<
MF
.
getName
(
)
<<
": "
<<
FuncSize
<<
"\n"
;
}


std
::
string
getInstruction
(
unsigned
char
*
bytes
,
int
size
)
{
LLVMInitializeARCTarget
(
)
;
LLVMInitializeARCTargetInfo
(
)
;
LLVMInitializeARCTargetMC
(
)
;
LLVMInitializeARCMCAsmInfo
(
)
;
LLVMInitializeARCMCCodeGenInfo
(
)
;
LLVMInitializeARCMCInstrInfo
(
)
;
LLVMInitializeARCMCLowerInstrInfo
(
)
;
std
::
string
error
;
Triple
TheTriple
(
Triple
::
normalize
(
""
)
)
;
TargetOptions
options
;
std
::
unique_ptr
<
TargetMachine
>
target
(
TargetRegistry
::
lookupTarget
(
""
,
TheTriple
,
error
)
)
;
if
(
!
target
)
{
return
"Error setting up target machine."
;
}
MCContext
*
mcc
=
new
MCContext
(
)
;
MCDisassembler
*
disasm
=
target
->
createMCDisassembler
(
TheTriple
,
*
mcc
)
;
std
::
unique_ptr
<
MCInstrInfo
>
MCII
(
target
->
createMCInstrInfo
(
)
)
;
std
::
unique_ptr
<
MCInstPrinter
>
InstPrinter
(
target
->
createMCInstPrinter
(
TheTriple
,
0
,
*
MCII
,
options
)
)
;
std
::
unique_ptr
<
MCELFStreamer
>
ElfStreamer
(
target
->
createMCObjectStreamer
(
TheTriple
,
getContext
(
)
,
*
MCII
,
*
SmallDataStreamer
,
*
*
mcc
,
codeModel
::
Default
,
False
,
False
,
nullptr
)
)
;
MCStreamer
*
mcs
=
new
MCStreamer
(
)
;
mcs
->
InitSections
(
)
;
SmallVector
<
char
,
16
>
codevec
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
codevec
.
push_back
(
bytes
[
i
]
)
;
}


"-bit instruction, falling back to 32-bit."

"-bit instruction with limm, try without it."


void runOnMachineFunction ( MachineFunction & MF ) { const TargetMachine & TM = MF . getTarget ( ) ; const TargetInstrInfo & TII = * TM . getInstrInfo ( ) ; const TargetRegisterInfo & TRI = * TM . getRegisterInfo ( ) ; for ( MachineFunction :: iterator I = MF . begin ( ) , E = MF . end ( ) ; I != E ; ++ I ) { MachineBasicBlock & MBB = * I ; for ( MachineBasicBlock :: iterator MI = MBB . begin ( ) , ME = MBB . end ( ) ; MI != ME ; ++ MI ) { MachineInstr & Inst = * MI ; switch ( Inst . getOpcode ( ) ) { case ARC :: ST_FAR : case ARC :: STH_FAR : case ARC :: STB_FAR : Register TargetReg = Inst . getOperand ( 0 ) . getReg ( ) ; Register StackPtrReg = TRI . getStackRegister ( ) ; BuildMI ( MBB , MI , DebugLoc ( ) , TII . get ( ARC :: LD ) ) . addReg ( TargetReg , RegState :: Define ) . addReg ( StackPtrReg ) ; int Offset = Inst . getOperand ( 1 ) . getImm ( ) ; BuildMI ( MBB , MI , DebugLoc ( ) , TII . get ( ARC :: ST ) ) . addReg ( TargetReg , RegState :: Kill ) . addReg ( StackPtrReg ) . addImm ( Offset ) ; MI -> eraseFromParent ( ) ; break ; default : break ; } } } }


bool determineCalleeSaves ( ) { const MCPhysReg * CalleeSavedRegs = ARC :: BLINK ; unsigned NumCalleeSavedRegs = sizeof ( CalleeSavedRegs ) / sizeof ( MCPhysReg ) ; for ( unsigned i = 0 ; i < NumCalleeSavedRegs ; i ++ ) { MCPhysReg CalleeSavedReg = CalleeSavedRegs [ i ] ; if ( CalleeSavedReg == ARC :: BLINK ) { TargetRegisterInfo :: getReservedRegs ( MF ) . addReg ( CalleeSavedReg ) ; } else { bool IsLiveIn = false ; for ( MachineFunction :: livein_iterator I = MF . livein_begin ( ) , E = MF . livein_end ( ) ; I != E ; ++ I ) { if ( I -> first == CalleeSavedReg ) { IsLiveIn = true ; break ; } } if ( ! IsLiveIn ) { TargetRegisterInfo :: getReservedRegs ( MF ) . addReg ( CalleeSavedReg ) ; } } } return true ; }


void eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB ) { const TargetInstrInfo * TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; for ( auto I = MBB . instr_begin ( ) , E = MBB . instr_end ( ) ; I != E ; ) { MachineInstr & MI = * I ; if ( MI . getOpcode ( ) == ARC :: ADJCALLSTACKDOWN || MI . getOpcode ( ) == ARC :: ADJCALLSTACKUP ) { const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( MCID . isPseudo ( ) ) { if ( TII -> useCallFramePseudoInstructions ( MF ) ) { LLVMContext & Ctx = MF . getFunction ( ) . getContext ( ) ; MachineInstr * NewMI = nullptr ; if ( MI . getOpcode ( ) == ARC :: ADJCALLSTACKDOWN ) { NewMI = BuildMI ( MF , MI . getDebugLoc ( ) , TII -> get ( ARC :: ADJCALLSTACKDOWN ) , MI . getOperand ( 0 ) . getReg ( ) , MI . getOperand ( 1 ) . getImm ( ) ) ; } else { NewMI = BuildMI ( MF , MI . getDebugLoc ( ) , TII -> get ( ARC :: ADJCALLSTACKUP ) , MI . getOperand ( 0 ) . getReg ( ) , MI . getOperand ( 1 ) . getImm ( ) ) ; } MBB . insertAfter ( MI , NewMI ) ; MI . eraseFromParent ( ) ; I = NewMI -> getIterator ( ) ; continue ; } } } ++ I ; } }


"Process function before frame finalized:\n"


bool restoreCalleeSavedRegisters ( MachineInstr & MI , MachineRegisterInfo & MRI ) { bool isProfitable = true ; const MCPhysReg * CalleeSavedRegs = MRI . getCalleeSavedRegs ( ) ; int Size = MRI . getNumVirtRegs ( ) ; for ( int i = 0 ; i < Size ; i ++ ) { if ( MRI . isAllocatable ( CalleeSavedRegs [ i ] ) ) { int StackSlot = MRI . getStackSlot ( CalleeSavedRegs [ i ] ) ; MachineInstrBuilder MIB = BuildMI ( * MI . getParent ( ) , MI , MI . getDebugLoc ( ) , get ( ARC :: LDWntausp ) , CalleeSavedRegs [ i ] ) ; MIB . addFrameIndex ( StackSlot ) ; MI . getParent ( ) -> insert ( MI , MIB ) ; isProfitable = false ; } } if ( isProfitable ) return true ; else { MachineInstrBuilder MIB = BuildMI ( * MI . getParent ( ) , MI , MI . getDebugLoc ( ) , get ( ARC :: MOVi ) , ARC :: R14 ) . addImm ( ARC :: R14 ) ; MI . getParent ( ) -> insert ( MI , MIB ) ; return false ; } }


bool spillCalleeSavedRegisters ( MachineFunction & MF ) { const ARCSubtarget & Subtarget = MF . getSubtarget < ARCSubtarget > ( ) ; const ARCRegisterInfo * RegInfo = Subtarget . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; bool HasCalleeSavedRegs = false ; for ( unsigned Reg : RegInfo -> getCalleeSavedRegs ( MF ) ) { if ( RegInfo -> isCalleeSavedReg ( MF , Reg ) ) { HasCalleeSavedRegs = true ; break ; } } if ( ! HasCalleeSavedRegs ) return false ; const TargetInstrInfo * TII = Subtarget . getInstrInfo ( ) ; for ( unsigned Reg : RegInfo -> getCalleeSavedRegs ( MF ) ) { if ( RegInfo -> isCalleeSavedReg ( MF , Reg ) ) { int FrameIdx = MFI . CreateStackObject ( RegInfo -> getSpillSize ( MF , Reg ) , RegInfo -> getSpillAlign ( MF , Reg ) ) ; MRI . setSimpleHint ( Reg , FrameIdx ) ; int64_t sp = ARC :: R14 ; BuildMI ( MF , DebugLoc ( ) , TII -> get ( ARC :: MOV_GPRetImm ) , sp ) . addImm ( FrameIdx ) ; } } return true ; }


bool restoreCalleeSavedRegisters ( ) { int targetVal = ARC :: R14 ; if ( targetVal * calleeSavedRegisterSize > callerSavedRegisterSize ) return true ; for ( int i = 0 ; i < calleeSavedRegisterSize ; ++ i ) { loadRegToStackSlot ( targetVal , i ) ; ++ targetVal ; } return false ; }


void determineCalleeSaves ( MachineFunction & MF , TargetRegisterInfo & TRI ) { const MCPhysReg * CalleeSavedRegs = TRI . getCalleeSavedRegs ( & MF ) ; unsigned NumCalleeSavedRegs = TRI . getNumCalleeSavedRegs ( & MF ) ; std :: set < MCPhysReg > CalleeSavedSet ; for ( unsigned i = 0 ; i < NumCalleeSavedRegs ; ++ i ) { MCPhysReg CalleeSavedReg = CalleeSavedRegs [ i ] ; if ( CalleeSavedReg == ARC :: BLINK ) { CalleeSavedSet . insert ( CalleeSavedReg ) ; } else { const TargetRegisterClass * RC = TRI . getRegClass ( CalleeSavedReg ) ; unsigned SpillSize = TRI . getSpillSize ( * RC ) ; int CSR = TRI . getCallPreservedMask ( & MF ) [ i ] ; if ( CSR ) { CalleeSavedSet . insert ( CalleeSavedReg ) ; } } }


void eliminateCallFramePseudoInstr ( Instruction * Instr , ARCMachineFunctionInfo * MFI , MachineBasicBlock * MBB ) { if ( Instr -> isCallFramePseudo ( ) ) { ARCCCState CCInfo ; CCInfo . AnalyzeCallOperands ( Chain , CC_ARVL , Ins , nullptr , nullptr ) ; int CallFramePseudo = CCInfo . ARCallFramePseudo ; if ( CallFramePseudo != 0 ) { MBB -> erase ( Instr ) ; CallFramePseudo += 2 * sizeof ( int ) ; Instr -> addOperand ( MachineOperand :: CreateImm ( CallFramePseudo ) ) ; MBB -> insert ( Instr ) ; } } }


"Process function before frame finalized: \n"


bool restoreCalleeSavedRegisters ( MachineFunction & MF ) { } Function definition : bool restoreCalleeSavedRegisters ( MachineFunction & MF ) { MachineBasicBlock & MBB = * MF . begin ( ) ; unsigned R14 = ARC :: R14 ; MachineFunctionInfo & MFI = MF . getInfo < MachineFunctionInfo > ( ) ; if ( ! MFI . shouldRestoreCalleeSavedRegisters ( ) ) { return false ; } int FI = MF . getFrameInfo ( ) . CreateStackObject ( 4 , 4 , false ) ; for ( const MCPhysReg * CSRegs = ARCRegisterInfo :: getCalleeSavedRegs ( ) ; * CSRegs != 0 ; ++ CSRegs ) { unsigned Reg = * CSRegs ; if ( ! ARCRegisterInfo :: isLegalForClass ( Reg , ARC :: ARCREG_I32 ) ) continue ; const TargetRegisterClass * RC = MF . getRegInfo ( ) . getRegClass ( Reg ) ; unsigned SubIdx = ARCRegisterInfo :: getSubRegIndex ( RC , Reg ) ; unsigned SubReg = ARCRegisterInfo :: getSubReg ( Reg , SubIdx ) ; BuildMI ( MBB , MBB . begin ( ) , DebugLoc ( ) , ARCInstrInfo :: get ( ARC :: LDRi2 ) , SubReg ) . addFrameIndex ( FI ) . addImm ( 0 ) ; FI += 4 ; } MachineInstrBuilder MIB = BuildMI ( MBB , MBBI , DebugLoc ( ) , ARCInstrInfo :: get ( ARC :: MOVAr2B ) ) . addReg ( R14 ) ; AddDefaultCC ( MIB ) ; return true ; }


bool spillCalleeSavedRegisters ( MachineInstr * MI ) { Register R14 = ARC :: R14 ; const MCPhysReg * SavedRegs = MF . getCalleeSavedRegs ( ) ; for ( unsigned i = 0 ; SavedRegs [ i ] != 0 ; ++ i ) { if ( SavedRegs [ i ] != R14 ) { if ( ! storeRegToStackSlot ( MI , i , true ) ) { return false ; } } } return true ; }


bool hasFP ( const Function & F ) { return true ; }


void assignCalleeSavedSpillSlots ( MachineFunction & MF ) { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; const MCPhysReg * CSRegs = MF . getSubtarget ( ) . getCalleeSavedRegs ( & MF ) ; std :: map < MCPhysReg , MCPhysReg > VVRCalleeSavedMap ; for ( unsigned i = 0 ; CSRegs [ i ] != 0 ; ++ i ) { if ( ! MRI . isAllocatable ( CSRegs [ i ] ) ) continue ; MCPhysReg VVR = TRI -> getVVRForCalleeSavedReg ( CSRegs [ i ] ) ; if ( VVR != 0 ) VVRCalleeSavedMap [ VVR ] = CSRegs [ i ] ; } for ( auto & it : VVRCalleeSavedMap ) { MCRegister VVR = MRI . getUniqueVReg ( it . first ) ; MCRegister CSReg = MRI . getUniqueVReg ( it . second ) ; MachineObject * VVRStackObject = MFI . CreateStackObject ( RC ) ; MRI . setSpillSlot ( VVR , VVRStackObject ) ; MachineObject * CSRegStackObject = MFI . getObjectForVReg ( CSReg ) ; MRI . setSpillSlot ( CSReg , CSRegStackObject ) ; } }


void
processFunctionBeforeFrameFinalized
(
MachineFunction
&
MF
)
{
int
stackSize
=
MF
.
getFrameInfo
(
)
.
getStackSize
(
)
;
std
::
cout
<<
"Current stack size: "
<<
stackSize
<<
"\n"
;
const
TargetRegisterClass
*
GPR32RegClass
=
ARC
::
GPR32RegClass
;
const
TargetRegisterClass
*
RegScavFI
=
MF
.
getRegInfo
(
)
.
createScavengingIndex
(
GPR32RegClass
)
;
std
::
cout
<<
"Created scavenging index RegScavFI="
<<
RegScavFI
<<
"\n"
;
}


bool restoreCalleeSavedRegisters ( ) { unsigned savedRegs [ ] = { ARC :: R14 } ; if ( savedRegs [ 0 ] == 0 ) return true ; for ( unsigned i = 0 ; i < savedRegs . size ( ) ; i ++ ) { unsigned reg = savedRegs [ i ] ; MachineInstr * loadInst = BuildMI ( * BB , InsertPt , DL , TII -> get ( ARC :: LD ) , ARC :: SP ) . addReg ( reg ) . addImm ( 0 ) ; BB -> insert ( InsertPt , loadInst ) ; } return false ; }


namespace { struct SpillCalleeSavedRegisters : public MachineFunctionPass { static char ID ; SpillCalleeSavedRegisters ( ) : MachineFunctionPass ( ID ) { } bool runOnMachineFunction ( MachineFunction & MF ) override ; } ; } bool SpillCalleeSavedRegisters :: runOnMachineFunction ( MachineFunction & MF ) { bool modified = false ; for ( MachineBasicBlock & MBB : MF ) { for ( MachineInstr & MI : MBB ) { if ( MI . isCall ( ) ) { for ( MachineOperand & MO : MI . operands ( ) ) { if ( MO . isRegMask ( ) ) { for ( unsigned Reg : MO . getRegMask ( ) ) { if ( TargetRegisterInfo :: isCalleeSaved ( Reg ) ) { BuildMI ( MBB , MI , DebugLoc ( ) , MF . getSubtarget ( ) . getInstrInfo ( ) -> get ( ARC :: STW ) ) . addReg ( ARC :: R14 ) . addReg ( Reg , RegState :: Kill ) ; modified = true ; } } break ; } } } } } return modified ; }


void
printInst
(
const
MCInst
&
Inst
,
raw_ostream
&
OS
,
const
MCAsmInfo
&
MAI
)
{
if
(
Inst
.
getOpcode
(
)
==
ARC
::
ARC
)
{
OS
<<
"ARC "
;
}
else
if
(
Inst
.
getOpcode
(
)
==
ARC
::
ARC
)
{
OS
<<
"ARC "
;
}
Inst
.
print
(
OS
,
&
MAI
)
;
OS
<<
"\n"
;
}


void
printInst
(
MCInst
Inst
,
raw_ostream
&
OS
)
{
if
(
Inst
.
getOpcode
(
)
==
ARC
::
ARC
)
{
OS
<<
"ARC"
;
}
else
if
(
Inst
.
getOpcode
(
)
==
ARC
::
ARC
)
{
OS
<<
"ARC"
;
}
else
{
OS
<<
Inst
.
getOpcode
(
)
;
}
for
(
unsigned
i
=
0
,
e
=
Inst
.
getNumOperands
(
)
;
i
!=
e
;
++
i
)
{
OS
<<
' '
;
const
MCOperand
&
Op
=
Inst
.
getOperand
(
i
)
;
if
(
Op
.
isReg
(
)
)
OS
<<
getRegisterName
(
Op
.
getReg
(
)
)
;
else
if
(
Op
.
isImm
(
)
)
OS
<<
formatImm
(
Op
.
getImm
(
)
)
;
else
if
(
Op
.
isFPImm
(
)
)
OS
<<
formatFPImm
(
Op
.
getFPImm
(
)
)
;
else
if
(
Op
.
isExpr
(
)
)
OS
<<
*
Op
.
getExpr
(
)
;
else
if
(
Op
.
isInst
(
)
)
OS
<<
*
Op
.
getInst
(
)
;
else
llvm_unreachable
(
"Invalid operand kind"
)
;
}
}


bool
analyzeBranch
(
MachineBasicBlock
&
MBB
)
{
MachineInstr
&
MI
=
MBB
.
back
(
)
;
for
(
int
i
=
0
;
i
<
MI
.
getNumOperands
(
)
;
i
++
)
{
MachineOperand
&
MO
=
MI
.
getOperand
(
i
)
;
if
(
MO
.
isTargetSpecific
(
)
)
{
if
(
MO
.
getTargetFlags
(
)
==
ARC
)
{
return
true
;
}
if
(
MO
.
getTargetFlags
(
)
==
"FBB should have been null."
)
{
return
true
;
}
}
}
return
false
;
}


"Only support GPR32 register class for loading from stack"


"Only support GPR32 stores to stack now"

"Only support 4-byte stores to stack now"


"Only support 4-byte loads from stack now."

"Only support GPR32 stores to stack now."


"Only support 4-byte stores to stack now."

"Couldn't get MachineMemOperand for store to stack."


int
FrameIndex
)
{
unsigned
LoadOpcode
=
ARC
::
LD_rs9
;
const
TargetRegisterClass
*
RC
=
&
ARC
::
GPR32RegClass
;
if
(
!
RC
->
contains
(
DestReg
)
)
{
report_fatal_error
(
"Can only load to a GPR32 register"
)
;
}
const
ARCSubtarget
&
Subtarget
=
MF
.
getSubtarget
<
ARCSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
Subtarget
.
getInstrInfo
(
)
;
const
TargetRegisterInfo
&
TRI
=
*
Subtarget
.
getRegisterInfo
(
)
;
int64_t
FrameOffset
=
MF
.
getFrameInfo
(
)
.
getObjectOffset
(
FrameIndex
)
;
Register
SPReg
=
TRI
.
getStackRegister
(
)
;
Register
TempReg
=
TRI
.
getMatchingSuperReg
(
DestReg
,
ARC
::
sub_r0_0
,
&
ARC
::
GPR32RegClass
)
;
BuildMI
(
MBB
,
MBBI
,
DebugLoc
(
)
,
TII
.
get
(
LoadOpcode
)
,
DestReg
)
.
addReg
(
SPReg
)
.
addImm
(
FrameOffset
)
.
addReg
(
TempReg
)
;
dbgs
(
)
<<
"Created load "
<<
printReg
(
DestReg
,
TRI
)
<<
" from FrameIndex "
<<
FrameIndex
<<
"\n"
;
}


"Only support GPR32 stores to stack now.\n"


bool getBaseAndOffsetPosition ( const MachineInstr * MI , unsigned & BaseReg , int64_t & Offset ) { unsigned ARC = MI -> getOperand ( 0 ) . getImm ( ) ; if ( ARC != 1 || ARC != 2 ) { return false ; } BaseReg = MI -> getOperand ( 1 ) . getReg ( ) ; Offset = MI -> getOperand ( 2 ) . getImm ( ) ; if ( ! TargetRegisterInfo :: isPhysicalRegister ( BaseReg ) ) { return false ; } if ( Offset > INT_MAX || Offset < INT_MIN ) { return false ; } return true ; }


unsigned int ARC :: getInstSizeInBytes ( const MachineInstr * MI ) const { switch ( MI -> getOpcode ( ) ) { default : return 0 ; case ARC :: ADD_rr : case ARC :: AND_rr : case ARC :: CMP_rr : case ARC :: CMP_rq : case ARC :: CMP_rqh : case ARC :: D32ADD_rr : case ARC :: D32AND_rr : case ARC :: D32OR_rr : case ARC :: D32SUB_rr : case ARC :: D32XOR_rr : case ARC :: LDDR_rr : case ARC :: LDW_rp : case ARC :: MOV_rr : case ARC :: MOVS_rr : case ARC :: MOVD_rr : case ARC :: OR_rr : case ARC :: SUB_rr : case ARC :: XOR_rr : return 4 ; case ARC :: ADD_krr : case ARC :: AND_krr : case ARC :: CMP_krr : case ARC :: D32ADD_krr : case ARC :: D32AND_krr : case ARC :: D32OR_krr : case ARC :: D32SUB_krr : case ARC :: D32XOR_krr : case ARC :: LDR_rkp : case ARC :: LDR_rrp : case ARC :: LDW_rq : case ARC :: MUL_rr : case ARC :: MUL_qrr : case ARC :: MUL_qrp : case ARC :: MUL_qrph : case ARC :: NOP : case ARC :: OR_krr : case ARC :: SWIX_rq : case ARC :: SUB_krr : case ARC :: XOR_krr : return 8 ; case ARC :: BR : case ARC :: J : return 12 ; case ARC :: CASrr : case ARC :: LDDR_rq : case ARC :: MOVh_rr : case ARC :: SWI : return 16 ; } }


bool isPostIncrement ( const TargetInstrInfo * TII , const MachineInstr * MI ) { unsigned int opcode = MI -> getOpcode ( ) ; return TII -> isPostIncrementOpcode ( opcode ) ; }


void
copyPhysReg
(
bit
RC
,
bit
SRC
,
bit
DST
)
{
if
(
RC
==
ARC
::
GPR32RegClass
)
{
if
(
SRC
==
ARC
::
GPR32RegClass
&&
DST
==
ARC
::
GPR32RegClass
)
{
ARC
::
MOV_rr
MI
=
(
ARC
::
MOV_rr
)
target
specific
value
;
MI
.
setSrcReg
(
SRC
)
;
MI
.
setDstReg
(
DST
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARC
::
MOV_rr
)
)
.
addReg
(
SRC
)
.
addReg
(
DST
)
;
}
else
{
llvm_unreachable
(
"Only GPR32 src/dest copy supported."
)
;
}
}
else
{
llvm_unreachable
(
"Only GPR32 src/dest copy supported."
)
;
}
}


"insertBranch must not be told to insert a fallthrough."

"ARC branch conditions have two components!"


void loadImmediate ( CodeGenFunction & CGF , llvm :: Value * Dest , llvm :: APInt ConstantValue , llvm :: DebugLoc Loc ) { llvm :: Type * Ty = Dest -> getType ( ) ; llvm :: ConstantInt * ConstInt = llvm :: ConstantInt :: get ( Ty , ConstantValue ) ; llvm :: SmallVector < llvm :: Value * , 2 > Args ; Args . push_back ( Dest ) ; Args . push_back ( ConstantInt ) ; llvm :: CallInst :: Create ( ARCRuntime :: getARCLongImmediateFn ( ) , Args , "" , CGF . Builder . GetInsertBlock ( ) ) ; if ( CGF . CGM . getCodeGenOpts ( ) . getDbgInfoKind ( ) != llvm :: CodeGenOptions :: NoDebugInfo ) { llvm :: MDBuilder MDB ( CGF . getLLVMContext ( ) ) ; llvm :: MDNode * DebugLoc = MDB . createDebugLocation ( Loc . getLine ( ) , Loc . getCol ( ) , CGF . EmitFunction ( unit ) . getSubprogram ( ) ) ; llvm :: CastInst * CI = llvm :: cast < llvm :: CastInst > ( CGF . Builder . GetInsertPoint ( ) ) ; CI -> setDebugLoc ( DebugLoc ) ; } if ( Ty != Dest -> getType ( ) ) { llvm :: CastInst * CI = llvm :: CastInst :: CreatePointerCast ( Dest , Ty , "" , CGF . Builder . GetInsertBlock ( ) ) ; CGF . Builder . Insert ( CI ) ; Dest = CI ; } CGF . Builder . CreateStore ( Dest , CGF . ReturnValue ) ; }


bool reverseBranchCondition ( ARCCC :: CondCode & Cond ) { if ( ! ARCCC :: isBranchCondition ( Cond ) ) { return true ; } switch ( Cond ) { case ARCCC :: EQ : Cond = ARCCC :: NE ; break ; case ARCCC :: NE : Cond = ARCCC :: EQ ; break ; case ARCCC :: EQ_A : Cond = ARCCC :: NE_A ; break ; case ARCCC :: NE_A : Cond = ARCCC :: EQ_A ; break ; case ARCCC :: EQ_N : Cond = ARCCC :: NE_N ; break ; case ARCCC :: NE_N : Cond = ARCCC :: EQ_N ; break ; case ARCCC :: LO : Cond = ARCCC :: HS ; break ; case ARCCC :: LO_N : Cond = ARCCC :: HS_N ; break ; case ARCCC :: HS : Cond = ARCCC :: LO ; break ; case ARCCC :: HS_N : Cond = ARCCC :: LO_N ; break ; case ARCCC :: HI : Cond = ARCCC :: LS ; break ; case ARCCC :: HI_N : Cond = ARCCC :: LS_N ; break ; case ARCCC :: LS : Cond = ARCCC :: HI ; break ; case ARCCC :: LS_N : Cond = ARCCC :: HI_N ; break ; default : return true ; } return false ; }


"Target machine does not support ARC architecture"

"Store to stack not supported for register class"


const DebugLoc & DL ) { MachineFunction & MF = MBB . getParent ( ) ; const TargetInstrInfo & TII = * MF . getSubtarget ( ) . getInstrInfo ( ) ; const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; unsigned LoadOp = 0 ; if ( RegClass -> hasSubClassEq ( & ARC :: GPR32RegClass ) ) LoadOp = ARC :: LD_rs9 ; MachineInstrBuilder LoadMI = BuildMI ( MBB , MBB . end ( ) , DL , TII . get ( LoadOp ) ) . addReg ( RegClass -> getRegister ( 0 ) ) . addFrameIndex ( SlotIndex ) . addImm ( 0 ) ; const MCInstrDesc & MCID = LoadMI -> getDesc ( ) ; if ( MCID . hasImplicitDefOfPhysReg ( ARC :: GPR32RegClass . getRegister ( 0 ) ) ) LoadMI . addRegMask ( TRI -> getSubRegMask ( ARC :: g21 ) ) ; DEBUG ( LoadMI -> print ( errs ( ) ) ) ; return LoadMI ; }


" to stack: Unsupported register class.\n"

" to stack: Invalid stack frame index.\n"


unsigned int getInstSizeInBytes ( const MachineInstr * MI ) { if ( ! MI -> getDesc ( ) . isPseudo ( ) ) { return MI -> getDesc ( ) . getSize ( ) ; } else { for ( const MachineOperand & MO : MI -> operands ( ) ) { if ( MO . isImm ( ) ) { unsigned int Size = MO . getImm ( ) ; if ( Size > 0 ) { return Size ; } } } return ARC :: ARCInstSize ; } }


TargetInstrInfo getRegisterInfo ( unsigned Reg ) { TargetInstrInfo RegisterInfo ; if ( Reg >= ARC :: R0 && Reg <= ARC :: SP ) { RegisterInfo . ARC = true ; RegisterInfo . ARCRegister = Reg ; } else { RegisterInfo . ARC = false ; RegisterInfo . ARCRegister = ARC :: NoRegister ; } return RegisterInfo ; }


void insertBranch ( MachineBasicBlock & MBB , MachineBasicBlock * TargetBB , DebugLoc DL ) { MachineInstrBuilder MIB = BuildMI ( & MBB , DL , get ( ARC :: BR ) ) ; MIB . addMBB ( TargetBB ) ; MIB . addImm ( 1 ) ; MBB . addSuccessor ( TargetBB ) ; MBB . updateTerminator ( ) ; }


unsigned
int
isLoadFromStackSlot
(
const
MachineInstr
*
MI
)
{
assert
(
MI
&&
"null machine instruction"
)
;
if
(
MI
->
getOpcode
(
)
==
ARC
::
LD16FI
||
MI
->
getOpcode
(
)
==
ARC
::
LD32FI
||
MI
->
getOpcode
(
)
==
ARC
::
LD64FI
)
{
unsigned
int
Reg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
unsigned
int
FrameIndex
=
MI
->
getOperand
(
1
)
.
getIndex
(
)
;
return
(
ARC
,
ARC
,
1
,
2
,
2
,
1
,
0
,
0
)
+
Reg
+
FrameIndex
;
}
return
0
;
}


bool isStore ( Recipe & R ) { if ( R . mayStoreMemory ( ) ) { const ARCSubtarget * Subtarget = R . getParent ( ) -> getSubtarget < ARCSubtarget > ( ) ; ARCII :: UnitMemOp Type = R . getAsmWriter ( ) . getSUnitMemOpIndex ( ) ; if ( Type == ARCII :: ST || Type == ARCII :: ST_arb_rs9 || Type == ARCII :: STH || Type == ARCII :: STH_arb_rs9 || Type == ARCII :: STB || Type == ARCII :: STB_arb_rs9 ) { return true ; } } return false ; }


bool isStoreToStackSlot ( const MachineInstr * MI , unsigned & SourceReg , int & FrameIndex ) { if ( MI -> getOpcode ( ) != ARC :: STRI32 ) return false ; SourceReg = MI -> getOperand ( 1 ) . getReg ( ) ; if ( ! ARC :: ACRMaskRegClass . contains ( SourceReg ) ) return false ; int64_t Offset = MI -> getOperand ( 2 ) . getImm ( ) ; if ( Offset != 0 ) return false ; FrameIndex = MI -> getOperand ( 0 ) . getIndex ( ) ; return true ; }


void
loadImmediate
(
ARMFunction
&
Function
,
REG
ArcReg
,
int
Imm
)
{
ARMBuilder
Builder
(
Function
)
;
int
ImmMin
=
255
;
int
ImmMax
=
255
;
REG
tmpReg
=
ARC
::
R0
;
if
(
Imm
>
ImmMax
||
Imm
<
ImmMin
)
{
Builder
.
buildMov
(
tmpReg
)
.
addImm
(
Imm
)
;
Imm
=
0
;
}
Builder
.
buildInstr
(
ARC
::
MOV_rs12
)
.
addReg
(
ArcReg
)
.
addImm
(
Imm
)
;
Builder
->
addAnnotation
(
"Need Arc long immediate instructions."
)
;
if
(
tmpReg
!=
ARC
::
R0
)
{
Builder
.
buildInstr
(
ARC
::
FREE
)
.
addReg
(
tmpReg
)
;
}
}


const
TargetRegisterClass
*
RC
)
{
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
int
FrameOffset
=
MFI
.
getObjectOffset
(
FrameIndex
)
;
MachineInstrBuilder
MIB
=
BuildMI
(
MBB
,
MBBI
,
DL
,
TII
.
get
(
ARC
::
LD_rs9
)
)
.
addReg
(
DestReg
,
RegState
::
Define
)
.
addImm
(
0
)
.
addImm
(
FrameOffset
)
;
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
MachinePointerInfo
::
getFixedStack
(
MF
,
FrameIndex
)
,
MachineMemOperand
::
MOLoad
,
MFI
.
getObjectSize
(
FrameIndex
)
,
MFI
.
getObjectAlign
(
FrameIndex
)
)
;
MIB
.
addMemOperand
(
MMO
)
;
DEBUG
(
dbgs
(
)
<<
"Created load reg="
<<
PrintReg
(
DestReg
)
<<
" from FrameIndex="
<<
FrameIndex
<<
"\n"
)
;
}


void removeBranch ( MachineBasicBlock * MBB ) { MachineInstr * LastInst = MBB -> getFirstTerminator ( ) ; if ( LastInst -> isBranch ( ) ) { MBB -> erase ( LastInst ) ; if ( MBB -> succ_empty ( ) ) { MBB -> getParent ( ) -> erase ( MBB ) ; } else { MBB -> removeSuccessor ( MBB -> succ_size ( ) - 1 ) ; } } }


"Only support GPR32 stores to stack now.\n"

"Only support 4-byte stores to stack now.\n"

"Cannot store to positive stack frame index.\n"

"Couldn't get MachineMemOperand for store to stack.\n"


void Select ( Node * N , InstructionList & Instructions ) { switch ( N -> getOpcode ( ) ) { case ARC :: MOV_rs12 : { MachineInstr * MI = BuildMI ( Instructions , N -> getDebugLoc ( ) , TII -> get ( ARC :: MOV_rs12 ) ) . addUse ( N -> getOperand ( 0 ) ) . addUse ( N -> getOperand ( 1 ) ) Instructions . push_back ( MI ) ; break ; } case ARC :: MOV_rlimm : { MachineInstr * MI = BuildMI ( Instructions , N -> getDebugLoc ( ) , TII -> get ( ARC :: MOV_rlimm ) ) . addUse ( N -> getOperand ( 0 ) ) . addImm ( N -> getOperand ( 1 ) . getImm ( ) ) Instructions . push_back ( MI ) ; break ; } case ARC :: ARC : { MachineInstr * MI = BuildMI ( Instructions , N -> getDebugLoc ( ) , TII -> get ( ARC :: ARC ) ) . addUse ( N -> getOperand ( 0 ) ) . addUse ( N -> getOperand ( 1 ) ) Instructions . push_back ( MI ) ; break ; } case ISD :: Constant : { unsigned int Val = N -> getConstantOperandVal ( 0 ) ; MachineInstr * MI = BuildMI ( Instructions , N -> getDebugLoc ( ) , TII -> get ( ARC :: ARC ) ) . addImm ( Val ) ; MI -> addReg ( ARC :: R0 ) ; Instructions . push_back ( MI ) ; break ; } } }