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

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM64 Address Type Promotion"
;
}
</s>

getPassName - Return a nice clean name for a pass .


<s> virtual void getAnalysisUsage ( AnalysisUsage & AU ) const { AU . setPreservesCFG ( ) ; AU . addRequired < DominatorTreeWrapperPass > ( ) ; AU . addPreserved < DominatorTreeWrapperPass > ( ) ; FunctionPass :: getAnalysisUsage ( AU ) ; } </s>


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"ARM64 Address Type Promotion"
;
}
</s>


<s>
bool
ARM64AddressTypePromotion
::
runOnFunction
(
Function
&
F
)
{
if
(
!
EnableAddressTypePromotion
||
F
.
isDeclaration
(
)
)
return
false
;
Func
=
&
F
;
ConsideredSExtType
=
Type
::
getInt64Ty
(
Func
->
getContext
(
)
)
;
DEBUG
(
dbgs
(
)
<<
"*** "
<<
getPassName
(
)
<<
": "
<<
Func
->
getName
(
)
<<
'\n'
)
;
Instructions
SExtInsts
;
analyzeSExtension
(
SExtInsts
)
;
return
propagateSignExtension
(
SExtInsts
)
;
}
</s>

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


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


<s>
const
char
*
getPassName
(
)
const
override
{
return
"AdvSIMD Scalar Operation Optimization"
;
}
</s>


<s>
bool
ARM64AdvSIMDScalar
::
runOnMachineFunction
(
MachineFunction
&
mf
)
{
bool
Changed
=
false
;
DEBUG
(
dbgs
(
)
<<
"***** ARM64AdvSIMDScalar *****\n"
)
;
const
TargetMachine
&
TM
=
mf
.
getTarget
(
)
;
MRI
=
&
mf
.
getRegInfo
(
)
;
TII
=
static_cast
<
const
ARM64InstrInfo
*
>
(
TM
.
getInstrInfo
(
)
)
;
for
(
MachineFunction
::
iterator
I
=
mf
.
begin
(
)
,
E
=
mf
.
end
(
)
;
I
!=
E
;
++
I
)
if
(
processMachineBasicBlock
(
I
)
)
Changed
=
true
;
return
Changed
;
}
</s>

runOnMachineFunction - Emit the function body .


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


<s>
const
char
*
getPassName
(
)
const
{
return
"AdvSIMD scalar operation optimization"
;
}
</s>


<s>
bool
ARM64AdvSIMDScalar
::
runOnMachineFunction
(
MachineFunction
&
mf
)
{
if
(
!
AdvSIMDScalar
)
return
false
;
bool
Changed
=
false
;
DEBUG
(
dbgs
(
)
<<
"***** ARM64AdvSIMDScalar *****\n"
)
;
const
TargetMachine
&
TM
=
mf
.
getTarget
(
)
;
MRI
=
&
mf
.
getRegInfo
(
)
;
TII
=
static_cast
<
const
ARM64InstrInfo
*
>
(
TM
.
getInstrInfo
(
)
)
;
for
(
MachineFunction
::
iterator
I
=
mf
.
begin
(
)
,
E
=
mf
.
end
(
)
;
I
!=
E
;
++
I
)
if
(
processMachineBasicBlock
(
I
)
)
Changed
=
true
;
return
Changed
;
}
</s>


<s> MCObjectWriter * createObjectWriter ( raw_ostream & OS ) const override { return createARM64ELFObjectWriter ( OS , OSABI , IsLittleEndian ) ; } </s>

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


<s>
const
MCFixupKindInfo
&
getFixupKindInfo
(
MCFixupKind
Kind
)
const
override
{
const
static
MCFixupKindInfo
Infos
[
ARM64
::
NumTargetFixupKinds
]
=
{
{
"fixup_arm64_pcrel_adr_imm21"
,
0
,
32
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_adrp_imm21"
,
0
,
32
,
PCRelFlagVal
}
,
{
"fixup_arm64_add_imm12"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale1"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale2"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale4"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale8"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale16"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldr_pcrel_imm19"
,
5
,
19
,
PCRelFlagVal
}
,
{
"fixup_arm64_movw"
,
5
,
16
,
0
}
,
{
"fixup_arm64_pcrel_branch14"
,
5
,
14
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_branch19"
,
5
,
19
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_branch26"
,
0
,
26
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_call26"
,
0
,
26
,
PCRelFlagVal
}
,
{
"fixup_arm64_tlsdesc_call"
,
0
,
0
,
0
}
}
;
if
(
Kind
<
FirstTargetFixupKind
)
return
MCAsmBackend
::
getFixupKindInfo
(
Kind
)
;
assert
(
unsigned
(
Kind
FirstTargetFixupKind
)
<
getNumFixupKinds
(
)
&&
"Invalid kind!"
)
;
return
Infos
[
Kind
FirstTargetFixupKind
]
;
}
</s>


<s> unsigned getNumFixupKinds ( ) const override { return ARM64 :: NumTargetFixupKinds ; } </s>

Get the number of target specific fixup kinds .


<s>
void
ARM64AsmBackend
::
applyFixup
(
const
MCFixup
&
Fixup
,
char
*
Data
,
unsigned
DataSize
,
uint64_t
Value
,
bool
IsPCRel
)
const
{
unsigned
NumBytes
=
getFixupKindNumBytes
(
Fixup
.
getKind
(
)
)
;
if
(
!
Value
)
return
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
Value
=
adjustFixupValue
(
Fixup
.
getKind
(
)
,
Value
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
assert
(
Offset
+
NumBytes
<=
DataSize
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
!=
NumBytes
;
++
i
)
Data
[
Offset
+
i
]
|=
uint8_t
(
(
Value
>>
(
i
*
8
)
)
&
0xff
)
;
}
</s>

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


<s> MCObjectWriter * createObjectWriter ( raw_ostream & OS ) const { return createARM64ELFObjectWriter ( OS , OSABI , IsLittleEndian ) ; } </s>


<s> bool ARM64AsmBackend :: fixupNeedsRelaxation ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout ) const { return int64_t ( Value ) != int64_t ( int8_t ( Value ) ) ; } </s>

Simple predicate for targets where ! Resolved implies requiring relaxation .


<s>
const
MCFixupKindInfo
&
getFixupKindInfo
(
MCFixupKind
Kind
)
const
{
const
static
MCFixupKindInfo
Infos
[
ARM64
::
NumTargetFixupKinds
]
=
{
{
"fixup_arm64_pcrel_adr_imm21"
,
0
,
32
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_adrp_imm21"
,
0
,
32
,
PCRelFlagVal
}
,
{
"fixup_arm64_add_imm12"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale1"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale2"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale4"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale8"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldst_imm12_scale16"
,
10
,
12
,
0
}
,
{
"fixup_arm64_ldr_pcrel_imm19"
,
5
,
19
,
PCRelFlagVal
}
,
{
"fixup_arm64_movw"
,
5
,
16
,
0
}
,
{
"fixup_arm64_pcrel_branch14"
,
5
,
14
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_branch19"
,
5
,
19
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_branch26"
,
0
,
26
,
PCRelFlagVal
}
,
{
"fixup_arm64_pcrel_call26"
,
0
,
26
,
PCRelFlagVal
}
,
{
"fixup_arm64_tlsdesc_call"
,
0
,
0
,
0
}
}
;
if
(
Kind
<
FirstTargetFixupKind
)
return
MCAsmBackend
::
getFixupKindInfo
(
Kind
)
;
assert
(
unsigned
(
Kind
FirstTargetFixupKind
)
<
getNumFixupKinds
(
)
&&
"Invalid kind!"
)
;
return
Infos
[
Kind
FirstTargetFixupKind
]
;
}
</s>


<s> unsigned getNumFixupKinds ( ) const { return ARM64 :: NumTargetFixupKinds ; } </s>


<s> unsigned getPointerSize ( ) const { return 8 ; } </s>

Layout pointer size in bytes , rounded up to a whole number of bytes .


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

Check whether the given instruction may need relaxation .


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


<s> bool ARM64AsmBackend :: writeNopData ( uint64_t Count , MCObjectWriter * OW ) const { if ( ( Count & 3 ) != 0 ) { for ( uint64_t i = 0 , e = ( Count & 3 ) ; i != e ; ++ i ) OW -> Write8 ( 0 ) ; } Count /= 4 ; for ( uint64_t i = 0 ; i != Count ; ++ i ) OW -> Write32 ( 0xd503201f ) ; return true ; } </s>

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


<s> SMLoc getEndLoc ( ) const override { return EndLoc ; } </s>

getEndLoc - Get the location of the last token of this operand .


<s>
unsigned
getReg
(
)
const
override
{
assert
(
Kind
==
k_Register
&&
"Invalid access!"
)
;
return
Reg
.
RegNum
;
}
</s>

Returns the register associated with this edge .


<s> SMLoc getStartLoc ( ) const override { return StartLoc ; } </s>

getStartLoc - Get the location of the first token of this operand .


<s> bool isImm ( ) const override { return Kind == k_Immediate ; } </s>


<s> bool isMem ( ) const override { return Kind == k_Memory ; } </s>


<s> bool isReg ( ) const override { return Kind == k_Register && ! Reg . isVector ; } </s>


<s> bool isToken ( ) const override { return Kind == k_Token ; } </s>


<s> void addExpr ( MCInst & Inst , const MCExpr * Expr ) const { if ( ! Expr ) Inst . addOperand ( MCOperand :: CreateImm ( 0 ) ) ; else if ( const MCConstantExpr * CE = dyn_cast < MCConstantExpr > ( Expr ) ) Inst . addOperand ( MCOperand :: CreateImm ( CE -> getValue ( ) ) ) ; else Inst . addOperand ( MCOperand :: CreateExpr ( Expr ) ) ; } </s>


<s> static ARM64Operand * CreateMem ( unsigned BaseRegNum , const MCExpr * Off , SMLoc S , SMLoc E , SMLoc OffsetLoc , MCContext & Ctx ) { ARM64Operand * Op = new ARM64Operand ( k_Memory , Ctx ) ; Op -> Mem . BaseRegNum = BaseRegNum ; Op -> Mem . OffsetRegNum = 0 ; Op -> Mem . OffsetImm = Off ; Op -> Mem . ExtType = ARM64_AM :: UXTX ; Op -> Mem . ShiftVal = 0 ; Op -> Mem . ExplicitShift = false ; Op -> Mem . Mode = ImmediateOffset ; Op -> OffsetLoc = OffsetLoc ; Op -> StartLoc = S ; Op -> EndLoc = E ; return Op ; } </s>


<s> static ARM64Operand * CreateReg ( unsigned RegNum , bool isVector , SMLoc S , SMLoc E , MCContext & Ctx ) { ARM64Operand * Op = new ARM64Operand ( k_Register , Ctx ) ; Op -> Reg . RegNum = RegNum ; Op -> Reg . isVector = isVector ; Op -> StartLoc = S ; Op -> EndLoc = E ; return Op ; } </s>

CreateReg - Allocate a single virtual register for the given type .


<s> bool Error ( SMLoc L , const Twine & Msg ) { return Parser . Error ( L , Msg ) ; } </s>

Return an error at the location L , with the message Msg .


<s> SMLoc getEndLoc ( ) const { return EndLoc ; } </s>


<s> SMLoc getLoc ( ) const { return Parser . getTok ( ) . getLoc ( ) ; } </s>

Get the source location of the point where the field was defined .


<s>
unsigned
getReg
(
)
const
{
assert
(
Kind
==
k_Register
&&
"Invalid access!"
)
;
return
Reg
.
RegNum
;
}
</s>


<s> SMLoc getStartLoc ( ) const { return StartLoc ; } </s>


<s> bool isBarrier ( ) const { return Kind == k_Barrier ; } </s>

Tests if this is an Order dependence that is marked as a barrier .


<s> bool isFPImm ( ) const { return Kind == k_FPImm ; } </s>

isFPImm - Tests if this is a MO_FPImmediate operand .


<s> bool isImm ( ) const { return Kind == k_Immediate ; } </s>


<s> bool isMem ( ) const { return Kind == k_Memory ; } </s>


<s> bool isReg ( ) const { return Kind == k_Register && ! Reg . isVector ; } </s>


<s> bool isToken ( ) const { return Kind == k_Token ; } </s>


<s> bool ARM64AsmParser :: ParseDirective ( AsmToken DirectiveID ) { StringRef IDVal = DirectiveID . getIdentifier ( ) ; SMLoc Loc = DirectiveID . getLoc ( ) ; if ( IDVal == ".hword" ) return parseDirectiveWord ( 2 , Loc ) ; if ( IDVal == ".word" ) return parseDirectiveWord ( 4 , Loc ) ; if ( IDVal == ".xword" ) return parseDirectiveWord ( 8 , Loc ) ; if ( IDVal == ".tlsdesccall" ) return parseDirectiveTLSDescCall ( Loc ) ; return parseDirectiveLOH ( IDVal , Loc ) ; } </s>

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


<s>
void
ARM64Operand
::
print
(
raw_ostream
&
OS
)
const
{
switch
(
Kind
)
{
case
k_FPImm
:
OS
<<
"<fpimm "
<<
getFPImm
(
)
<<
"("
<<
ARM64_AM
::
getFPImmFloat
(
getFPImm
(
)
)
<<
") >"
;
break
;
case
k_Barrier
:
{
bool
Valid
;
StringRef
Name
=
ARM64DB
::
DBarrierMapper
(
)
.
toString
(
getBarrier
(
)
,
Valid
)
;
if
(
Valid
)
OS
<<
"<barrier "
<<
Name
<<
">"
;
else
OS
<<
"<barrier invalid #"
<<
getBarrier
(
)
<<
">"
;
break
;
}
case
k_Immediate
:
getImm
(
)
->
print
(
OS
)
;
break
;
case
k_Memory
:
OS
<<
"<memory>"
;
break
;
case
k_Register
:
OS
<<
"<register "
<<
getReg
(
)
<<
">"
;
break
;
case
k_VectorList
:
{
OS
<<
"<vectorlist "
;
unsigned
Reg
=
getVectorListStart
(
)
;
for
(
unsigned
i
=
0
,
e
=
getVectorListCount
(
)
;
i
!=
e
;
++
i
)
OS
<<
Reg
+
i
<<
" "
;
OS
<<
">"
;
break
;
}
case
k_VectorIndex
:
OS
<<
"<vectorindex "
<<
getVectorIndex
(
)
<<
">"
;
break
;
case
k_SysReg
:
OS
<<
"<sysreg: "
<<
getSysReg
(
)
<<
'>'
;
break
;
case
k_Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
case
k_SysCR
:
OS
<<
"c"
<<
getSysCR
(
)
;
break
;
case
k_Prefetch
:
{
bool
Valid
;
StringRef
Name
=
ARM64PRFM
::
PRFMMapper
(
)
.
toString
(
getPrefetch
(
)
,
Valid
)
;
if
(
Valid
)
OS
<<
"<prfop "
<<
Name
<<
">"
;
else
OS
<<
"<prfop invalid #"
<<
getPrefetch
(
)
<<
">"
;
break
;
}
case
k_Shifter
:
{
unsigned
Val
=
getShifter
(
)
;
OS
<<
"<"
<<
ARM64_AM
::
getShiftName
(
ARM64_AM
::
getShiftType
(
Val
)
)
<<
" #"
<<
ARM64_AM
::
getShiftValue
(
Val
)
<<
">"
;
break
;
}
case
k_Extend
:
{
unsigned
Val
=
getExtend
(
)
;
OS
<<
"<"
<<
ARM64_AM
::
getExtendName
(
ARM64_AM
::
getArithExtendType
(
Val
)
)
<<
" #"
<<
ARM64_AM
::
getArithShiftValue
(
Val
)
<<
">"
;
break
;
}
}
}
</s>

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

ARM64
ARM64
"<fpimm "
"("
ARM64_AM::getFPImmFloat
") >"
ARM64DB::DBarrierMapper
"<barrier "
">"
"<barrier invalid #"
">"
"<memory>"
"<register "
">"
"<vectorlist "
0
" "
">"
"<vectorindex "
">"
"<sysreg: "
"'"
"'"
"c"
ARM64PRFM::PRFMMapper
"<prfop "
">"
"<prfop invalid #"
">"
"<"
ARM64_AM::getShiftName
ARM64_AM::getShiftType
" #"
ARM64_AM::getShiftValue
">"
"<"
ARM64_AM::getExtendName
ARM64_AM::getArithExtendType
" #"
ARM64_AM::getArithShiftValue
">"


<s>
int
ARM64AsmParser
::
tryParseRegister
(
)
{
const
AsmToken
&
Tok
=
Parser
.
getTok
(
)
;
assert
(
Tok
.
is
(
AsmToken
::
Identifier
)
&&
"Token is not an Identifier"
)
;
std
::
string
lowerCase
=
Tok
.
getString
(
)
.
lower
(
)
;
unsigned
RegNum
=
MatchRegisterName
(
lowerCase
)
;
if
(
RegNum
==
0
)
RegNum
=
StringSwitch
<
unsigned
>
(
lowerCase
)
.
Case
(
"fp"
,
ARM64
::
FP
)
.
Case
(
"lr"
,
ARM64
::
LR
)
.
Case
(
"x31"
,
ARM64
::
XZR
)
.
Case
(
"w31"
,
ARM64
::
WZR
)
.
Default
(
0
)
;
if
(
RegNum
==
0
)
return
1
;
Parser
.
Lex
(
)
;
return
RegNum
;
}
</s>

tryParseRegister - parse one register if possible


<s> unsigned ARM64AsmParser :: validateTargetOperandClass ( MCParsedAsmOperand * AsmOp , unsigned Kind ) { ARM64Operand * Op = static_cast < ARM64Operand * > ( AsmOp ) ; int64_t ExpectedVal ; switch ( Kind ) { default : return Match_InvalidOperand ; case MCK__35_0 : ExpectedVal = 0 ; break ; case MCK__35_1 : ExpectedVal = 1 ; break ; case MCK__35_12 : ExpectedVal = 12 ; break ; case MCK__35_16 : ExpectedVal = 16 ; break ; case MCK__35_2 : ExpectedVal = 2 ; break ; case MCK__35_24 : ExpectedVal = 24 ; break ; case MCK__35_3 : ExpectedVal = 3 ; break ; case MCK__35_32 : ExpectedVal = 32 ; break ; case MCK__35_4 : ExpectedVal = 4 ; break ; case MCK__35_48 : ExpectedVal = 48 ; break ; case MCK__35_6 : ExpectedVal = 6 ; break ; case MCK__35_64 : ExpectedVal = 64 ; break ; case MCK__35_8 : ExpectedVal = 8 ; break ; } if ( ! Op -> isImm ( ) ) return Match_InvalidOperand ; const MCConstantExpr * CE = dyn_cast < MCConstantExpr > ( Op -> getImm ( ) ) ; if ( ! CE ) return Match_InvalidOperand ; if ( CE -> getValue ( ) == ExpectedVal ) return Match_Success ; return Match_InvalidOperand ; } </s>

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


<s> void Warning ( SMLoc L , const Twine & Msg ) { Parser . Warning ( L , Msg ) ; } </s>

Emit a warning at the location L , with the message Msg .


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const override { AsmPrinter :: getAnalysisUsage ( AU ) ; AU . setPreservesAll ( ) ; } </s>

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


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

getPassName - Return a nice clean name for a pass .


<s> bool runOnMachineFunction ( MachineFunction & F ) override { ARM64FI = F . getInfo < ARM64FunctionInfo > ( ) ; return AsmPrinter :: runOnMachineFunction ( F ) ; } </s>

runOnMachineFunction - Emit the function body .


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const { AsmPrinter :: getAnalysisUsage ( AU ) ; AU . setPreservesAll ( ) ; } </s>


<s> MCSymbol * ARM64AsmPrinter :: GetCPISymbol ( unsigned CPID ) const { if ( getDataLayout ( ) . getLinkerPrivateGlobalPrefix ( ) [ 0 ] ) return OutContext . GetOrCreateSymbol ( Twine ( getDataLayout ( ) . getLinkerPrivateGlobalPrefix ( ) ) + "CPI" + Twine ( getFunctionNumber ( ) ) + "_" + Twine ( CPID ) ) ; return OutContext . GetOrCreateSymbol ( Twine ( getDataLayout ( ) . getPrivateGlobalPrefix ( ) ) + "CPI" + Twine ( getFunctionNumber ( ) ) + "_" + Twine ( CPID ) ) ; } </s>

Return the symbol for the specified constant pool entry .


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


<s> bool lowerOperand ( const MachineOperand & MO , MCOperand & MCOp ) const { return MCInstLowering . lowerOperand ( MO , MCOp ) ; } </s>

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


<s>
bool
ARM64AsmPrinter
::
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNum
,
unsigned
AsmVariant
,
const
char
*
ExtraCode
,
raw_ostream
&
O
)
{
if
(
ExtraCode
&&
ExtraCode
[
0
]
)
return
true
;
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNum
)
;
assert
(
MO
.
isReg
(
)
&&
"unexpected inline asm memory operand"
)
;
O
<<
"["
<<
ARM64InstPrinter
::
getRegisterName
(
MO
.
getReg
(
)
)
<<
"]"
;
return
false
;
}
</s>

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


<s> bool ARM64AsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNum , unsigned AsmVariant , const char * ExtraCode , raw_ostream & O ) { const MachineOperand & MO = MI -> getOperand ( OpNum ) ; if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'w' : case 'x' : if ( MO . isReg ( ) ) return printAsmMRegister ( MO , ExtraCode [ 0 ] , O ) ; if ( MO . isImm ( ) && MO . getImm ( ) == 0 ) { unsigned Reg = ExtraCode [ 0 ] == 'w' ? ARM64 :: WZR : ARM64 :: XZR ; O << ARM64InstPrinter :: getRegisterName ( Reg ) ; return false ; } printOperand ( MI , OpNum , O ) ; return false ; case 'b' : case 'h' : case 's' : case 'd' : case 'q' : if ( MO . isReg ( ) ) { const TargetRegisterClass * RC ; switch ( ExtraCode [ 0 ] ) { case 'b' : RC = & ARM64 :: FPR8RegClass ; break ; case 'h' : RC = & ARM64 :: FPR16RegClass ; break ; case 's' : RC = & ARM64 :: FPR32RegClass ; break ; case 'd' : RC = & ARM64 :: FPR64RegClass ; break ; case 'q' : RC = & ARM64 :: FPR128RegClass ; break ; default : return true ; } return printAsmRegInClass ( MO , RC , false , O ) ; } printOperand ( MI , OpNum , O ) ; return false ; } } if ( MO . isReg ( ) ) { unsigned Reg = MO . getReg ( ) ; if ( ARM64 :: GPR32allRegClass . contains ( Reg ) || ARM64 :: GPR64allRegClass . contains ( Reg ) ) return printAsmMRegister ( MO , 'x' , O ) ; return printAsmRegInClass ( MO , & ARM64 :: FPR128RegClass , true , O ) ; } printOperand ( MI , OpNum , O ) ; return false ; } </s>

PrintAsmOperand - Print out an operand for an inline asm expression .


<s> bool runOnMachineFunction ( MachineFunction & F ) { ARM64FI = F . getInfo < ARM64FunctionInfo > ( ) ; return AsmPrinter :: runOnMachineFunction ( F ) ; } </s>


<s> StringRef ARM64NamedImmMapper :: toString ( uint32_t Value , bool & Valid ) const { for ( unsigned i = 0 ; i < NumPairs ; ++ i ) { if ( Pairs [ i ] . Value == Value ) { Valid = true ; return Pairs [ i ] . Name ; } } Valid = false ; return StringRef ( ) ; } </s>

Convert to a decimal representation in a string .


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM64 branch relaxation pass"
;
}
</s>


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"ARM64 branch relaxation pass"
;
}
</s>


<s> static bool isConditionalBranch ( unsigned Opc ) { switch ( Opc ) { default : return false ; case ARM64 :: TBZ : case ARM64 :: TBNZ : case ARM64 :: CBZW : case ARM64 :: CBNZW : case ARM64 :: CBZX : case ARM64 :: CBNZX : case ARM64 :: Bcc : return true ; } } </s>

Return true if this is a branch which may fall through to the next instruction or may transfer control flow to some other block .


<s> unsigned postOffset ( unsigned LogAlign = 0 ) const { unsigned PO = Offset + Size ; unsigned Align = 1 << LogAlign ; return ( PO + Align - 1 ) / Align * Align ; } </s>

Compute the offset immediately following this block .


<s>
bool
ARM64BranchRelaxation
::
runOnMachineFunction
(
MachineFunction
&
mf
)
{
MF
=
&
mf
;
if
(
!
BranchRelaxation
)
return
false
;
DEBUG
(
dbgs
(
)
<<
"***** ARM64BranchRelaxation *****\n"
)
;
TII
=
(
const
ARM64InstrInfo
*
)
MF
->
getTarget
(
)
.
getInstrInfo
(
)
;
MF
->
RenumberBlocks
(
)
;
scanFunction
(
)
;
DEBUG
(
dbgs
(
)
<<
"  Basic blocks before relaxation\n"
)
;
DEBUG
(
dumpBBs
(
)
)
;
bool
MadeChange
=
false
;
while
(
relaxBranchInstructions
(
)
)
MadeChange
=
true
;
verify
(
)
;
DEBUG
(
dbgs
(
)
<<
"  Basic blocks after relaxation\n"
)
;
DEBUG
(
dbgs
(
)
<<
'\n'
;
dumpBBs
(
)
)
;
BlockInfo
.
clear
(
)
;
return
MadeChange
;
}
</s>


<s> void ARM64BranchRelaxation :: verify ( ) { unsigned PrevNum = MF -> begin ( ) -> getNumber ( ) ; for ( MachineBasicBlock & MBB : * MF ) { unsigned Align = MBB . getAlignment ( ) ; unsigned Num = MBB . getNumber ( ) ; assert ( BlockInfo [ Num ] . Offset % ( 1u << Align ) == 0 ) ; assert ( ! Num || BlockInfo [ PrevNum ] . postOffset ( ) <= BlockInfo [ Num ] . Offset ) ; PrevNum = Num ; } } </s>


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


<s>
const
char
*
getPassName
(
)
const
override
{
return
"Local Dynamic TLS Access Clean-up"
;
}
</s>


<s> bool runOnMachineFunction ( MachineFunction & MF ) override { ARM64FunctionInfo * AFI = MF . getInfo < ARM64FunctionInfo > ( ) ; if ( AFI -> getNumLocalDynamicTLSAccesses ( ) < 2 ) { return false ; } MachineDominatorTree * DT = & getAnalysis < MachineDominatorTree > ( ) ; return VisitNode ( DT -> getRootNode ( ) , 0 ) ; } </s>


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


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"Local Dynamic TLS Access Clean-up"
;
}
</s>


<s> virtual bool runOnMachineFunction ( MachineFunction & MF ) { ARM64FunctionInfo * AFI = MF . getInfo < ARM64FunctionInfo > ( ) ; if ( AFI -> getNumLocalDynamicTLSAccesses ( ) < 2 ) { return false ; } MachineDominatorTree * DT = & getAnalysis < MachineDominatorTree > ( ) ; return VisitNode ( DT -> getRootNode ( ) , 0 ) ; } </s>


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


"ARM64 Collect Linker Optimization Hint (LOH)"


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


"No MachineFunctionInfo for this function!"


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM64 Conditional Compares"
;
}
</s>


<s> void ARM64ConditionalCompares :: getAnalysisUsage ( AnalysisUsage & AU ) const { AU . addRequired < MachineBranchProbabilityInfo > ( ) ; AU . addRequired < MachineDominatorTree > ( ) ; AU . addPreserved < MachineDominatorTree > ( ) ; AU . addRequired < MachineLoopInfo > ( ) ; AU . addPreserved < MachineLoopInfo > ( ) ; AU . addRequired < MachineTraceMetrics > ( ) ; AU . addPreserved < MachineTraceMetrics > ( ) ; MachineFunctionPass :: getAnalysisUsage ( AU ) ; } </s>


<s>
const
char
*
getPassName
(
)
const
{
return
"ARM64 Conditional Compares"
;
}
</s>


<s> bool SSACCmpConv :: isDeadDef ( unsigned DstReg ) { if ( DstReg == ARM64 :: WZR || DstReg == ARM64 :: XZR ) return true ; if ( ! TargetRegisterInfo :: isVirtualRegister ( DstReg ) ) return false ; return MRI -> use_nodbg_empty ( DstReg ) ; } </s>

Return true if this instruction has a dead def .


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


<s>
const
char
*
getPassName
(
)
const
override
{
return
"Dead register definitions"
;
}
</s>


<s>
const
char
*
getPassName
(
)
const
{
return
"Dead register definitions"
;
}
</s>


<s>
static
bool
Check
(
DecodeStatus
&
Out
,
DecodeStatus
In
)
{
switch
(
In
)
{
case
MCDisassembler
::
Success
:
return
true
;
case
MCDisassembler
::
SoftFail
:
Out
=
In
;
return
true
;
case
MCDisassembler
::
Fail
:
Out
=
In
;
return
false
;
}
llvm_unreachable
(
"Invalid DecodeStatus!"
)
;
}
</s>

Matches check string and its `` not strings '' and/or `` dag strings '' .


<s> DecodeStatus ARM64Disassembler :: getInstruction ( MCInst & MI , uint64_t & Size , const MemoryObject & Region , uint64_t Address , raw_ostream & os , raw_ostream & cs ) const { CommentStream = & cs ; uint8_t bytes [ 4 ] ; Size = 0 ; if ( Region . readBytes ( Address , 4 , ( uint8_t * ) bytes ) == - 1 ) return Fail ; Size = 4 ; uint32_t insn = ( bytes [ 3 ] << 24 ) | ( bytes [ 2 ] << 16 ) | ( bytes [ 1 ] << 8 ) | ( bytes [ 0 ] << 0 ) ; return decodeInstruction ( DecoderTable32 , MI , insn , Address , this , STI ) ; } </s>

Returns the disassembly of a single instruction .


<s> DecodeStatus ARM64Disassembler :: getInstruction ( MCInst & MI , uint64_t & Size , const MemoryObject & Region , uint64_t Address , raw_ostream & os , raw_ostream & cs ) const { CommentStream = & cs ; uint8_t bytes [ 4 ] ; Size = 0 ; if ( Region . readBytes ( Address , 4 , ( uint8_t * ) bytes ) == - 1 ) return Fail ; Size = 4 ; uint32_t insn = ( bytes [ 3 ] << 24 ) | ( bytes [ 2 ] << 16 ) | ( bytes [ 1 ] << 8 ) | ( bytes [ 0 ] << 0 ) ; DecodeStatus result = decodeInstruction ( DecoderTable32 , MI , insn , Address , this , STI ) ; if ( ! result ) return Fail ; return Success ; } </s>


<s> void EmitInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI ) override { EmitA64MappingSymbol ( ) ; MCELFStreamer :: EmitInstruction ( Inst , STI ) ; } </s>

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


<s> virtual void EmitInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI ) { EmitA64MappingSymbol ( ) ; MCELFStreamer :: EmitInstruction ( Inst , STI ) ; } </s>


"ARM64 pseudo instruction expansion pass"


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


<s> bool ARM64FastISel :: isTypeLegal ( Type * Ty , MVT & VT ) { EVT evt = TLI . getValueType ( Ty , true ) ; if ( evt == MVT :: Other || ! evt . isSimple ( ) ) return false ; VT = evt . getSimpleVT ( ) ; if ( VT == MVT :: f128 ) return false ; return TLI . isTypeLegal ( VT ) ; } </s>


<s> CCAssignFn * ARM64FastISel :: CCAssignFnForCall ( CallingConv :: ID CC ) const { if ( CC == CallingConv :: WebKit_JS ) return CC_ARM64_WebKit_JS ; return Subtarget -> isTargetDarwin ( ) ? CC_ARM64_DarwinPCS : CC_ARM64_AAPCS ; } </s>

Selects the correct CCAssignFn for a given CallingConvention value .


<s> llvm :: FastISel * ARM64 :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) { return new ARM64FastISel ( funcInfo , libInfo ) ; } </s>

This method returns a target specific FastISel object , or null if the target does not support `` fast '' ISel .


<s> BaseKind getKind ( ) const { return Kind ; } </s>


<s> int64_t getOffset ( ) { return Offset ; } </s>

Get the offest of a string in the string table .


<s>
unsigned
getReg
(
)
const
{
assert
(
isRegBase
(
)
&&
"Invalid base register access!"
)
;
return
Base
.
Reg
;
}
</s>

Returns the register associated with this edge .


<s> bool ARM64FastISel :: isTypeLegal ( Type * Ty , MVT & VT ) { EVT evt = TLI . getValueType ( Ty , true ) ; if ( evt == MVT :: Other || ! evt . isSimple ( ) ) return false ; VT = evt . getSimpleVT ( ) ; return TLI . isTypeLegal ( VT ) ; } </s>


<s> bool isValid ( ) { return isFIBase ( ) || ( isRegBase ( ) && getReg ( ) != 0 ) ; } </s>

Returns true if this iterator is still pointing at a valid entry .


<s> void setKind ( BaseKind K ) { Kind = K ; } </s>


<s>
void
setReg
(
unsigned
Reg
)
{
assert
(
isRegBase
(
)
&&
"Invalid base register access!"
)
;
Base
.
Reg
=
Reg
;
}
</s>

Assigns the associated register for this edge .


<s> bool ARM64FrameLowering :: canUseRedZone ( const MachineFunction & MF ) const { if ( ! EnableRedZone ) return false ; if ( MF . getFunction ( ) -> getAttributes ( ) . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: NoRedZone ) ) return false ; const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; const ARM64FunctionInfo * AFI = MF . getInfo < ARM64FunctionInfo > ( ) ; unsigned NumBytes = AFI -> getLocalStackSize ( ) ; if ( MFI -> hasCalls ( ) || hasFP ( MF ) || NumBytes > 128 ) return false ; return true ; } </s>

Can this function use the red zone for local allocations .


<s>
void
ARM64FrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
)
const
{
const
TargetFrameLowering
*
TFI
=
MF
.
getTarget
(
)
.
getFrameLowering
(
)
;
const
ARM64InstrInfo
*
TII
=
static_cast
<
const
ARM64InstrInfo
*
>
(
MF
.
getTarget
(
)
.
getInstrInfo
(
)
)
;
if
(
!
TFI
->
hasReservedCallFrame
(
MF
)
)
{
MachineInstr
*
Old
=
I
;
DebugLoc
DL
=
Old
->
getDebugLoc
(
)
;
unsigned
Amount
=
Old
->
getOperand
(
0
)
.
getImm
(
)
;
if
(
Amount
!=
0
)
{
unsigned
Align
=
TFI
->
getStackAlignment
(
)
;
Amount
=
(
Amount
+
Align
1
)
/
Align
*
Align
;
unsigned
Opc
=
Old
->
getOpcode
(
)
;
if
(
Opc
==
ARM64
::
ADJCALLSTACKDOWN
)
{
emitFrameOffset
(
MBB
,
I
,
DL
,
ARM64
::
SP
,
ARM64
::
SP
,
Amount
,
TII
)
;
}
else
{
assert
(
Opc
==
ARM64
::
ADJCALLSTACKUP
&&
"expected ADJCALLSTACKUP"
)
;
emitFrameOffset
(
MBB
,
I
,
DL
,
ARM64
::
SP
,
ARM64
::
SP
,
Amount
,
TII
)
;
}
}
}
MBB
.
erase
(
I
)
;
}
</s>

This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy pseudo instructions ( but only if the Target is using them ) .


"Can only insert epilog into returning blocks"


<s> static unsigned estimateStackSize ( MachineFunction & MF ) { const MachineFrameInfo * FFI = MF . getFrameInfo ( ) ; int Offset = 0 ; for ( int i = FFI -> getObjectIndexBegin ( ) ; i != 0 ; ++ i ) { int FixedOff = - FFI -> getObjectOffset ( i ) ; if ( FixedOff > Offset ) Offset = FixedOff ; } for ( unsigned i = 0 , e = FFI -> getObjectIndexEnd ( ) ; i != e ; ++ i ) { if ( FFI -> isDeadObjectIndex ( i ) ) continue ; Offset += FFI -> getObjectSize ( i ) ; unsigned Align = FFI -> getObjectAlignment ( i ) ; Offset = ( Offset + Align - 1 ) / Align * Align ; } return ( unsigned ) Offset ; } </s>

Estimate and return the size of the stack frame .


<s> int ARM64FrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , unsigned & FrameReg ) const { return resolveFrameIndexReference ( MF , FI , FrameReg ) ; } </s>

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


<s>
bool
ARM64FrameLowering
::
hasFP
(
const
MachineFunction
&
MF
)
const
{
const
MachineFrameInfo
*
MFI
=
MF
.
getFrameInfo
(
)
;
const
TargetRegisterInfo
*
RegInfo
=
MF
.
getTarget
(
)
.
getRegisterInfo
(
)
;
assert
(
!
RegInfo
->
needsStackRealignment
(
MF
)
&&
"No stack realignment on ARM64!"
)
;
return
(
MFI
->
hasCalls
(
)
||
MFI
->
hasVarSizedObjects
(
)
||
MFI
->
isFrameAddressTaken
(
)
)
;
}
</s>

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


<s> bool ARM64FrameLowering :: hasReservedCallFrame ( const MachineFunction & MF ) const { return ! MF . getFrameInfo ( ) -> hasVarSizedObjects ( ) ; } </s>

hasReservedCallFrame - Under normal circumstances , when a frame pointer is not required , we reserve argument space for call sites in the function immediately on entry to the current function .


"Odd number of callee-saved regs to spill!"

"Expected GPR64 callee-saved register pair!"

"Expected FPR64 callee-saved register pair!"

"Offset out of bounds for LDP immediate"

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


"Offset out of bounds for STP immediate"

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


<s>
void
ARM64AppleInstPrinter
::
printInst
(
const
MCInst
*
MI
,
raw_ostream
&
O
,
StringRef
Annot
)
{
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
StringRef
Layout
,
Mnemonic
;
bool
IsTbx
;
if
(
isTblTbxInstruction
(
MI
->
getOpcode
(
)
,
Layout
,
IsTbx
)
)
{
O
<<
"\t"
<<
(
IsTbx
"tbx"
:
"tbl"
)
<<
Layout
<<
'\t'
<<
getRegisterName
(
MI
->
getOperand
(
0
)
.
getReg
(
)
,
ARM64
::
vreg
)
<<
", "
;
unsigned
ListOpNum
=
IsTbx
2
:
1
;
printVectorList
(
MI
,
ListOpNum
,
O
,
""
)
;
O
<<
", "
<<
getRegisterName
(
MI
->
getOperand
(
ListOpNum
+
1
)
.
getReg
(
)
,
ARM64
::
vreg
)
;
printAnnotation
(
O
,
Annot
)
;
return
;
}
if
(
LdStNInstrDesc
*
LdStDesc
=
getLdStNInstrDesc
(
Opcode
)
)
{
O
<<
"\t"
<<
LdStDesc
->
Mnemonic
<<
LdStDesc
->
Layout
<<
'\t'
;
int
OpNum
=
LdStDesc
->
ListOperand
;
printVectorList
(
MI
,
OpNum
++
,
O
,
""
)
;
if
(
LdStDesc
->
HasLane
)
O
<<
'['
<<
MI
->
getOperand
(
OpNum
++
)
.
getImm
(
)
<<
']'
;
unsigned
AddrReg
=
MI
->
getOperand
(
OpNum
++
)
.
getReg
(
)
;
O
<<
", ["
<<
getRegisterName
(
AddrReg
)
<<
']'
;
if
(
LdStDesc
->
NaturalOffset
!=
0
)
{
unsigned
Reg
=
MI
->
getOperand
(
OpNum
++
)
.
getReg
(
)
;
if
(
Reg
!=
ARM64
::
XZR
)
O
<<
", "
<<
getRegisterName
(
Reg
)
;
else
{
assert
(
LdStDesc
->
NaturalOffset
&&
"no offset on post-inc instruction?"
)
;
O
<<
", #"
<<
LdStDesc
->
NaturalOffset
;
}
}
printAnnotation
(
O
,
Annot
)
;
return
;
}
ARM64InstPrinter
::
printInst
(
MI
,
O
,
Annot
)
;
}
</s>

Print the specified MCInst to the specified raw_ostream .


<s> void ARM64InstPrinter :: printImplicitlyTypedVectorList ( const MCInst * MI , unsigned OpNum , raw_ostream & O ) { printVectorList ( MI , OpNum , O , "" ) ; } </s>

Print a list of vector registers where the type suffix is implicit ( i.e .


<s>
void
ARM64AppleInstPrinter
::
printInst
(
const
MCInst
*
MI
,
raw_ostream
&
O
,
StringRef
Annot
)
{
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
StringRef
Layout
,
Mnemonic
;
bool
IsTbx
;
if
(
isTblTbxInstruction
(
MI
->
getOpcode
(
)
,
Layout
,
IsTbx
)
)
{
O
<<
"\t"
<<
(
IsTbx
"tbx"
:
"tbl"
)
<<
Layout
<<
'\t'
<<
getRegisterName
(
MI
->
getOperand
(
0
)
.
getReg
(
)
,
ARM64
::
vreg
)
<<
", "
;
unsigned
ListOpNum
=
IsTbx
2
:
1
;
printVectorList
(
MI
,
ListOpNum
,
O
,
""
)
;
O
<<
", "
<<
getRegisterName
(
MI
->
getOperand
(
ListOpNum
+
1
)
.
getReg
(
)
,
ARM64
::
vreg
)
;
printAnnotation
(
O
,
Annot
)
;
return
;
}
if
(
LdStNInstrDesc
*
LdStDesc
=
getLdStNInstrDesc
(
Opcode
)
)
{
O
<<
"\t"
<<
LdStDesc
->
Mnemonic
<<
LdStDesc
->
Layout
<<
'\t'
;
printVectorList
(
MI
,
0
,
O
,
""
)
;
if
(
LdStDesc
->
LaneOperand
!=
0
)
O
<<
'['
<<
MI
->
getOperand
(
LdStDesc
->
LaneOperand
)
.
getImm
(
)
<<
']'
;
unsigned
AddrOpNum
=
LdStDesc
->
LaneOperand
+
1
;
unsigned
AddrReg
=
MI
->
getOperand
(
AddrOpNum
)
.
getReg
(
)
;
O
<<
", ["
<<
getRegisterName
(
AddrReg
)
<<
']'
;
if
(
LdStDesc
->
NaturalOffset
!=
0
)
{
unsigned
Reg
=
MI
->
getOperand
(
AddrOpNum
+
1
)
.
getReg
(
)
;
if
(
Reg
!=
ARM64
::
XZR
)
O
<<
", "
<<
getRegisterName
(
Reg
)
;
else
{
assert
(
LdStDesc
->
NaturalOffset
&&
"no offset on post-inc instruction?"
)
;
O
<<
", #"
<<
LdStDesc
->
NaturalOffset
;
}
}
printAnnotation
(
O
,
Annot
)
;
return
;
}
ARM64InstPrinter
::
printInst
(
MI
,
O
,
Annot
)
;
}
</s>


<s> void ARM64InstPrinter :: printRegName ( raw_ostream & OS , unsigned RegNo ) const { OS << getRegisterName ( RegNo ) ; } </s>


<s> bool ARM64InstrInfo :: analyzeCompare ( const MachineInstr * MI , unsigned & SrcReg , unsigned & SrcReg2 , int & CmpMask , int & CmpValue ) const { switch ( MI -> getOpcode ( ) ) { default : break ; case ARM64 :: SUBSWrr : case ARM64 :: SUBSWrs : case ARM64 :: SUBSWrx : case ARM64 :: SUBSXrr : case ARM64 :: SUBSXrs : case ARM64 :: SUBSXrx : case ARM64 :: ADDSWrr : case ARM64 :: ADDSWrs : case ARM64 :: ADDSWrx : case ARM64 :: ADDSXrr : case ARM64 :: ADDSXrs : case ARM64 :: ADDSXrx : SrcReg = MI -> getOperand ( 1 ) . getReg ( ) ; SrcReg2 = MI -> getOperand ( 2 ) . getReg ( ) ; CmpMask = ~ 0 ; CmpValue = 0 ; return true ; case ARM64 :: SUBSWri : case ARM64 :: ADDSWri : case ARM64 :: SUBSXri : case ARM64 :: ADDSXri : SrcReg = MI -> getOperand ( 1 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = ~ 0 ; CmpValue = MI -> getOperand ( 2 ) . getImm ( ) ; return true ; case ARM64 :: ANDSWri : case ARM64 :: ANDSXri : SrcReg = MI -> getOperand ( 1 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = ~ 0 ; CmpValue = ARM64_AM :: decodeLogicalImmediate ( MI -> getOperand ( 2 ) . getImm ( ) , MI -> getOpcode ( ) == ARM64 :: ANDSWri ? 32 : 64 ) ; return true ; } return false ; } </s>

analyzeCompare - For a comparison instruction , return the source registers in SrcReg and SrcReg2 if having two register operands , and the value it compares against in CmpValue .


<s> bool ARM64InstrInfo :: canInsertSelect ( const MachineBasicBlock & MBB , const SmallVectorImpl < MachineOperand > & Cond , unsigned TrueReg , unsigned FalseReg , int & CondCycles , int & TrueCycles , int & FalseCycles ) const { const MachineRegisterInfo & MRI = MBB . getParent ( ) -> getRegInfo ( ) ; const TargetRegisterClass * RC = RI . getCommonSubClass ( MRI . getRegClass ( TrueReg ) , MRI . getRegClass ( FalseReg ) ) ; if ( ! RC ) return false ; unsigned ExtraCondLat = Cond . size ( ) != 1 ; if ( ARM64 :: GPR64allRegClass . hasSubClassEq ( RC ) || ARM64 :: GPR32allRegClass . hasSubClassEq ( RC ) ) { CondCycles = 1 + ExtraCondLat ; TrueCycles = FalseCycles = 1 ; if ( canFoldIntoCSel ( MRI , TrueReg ) ) TrueCycles = 0 ; else if ( canFoldIntoCSel ( MRI , FalseReg ) ) FalseCycles = 0 ; return true ; } if ( ARM64 :: FPR64RegClass . hasSubClassEq ( RC ) || ARM64 :: FPR32RegClass . hasSubClassEq ( RC ) ) { CondCycles = 5 + ExtraCondLat ; TrueCycles = FalseCycles = 2 ; return true ; } return false ; } </s>

Return true if it is possible to insert a select instruction that chooses between TrueReg and FalseReg based on the condition code in Cond .


<s> MachineInstr * ARM64InstrInfo :: foldMemoryOperandImpl ( MachineFunction & MF , MachineInstr * MI , const SmallVectorImpl < unsigned > & Ops , int FrameIndex ) const { if ( MI -> isCopy ( ) ) { unsigned DstReg = MI -> getOperand ( 0 ) . getReg ( ) ; unsigned SrcReg = MI -> getOperand ( 1 ) . getReg ( ) ; if ( SrcReg == ARM64 :: SP && TargetRegisterInfo :: isVirtualRegister ( DstReg ) ) { MF . getRegInfo ( ) . constrainRegClass ( DstReg , & ARM64 :: GPR64RegClass ) ; return nullptr ; } if ( DstReg == ARM64 :: SP && TargetRegisterInfo :: isVirtualRegister ( SrcReg ) ) { MF . getRegInfo ( ) . constrainRegClass ( SrcReg , & ARM64 :: GPR64RegClass ) ; return nullptr ; } } return nullptr ; } </s>

foldMemoryOperand - Same as the previous version except it allows folding of any load and store from / to any address , not just from a specific stack slot .


<s> const ARM64RegisterInfo & getRegisterInfo ( ) const { return RI ; } </s>

getRegisterInfo - TargetInstrInfo is a superset of MRegister info .


<s> bool ARM64InstrInfo :: isCoalescableExtInstr ( const MachineInstr & MI , unsigned & SrcReg , unsigned & DstReg , unsigned & SubIdx ) const { switch ( MI . getOpcode ( ) ) { default : return false ; case ARM64 :: SBFMXri : case ARM64 :: UBFMXri : if ( MI . getOperand ( 2 ) . getImm ( ) != 0 || MI . getOperand ( 3 ) . getImm ( ) != 31 ) return false ; SrcReg = MI . getOperand ( 1 ) . getReg ( ) ; DstReg = MI . getOperand ( 0 ) . getReg ( ) ; SubIdx = ARM64 :: sub_32 ; return true ; } } </s>

isCoalescableExtInstr - Return true if the instruction is a `` coalescable '' extension instruction .


<s>
bool
ARM64InstrInfo
::
isFPRCopy
(
const
MachineInstr
*
MI
)
const
{
switch
(
MI
->
getOpcode
(
)
)
{
default
:
break
;
case
TargetOpcode
::
COPY
:
{
unsigned
DstReg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
return
(
ARM64
::
FPR64RegClass
.
contains
(
DstReg
)
||
ARM64
::
FPR128RegClass
.
contains
(
DstReg
)
)
;
}
case
ARM64
::
ORRv16i8
:
if
(
MI
->
getOperand
(
1
)
.
getReg
(
)
==
MI
->
getOperand
(
2
)
.
getReg
(
)
)
{
assert
(
MI
->
getDesc
(
)
.
getNumOperands
(
)
==
3
&&
MI
->
getOperand
(
0
)
.
isReg
(
)
&&
"invalid ORRv16i8 operands"
)
;
return
true
;
}
}
return
false
;
}
</s>

Does this instruction rename an FPR without modifying bits ?


<s>
bool
ARM64InstrInfo
::
isGPRCopy
(
const
MachineInstr
*
MI
)
const
{
switch
(
MI
->
getOpcode
(
)
)
{
default
:
break
;
case
TargetOpcode
::
COPY
:
{
unsigned
DstReg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
return
(
ARM64
::
GPR32RegClass
.
contains
(
DstReg
)
||
ARM64
::
GPR64RegClass
.
contains
(
DstReg
)
)
;
}
case
ARM64
::
ORRXrs
:
if
(
MI
->
getOperand
(
1
)
.
getReg
(
)
==
ARM64
::
XZR
)
{
assert
(
MI
->
getDesc
(
)
.
getNumOperands
(
)
==
4
&&
MI
->
getOperand
(
3
)
.
getImm
(
)
==
0
&&
"invalid ORRrs operands"
)
;
return
true
;
}
case
ARM64
::
ADDXri
:
if
(
MI
->
getOperand
(
2
)
.
getImm
(
)
==
0
)
{
assert
(
MI
->
getDesc
(
)
.
getNumOperands
(
)
==
4
&&
MI
->
getOperand
(
3
)
.
getImm
(
)
==
0
&&
"invalid ADDXri operands"
)
;
return
true
;
}
}
return
false
;
}
</s>

Does this instruction rename a GPR without modifying bits ?


<s>
bool
ARM64InstrInfo
::
isGPRZero
(
const
MachineInstr
*
MI
)
const
{
switch
(
MI
->
getOpcode
(
)
)
{
default
:
break
;
case
ARM64
::
MOVZWi
:
case
ARM64
::
MOVZXi
:
if
(
MI
->
getOperand
(
1
)
.
isImm
(
)
&&
MI
->
getOperand
(
1
)
.
getImm
(
)
==
0
)
{
assert
(
MI
->
getDesc
(
)
.
getNumOperands
(
)
==
3
&&
MI
->
getOperand
(
2
)
.
getImm
(
)
==
0
&&
"invalid MOVZi operands"
)
;
return
true
;
}
break
;
case
ARM64
::
ANDWri
:
return
MI
->
getOperand
(
1
)
.
getReg
(
)
==
ARM64
::
WZR
;
case
ARM64
::
ANDXri
:
return
MI
->
getOperand
(
1
)
.
getReg
(
)
==
ARM64
::
XZR
;
case
TargetOpcode
::
COPY
:
return
MI
->
getOperand
(
1
)
.
getReg
(
)
==
ARM64
::
WZR
;
}
return
false
;
}
</s>

Does this instruction set its full destination register to zero ?


<s>
bool
ARM64InstrInfo
::
isLdStPairSuppressed
(
const
MachineInstr
*
MI
)
const
{
assert
(
MOSuppressPair
<
(
1
<<
MachineMemOperand
::
MOTargetNumBits
)
&&
"Too many target MO flags"
)
;
for
(
auto
*
MM
:
MI
->
memoperands
(
)
)
{
if
(
MM
->
getFlags
(
)
&
(
MOSuppressPair
<<
MachineMemOperand
::
MOTargetStartBit
)
)
{
return
true
;
}
}
return
false
;
}
</s>

Return true if pairing the given load or store is hinted to be unprofitable .


<s> unsigned ARM64InstrInfo :: isLoadFromStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { default : break ; case ARM64 :: LDRWui : case ARM64 :: LDRXui : case ARM64 :: LDRBui : case ARM64 :: LDRHui : case ARM64 :: LDRSui : case ARM64 :: LDRDui : case ARM64 :: LDRQui : if ( MI -> getOperand ( 0 ) . getSubReg ( ) == 0 && MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) && MI -> getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; } return 0 ; } </s>

isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot , return the virtual or physical register number of the destination along with the FrameIndex of the loaded stack slot .


<s> unsigned ARM64InstrInfo :: isStoreToStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { default : break ; case ARM64 :: STRWui : case ARM64 :: STRXui : case ARM64 :: STRBui : case ARM64 :: STRHui : case ARM64 :: STRSui : case ARM64 :: STRDui : case ARM64 :: STRQui : if ( MI -> getOperand ( 0 ) . getSubReg ( ) == 0 && MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) && MI -> getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; } return 0 ; } </s>

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


<s>
void
ARM64InstrInfo
::
suppressLdStPair
(
MachineInstr
*
MI
)
const
{
if
(
MI
->
memoperands_empty
(
)
)
return
;
assert
(
MOSuppressPair
<
(
1
<<
MachineMemOperand
::
MOTargetNumBits
)
&&
"Too many target MO flags"
)
;
(
*
MI
->
memoperands_begin
(
)
)
->
setFlags
(
MOSuppressPair
<<
MachineMemOperand
::
MOTargetStartBit
)
;
}
</s>

Hint that pairing the given load or store is unprofitable .


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM64 Instruction Selection"
;
}
</s>

getPassName - Return a nice clean name for a pass .


<s> bool runOnMachineFunction ( MachineFunction & MF ) override { AttributeSet FnAttrs = MF . getFunction ( ) -> getAttributes ( ) ; ForCodeSize = FnAttrs . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: OptimizeForSize ) || FnAttrs . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: MinSize ) ; return SelectionDAGISel :: runOnMachineFunction ( MF ) ; } </s>

runOnMachineFunction - Emit the function body .


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"ARM64 Instruction Selection"
;
}
</s>


<s> virtual bool runOnMachineFunction ( MachineFunction & MF ) { AttributeSet FnAttrs = MF . getFunction ( ) -> getAttributes ( ) ; ForCodeSize = FnAttrs . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: OptimizeForSize ) || FnAttrs . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: MinSize ) ; return SelectionDAGISel :: runOnMachineFunction ( MF ) ; } </s>


<s>
bool
ARM64DAGToDAGISel
::
SelectInlineAsmMemoryOperand
(
const
SDValue
&
Op
,
char
ConstraintCode
,
std
::
vector
<
SDValue
>
&
OutOps
)
{
assert
(
ConstraintCode
==
'm'
&&
"unexpected asm memory constraint"
)
;
OutOps
.
push_back
(
Op
)
;
return
false
;
}
</s>

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


<s> WidenVector ( SelectionDAG & DAG ) : DAG ( DAG ) { } </s>

Widen the vector up to the next power of two using INSERT_SUBVECTOR .


<s> std :: pair < unsigned , const TargetRegisterClass * > ARM64TargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'r' : if ( VT . getSizeInBits ( ) == 64 ) return std :: make_pair ( 0U , & ARM64 :: GPR64commonRegClass ) ; return std :: make_pair ( 0U , & ARM64 :: GPR32commonRegClass ) ; case 'w' : if ( VT == MVT :: f32 ) return std :: make_pair ( 0U , & ARM64 :: FPR32RegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return std :: make_pair ( 0U , & ARM64 :: FPR64RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return std :: make_pair ( 0U , & ARM64 :: FPR128RegClass ) ; break ; case 'x' : if ( VT . getSizeInBits ( ) == 128 ) return std :: make_pair ( 0U , & ARM64 :: FPR128_loRegClass ) ; break ; } } if ( StringRef ( "{cc}" ) . equals_lower ( Constraint ) ) return std :: make_pair ( unsigned ( ARM64 :: NZCV ) , & ARM64 :: CCRRegClass ) ; std :: pair < unsigned , const TargetRegisterClass * > Res ; Res = TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; if ( ! Res . second ) { unsigned Size = Constraint . size ( ) ; if ( ( Size == 4 || Size == 5 ) && Constraint [ 0 ] == '{' && tolower ( Constraint [ 1 ] ) == 'v' && Constraint [ Size - 1 ] == '}' ) { const std :: string Reg = std :: string ( & Constraint [ 2 ] , & Constraint [ Size - 1 ] ) ; int RegNo = atoi ( Reg . c_str ( ) ) ; if ( RegNo >= 0 && RegNo <= 31 ) { Res . first = ARM64 :: FPR128RegClass . getRegister ( RegNo ) ; Res . second = & ARM64 :: FPR128RegClass ; } } } return Res ; } </s>

Given a physical register constraint ( e.g .


<s>
unsigned
ARM64TargetLowering
::
getRegisterByName
(
const
char
*
RegName
)
const
{
unsigned
Reg
=
StringSwitch
<
unsigned
>
(
RegName
)
.
Case
(
"sp"
,
ARM64
::
SP
)
.
Default
(
0
)
;
if
(
Reg
)
return
Reg
;
report_fatal_error
(
"Invalid register name global variable"
)
;
}
</s>

Return the register ID of the name passed in .


<s> bool ARM64TargetLowering :: isDesirableToCommuteWithShift ( const SDNode * N ) const { EVT VT = N -> getValueType ( 0 ) ; if ( N -> getOpcode ( ) == ISD :: AND && ( VT == MVT :: i32 || VT == MVT :: i64 ) && isa < ConstantSDNode > ( N -> getOperand ( 1 ) ) ) { uint64_t TruncMask = N -> getConstantOperandVal ( 1 ) ; if ( isMask_64 ( TruncMask ) && N -> getOperand ( 0 ) . getOpcode ( ) == ISD :: SRL && isa < ConstantSDNode > ( N -> getOperand ( 0 ) -> getOperand ( 1 ) ) ) return false ; } return true ; } </s>

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


<s> SDValue ARM64TargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { SelectionDAG & DAG = DCI . DAG ; switch ( N -> getOpcode ( ) ) { default : break ; case ISD :: ADD : case ISD :: SUB : return performAddSubLongCombine ( N , DCI , DAG ) ; case ISD :: XOR : return performXorCombine ( N , DAG , DCI , Subtarget ) ; case ISD :: MUL : return performMulCombine ( N , DAG , DCI , Subtarget ) ; case ISD :: SINT_TO_FP : case ISD :: UINT_TO_FP : return performIntToFpCombine ( N , DAG ) ; case ISD :: OR : return performORCombine ( N , DCI , Subtarget ) ; case ISD :: INTRINSIC_WO_CHAIN : return performIntrinsicCombine ( N , DCI , Subtarget ) ; case ISD :: ANY_EXTEND : case ISD :: ZERO_EXTEND : case ISD :: SIGN_EXTEND : return performExtendCombine ( N , DCI , DAG ) ; case ISD :: BITCAST : return performBitcastCombine ( N , DCI , DAG ) ; case ISD :: CONCAT_VECTORS : return performConcatVectorsCombine ( N , DCI , DAG ) ; case ISD :: SELECT : return performSelectCombine ( N , DAG ) ; case ISD :: VSELECT : return performVSelectCombine ( N , DCI . DAG ) ; case ISD :: STORE : return performSTORECombine ( N , DCI , DAG , Subtarget ) ; case ARM64ISD :: BRCOND : return performBRCONDCombine ( N , DCI , DAG ) ; } return SDValue ( ) ; } </s>

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


<s> bool ARM64TargetLowering :: CanLowerReturn ( CallingConv :: ID CallConv , MachineFunction & MF , bool isVarArg , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) const { CCAssignFn * RetCC = CallConv == CallingConv :: WebKit_JS ? RetCC_ARM64_WebKit_JS : RetCC_ARM64_AAPCS ; SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , isVarArg , MF , getTargetMachine ( ) , RVLocs , Context ) ; return CCInfo . CheckReturn ( Outs , RetCC ) ; } </s>

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


<s>
CCAssignFn
*
ARM64TargetLowering
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
IsVarArg
)
const
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention."
)
;
case
CallingConv
::
WebKit_JS
:
return
CC_ARM64_WebKit_JS
;
case
CallingConv
::
C
:
case
CallingConv
::
Fast
:
if
(
!
Subtarget
->
isTargetDarwin
(
)
)
return
CC_ARM64_AAPCS
;
return
IsVarArg
CC_ARM64_DarwinPCS_VarArg
:
CC_ARM64_DarwinPCS
;
}
}
</s>

Selects the correct CCAssignFn for a given CallingConvention value .


<s> FastISel * ARM64TargetLowering :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) const { return ARM64 :: createFastISel ( funcInfo , libInfo ) ; } </s>

This method returns a target specific FastISel object , or null if the target does not support `` fast '' ISel .


"Unexpected instruction for custom inserter!"

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


<s> Value * ARM64TargetLowering :: emitLoadLinked ( IRBuilder < > & Builder , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; Type * ValTy = cast < PointerType > ( Addr -> getType ( ) ) -> getElementType ( ) ; bool IsAcquire = Ord == Acquire || Ord == AcquireRelease || Ord == SequentiallyConsistent ; if ( ValTy -> getPrimitiveSizeInBits ( ) == 128 ) { Intrinsic :: ID Int = IsAcquire ? Intrinsic :: arm64_ldaxp : Intrinsic :: arm64_ldxp ; Function * Ldxr = llvm :: Intrinsic :: getDeclaration ( M , Int ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; Value * LoHi = Builder . CreateCall ( Ldxr , Addr , "lohi" ) ; Value * Lo = Builder . CreateExtractValue ( LoHi , 0 , "lo" ) ; Value * Hi = Builder . CreateExtractValue ( LoHi , 1 , "hi" ) ; Lo = Builder . CreateZExt ( Lo , ValTy , "lo64" ) ; Hi = Builder . CreateZExt ( Hi , ValTy , "hi64" ) ; return Builder . CreateOr ( Lo , Builder . CreateShl ( Hi , ConstantInt :: get ( ValTy , 64 ) ) , "val64" ) ; } Type * Tys [ ] = { Addr -> getType ( ) } ; Intrinsic :: ID Int = IsAcquire ? Intrinsic :: arm64_ldaxr : Intrinsic :: arm64_ldxr ; Function * Ldxr = llvm :: Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateTruncOrBitCast ( Builder . CreateCall ( Ldxr , Addr ) , cast < PointerType > ( Addr -> getType ( ) ) -> getElementType ( ) ) ; } </s>

Perform a load-linked operation on Addr , returning a `` Value * '' with the corresponding pointee type .


<s> Value * ARM64TargetLowering :: emitStoreConditional ( IRBuilder < > & Builder , Value * Val , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; bool IsRelease = Ord == Release || Ord == AcquireRelease || Ord == SequentiallyConsistent ; if ( Val -> getType ( ) -> getPrimitiveSizeInBits ( ) == 128 ) { Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm64_stlxp : Intrinsic :: arm64_stxp ; Function * Stxr = Intrinsic :: getDeclaration ( M , Int ) ; Type * Int64Ty = Type :: getInt64Ty ( M -> getContext ( ) ) ; Value * Lo = Builder . CreateTrunc ( Val , Int64Ty , "lo" ) ; Value * Hi = Builder . CreateTrunc ( Builder . CreateLShr ( Val , 64 ) , Int64Ty , "hi" ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; return Builder . CreateCall3 ( Stxr , Lo , Hi , Addr ) ; } Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm64_stlxr : Intrinsic :: arm64_stxr ; Type * Tys [ ] = { Addr -> getType ( ) } ; Function * Stxr = Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateCall2 ( Stxr , Builder . CreateZExtOrBitCast ( Val , Stxr -> getFunctionType ( ) -> getParamType ( 0 ) ) , Addr ) ; } </s>

Perform a store-conditional operation to Addr .


<s> ARM64TargetLowering :: ConstraintType ARM64TargetLowering :: getConstraintType ( const std :: string & Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'z' : return C_Other ; case 'x' : case 'w' : return C_RegisterClass ; case 'Q' : return C_Memory ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

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


<s> static unsigned getIntrinsicID ( const SDNode * N ) { unsigned Opcode = N -> getOpcode ( ) ; switch ( Opcode ) { default : return Intrinsic :: not_intrinsic ; case ISD :: INTRINSIC_WO_CHAIN : { unsigned IID = cast < ConstantSDNode > ( N -> getOperand ( 0 ) ) -> getZExtValue ( ) ; if ( IID < Intrinsic :: num_intrinsics ) return IID ; return Intrinsic :: not_intrinsic ; } } } </s>

Return the target intrinsic ID of a function , or 0 .


<s> EVT ARM64TargetLowering :: getOptimalMemOpType ( uint64_t Size , unsigned DstAlign , unsigned SrcAlign , bool IsMemset , bool ZeroMemset , bool MemcpyStrSrc , MachineFunction & MF ) const { bool Fast ; const Function * F = MF . getFunction ( ) ; if ( Subtarget -> hasFPARMv8 ( ) && ! IsMemset && Size >= 16 && ! F -> getAttributes ( ) . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: NoImplicitFloat ) && ( memOpAlign ( SrcAlign , DstAlign , 16 ) || ( allowsUnalignedMemoryAccesses ( MVT :: f128 , 0 , & Fast ) && Fast ) ) ) return MVT :: f128 ; return Size >= 8 ? MVT :: i64 : MVT :: i32 ; } </s>

It returns EVT : :Other if the type should be determined using generic target-independent logic .


<s> bool ARM64TargetLowering :: getPostIndexedAddressParts ( SDNode * N , SDNode * Op , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { EVT VT ; SDValue Ptr ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { VT = LD -> getMemoryVT ( ) ; Ptr = LD -> getBasePtr ( ) ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { VT = ST -> getMemoryVT ( ) ; Ptr = ST -> getBasePtr ( ) ; } else return false ; bool IsInc ; if ( ! getIndexedAddressParts ( Op , Base , Offset , AM , IsInc , DAG ) ) return false ; if ( Ptr != Base ) return false ; AM = IsInc ? ISD :: POST_INC : ISD :: POST_DEC ; return true ; } </s>

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


<s> bool ARM64TargetLowering :: getPreIndexedAddressParts ( SDNode * N , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { EVT VT ; SDValue Ptr ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { VT = LD -> getMemoryVT ( ) ; Ptr = LD -> getBasePtr ( ) ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { VT = ST -> getMemoryVT ( ) ; Ptr = ST -> getBasePtr ( ) ; } else return false ; bool IsInc ; if ( ! getIndexedAddressParts ( Ptr . getNode ( ) , Base , Offset , AM , IsInc , DAG ) ) return false ; AM = IsInc ? ISD :: PRE_INC : ISD :: PRE_DEC ; return true ; } </s>

Returns true by value , base pointer and offset pointer and addressing mode by reference if the node 's address can be legally represented as pre-indexed load / store address .


<s> std :: pair < unsigned , const TargetRegisterClass * > ARM64TargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'r' : if ( VT . getSizeInBits ( ) == 64 ) return std :: make_pair ( 0U , & ARM64 :: GPR64commonRegClass ) ; return std :: make_pair ( 0U , & ARM64 :: GPR32commonRegClass ) ; case 'w' : if ( VT == MVT :: f32 ) return std :: make_pair ( 0U , & ARM64 :: FPR32RegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return std :: make_pair ( 0U , & ARM64 :: FPR64RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return std :: make_pair ( 0U , & ARM64 :: FPR128RegClass ) ; break ; case 'x' : if ( VT . getSizeInBits ( ) == 128 ) return std :: make_pair ( 0U , & ARM64 :: FPR128_loRegClass ) ; break ; } } if ( StringRef ( "{cc}" ) . equals_lower ( Constraint ) ) return std :: make_pair ( unsigned ( ARM64 :: CPSR ) , & ARM64 :: CCRRegClass ) ; std :: pair < unsigned , const TargetRegisterClass * > Res ; Res = TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; if ( ! Res . second ) { unsigned Size = Constraint . size ( ) ; if ( ( Size == 4 || Size == 5 ) && Constraint [ 0 ] == '{' && tolower ( Constraint [ 1 ] ) == 'v' && Constraint [ Size - 1 ] == '}' ) { const std :: string Reg = std :: string ( & Constraint [ 2 ] , & Constraint [ Size - 1 ] ) ; int RegNo = atoi ( Reg . c_str ( ) ) ; if ( RegNo >= 0 && RegNo <= 31 ) { Res . first = ARM64 :: FPR128RegClass . getRegister ( RegNo ) ; Res . second = & ARM64 :: FPR128RegClass ; } } } return Res ; } </s>


<s> MVT ARM64TargetLowering :: getScalarShiftAmountTy ( EVT LHSTy ) const { return MVT :: i64 ; } </s>

Return the type to use for a scalar shift opcode , given the shifted amount type .


<s> int ARM64TargetLowering :: getScalingFactorCost ( const AddrMode & AM , Type * Ty ) const { if ( isLegalAddressingMode ( AM , Ty ) ) return AM . Scale != 0 && AM . Scale != 1 ; return - 1 ; } </s>

Return the cost of the scaling factor used in the addressing mode represented by AM for this target , for a load/store of the specified type .


<s> const MCPhysReg * ARM64TargetLowering :: getScratchRegisters ( CallingConv :: ID ) const { static const MCPhysReg ScratchRegs [ ] = { ARM64 :: X16 , ARM64 :: X17 , ARM64 :: LR , 0 } ; return ScratchRegs ; } </s>

Returns a 0 terminated array of registers that can be safely used as scratch registers .


<s> EVT ARM64TargetLowering :: getSetCCResultType ( LLVMContext & , EVT VT ) const { if ( ! VT . isVector ( ) ) return MVT :: i32 ; return VT . changeVectorElementTypeToInteger ( ) ; } </s>

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


<s> TargetLowering :: ConstraintWeight ARM64TargetLowering :: getSingleConstraintMatchWeight ( AsmOperandInfo & info , const char * constraint ) const { ConstraintWeight weight = CW_Invalid ; Value * CallOperandVal = info . CallOperandVal ; if ( ! CallOperandVal ) return CW_Default ; Type * type = CallOperandVal -> getType ( ) ; switch ( * constraint ) { default : weight = TargetLowering :: getSingleConstraintMatchWeight ( info , constraint ) ; break ; case 'x' : case 'w' : if ( type -> isFloatingPointTy ( ) || type -> isVectorTy ( ) ) weight = CW_Register ; break ; case 'z' : weight = CW_Constant ; break ; } return weight ; } </s>

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


<s> bool ARM64TargetLowering :: hasPairedLoad ( EVT LoadedType , unsigned & RequiredAligment ) const { if ( ! LoadedType . isSimple ( ) || ( ! LoadedType . isInteger ( ) && ! LoadedType . isFloatingPoint ( ) ) ) return false ; RequiredAligment = 0 ; unsigned NumBits = LoadedType . getSizeInBits ( ) ; return NumBits == 32 || NumBits == 64 ; } </s>

Return true if the target supplies and combines to a paired load two loaded values of type LoadedType next to each other in memory .


<s> bool ARM64TargetLowering :: isEligibleForTailCallOptimization ( SDValue Callee , CallingConv :: ID CalleeCC , bool isVarArg , bool isCalleeStructRet , bool isCallerStructRet , const SmallVectorImpl < ISD :: OutputArg > & Outs , const SmallVectorImpl < SDValue > & OutVals , const SmallVectorImpl < ISD :: InputArg > & Ins , SelectionDAG & DAG ) const { if ( isVarArg && ! Outs . empty ( ) ) return false ; if ( isCalleeStructRet || isCallerStructRet ) return false ; if ( ! Outs . empty ( ) ) { SmallVector < CCValAssign , 16 > ArgLocs ; CCState CCInfo ( CalleeCC , isVarArg , DAG . getMachineFunction ( ) , getTargetMachine ( ) , ArgLocs , * DAG . getContext ( ) ) ; CCAssignFn * AssignFn = CCAssignFnForCall ( CalleeCC , false ) ; CCInfo . AnalyzeCallOperands ( Outs , AssignFn ) ; if ( CCInfo . getNextStackOffset ( ) ) { for ( unsigned i = 0 , realArgIdx = 0 , e = ArgLocs . size ( ) ; i != e ; ++ i , ++ realArgIdx ) { CCValAssign & VA = ArgLocs [ i ] ; if ( VA . getLocInfo ( ) == CCValAssign :: Indirect ) return false ; if ( VA . needsCustom ( ) ) { return false ; } else if ( ! VA . isRegLoc ( ) ) { return false ; } } } } return true ; } </s>

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


<s> bool ARM64TargetLowering :: isFMAFasterThanFMulAndFAdd ( EVT VT ) const { VT = VT . getScalarType ( ) ; if ( ! VT . isSimple ( ) ) return false ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { case MVT :: f32 : case MVT :: f64 : return true ; default : break ; } return false ; } </s>

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


<s> bool ARM64TargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT ) const { if ( Imm . isPosZero ( ) && ( VT == MVT :: f64 || VT == MVT :: f32 ) ) return true ; if ( VT == MVT :: f64 ) return ARM64_AM :: getFP64Imm ( Imm ) != - 1 ; else if ( VT == MVT :: f32 ) return ARM64_AM :: getFP32Imm ( Imm ) != - 1 ; return false ; } </s>

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


<s> bool ARM64TargetLowering :: isLegalAddImmediate ( int64_t Immed ) const { if ( ( Immed >> 12 ) == 0 || ( ( Immed & 0xfff ) == 0 && Immed >> 24 == 0 ) ) return true ; return false ; } </s>

Return true if the specified immediate is legal add immediate , that is the target has add instructions which can add a register and the immediate without having to materialize the immediate into a register .


<s> bool ARM64TargetLowering :: isLegalAddressingMode ( const AddrMode & AM , Type * Ty ) const { if ( AM . BaseGV ) return false ; if ( AM . HasBaseReg && AM . BaseOffs && AM . Scale ) return false ; uint64_t NumBytes = 0 ; if ( Ty -> isSized ( ) ) { uint64_t NumBits = getDataLayout ( ) -> getTypeSizeInBits ( Ty ) ; NumBytes = NumBits / 8 ; if ( ! isPowerOf2_64 ( NumBits ) ) NumBytes = 0 ; } if ( ! AM . Scale ) { int64_t Offset = AM . BaseOffs ; if ( Offset >= - ( 1LL << 9 ) && Offset <= ( 1LL << 9 ) - 1 ) return true ; unsigned shift = Log2_64 ( NumBytes ) ; if ( NumBytes && Offset > 0 && ( Offset / NumBytes ) <= ( 1LL << 12 ) - 1 && ( Offset >> shift ) << shift == Offset ) return true ; return false ; } if ( ! AM . Scale || AM . Scale == 1 || ( AM . Scale > 0 && ( uint64_t ) AM . Scale == NumBytes ) ) return true ; return false ; } </s>

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


<s> bool ARM64TargetLowering :: isLegalICmpImmediate ( int64_t Immed ) const { if ( Immed < 0 ) Immed *= - 1 ; return isLegalAddImmediate ( Immed ) ; } </s>

Return true if the specified immediate is legal icmp immediate , that is the target has icmp instructions which can compare a register against the immediate without having to materialize the immediate into a register .


<s> bool isNoopAddrSpaceCast ( unsigned SrcAS , unsigned DestAS ) const override { return true ; } </s>

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


<s> bool ARM64TargetLowering :: isOffsetFoldingLegal ( const GlobalAddressSDNode * GA ) const { return false ; } </s>

Return true if folding a constant offset with the given GlobalAddress is legal .


<s> bool ARM64TargetLowering :: isShuffleMaskLegal ( const SmallVectorImpl < int > & M , EVT VT ) const { if ( VT . getVectorNumElements ( ) == 4 && ( VT . is128BitVector ( ) || VT . is64BitVector ( ) ) ) { unsigned PFIndexes [ 4 ] ; for ( unsigned i = 0 ; i != 4 ; ++ i ) { if ( M [ i ] < 0 ) PFIndexes [ i ] = 8 ; else PFIndexes [ i ] = M [ i ] ; } unsigned PFTableIndex = PFIndexes [ 0 ] * 9 * 9 * 9 + PFIndexes [ 1 ] * 9 * 9 + PFIndexes [ 2 ] * 9 + PFIndexes [ 3 ] ; unsigned PFEntry = PerfectShuffleTable [ PFTableIndex ] ; unsigned Cost = ( PFEntry >> 30 ) ; if ( Cost <= 4 ) return true ; } bool DummyBool ; int DummyInt ; unsigned DummyUnsigned ; return ( ShuffleVectorSDNode :: isSplatMask ( & M [ 0 ] , VT ) || isREVMask ( M , VT , 64 ) || isREVMask ( M , VT , 32 ) || isREVMask ( M , VT , 16 ) || isEXTMask ( M , VT , DummyBool , DummyUnsigned ) || isTRNMask ( M , VT , DummyUnsigned ) || isUZPMask ( M , VT , DummyUnsigned ) || isZIPMask ( M , VT , DummyUnsigned ) || isTRN_v_undef_Mask ( M , VT , DummyUnsigned ) || isUZP_v_undef_Mask ( M , VT , DummyUnsigned ) || isZIP_v_undef_Mask ( M , VT , DummyUnsigned ) || isINSMask ( M , VT . getVectorNumElements ( ) , DummyBool , DummyInt ) || isConcatMask ( M , VT , VT . getSizeInBits ( ) == 128 ) ) ; } </s>

Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations , those with specific masks .


<s> bool ARM64TargetLowering :: isTruncateFree ( EVT VT1 , EVT VT2 ) const { if ( ! VT1 . isInteger ( ) || ! VT2 . isInteger ( ) ) return false ; unsigned NumBits1 = VT1 . getSizeInBits ( ) ; unsigned NumBits2 = VT2 . getSizeInBits ( ) ; if ( NumBits1 <= NumBits2 ) return false ; return true ; } </s>

Return true if it 's free to truncate a value of type Ty1 to type Ty2 .


<s> bool ARM64TargetLowering :: isUsedByReturnOnly ( SDNode * N , SDValue & Chain ) const { if ( N -> getNumValues ( ) != 1 ) return false ; if ( ! N -> hasNUsesOfValue ( 1 , 0 ) ) return false ; SDValue TCChain = Chain ; SDNode * Copy = * N -> use_begin ( ) ; if ( Copy -> getOpcode ( ) == ISD :: CopyToReg ) { if ( Copy -> getOperand ( Copy -> getNumOperands ( ) - 1 ) . getValueType ( ) == MVT :: Glue ) return false ; TCChain = Copy -> getOperand ( 0 ) ; } else if ( Copy -> getOpcode ( ) != ISD :: FP_EXTEND ) return false ; bool HasRet = false ; for ( SDNode * Node : Copy -> uses ( ) ) { if ( Node -> getOpcode ( ) != ARM64ISD :: RET_FLAG ) return false ; HasRet = true ; } if ( ! HasRet ) return false ; Chain = TCChain ; return true ; } </s>

Return true if result of the specified node is used by a return node only .


<s> bool ARM64TargetLowering :: isZExtFree ( SDValue Val , EVT VT2 ) const { EVT VT1 = Val . getValueType ( ) ; if ( isZExtFree ( VT1 , VT2 ) ) { return true ; } if ( Val . getOpcode ( ) != ISD :: LOAD ) return false ; return ( VT1 . isSimple ( ) && VT1 . isInteger ( ) && VT2 . isSimple ( ) && VT2 . isInteger ( ) && VT1 . getSizeInBits ( ) <= 32 ) ; } </s>

Return true if zero-extending the specific node Val to type VT2 is free ( either because it 's implicitly zero-extended such as ARM ldrb / ldrh or because it 's folded such as X86 zero-extending loads ) .


"unexpected return calling convention register assignment"

LowerCallResult - Lower the result values of an ISD : :CALL into the appropriate copies out of appropriate physical registers .


<s>
SDValue
ARM64TargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
SDLoc
DL
,
SelectionDAG
&
DAG
)
const
{
CCAssignFn
*
RetCC
=
CallConv
==
CallingConv
::
WebKit_JS
RetCC_ARM64_WebKit_JS
:
RetCC_ARM64_AAPCS
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
isVarArg
,
DAG
.
getMachineFunction
(
)
,
getTargetMachine
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
realRVLocIdx
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
,
++
realRVLocIdx
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
SDValue
Arg
=
OutVals
[
realRVLocIdx
]
;
switch
(
VA
.
getLocInfo
(
)
)
{
default
:
llvm_unreachable
(
"Unknown loc info!"
)
;
case
CCValAssign
::
Full
:
break
;
case
CCValAssign
::
BCvt
:
Arg
=
DAG
.
getNode
(
ISD
::
BITCAST
,
DL
,
VA
.
getLocVT
(
)
,
Arg
)
;
break
;
}
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
Arg
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
ARM64ISD
::
RET_FLAG
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

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


<s> bool ARM64TargetLowering :: mayBeEmittedAsTailCall ( CallInst * CI ) const { if ( ! EnableARM64TailCalls ) return false ; if ( ! CI -> isTailCall ( ) ) return false ; return true ; } </s>

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


<s> SDValue ARM64TargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { SelectionDAG & DAG = DCI . DAG ; switch ( N -> getOpcode ( ) ) { default : break ; case ISD :: ADD : case ISD :: SUB : return performAddSubLongCombine ( N , DCI , DAG ) ; case ISD :: XOR : return performXorCombine ( N , DAG , DCI , Subtarget ) ; case ISD :: MUL : return performMulCombine ( N , DAG , DCI , Subtarget ) ; case ISD :: SINT_TO_FP : case ISD :: UINT_TO_FP : return performIntToFpCombine ( N , DAG ) ; case ISD :: OR : return performORCombine ( N , DCI , Subtarget ) ; case ISD :: INTRINSIC_WO_CHAIN : return performIntrinsicCombine ( N , DCI , Subtarget ) ; case ISD :: ANY_EXTEND : case ISD :: ZERO_EXTEND : case ISD :: SIGN_EXTEND : return performExtendCombine ( N , DCI , DAG ) ; case ISD :: BITCAST : return performBitcastCombine ( N , DCI , DAG ) ; case ISD :: CONCAT_VECTORS : return performConcatVectorsCombine ( N , DCI , DAG ) ; case ISD :: VSELECT : return performVSelectCombine ( N , DCI . DAG ) ; case ISD :: STORE : return performSTORECombine ( N , DCI , DAG , Subtarget ) ; case ARM64ISD :: BRCOND : return performBRCONDCombine ( N , DCI , DAG ) ; } return SDValue ( ) ; } </s>

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


<s>
void
ARM64TargetLowering
::
ReplaceNodeResults
(
SDNode
*
N
,
SmallVectorImpl
<
SDValue
>
&
Results
,
SelectionDAG
&
DAG
)
const
{
switch
(
N
->
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom expand this"
)
;
case
ISD
::
FP_TO_UINT
:
case
ISD
::
FP_TO_SINT
:
assert
(
N
->
getValueType
(
0
)
==
MVT
::
i128
&&
"unexpected illegal conversion"
)
;
return
;
}
}
</s>

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


<s> bool ARM64TargetLowering :: shouldConvertConstantLoadToIntImm ( const APInt & Imm , Type * Ty ) const { assert ( Ty -> isIntegerTy ( ) ) ; unsigned BitSize = Ty -> getPrimitiveSizeInBits ( ) ; if ( BitSize == 0 ) return false ; int64_t Val = Imm . getSExtValue ( ) ; if ( Val == 0 || ARM64_AM :: isLogicalImmediate ( Val , BitSize ) ) return true ; if ( ( int64_t ) Val < 0 ) Val = ~ Val ; if ( BitSize == 32 ) Val &= ( 1LL << 32 ) - 1 ; unsigned LZ = countLeadingZeros ( ( uint64_t ) Val ) ; unsigned Shift = ( 63 - LZ ) / 16 ; return ( Shift < 3 ) ? true : false ; } </s>

Returns true if it is beneficial to convert a load of a constant to just the constant itself .


<s> static SDValue WidenVector ( SDValue V64Reg , SelectionDAG & DAG ) { EVT VT = V64Reg . getValueType ( ) ; unsigned NarrowSize = VT . getVectorNumElements ( ) ; MVT EltTy = VT . getVectorElementType ( ) . getSimpleVT ( ) ; MVT WideTy = MVT :: getVectorVT ( EltTy , 2 * NarrowSize ) ; SDLoc DL ( V64Reg ) ; return DAG . getNode ( ISD :: INSERT_SUBVECTOR , DL , WideTy , DAG . getUNDEF ( WideTy ) , V64Reg , DAG . getConstant ( 0 , MVT :: i32 ) ) ; } </s>

Widen the vector up to the next power of two using INSERT_SUBVECTOR .


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM64 load / store optimization pass"
;
}
</s>

getPassName - Return a nice clean name for a pass .


<s> bool ARM64LoadStoreOpt :: runOnMachineFunction ( MachineFunction & Fn ) { const TargetMachine & TM = Fn . getTarget ( ) ; TII = static_cast < const ARM64InstrInfo * > ( TM . getInstrInfo ( ) ) ; TRI = TM . getRegisterInfo ( ) ; bool Modified = false ; for ( auto & MBB : Fn ) Modified |= optimizeBlock ( MBB ) ; return Modified ; } </s>

runOnMachineFunction - Emit the function body .


<s>
int
ARM64LoadStoreOpt
::
getMemSize
(
MachineInstr
*
MemMI
)
{
switch
(
MemMI
->
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Opcode has has unknown size!"
)
;
case
ARM64
::
STRSui
:
case
ARM64
::
STURSi
:
return
4
;
case
ARM64
::
STRDui
:
case
ARM64
::
STURDi
:
return
8
;
case
ARM64
::
STRQui
:
case
ARM64
::
STURQi
:
return
16
;
case
ARM64
::
STRWui
:
case
ARM64
::
STURWi
:
return
4
;
case
ARM64
::
STRXui
:
case
ARM64
::
STURXi
:
return
8
;
case
ARM64
::
LDRSui
:
case
ARM64
::
LDURSi
:
return
4
;
case
ARM64
::
LDRDui
:
case
ARM64
::
LDURDi
:
return
8
;
case
ARM64
::
LDRQui
:
case
ARM64
::
LDURQi
:
return
16
;
case
ARM64
::
LDRWui
:
case
ARM64
::
LDURWi
:
return
4
;
case
ARM64
::
LDRXui
:
case
ARM64
::
LDURXi
:
return
8
;
}
}
</s>

Returns the size in bytes of the memory access .


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"ARM64 load / store optimization pass"
;
}
</s>


<s> bool ARM64LoadStoreOpt :: runOnMachineFunction ( MachineFunction & Fn ) { if ( ! DoLoadStoreOpt ) return false ; const TargetMachine & TM = Fn . getTarget ( ) ; TII = static_cast < const ARM64InstrInfo * > ( TM . getInstrInfo ( ) ) ; TRI = TM . getRegisterInfo ( ) ; bool Modified = false ; for ( auto & MBB : Fn ) Modified |= optimizeBlock ( MBB ) ; return Modified ; } </s>


<s> void addLOHDirective ( MCLOHType Kind , const MILOHArgs & Args ) { LOHContainerSet . push_back ( MILOHDirective ( Kind , Args ) ) ; LOHRelated . insert ( Args . begin ( ) , Args . end ( ) ) ; } </s>

Add a LOH directive of this Kind and this Args .


<s> MCLOHType getKind ( ) const { return Kind ; } </s>


<s>
uint32_t
ARM64MCCodeEmitter
::
getBranchTargetOpValue
(
const
MCInst
&
MI
,
unsigned
OpIdx
,
SmallVectorImpl
<
MCFixup
>
&
Fixups
,
const
MCSubtargetInfo
&
STI
)
const
{
const
MCOperand
&
MO
=
MI
.
getOperand
(
OpIdx
)
;
if
(
MO
.
isImm
(
)
)
return
MO
.
getImm
(
)
;
assert
(
MO
.
isExpr
(
)
&&
"Unexpected ADR target type!"
)
;
MCFixupKind
Kind
=
MI
.
getOpcode
(
)
==
ARM64
::
BL
MCFixupKind
(
ARM64
::
fixup_arm64_pcrel_call26
)
:
MCFixupKind
(
ARM64
::
fixup_arm64_pcrel_branch26
)
;
Fixups
.
push_back
(
MCFixup
::
Create
(
0
,
MO
.
getExpr
(
)
,
Kind
,
MI
.
getLoc
(
)
)
)
;
++
MCNumFixups
;
return
0
;
}
</s>

getBranchTargetOpValue - Return binary encoding of the branch target operand .


<s>
unsigned
ARM64MCCodeEmitter
::
getMachineOpValue
(
const
MCInst
&
MI
,
const
MCOperand
&
MO
,
SmallVectorImpl
<
MCFixup
>
&
Fixups
,
const
MCSubtargetInfo
&
STI
)
const
{
if
(
MO
.
isReg
(
)
)
return
Ctx
.
getRegisterInfo
(
)
->
getEncodingValue
(
MO
.
getReg
(
)
)
;
else
{
assert
(
MO
.
isImm
(
)
&&
"did not expect relocated expression"
)
;
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
}
assert
(
0
&&
"Unable to encode MCOperand!"
)
;
return
0
;
}
</s>

getMachineOpValue - Return binary encoding of operand .


<s>
StringRef
ARM64MCExpr
::
getVariantKindName
(
)
const
{
switch
(
static_cast
<
uint32_t
>
(
getKind
(
)
)
)
{
case
VK_CALL
:
return
""
;
case
VK_LO12
:
return
":lo12:"
;
case
VK_ABS_G3
:
return
":abs_g3:"
;
case
VK_ABS_G2
:
return
":abs_g2:"
;
case
VK_ABS_G2_S
:
return
":abs_g2_s:"
;
case
VK_ABS_G2_NC
:
return
":abs_g2_nc:"
;
case
VK_ABS_G1
:
return
":abs_g1:"
;
case
VK_ABS_G1_S
:
return
":abs_g1_s:"
;
case
VK_ABS_G1_NC
:
return
":abs_g1_nc:"
;
case
VK_ABS_G0
:
return
":abs_g0:"
;
case
VK_ABS_G0_S
:
return
":abs_g0_s:"
;
case
VK_ABS_G0_NC
:
return
":abs_g0_nc:"
;
case
VK_DTPREL_G2
:
return
":dtprel_g2:"
;
case
VK_DTPREL_G1
:
return
":dtprel_g1:"
;
case
VK_DTPREL_G1_NC
:
return
":dtprel_g1_nc:"
;
case
VK_DTPREL_G0
:
return
":dtprel_g0:"
;
case
VK_DTPREL_G0_NC
:
return
":dtprel_g0_nc:"
;
case
VK_DTPREL_HI12
:
return
":dtprel_hi12:"
;
case
VK_DTPREL_LO12
:
return
":dtprel_lo12:"
;
case
VK_DTPREL_LO12_NC
:
return
":dtprel_lo12_nc:"
;
case
VK_TPREL_G2
:
return
":tprel_g2:"
;
case
VK_TPREL_G1
:
return
":tprel_g1:"
;
case
VK_TPREL_G1_NC
:
return
":tprel_g1_nc:"
;
case
VK_TPREL_G0
:
return
":tprel_g0:"
;
case
VK_TPREL_G0_NC
:
return
":tprel_g0_nc:"
;
case
VK_TPREL_HI12
:
return
":tprel_hi12:"
;
case
VK_TPREL_LO12
:
return
":tprel_lo12:"
;
case
VK_TPREL_LO12_NC
:
return
":tprel_lo12_nc:"
;
case
VK_TLSDESC_LO12
:
return
":tlsdesc_lo12:"
;
case
VK_ABS_PAGE
:
return
""
;
case
VK_GOT_PAGE
:
return
":got:"
;
case
VK_GOT_LO12
:
return
":got_lo12:"
;
case
VK_GOTTPREL_PAGE
:
return
":gottprel:"
;
case
VK_GOTTPREL_LO12_NC
:
return
":gottprel_lo12:"
;
case
VK_GOTTPREL_G1
:
return
":gottprel_g1:"
;
case
VK_GOTTPREL_G0_NC
:
return
":gottprel_g0_nc:"
;
case
VK_TLSDESC
:
return
""
;
case
VK_TLSDESC_PAGE
:
return
":tlsdesc:"
;
default
:
llvm_unreachable
(
"Invalid ELF symbol kind"
)
;
}
}
</s>

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


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

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


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

Construct a unary instruction , given the opcode and an operand .


<s> VariantKind getKind ( ) const { return static_cast < VariantKind > ( Kind ) ; } </s>


<s> const MCExpr * getSubExpr ( ) const { return Expr ; } </s>

getSubExpr - Get the child of this expression .


<s>
StringRef
ARM64MCExpr
::
getVariantKindName
(
)
const
{
switch
(
static_cast
<
uint32_t
>
(
getKind
(
)
)
)
{
case
VK_CALL
:
return
""
;
case
VK_LO12
:
return
":lo12:"
;
case
VK_ABS_G3
:
return
":abs_g3:"
;
case
VK_ABS_G2
:
return
":abs_g2:"
;
case
VK_ABS_G2_S
:
return
":abs_g2_s:"
;
case
VK_ABS_G2_NC
:
return
":abs_g2_nc:"
;
case
VK_ABS_G1
:
return
":abs_g1:"
;
case
VK_ABS_G1_S
:
return
":abs_g1_s:"
;
case
VK_ABS_G1_NC
:
return
":abs_g1_nc:"
;
case
VK_ABS_G0
:
return
":abs_g0:"
;
case
VK_ABS_G0_S
:
return
":abs_g0_s:"
;
case
VK_ABS_G0_NC
:
return
":abs_g0_nc:"
;
case
VK_DTPREL_G2
:
return
":dtprel_g2:"
;
case
VK_DTPREL_G1
:
return
":dtprel_g1:"
;
case
VK_DTPREL_G1_NC
:
return
":dtprel_g1_nc:"
;
case
VK_DTPREL_G0
:
return
":dtprel_g0:"
;
case
VK_DTPREL_G0_NC
:
return
":dtprel_g0_nc:"
;
case
VK_DTPREL_LO12
:
return
":dtprel_lo12:"
;
case
VK_DTPREL_LO12_NC
:
return
":dtprel_lo12_nc:"
;
case
VK_TPREL_G2
:
return
":tprel_g2:"
;
case
VK_TPREL_G1
:
return
":tprel_g1:"
;
case
VK_TPREL_G1_NC
:
return
":tprel_g1_nc:"
;
case
VK_TPREL_G0
:
return
":tprel_g0:"
;
case
VK_TPREL_G0_NC
:
return
":tprel_g0_nc:"
;
case
VK_TPREL_LO12
:
return
":tprel_lo12:"
;
case
VK_TPREL_LO12_NC
:
return
":tprel_lo12_nc:"
;
case
VK_TLSDESC_LO12
:
return
":tlsdesc_lo12:"
;
case
VK_ABS_PAGE
:
return
""
;
case
VK_GOT_PAGE
:
return
":got:"
;
case
VK_GOT_LO12
:
return
":got_lo12:"
;
case
VK_GOTTPREL_PAGE
:
return
":gottprel:"
;
case
VK_GOTTPREL_LO12_NC
:
return
":gottprel_lo12:"
;
case
VK_GOTTPREL_G1
:
return
":gottprel_g1:"
;
case
VK_GOTTPREL_G0_NC
:
return
":gottprel_g0_nc:"
;
case
VK_TLSDESC
:
return
""
;
case
VK_TLSDESC_PAGE
:
return
":tlsdesc:"
;
default
:
llvm_unreachable
(
"Invalid ELF symbol kind"
)
;
}
}
</s>


<s> MCSymbol * ARM64MCInstLower :: GetExternalSymbolSymbol ( const MachineOperand & MO ) const { return Printer . GetExternalSymbolSymbol ( MO . getSymbolName ( ) ) ; } </s>

Return the MCSymbol for the specified ExternalSymbol .


<s>
bool
ARM64MCInstLower
::
lowerOperand
(
const
MachineOperand
&
MO
,
MCOperand
&
MCOp
)
const
{
switch
(
MO
.
getType
(
)
)
{
default
:
assert
(
0
&&
"unknown operand type"
)
;
case
MachineOperand
::
MO_Register
:
if
(
MO
.
isImplicit
(
)
)
return
false
;
MCOp
=
MCOperand
::
CreateReg
(
MO
.
getReg
(
)
)
;
break
;
case
MachineOperand
::
MO_RegisterMask
:
return
false
;
case
MachineOperand
::
MO_Immediate
:
MCOp
=
MCOperand
::
CreateImm
(
MO
.
getImm
(
)
)
;
break
;
case
MachineOperand
::
MO_MachineBasicBlock
:
MCOp
=
MCOperand
::
CreateExpr
(
MCSymbolRefExpr
::
Create
(
MO
.
getMBB
(
)
->
getSymbol
(
)
,
Ctx
)
)
;
break
;
case
MachineOperand
::
MO_GlobalAddress
:
MCOp
=
LowerSymbolOperand
(
MO
,
GetGlobalAddressSymbol
(
MO
)
)
;
break
;
case
MachineOperand
::
MO_ExternalSymbol
:
MCOp
=
LowerSymbolOperand
(
MO
,
GetExternalSymbolSymbol
(
MO
)
)
;
break
;
case
MachineOperand
::
MO_JumpTableIndex
:
MCOp
=
LowerSymbolOperand
(
MO
,
Printer
.
GetJTISymbol
(
MO
.
getIndex
(
)
)
)
;
break
;
case
MachineOperand
::
MO_ConstantPoolIndex
:
MCOp
=
LowerSymbolOperand
(
MO
,
Printer
.
GetCPISymbol
(
MO
.
getIndex
(
)
)
)
;
break
;
case
MachineOperand
::
MO_BlockAddress
:
MCOp
=
LowerSymbolOperand
(
MO
,
Printer
.
GetBlockAddressSymbol
(
MO
.
getBlockAddress
(
)
)
)
;
break
;
}
return
true
;
}
</s>

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


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . setPreservesCFG ( ) ; AU . addRequired < DominatorTreeWrapperPass > ( ) ; AU . addPreserved < DominatorTreeWrapperPass > ( ) ; } </s>

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM64 Promote Constant"
;
}
</s>


<s> bool runOnModule ( Module & M ) override { DEBUG ( dbgs ( ) << getPassName ( ) << '\n' ) ; bool Changed = false ; for ( auto & MF : M ) { Changed |= runOnFunction ( MF ) ; } return Changed ; } </s>

runOnModule - Virtual method overriden by subclasses to process the module being operated on .


<s> virtual void getAnalysisUsage ( AnalysisUsage & AU ) const { AU . setPreservesCFG ( ) ; AU . addRequired < DominatorTreeWrapperPass > ( ) ; AU . addPreserved < DominatorTreeWrapperPass > ( ) ; } </s>


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"ARM64 Promote Constant"
;
}
</s>


<s> bool ARM64PromoteConstant :: runOnFunction ( Function & F ) { bool LocalChange = false ; SmallSet < Constant * , 8 > AlreadyChecked ; for ( auto & MBB : F ) { for ( auto & MI : MBB ) { for ( unsigned OpIdx = 0 , EndOpIdx = MI . getNumOperands ( ) ; OpIdx != EndOpIdx ; ++ OpIdx ) { Constant * Cst = dyn_cast < Constant > ( MI . getOperand ( OpIdx ) ) ; if ( Cst && ! isa < GlobalValue > ( Cst ) && ! isa < ConstantExpr > ( Cst ) && AlreadyChecked . insert ( Cst ) ) LocalChange |= promoteConstant ( Cst ) ; } } } return LocalChange ; } </s>

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


<s> bool runOnModule ( Module & M ) { DEBUG ( dbgs ( ) << getPassName ( ) << '\n' ) ; bool Changed = false ; for ( auto & MF : M ) { Changed |= runOnFunction ( MF ) ; } return Changed ; } </s>


<s> unsigned getCSRFirstUseCost ( ) const override { return 5 ; } </s>

Allow the target to override the cost of using a callee-saved register for the first time .


<s>
void
ARM64RegisterInfo
::
eliminateFrameIndex
(
MachineBasicBlock
::
iterator
II
,
int
SPAdj
,
unsigned
FIOperandNum
,
RegScavenger
*
RS
)
const
{
assert
(
SPAdj
==
0
&&
"Unexpected"
)
;
MachineInstr
&
MI
=
*
II
;
MachineBasicBlock
&
MBB
=
*
MI
.
getParent
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
ARM64FrameLowering
*
TFI
=
static_cast
<
const
ARM64FrameLowering
*
>
(
MF
.
getTarget
(
)
.
getFrameLowering
(
)
)
;
int
FrameIndex
=
MI
.
getOperand
(
FIOperandNum
)
.
getIndex
(
)
;
unsigned
FrameReg
;
int
Offset
;
if
(
MI
.
isDebugValue
(
)
||
MI
.
getOpcode
(
)
==
TargetOpcode
::
STACKMAP
||
MI
.
getOpcode
(
)
==
TargetOpcode
::
PATCHPOINT
)
{
Offset
=
TFI
->
resolveFrameIndexReference
(
MF
,
FrameIndex
,
FrameReg
,
true
)
;
Offset
+=
MI
.
getOperand
(
FIOperandNum
+
1
)
.
getImm
(
)
;
MI
.
getOperand
(
FIOperandNum
)
.
ChangeToRegister
(
FrameReg
,
false
)
;
MI
.
getOperand
(
FIOperandNum
+
1
)
.
ChangeToImmediate
(
Offset
)
;
return
;
}
Offset
=
TFI
->
resolveFrameIndexReference
(
MF
,
FrameIndex
,
FrameReg
)
;
if
(
rewriteARM64FrameIndex
(
MI
,
FIOperandNum
,
FrameReg
,
Offset
,
TII
)
)
return
;
assert
(
(
!
RS
||
!
RS
->
isScavengingFrameIndex
(
FrameIndex
)
)
&&
"Emergency spill slot is out of reach"
)
;
unsigned
ScratchReg
=
MF
.
getRegInfo
(
)
.
createVirtualRegister
(
&
ARM64
::
GPR64RegClass
)
;
emitFrameOffset
(
MBB
,
II
,
MI
.
getDebugLoc
(
)
,
ScratchReg
,
FrameReg
,
Offset
,
TII
)
;
MI
.
getOperand
(
FIOperandNum
)
.
ChangeToRegister
(
ScratchReg
,
false
,
false
,
true
)
;
}
</s>

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


<s>
const
MCPhysReg
*
ARM64RegisterInfo
::
getCalleeSavedRegs
(
const
MachineFunction
*
MF
)
const
{
assert
(
MF
&&
"Invalid MachineFunction pointer."
)
;
if
(
MF
->
getFunction
(
)
->
getCallingConv
(
)
==
CallingConv
::
AnyReg
)
return
CSR_ARM64_AllRegs_SaveList
;
else
return
CSR_ARM64_AAPCS_SaveList
;
}
</s>


<s> const uint32_t * ARM64RegisterInfo :: getCallPreservedMask ( CallingConv :: ID CC ) const { if ( CC == CallingConv :: AnyReg ) return CSR_ARM64_AllRegs_RegMask ; else return CSR_ARM64_AAPCS_RegMask ; } </s>

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


<s> const TargetRegisterClass * ARM64RegisterInfo :: getCrossCopyRegClass ( const TargetRegisterClass * RC ) const { if ( RC == & ARM64 :: CCRRegClass ) return nullptr ; return RC ; } </s>

getCrossCopyRegClass - Returns a legal register class to copy a register in the specified class to or from .


<s> unsigned getCSRFirstUseCost ( ) const { return 5 ; } </s>


<s> unsigned ARM64RegisterInfo :: getFrameRegister ( const MachineFunction & MF ) const { const TargetFrameLowering * TFI = MF . getTarget ( ) . getFrameLowering ( ) ; return TFI -> hasFP ( MF ) ? ARM64 :: FP : ARM64 :: SP ; } </s>


<s> const TargetRegisterClass * ARM64RegisterInfo :: getPointerRegClass ( const MachineFunction & MF , unsigned Kind ) const { return & ARM64 :: GPR64RegClass ; } </s>

getPointerRegClass - Returns a TargetRegisterClass used for pointer values .


<s> unsigned ARM64RegisterInfo :: getRegPressureLimit ( const TargetRegisterClass * RC , MachineFunction & MF ) const { const TargetFrameLowering * TFI = MF . getTarget ( ) . getFrameLowering ( ) ; switch ( RC -> getID ( ) ) { default : return 0 ; case ARM64 :: GPR32RegClassID : case ARM64 :: GPR32spRegClassID : case ARM64 :: GPR32allRegClassID : case ARM64 :: GPR64spRegClassID : case ARM64 :: GPR64allRegClassID : case ARM64 :: GPR64RegClassID : case ARM64 :: GPR32commonRegClassID : case ARM64 :: GPR64commonRegClassID : return 32 - 1 - ( TFI -> hasFP ( MF ) || STI -> isTargetDarwin ( ) ) - STI -> isTargetDarwin ( ) - hasBasePointer ( MF ) ; case ARM64 :: FPR8RegClassID : case ARM64 :: FPR16RegClassID : case ARM64 :: FPR32RegClassID : case ARM64 :: FPR64RegClassID : case ARM64 :: FPR128RegClassID : return 32 ; case ARM64 :: DDRegClassID : case ARM64 :: DDDRegClassID : case ARM64 :: DDDDRegClassID : case ARM64 :: QQRegClassID : case ARM64 :: QQQRegClassID : case ARM64 :: QQQQRegClassID : return 32 ; case ARM64 :: FPR128_loRegClassID : return 16 ; } } </s>

Return the register pressure `` high water mark '' for the specific register class .


<s> BitVector ARM64RegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { const TargetFrameLowering * TFI = MF . getTarget ( ) . getFrameLowering ( ) ; BitVector Reserved ( getNumRegs ( ) ) ; Reserved . set ( ARM64 :: SP ) ; Reserved . set ( ARM64 :: XZR ) ; Reserved . set ( ARM64 :: WSP ) ; Reserved . set ( ARM64 :: WZR ) ; if ( TFI -> hasFP ( MF ) || STI -> isTargetDarwin ( ) ) { Reserved . set ( ARM64 :: FP ) ; Reserved . set ( ARM64 :: W29 ) ; } if ( STI -> isTargetDarwin ( ) ) { Reserved . set ( ARM64 :: X18 ) ; Reserved . set ( ARM64 :: W18 ) ; } if ( hasBasePointer ( MF ) ) { Reserved . set ( ARM64 :: X19 ) ; Reserved . set ( ARM64 :: W19 ) ; } return Reserved ; } </s>

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


<s> const uint32_t * ARM64RegisterInfo :: getThisReturnPreservedMask ( CallingConv :: ID ) const { return CSR_ARM64_AAPCS_ThisReturn_RegMask ; } </s>

getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned ' is on an i32 first argument if the calling convention is one that can ( partially ) model this attribute with a preserved mask ( i.e .


"Unable to get the legal offset for nil instruction."

Determine whether a given base register plus offset immediate is encodable to resolve a frame index .


<s> void ARM64RegisterInfo :: materializeFrameBaseRegister ( MachineBasicBlock * MBB , unsigned BaseReg , int FrameIdx , int64_t Offset ) const { MachineBasicBlock :: iterator Ins = MBB -> begin ( ) ; DebugLoc DL ; if ( Ins != MBB -> end ( ) ) DL = Ins -> getDebugLoc ( ) ; const MCInstrDesc & MCID = TII -> get ( ARM64 :: ADDXri ) ; MachineRegisterInfo & MRI = MBB -> getParent ( ) -> getRegInfo ( ) ; const MachineFunction & MF = * MBB -> getParent ( ) ; MRI . constrainRegClass ( BaseReg , TII -> getRegClass ( MCID , 0 , this , MF ) ) ; unsigned Shifter = ARM64_AM :: getShifterImm ( ARM64_AM :: LSL , 0 ) ; BuildMI ( * MBB , Ins , DL , MCID , BaseReg ) . addFrameIndex ( FrameIdx ) . addImm ( Offset ) . addImm ( Shifter ) ; } </s>

Insert defining instruction ( s ) for a pointer to FrameIdx before insertion point I .


"Instr doesn't have FrameIndex operand!"

Returns true if the instruction 's frame index reference would be better served by a base register other than FP or SP .


<s> bool ARM64RegisterInfo :: requiresFrameIndexScavenging ( const MachineFunction & MF ) const { return true ; } </s>

Returns true if the target requires post PEI scavenging of registers for materializing frame index constants .


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

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


<s> bool ARM64RegisterInfo :: requiresVirtualBaseRegisters ( const MachineFunction & MF ) const { return true ; } </s>

Returns true if the target wants the LocalStackAllocation pass to be run and virtual base registers used for more efficient stack access .


Resolve a frame index operand of an instruction to reference the indicated base register plus offset instead .


<s> bool ARM64RegisterInfo :: useFPForScavengingIndex ( const MachineFunction & MF ) const { const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; return MFI -> hasVarSizedObjects ( ) && ! hasBasePointer ( MF ) ; } </s>

Returns true if the target wants to use frame pointer based accesses to spill to the scavenger emergency spill slot .


<s> SDValue ARM64SelectionDAGInfo :: EmitTargetCodeForMemset ( SelectionDAG & DAG , SDLoc dl , SDValue Chain , SDValue Dst , SDValue Src , SDValue Size , unsigned Align , bool isVolatile , MachinePointerInfo DstPtrInfo ) const { ConstantSDNode * V = dyn_cast < ConstantSDNode > ( Src ) ; ConstantSDNode * SizeValue = dyn_cast < ConstantSDNode > ( Size ) ; const char * bzeroEntry = ( V && V -> isNullValue ( ) ) ? Subtarget -> getBZeroEntry ( ) : nullptr ; if ( bzeroEntry && ( ! SizeValue || SizeValue -> getZExtValue ( ) > 256 ) ) { const ARM64TargetLowering & TLI = * static_cast < const ARM64TargetLowering * > ( DAG . getTarget ( ) . getTargetLowering ( ) ) ; EVT IntPtr = TLI . getPointerTy ( ) ; Type * IntPtrTy = getDataLayout ( ) -> getIntPtrType ( * DAG . getContext ( ) ) ; TargetLowering :: ArgListTy Args ; TargetLowering :: ArgListEntry Entry ; Entry . Node = Dst ; Entry . Ty = IntPtrTy ; Args . push_back ( Entry ) ; Entry . Node = Size ; Args . push_back ( Entry ) ; TargetLowering :: CallLoweringInfo CLI ( Chain , Type :: getVoidTy ( * DAG . getContext ( ) ) , false , false , false , false , 0 , CallingConv :: C , false , false , false , DAG . getExternalSymbol ( bzeroEntry , IntPtr ) , Args , DAG , dl ) ; std :: pair < SDValue , SDValue > CallResult = TLI . LowerCallTo ( CLI ) ; return CallResult . second ; } return SDValue ( ) ; } </s>

Emit target-specific code that performs a memset .


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

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


<s>
virtual
const
char
*
getPassName
(
)
const
override
{
return
"ARM64 Store Pair Suppression"
;
}
</s>

getPassName - Return a nice clean name for a pass .


"  Skipping pass: no machine model present.\n"

runOnMachineFunction - Emit the function body .


<s> unsigned char ARM64Subtarget :: ClassifyGlobalReference ( const GlobalValue * GV , const TargetMachine & TM ) const { bool isDecl = GV -> hasAvailableExternallyLinkage ( ) ; if ( GV -> isDeclaration ( ) && ! GV -> isMaterializable ( ) ) isDecl = true ; if ( TM . getCodeModel ( ) == CodeModel :: Large && isTargetMachO ( ) ) return ARM64II :: MO_GOT ; if ( TM . getCodeModel ( ) == CodeModel :: Small && GV -> isWeakForLinker ( ) && isDecl ) return ARM64II :: MO_GOT ; if ( TM . getRelocationModel ( ) != Reloc :: Static && GV -> hasDefaultVisibility ( ) ) { if ( isTargetMachO ( ) ) return ( isDecl || GV -> isWeakForLinker ( ) ) ? ARM64II :: MO_GOT : ARM64II :: MO_NO_FLAG ; else return GV -> hasLocalLinkage ( ) ? ARM64II :: MO_NO_FLAG : ARM64II :: MO_GOT ; } return ARM64II :: MO_NO_FLAG ; } </s>

ClassifyGlobalReference - Find the target operand flags that describe how a global value should be referenced for the current subtarget .


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

Enable the MachineScheduler pass for all X86 subtargets .


<s> unsigned getMaxInlineSizeThreshold ( ) const { return 64 ; } </s>

Returns the maximum memset / memcpy size that still makes it profitable to inline the call .


<s> bool isLittleEndian ( ) const { return IsLittleEndian ; } </s>

Tests whether the target triple is little endian .


<s> void ARM64Subtarget :: overrideSchedPolicy ( MachineSchedPolicy & Policy , MachineInstr * begin , MachineInstr * end , unsigned NumRegionInstrs ) const { Policy . OnlyTopDown = false ; Policy . OnlyBottomUp = false ; } </s>

Override generic scheduling policy within a region .


<s> bool ARM64PassConfig :: addILPOpts ( ) { if ( EnableCCMP ) addPass ( createARM64ConditionalCompares ( ) ) ; if ( EnableEarlyIfConvert ) addPass ( & EarlyIfConverterID ) ; if ( EnableStPairSuppress ) addPass ( createARM64StorePairSuppressPass ( ) ) ; return true ; } </s>

Add passes that optimize instruction level parallelism for out-of-order targets .


<s> bool ARM64PassConfig :: addPostRegAlloc ( ) { if ( TM -> getOptLevel ( ) != CodeGenOpt :: None && EnableDeadRegisterElimination ) addPass ( createARM64DeadRegisterDefinitions ( ) ) ; return true ; } </s>

This method may be implemented by targets that want to run passes after register allocation pass pipeline but before prolog-epilog insertion .


<s> bool ARM64PassConfig :: addPreRegAlloc ( ) { if ( TM -> getOptLevel ( ) != CodeGenOpt :: None && EnableAdvSIMDScalar ) addPass ( createARM64AdvSIMDScalar ( ) ) ; return true ; } </s>

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


<s> bool ARM64PassConfig :: addPreSched2 ( ) { addPass ( createARM64ExpandPseudoPass ( ) ) ; if ( TM -> getOptLevel ( ) != CodeGenOpt :: None && EnableLoadStoreOpt ) addPass ( createARM64LoadStoreOptimizationPass ( ) ) ; return true ; } </s>

This method may be implemented by targets that want to run passes after prolog-epilog insertion and before the second instruction scheduling pass .


<s> bool ARM64PassConfig :: addILPOpts ( ) { if ( EnableCCMP ) addPass ( createARM64ConditionalCompares ( ) ) ; addPass ( & EarlyIfConverterID ) ; if ( EnableStPairSuppress ) addPass ( createARM64StorePairSuppressPass ( ) ) ; return true ; } </s>