<s>
bool
ARMBaseInstrInfo
::
analyzeBranch
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
*
&
TBB
,
MachineBasicBlock
*
&
FBB
,
SmallVectorImpl
<
MachineOperand
>
&
Cond
,
bool
AllowModify
)
const
{
TBB
=
nullptr
;
FBB
=
nullptr
;
MachineBasicBlock
::
instr_iterator
I
=
MBB
.
instr_end
(
)
;
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
while
(
isPredicated
(
*
I
)
||
I
->
isTerminator
(
)
||
I
->
isDebugValue
(
)
)
{
bool
CantAnalyze
=
false
;
while
(
I
->
isDebugInstr
(
)
||
!
I
->
isTerminator
(
)
||
isSpeculationBarrierEndBBOpcode
(
I
->
getOpcode
(
)
)
||
I
->
getOpcode
(
)
==
ARM
::
t2DoLoopStartTP
)
{
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
}
if
(
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
CantAnalyze
=
true
;
}
else
if
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
}
else
if
(
isCondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
if
(
!
Cond
.
empty
(
)
)
return
true
;
assert
(
!
FBB
&&
"FBB should have been null."
)
;
FBB
=
TBB
;
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
Cond
.
push_back
(
I
->
getOperand
(
1
)
)
;
Cond
.
push_back
(
I
->
getOperand
(
2
)
)
;
}
else
if
(
I
->
isReturn
(
)
)
{
CantAnalyze
=
true
;
}
else
{
return
true
;
}
if
(
!
isPredicated
(
*
I
)
&&
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
||
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
||
I
->
isReturn
(
)
)
)
{
Cond
.
clear
(
)
;
FBB
=
nullptr
;
if
(
AllowModify
)
{
MachineBasicBlock
::
iterator
DI
=
std
::
next
(
I
)
;
while
(
DI
!=
MBB
.
instr_end
(
)
)
{
MachineInstr
&
InstToDelete
=
*
DI
;
++
DI
;
if
(
isSpeculationBarrierEndBBOpcode
(
InstToDelete
.
getOpcode
(
)
)
)
continue
;
InstToDelete
.
eraseFromParent
(
)
;
}
}
}
if
(
CantAnalyze
)
{
if
(
AllowModify
&&
!
isPredicated
(
MBB
.
back
(
)
)
&&
isUncondBranchOpcode
(
MBB
.
back
(
)
.
getOpcode
(
)
)
&&
TBB
&&
MBB
.
isLayoutSuccessor
(
TBB
)
)
removeBranch
(
MBB
)
;
return
true
;
}
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
}
return
false
;
}
</s>

analyzeBranch - Analyze the branching code at the end of MBB , returning true if it can not be understood ( e.g .


<s> bool ARMBaseInstrInfo :: analyzeCompare ( const MachineInstr & MI , Register & SrcReg , Register & SrcReg2 , int64_t & CmpMask , int64_t & CmpValue ) const { switch ( MI . getOpcode ( ) ) { default : break ; case ARM :: CMPri : case ARM :: t2CMPri : case ARM :: tCMPi8 : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = ~ 0 ; CmpValue = MI . getOperand ( 1 ) . getImm ( ) ; return true ; case ARM :: CMPrr : case ARM :: t2CMPrr : case ARM :: tCMPr : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = MI . getOperand ( 1 ) . getReg ( ) ; CmpMask = ~ 0 ; CmpValue = 0 ; return true ; case ARM :: TSTri : case ARM :: t2TSTri : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = MI . getOperand ( 1 ) . getImm ( ) ; CmpValue = 0 ; 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 .


"Can't break virtual register dependencies."

Insert a dependency-breaking instruction before MI to eliminate an unwanted dependency on OpNum .


<s>
void
ARMBaseInstrInfo
::
buildOutlinedFrame
(
MachineBasicBlock
&
MBB
,
MachineFunction
&
MF
,
const
outliner
::
OutlinedFunction
&
OF
)
const
{
if
(
OF
.
FrameConstructionID
==
MachineOutlinerThunk
)
{
MachineInstr
*
Call
=
&
*
MBB
.
instr_end
(
)
;
bool
isThumb
=
Subtarget
.
isThumb
(
)
;
unsigned
FuncOp
=
isThumb
2
:
0
;
unsigned
Opc
=
Call
->
getOperand
(
FuncOp
)
.
isReg
(
)
isThumb
ARM
::
tTAILJMPr
:
ARM
::
TAILJMPr
:
isThumb
Subtarget
.
isTargetMachO
(
)
ARM
::
tTAILJMPd
:
ARM
::
tTAILJMPdND
:
ARM
::
TAILJMPd
;
MachineInstrBuilder
MIB
=
BuildMI
(
MBB
,
MBB
.
end
(
)
,
DebugLoc
(
)
,
get
(
Opc
)
)
.
add
(
Call
->
getOperand
(
FuncOp
)
)
;
if
(
isThumb
&&
!
Call
->
getOperand
(
FuncOp
)
.
isReg
(
)
)
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
Call
->
eraseFromParent
(
)
;
}
auto
IsNonTailCall
=
[
]
(
MachineInstr
&
MI
)
{
return
MI
.
isCall
(
)
&&
!
MI
.
isReturn
(
)
;
}
;
if
(
llvm
::
any_of
(
MBB
.
instrs
(
)
,
IsNonTailCall
)
)
{
MachineBasicBlock
::
iterator
It
=
MBB
.
begin
(
)
;
MachineBasicBlock
::
iterator
Et
=
MBB
.
end
(
)
;
if
(
OF
.
FrameConstructionID
==
MachineOutlinerTailCall
||
OF
.
FrameConstructionID
==
MachineOutlinerThunk
)
Et
=
std
::
prev
(
MBB
.
end
(
)
)
;
if
(
!
MBB
.
isLiveIn
(
ARM
::
LR
)
)
MBB
.
addLiveIn
(
ARM
::
LR
)
;
saveLROnStack
(
MBB
,
It
)
;
emitCFIForLRSaveOnStack
(
MBB
,
It
)
;
assert
(
OF
.
FrameConstructionID
!=
MachineOutlinerDefault
&&
"Can only fix up stack references once"
)
;
fixupPostOutline
(
MBB
)
;
restoreLRFromStack
(
MBB
,
Et
)
;
emitCFIForLRRestoreFromStack
(
MBB
,
Et
)
;
}
if
(
OF
.
FrameConstructionID
==
MachineOutlinerTailCall
||
OF
.
FrameConstructionID
==
MachineOutlinerThunk
)
return
;
BuildMI
(
MBB
,
MBB
.
end
(
)
,
DebugLoc
(
)
,
get
(
Subtarget
.
getReturnOpcode
(
)
)
)
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
if
(
OF
.
FrameConstructionID
!=
MachineOutlinerDefault
&&
OF
.
Candidates
[
0
]
.
CallConstructionID
!=
MachineOutlinerDefault
)
return
;
fixupPostOutline
(
MBB
)
;
}
</s>

Insert a custom frame for outlined functions .

ARM
ARM
2
0
ARM::tTAILJMPr
ARM::TAILJMPr
ARM::tTAILJMPd
ARM::tTAILJMPdND
ARM::TAILJMPd
ARMCC::AL
ARM::LR
ARM::LR
"Can only fix up stack references once"
ARMCC::AL
0


<s> bool ARMBaseInstrInfo :: ClobbersPredicate ( MachineInstr & MI , std :: vector < MachineOperand > & Pred , bool SkipDead ) const { bool Found = false ; for ( unsigned i = 0 , e = MI . getNumOperands ( ) ; i != e ; ++ i ) { const MachineOperand & MO = MI . getOperand ( i ) ; bool ClobbersCPSR = MO . isRegMask ( ) && MO . clobbersPhysReg ( ARM :: CPSR ) ; bool IsCPSR = MO . isReg ( ) && MO . isDef ( ) && MO . getReg ( ) == ARM :: CPSR ; if ( ClobbersCPSR || IsCPSR ) { const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( MCID . TSFlags & ARMII :: ThumbArithFlagSetting && MO . isDead ( ) && SkipDead ) continue ; Pred . push_back ( MO ) ; Found = true ; } } return Found ; } </s>

If the specified instruction defines any predicate or condition code register ( s ) used for predication , returns true as well as the definition predicate ( s ) by reference .

ARM ARM 0 ARM::CPSR ARM::CPSR ARMII::ThumbArithFlagSetting


<s> MachineInstr * ARMBaseInstrInfo :: commuteInstructionImpl ( MachineInstr & MI , bool NewMI , unsigned OpIdx1 , unsigned OpIdx2 ) const { switch ( MI . getOpcode ( ) ) { case ARM :: MOVCCr : case ARM :: t2MOVCCr : { Register PredReg ; ARMCC :: CondCodes CC = getInstrPredicate ( MI , PredReg ) ; if ( CC == ARMCC :: AL || PredReg != ARM :: CPSR ) return nullptr ; MachineInstr * CommutedMI = TargetInstrInfo :: commuteInstructionImpl ( MI , NewMI , OpIdx1 , OpIdx2 ) ; if ( ! CommutedMI ) return nullptr ; CommutedMI -> getOperand ( CommutedMI -> findFirstPredOperandIdx ( ) ) . setImm ( ARMCC :: getOppositeCondition ( CC ) ) ; return CommutedMI ; } } return TargetInstrInfo :: commuteInstructionImpl ( MI , NewMI , OpIdx1 , OpIdx2 ) ; } </s>

Commutes the operands in the given instruction by changing the operands order and/or changing the instruction 's opcode and/or the immediate value operand .

ARM ARM ARM::MOVCCr ARM::t2MOVCCr ARMCC::CondCodes ARMCC::AL ARM::CPSR ARMCC::getOppositeCondition


<s> ScheduleHazardRecognizer * ARMBaseInstrInfo :: CreateTargetMIHazardRecognizer ( const InstrItineraryData * II , const ScheduleDAGMI * DAG ) const { MultiHazardRecognizer * MHR = new MultiHazardRecognizer ( ) ; if ( Subtarget . isCortexM7 ( ) && ! DAG -> hasVRegLiveness ( ) ) MHR -> AddHazardRecognizer ( std :: make_unique < ARMBankConflictHazardRecognizer > ( DAG , 0x4 , true ) ) ; auto BHR = TargetInstrInfo :: CreateTargetMIHazardRecognizer ( II , DAG ) ; MHR -> AddHazardRecognizer ( std :: unique_ptr < ScheduleHazardRecognizer > ( BHR ) ) ; return MHR ; } </s>

Allocate and return a hazard recognizer to use for this target when scheduling the machine instructions before register allocation .


<s> ScheduleHazardRecognizer * ARMBaseInstrInfo :: CreateTargetPostRAHazardRecognizer ( const InstrItineraryData * II , const ScheduleDAG * DAG ) const { MultiHazardRecognizer * MHR = new MultiHazardRecognizer ( ) ; if ( Subtarget . isThumb2 ( ) || Subtarget . hasVFP2Base ( ) ) MHR -> AddHazardRecognizer ( std :: make_unique < ARMHazardRecognizerFPMLx > ( ) ) ; auto BHR = TargetInstrInfo :: CreateTargetPostRAHazardRecognizer ( II , DAG ) ; if ( BHR ) MHR -> AddHazardRecognizer ( std :: unique_ptr < ScheduleHazardRecognizer > ( BHR ) ) ; return MHR ; } </s>

Allocate and return a hazard recognizer to use for by non-scheduling passes .


<s> Optional < ParamLoadedValue > ARMBaseInstrInfo :: describeLoadedValue ( const MachineInstr & MI , Register Reg ) const { if ( auto DstSrcPair = isCopyInstrImpl ( MI ) ) { Register DstReg = DstSrcPair -> Destination -> getReg ( ) ; if ( DstReg != Reg ) return None ; } return TargetInstrInfo :: describeLoadedValue ( MI , Reg ) ; } </s>

Produce the expression describing the MI loading a value into the physical register Reg .


"LOAD_STACK_GUARD currently supported only for MachO."

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


<s> unsigned ARMBaseInstrInfo :: extraSizeToPredicateInstructions ( const MachineFunction & MF , unsigned NumInsts ) const { if ( ! Subtarget . isThumb2 ( ) ) return 0 ; unsigned MaxInsts = Subtarget . restrictIT ( ) ? 1 : 4 ; return divideCeil ( NumInsts , MaxInsts ) * 2 ; } </s>

Return the increase in code size needed to predicate a contiguous run of NumInsts instructions .


<s>
bool
ARMBaseInstrInfo
::
getInsertSubregLikeInputs
(
const
MachineInstr
&
MI
,
unsigned
DefIdx
,
RegSubRegPair
&
BaseReg
,
RegSubRegPairAndIdx
&
InsertedReg
)
const
{
assert
(
DefIdx
<
MI
.
getDesc
(
)
.
getNumDefs
(
)
&&
"Invalid definition index"
)
;
assert
(
MI
.
isInsertSubregLike
(
)
&&
"Invalid kind of instruction"
)
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VSETLNi32
:
case
ARM
::
MVE_VMOV_to_lane_32
:
const
MachineOperand
&
MOBaseReg
=
MI
.
getOperand
(
1
)
;
const
MachineOperand
&
MOInsertedReg
=
MI
.
getOperand
(
2
)
;
if
(
MOInsertedReg
.
isUndef
(
)
)
return
false
;
const
MachineOperand
&
MOIndex
=
MI
.
getOperand
(
3
)
;
BaseReg
.
Reg
=
MOBaseReg
.
getReg
(
)
;
BaseReg
.
SubReg
=
MOBaseReg
.
getSubReg
(
)
;
InsertedReg
.
Reg
=
MOInsertedReg
.
getReg
(
)
;
InsertedReg
.
SubReg
=
MOInsertedReg
.
getSubReg
(
)
;
InsertedReg
.
SubIdx
=
ARM
::
ssub_0
+
MOIndex
.
getImm
(
)
;
return
true
;
}
llvm_unreachable
(
"Target dependent opcode missing"
)
;
}
</s>

Target-dependent implementation of getInsertSubregInputs .


<s> unsigned ARMBaseInstrInfo :: getInstrLatency ( const InstrItineraryData * ItinData , const MachineInstr & MI , unsigned * PredCost ) const { if ( MI . isCopyLike ( ) || MI . isInsertSubreg ( ) || MI . isRegSequence ( ) || MI . isImplicitDef ( ) ) return 1 ; if ( MI . isBundle ( ) ) { unsigned Latency = 0 ; MachineBasicBlock :: const_instr_iterator I = MI . getIterator ( ) ; MachineBasicBlock :: const_instr_iterator E = MI . getParent ( ) -> instr_end ( ) ; while ( ++ I != E && I -> isInsideBundle ( ) ) { if ( I -> getOpcode ( ) != ARM :: t2IT ) Latency += getInstrLatency ( ItinData , * I , PredCost ) ; } return Latency ; } const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( PredCost && ( MCID . isCall ( ) || ( MCID . hasImplicitDefOfPhysReg ( ARM :: CPSR ) && ! Subtarget . cheapPredicableCPSRDef ( ) ) ) ) { * PredCost = 1 ; } if ( ! ItinData ) return MI . mayLoad ( ) ? 3 : 1 ; unsigned Class = MCID . getSchedClass ( ) ; if ( ! ItinData -> isEmpty ( ) && ItinData -> getNumMicroOps ( Class ) < 0 ) return getNumMicroOps ( ItinData , MI ) ; unsigned Latency = ItinData -> getStageLatency ( Class ) ; unsigned DefAlign = MI . hasOneMemOperand ( ) ? ( * MI . memoperands_begin ( ) ) -> getAlign ( ) . value ( ) : 0 ; int Adj = adjustDefLatency ( Subtarget , MI , MCID , DefAlign ) ; if ( Adj >= 0 || ( int ) Latency > - Adj ) { return Latency + Adj ; } return Latency ; } </s>

Compute the instruction latency of a given instruction .


<s> unsigned ARMBaseInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { const MachineBasicBlock & MBB = * MI . getParent ( ) ; const MachineFunction * MF = MBB . getParent ( ) ; const MCAsmInfo * MAI = MF -> getTarget ( ) . getMCAsmInfo ( ) ; const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( MCID . getSize ( ) ) return MCID . getSize ( ) ; switch ( MI . getOpcode ( ) ) { default : return 0 ; case TargetOpcode :: BUNDLE : return getInstBundleLength ( MI ) ; case ARM :: MOVi16_ga_pcrel : case ARM :: MOVTi16_ga_pcrel : case ARM :: t2MOVi16_ga_pcrel : case ARM :: t2MOVTi16_ga_pcrel : return 4 ; case ARM :: MOVi32imm : case ARM :: t2MOVi32imm : return 8 ; case ARM :: CONSTPOOL_ENTRY : case ARM :: JUMPTABLE_INSTS : case ARM :: JUMPTABLE_ADDRS : case ARM :: JUMPTABLE_TBB : case ARM :: JUMPTABLE_TBH : return MI . getOperand ( 2 ) . getImm ( ) ; case ARM :: Int_eh_sjlj_longjmp : return 16 ; case ARM :: tInt_eh_sjlj_longjmp : return 10 ; case ARM :: tInt_WIN_eh_sjlj_longjmp : return 12 ; case ARM :: Int_eh_sjlj_setjmp : case ARM :: Int_eh_sjlj_setjmp_nofp : return 20 ; case ARM :: tInt_eh_sjlj_setjmp : case ARM :: t2Int_eh_sjlj_setjmp : case ARM :: t2Int_eh_sjlj_setjmp_nofp : return 12 ; case ARM :: SPACE : return MI . getOperand ( 1 ) . getImm ( ) ; case ARM :: INLINEASM : case ARM :: INLINEASM_BR : { unsigned Size = getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * MAI ) ; if ( ! MF -> getInfo < ARMFunctionInfo > ( ) -> isThumbFunction ( ) ) Size = alignTo ( Size , 4 ) ; return Size ; } case ARM :: SpeculationBarrierISBDSBEndBB : case ARM :: t2SpeculationBarrierISBDSBEndBB : return 8 ; case ARM :: SpeculationBarrierSBEndBB : case ARM :: t2SpeculationBarrierSBEndBB : return 4 ; } } </s>

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


<s>
unsigned
ARMBaseInstrInfo
::
getPartialRegUpdateClearance
(
const
MachineInstr
&
MI
,
unsigned
OpNum
,
const
TargetRegisterInfo
*
TRI
)
const
{
auto
PartialUpdateClearance
=
Subtarget
.
getPartialUpdateClearance
(
)
;
if
(
!
PartialUpdateClearance
)
return
0
;
assert
(
TRI
&&
"Need TRI instance"
)
;
const
MachineOperand
&
MO
=
MI
.
getOperand
(
OpNum
)
;
if
(
MO
.
readsReg
(
)
)
return
0
;
Register
Reg
=
MO
.
getReg
(
)
;
int
UseOp
=
1
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VLDRS
:
case
ARM
::
FCONSTS
:
case
ARM
::
VMOVSR
:
case
ARM
::
VMOVv8i8
:
case
ARM
::
VMOVv4i16
:
case
ARM
::
VMOVv2i32
:
case
ARM
::
VMOVv2f32
:
case
ARM
::
VMOVv1i64
:
UseOp
=
MI
.
findRegisterUseOperandIdx
(
Reg
,
false
,
TRI
)
;
break
;
case
ARM
::
VLD1LNd32
:
UseOp
=
3
;
break
;
default
:
return
0
;
}
if
(
UseOp
!=
1
&&
MI
.
getOperand
(
UseOp
)
.
readsReg
(
)
)
return
0
;
if
(
Register
::
isVirtualRegister
(
Reg
)
)
{
if
(
!
MO
.
getSubReg
(
)
||
MI
.
readsVirtualRegister
(
Reg
)
)
return
0
;
}
else
if
(
ARM
::
SPRRegClass
.
contains
(
Reg
)
)
{
unsigned
DReg
=
TRI
->
getMatchingSuperReg
(
Reg
,
ARM
::
ssub_0
,
&
ARM
::
DPRRegClass
)
;
if
(
!
DReg
||
!
MI
.
definesRegister
(
DReg
,
TRI
)
)
return
0
;
}
return
PartialUpdateClearance
;
}
</s>

Inform the BreakFalseDeps pass how many idle instructions we would like before a partial register update .


<s>
MachineBasicBlock
::
iterator
ARMBaseInstrInfo
::
insertOutlinedCall
(
Module
&
M
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
&
It
,
MachineFunction
&
MF
,
const
outliner
::
Candidate
&
C
)
const
{
MachineInstrBuilder
MIB
;
MachineBasicBlock
::
iterator
CallPt
;
unsigned
Opc
;
bool
isThumb
=
Subtarget
.
isThumb
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerTailCall
)
{
Opc
=
isThumb
Subtarget
.
isTargetMachO
(
)
ARM
::
tTAILJMPd
:
ARM
::
tTAILJMPdND
:
ARM
::
TAILJMPd
;
MIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
isThumb
)
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
It
=
MBB
.
insert
(
It
,
MIB
)
;
return
It
;
}
Opc
=
isThumb
ARM
::
tBL
:
ARM
::
BL
;
MachineInstrBuilder
CallMIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
;
if
(
isThumb
)
CallMIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
CallMIB
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerNoLRSave
||
C
.
CallConstructionID
==
MachineOutlinerThunk
)
{
It
=
MBB
.
insert
(
It
,
CallMIB
)
;
return
It
;
}
const
ARMFunctionInfo
&
AFI
=
*
C
.
getMF
(
)
->
getInfo
<
ARMFunctionInfo
>
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerRegSave
)
{
unsigned
Reg
=
findRegisterToSaveLRTo
(
C
)
;
assert
(
Reg
!=
0
&&
"No callee-saved register available?"
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
Reg
,
ARM
::
LR
,
true
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRSaveToReg
(
MBB
,
It
,
Reg
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
ARM
::
LR
,
Reg
,
true
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRRestoreFromReg
(
MBB
,
It
)
;
It
;
return
CallPt
;
}
if
(
!
MBB
.
isLiveIn
(
ARM
::
LR
)
)
MBB
.
addLiveIn
(
ARM
::
LR
)
;
saveLROnStack
(
MBB
,
It
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRSaveOnStack
(
MBB
,
It
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
restoreLRFromStack
(
MBB
,
It
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRRestoreFromStack
(
MBB
,
It
)
;
It
;
return
CallPt
;
}
</s>

Insert a call to an outlined function into the program .

ARM
ARM
ARM::tTAILJMPd
ARM::tTAILJMPdND
ARM::TAILJMPd
ARMCC::AL
ARM::tBL
ARM::BL
ARMCC::AL
ARM
ARM
0
"No callee-saved register available?"
ARM::LR
ARM::LR
ARM::LR
ARM::LR


<s> Optional < RegImmPair > ARMBaseInstrInfo :: isAddImmediate ( const MachineInstr & MI , Register Reg ) const { int Sign = 1 ; unsigned Opcode = MI . getOpcode ( ) ; int64_t Offset = 0 ; const MachineOperand & Op0 = MI . getOperand ( 0 ) ; if ( ! Op0 . isReg ( ) || Reg != Op0 . getReg ( ) ) return None ; if ( Opcode == ARM :: SUBri ) Sign = - 1 ; else if ( Opcode != ARM :: ADDri ) return None ; if ( ! MI . getOperand ( 1 ) . isReg ( ) || ! MI . getOperand ( 2 ) . isImm ( ) ) return None ; Offset = MI . getOperand ( 2 ) . getImm ( ) * Sign ; return RegImmPair { MI . getOperand ( 1 ) . getReg ( ) , Offset } ; } </s>

If the specific machine instruction is an instruction that adds an immediate value and a register , and stores the result in the given register Reg , return a pair of the source register and the offset which has been added .


<s> Optional < DestSourcePair > ARMBaseInstrInfo :: isCopyInstrImpl ( const MachineInstr & MI ) const { if ( ! MI . isMoveReg ( ) || ( MI . getOpcode ( ) == ARM :: VORRq && MI . getOperand ( 1 ) . getReg ( ) != MI . getOperand ( 2 ) . getReg ( ) ) ) return None ; return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; } </s>

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


<s> bool ARMBaseInstrInfo :: isFunctionSafeToOutlineFrom ( MachineFunction & MF , bool OutlineFromLinkOnceODRs ) const { const Function & F = MF . getFunction ( ) ; if ( ! OutlineFromLinkOnceODRs && F . hasLinkOnceODRLinkage ( ) ) return false ; if ( F . hasSection ( ) ) return false ; if ( MF . getInfo < ARMFunctionInfo > ( ) -> isThumb1OnlyFunction ( ) ) return false ; return true ; } </s>

Return true if the function can safely be outlined from .


<s> unsigned ARMBaseInstrInfo :: isLoadFromStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : break ; case ARM :: LDRrs : case ARM :: t2LDRs : if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isReg ( ) && MI . getOperand ( 3 ) . isImm ( ) && MI . getOperand ( 2 ) . getReg ( ) == 0 && MI . getOperand ( 3 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: LDRi12 : case ARM :: t2LDRi12 : case ARM :: tLDRspi : case ARM :: VLDRD : case ARM :: VLDRS : case ARM :: VLDR_P0_off : case ARM :: MVE_VLDRWU32 : if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VLD1q64 : case ARM :: VLD1d8TPseudo : case ARM :: VLD1d16TPseudo : case ARM :: VLD1d32TPseudo : case ARM :: VLD1d64TPseudo : case ARM :: VLD1d8QPseudo : case ARM :: VLD1d16QPseudo : case ARM :: VLD1d32QPseudo : case ARM :: VLD1d64QPseudo : if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 0 ) . getSubReg ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VLDMQIA : if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 0 ) . getSubReg ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: MQQPRLoad : case ARM :: MQQQQPRLoad : if ( MI . getOperand ( 1 ) . isFI ( ) ) { 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 .


"Suitable Machine Function for outlining must track liveness"

Optional target hook that returns true if MBB is safe to outline from , and returns any target-specific information in Flags .


<s> bool ARMBaseInstrInfo :: isPredicable ( const MachineInstr & MI ) const { if ( ! MI . isPredicable ( ) ) return false ; if ( MI . isBundle ( ) ) return false ; if ( ! isEligibleForITBlock ( & MI ) ) return false ; const MachineFunction * MF = MI . getParent ( ) -> getParent ( ) ; const ARMFunctionInfo * AFI = MF -> getInfo < ARMFunctionInfo > ( ) ; if ( ( MI . getDesc ( ) . TSFlags & ARMII :: DomainMask ) == ARMII :: DomainNEON ) return false ; const ARMSubtarget & ST = MF -> getSubtarget < ARMSubtarget > ( ) ; if ( ST . hardenSlsRetBr ( ) && isIndirectControlFlowNotComingBack ( MI ) ) return false ; if ( ST . hardenSlsBlr ( ) && isIndirectCall ( MI ) ) return false ; if ( AFI -> isThumb2Function ( ) ) { if ( getSubtarget ( ) . restrictIT ( ) ) return isV8EligibleForIT ( & MI ) ; } return true ; } </s>

Return true if the specified instruction can be predicated .

ARM ARM ARM ARM ARMII::DomainMask ARMII::DomainNEON ARM ARM


<s> bool ARMBaseInstrInfo :: isReallyTriviallyReMaterializable ( const MachineInstr & MI , AAResults * AA ) const { return isVCTP ( & MI ) && ! isPredicated ( MI ) ; } </s>

For instructions with opcodes for which the M_REMATERIALIZABLE flag is set , this hook lets the target specify whether the instruction is actually trivially rematerializable , taking into consideration its operands .


<s> bool ARMBaseInstrInfo :: isSchedulingBoundary ( const MachineInstr & MI , const MachineBasicBlock * MBB , const MachineFunction & MF ) const { if ( MI . isDebugInstr ( ) ) return false ; if ( MI . isTerminator ( ) || MI . isPosition ( ) ) return true ; if ( MI . getOpcode ( ) == TargetOpcode :: INLINEASM_BR ) return true ; MachineBasicBlock :: const_iterator I = MI ; while ( ++ I != MBB -> end ( ) && I -> isDebugInstr ( ) ) ; if ( I != MBB -> end ( ) && I -> getOpcode ( ) == ARM :: t2IT ) return true ; if ( ! MI . isCall ( ) && MI . definesRegister ( ARM :: SP ) ) return true ; return false ; } </s>

isSchedulingBoundary - Overrides the isSchedulingBoundary from Codegen/TargetInstrInfo.cpp to make it capable of identifying ENDBR intructions and prevent it from being re-scheduled .


<s> unsigned ARMBaseInstrInfo :: isStoreToStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : break ; case ARM :: STRrs : case ARM :: t2STRs : if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isReg ( ) && MI . getOperand ( 3 ) . isImm ( ) && MI . getOperand ( 2 ) . getReg ( ) == 0 && MI . getOperand ( 3 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: STRi12 : case ARM :: t2STRi12 : case ARM :: tSTRspi : case ARM :: VSTRD : case ARM :: VSTRS : case ARM :: VSTR_P0_off : case ARM :: MVE_VSTRWU32 : if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VST1q64 : case ARM :: VST1d64TPseudo : case ARM :: VST1d64QPseudo : if ( MI . getOperand ( 0 ) . isFI ( ) && MI . getOperand ( 2 ) . getSubReg ( ) == 0 ) { FrameIndex = MI . getOperand ( 0 ) . getIndex ( ) ; return MI . getOperand ( 2 ) . getReg ( ) ; } break ; case ARM :: VSTMQIA : if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 0 ) . getSubReg ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: MQQPRStore : case ARM :: MQQQQPRStore : if ( MI . getOperand ( 1 ) . isFI ( ) ) { 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>
MachineInstr
*
ARMBaseInstrInfo
::
optimizeSelect
(
MachineInstr
&
MI
,
SmallPtrSetImpl
<
MachineInstr
*
>
&
SeenMIs
,
bool
PreferFalse
)
const
{
assert
(
(
MI
.
getOpcode
(
)
==
ARM
::
MOVCCr
||
MI
.
getOpcode
(
)
==
ARM
::
t2MOVCCr
)
&&
"Unknown select instruction"
)
;
MachineRegisterInfo
&
MRI
=
MI
.
getParent
(
)
->
getParent
(
)
->
getRegInfo
(
)
;
MachineInstr
*
DefMI
=
canFoldIntoMOVCC
(
MI
.
getOperand
(
2
)
.
getReg
(
)
,
MRI
,
this
)
;
bool
Invert
=
!
DefMI
;
if
(
!
DefMI
)
DefMI
=
canFoldIntoMOVCC
(
MI
.
getOperand
(
1
)
.
getReg
(
)
,
MRI
,
this
)
;
if
(
!
DefMI
)
return
nullptr
;
MachineOperand
FalseReg
=
MI
.
getOperand
(
Invert
2
:
1
)
;
Register
DestReg
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
const
TargetRegisterClass
*
PreviousClass
=
MRI
.
getRegClass
(
FalseReg
.
getReg
(
)
)
;
if
(
!
MRI
.
constrainRegClass
(
DestReg
,
PreviousClass
)
)
return
nullptr
;
MachineInstrBuilder
NewMI
=
BuildMI
(
*
MI
.
getParent
(
)
,
MI
,
MI
.
getDebugLoc
(
)
,
DefMI
->
getDesc
(
)
,
DestReg
)
;
const
MCInstrDesc
&
DefDesc
=
DefMI
->
getDesc
(
)
;
for
(
unsigned
i
=
1
,
e
=
DefDesc
.
getNumOperands
(
)
;
i
!=
e
&&
!
DefDesc
.
OpInfo
[
i
]
.
isPredicate
(
)
;
++
i
)
NewMI
.
add
(
DefMI
->
getOperand
(
i
)
)
;
unsigned
CondCode
=
MI
.
getOperand
(
3
)
.
getImm
(
)
;
if
(
Invert
)
NewMI
.
addImm
(
ARMCC
::
getOppositeCondition
(
ARMCC
::
CondCodes
(
CondCode
)
)
)
;
else
NewMI
.
addImm
(
CondCode
)
;
NewMI
.
add
(
MI
.
getOperand
(
4
)
)
;
if
(
NewMI
->
hasOptionalDef
(
)
)
NewMI
.
add
(
condCodeOp
(
)
)
;
FalseReg
.
setImplicit
(
)
;
NewMI
.
add
(
FalseReg
)
;
NewMI
->
tieOperands
(
0
,
NewMI
->
getNumOperands
(
)
1
)
;
SeenMIs
.
insert
(
NewMI
)
;
SeenMIs
.
erase
(
DefMI
)
;
if
(
DefMI
->
getParent
(
)
!=
MI
.
getParent
(
)
)
NewMI
->
clearKillInfo
(
)
;
DefMI
->
eraseFromParent
(
)
;
return
NewMI
;
}
</s>

Given a select instruction that was understood by analyzeSelect and returned Optimizable = true , attempt to optimize MI by merging it with one of its operands .


"if conversion tried to stop defining used CPSR"

Convert the instruction into a predicated instruction .


<s> unsigned ARMBaseInstrInfo :: predictBranchSizeForIfCvt ( MachineInstr & MI ) const { if ( MI . getOpcode ( ) == ARM :: t2Bcc && findCMPToFoldIntoCBZ ( & MI , & getRegisterInfo ( ) ) ) return 0 ; unsigned Size = getInstSizeInBytes ( MI ) ; if ( Subtarget . isThumb2 ( ) ) Size /= 2 ; return Size ; } </s>

Return an estimate for the code size reduction ( in bytes ) which will be caused by removing the given branch instruction during if-conversion .


<s> void ARMBaseInstrInfo :: reMaterialize ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator I , Register DestReg , unsigned SubIdx , const MachineInstr & Orig , const TargetRegisterInfo & TRI ) const { unsigned Opcode = Orig . getOpcode ( ) ; switch ( Opcode ) { default : { MachineInstr * MI = MBB . getParent ( ) -> CloneMachineInstr ( & Orig ) ; MI -> substituteRegister ( Orig . getOperand ( 0 ) . getReg ( ) , DestReg , SubIdx , TRI ) ; MBB . insert ( I , MI ) ; break ; } case ARM :: tLDRpci_pic : case ARM :: t2LDRpci_pic : { MachineFunction & MF = * MBB . getParent ( ) ; unsigned CPI = Orig . getOperand ( 1 ) . getIndex ( ) ; unsigned PCLabelId = duplicateCPV ( MF , CPI ) ; BuildMI ( MBB , I , Orig . getDebugLoc ( ) , get ( Opcode ) , DestReg ) . addConstantPoolIndex ( CPI ) . addImm ( PCLabelId ) . cloneMemRefs ( Orig ) ; break ; } } } </s>

Re-issue the specified 'original ' instruction at the specific location targeting a new destination register .


<s> bool ARMBaseInstrInfo :: shouldOutlineFromFunctionByDefault ( MachineFunction & MF ) const { return Subtarget . isMClass ( ) && MF . getFunction ( ) . hasMinSize ( ) ; } </s>

Return true if the function should be outlined from by default .


<s> bool ARMBaseInstrInfo :: shouldSink ( const MachineInstr & MI ) const { if ( isPredicated ( MI ) ) return true ; MachineBasicBlock :: const_iterator Next = & MI ; ++ Next ; Register SrcReg , SrcReg2 ; int64_t CmpMask , CmpValue ; bool IsThumb1 ; if ( Next != MI . getParent ( ) -> end ( ) && analyzeCompare ( * Next , SrcReg , SrcReg2 , CmpMask , CmpValue ) && isRedundantFlagInstr ( & * Next , SrcReg , SrcReg2 , CmpValue , & MI , IsThumb1 ) ) return false ; return true ; } </s>

Return true if the instruction should be sunk by MachineSink .


"Pseudo flag setting opcodes only exist in Selection DAG"

"Non-flag-setting Thumb1 mov is v6-only"

"Unsupported register in Thumb1 push/pop"

"Incorrect array index for MVE_VMOV_q_rr"

Perform target-specific instruction verification .


<s>
MachineInstr
*
ARMBaseInstrInfo
::
optimizeSelect
(
MachineInstr
*
MI
,
SmallPtrSetImpl
<
MachineInstr
*
>
&
SeenMIs
,
bool
PreferFalse
)
const
{
assert
(
(
MI
->
getOpcode
(
)
==
ARM
::
MOVCCr
||
MI
->
getOpcode
(
)
==
ARM
::
t2MOVCCr
)
&&
"Unknown select instruction"
)
;
MachineRegisterInfo
&
MRI
=
MI
->
getParent
(
)
->
getParent
(
)
->
getRegInfo
(
)
;
MachineInstr
*
DefMI
=
canFoldIntoMOVCC
(
MI
->
getOperand
(
2
)
.
getReg
(
)
,
MRI
,
this
)
;
bool
Invert
=
!
DefMI
;
if
(
!
DefMI
)
DefMI
=
canFoldIntoMOVCC
(
MI
->
getOperand
(
1
)
.
getReg
(
)
,
MRI
,
this
)
;
if
(
!
DefMI
)
return
nullptr
;
MachineOperand
FalseReg
=
MI
->
getOperand
(
Invert
2
:
1
)
;
unsigned
DestReg
=
MI
->
getOperand
(
0
)
.
getReg
(
)
;
const
TargetRegisterClass
*
PreviousClass
=
MRI
.
getRegClass
(
FalseReg
.
getReg
(
)
)
;
if
(
!
MRI
.
constrainRegClass
(
DestReg
,
PreviousClass
)
)
return
nullptr
;
MachineInstrBuilder
NewMI
=
BuildMI
(
*
MI
->
getParent
(
)
,
MI
,
MI
->
getDebugLoc
(
)
,
DefMI
->
getDesc
(
)
,
DestReg
)
;
const
MCInstrDesc
&
DefDesc
=
DefMI
->
getDesc
(
)
;
for
(
unsigned
i
=
1
,
e
=
DefDesc
.
getNumOperands
(
)
;
i
!=
e
&&
!
DefDesc
.
OpInfo
[
i
]
.
isPredicate
(
)
;
++
i
)
NewMI
.
addOperand
(
DefMI
->
getOperand
(
i
)
)
;
unsigned
CondCode
=
MI
->
getOperand
(
3
)
.
getImm
(
)
;
if
(
Invert
)
NewMI
.
addImm
(
ARMCC
::
getOppositeCondition
(
ARMCC
::
CondCodes
(
CondCode
)
)
)
;
else
NewMI
.
addImm
(
CondCode
)
;
NewMI
.
addOperand
(
MI
->
getOperand
(
4
)
)
;
if
(
NewMI
->
hasOptionalDef
(
)
)
AddDefaultCC
(
NewMI
)
;
FalseReg
.
setImplicit
(
)
;
NewMI
.
addOperand
(
FalseReg
)
;
NewMI
->
tieOperands
(
0
,
NewMI
->
getNumOperands
(
)
1
)
;
SeenMIs
.
insert
(
NewMI
)
;
SeenMIs
.
erase
(
DefMI
)
;
DefMI
->
eraseFromParent
(
)
;
return
NewMI
;
}
</s>


<s> MachineInstr * ARMBaseInstrInfo :: foldMemoryOperandImpl ( MachineFunction & MF , MachineInstr * MI , const SmallVectorImpl < unsigned > & Ops , MachineInstr * LoadMI ) const { return 0 ; } </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> unsigned ARMBaseInstrInfo :: isLoadFromStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { default : break ; case ARM :: LDR : case ARM :: t2LDRs : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isReg ( ) && MI -> getOperand ( 3 ) . isImm ( ) && MI -> getOperand ( 2 ) . getReg ( ) == 0 && MI -> getOperand ( 3 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: t2LDRi12 : case ARM :: tRestore : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) && MI -> getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VLDRD : case ARM :: VLDRS : if ( 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>


<s> unsigned ARMBaseInstrInfo :: isStoreToStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { default : break ; case ARM :: STR : case ARM :: t2STRs : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isReg ( ) && MI -> getOperand ( 3 ) . isImm ( ) && MI -> getOperand ( 2 ) . getReg ( ) == 0 && MI -> getOperand ( 3 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: t2STRi12 : case ARM :: tSpill : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) && MI -> getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VSTRD : case ARM :: VSTRS : if ( 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>


<s>
void
ARMBaseInstrInfo
::
loadRegFromStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
unsigned
DestReg
,
int
FI
,
const
TargetRegisterClass
*
RC
)
const
{
DebugLoc
DL
=
DebugLoc
::
getUnknownLoc
(
)
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
MachineFrameInfo
&
MFI
=
*
MF
.
getFrameInfo
(
)
;
unsigned
Align
=
MFI
.
getObjectAlignment
(
FI
)
;
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
PseudoSourceValue
::
getFixedStack
(
FI
)
,
MachineMemOperand
::
MOLoad
,
0
,
MFI
.
getObjectSize
(
FI
)
,
Align
)
;
if
(
RC
==
ARM
::
tGPRRegisterClass
)
RC
=
ARM
::
GPRRegisterClass
;
if
(
RC
==
ARM
::
GPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
LDR
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addReg
(
0
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
DPRRegisterClass
||
RC
==
ARM
::
DPR_VFP2RegisterClass
||
RC
==
ARM
::
DPR_8RegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLDRD
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
SPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLDRS
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
{
assert
(
(
RC
==
ARM
::
QPRRegisterClass
||
RC
==
ARM
::
QPR_VFP2RegisterClass
||
RC
==
ARM
::
QPR_8RegisterClass
)
&&
"Unknown regclass!"
)
;
if
(
Align
>=
16
&&
(
getRegisterInfo
(
)
.
canRealignStack
(
MF
)
)
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLD1q64
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addImm
(
0
)
.
addImm
(
128
)
.
addMemOperand
(
MMO
)
)
;
}
else
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLDRQ
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
}
}
</s>

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


<s> bool ARMBaseInstrInfo :: produceSameValue ( const MachineInstr * MI0 , const MachineInstr * MI1 ) const { int Opcode = MI0 -> getOpcode ( ) ; if ( Opcode == ARM :: t2LDRpci || Opcode == ARM :: t2LDRpci_pic || Opcode == ARM :: tLDRpci || Opcode == ARM :: tLDRpci_pic ) { if ( MI1 -> getOpcode ( ) != Opcode ) return false ; if ( MI0 -> getNumOperands ( ) != MI1 -> getNumOperands ( ) ) return false ; const MachineOperand & MO0 = MI0 -> getOperand ( 1 ) ; const MachineOperand & MO1 = MI1 -> getOperand ( 1 ) ; if ( MO0 . getOffset ( ) != MO1 . getOffset ( ) ) return false ; const MachineFunction * MF = MI0 -> getParent ( ) -> getParent ( ) ; const MachineConstantPool * MCP = MF -> getConstantPool ( ) ; int CPI0 = MO0 . getIndex ( ) ; int CPI1 = MO1 . getIndex ( ) ; const MachineConstantPoolEntry & MCPE0 = MCP -> getConstants ( ) [ CPI0 ] ; const MachineConstantPoolEntry & MCPE1 = MCP -> getConstants ( ) [ CPI1 ] ; ARMConstantPoolValue * ACPV0 = static_cast < ARMConstantPoolValue * > ( MCPE0 . Val . MachineCPVal ) ; ARMConstantPoolValue * ACPV1 = static_cast < ARMConstantPoolValue * > ( MCPE1 . Val . MachineCPVal ) ; return ACPV0 -> hasSameValue ( ACPV1 ) ; } return MI0 -> isIdenticalTo ( MI1 , MachineInstr :: IgnoreVRegDefs ) ; } </s>

Return true if two machine instructions would produce identical values .


<s> void ARMBaseInstrInfo :: reMaterialize ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator I , unsigned DestReg , unsigned SubIdx , const MachineInstr * Orig , const TargetRegisterInfo * TRI ) const { if ( SubIdx && TargetRegisterInfo :: isPhysicalRegister ( DestReg ) ) { DestReg = TRI -> getSubReg ( DestReg , SubIdx ) ; SubIdx = 0 ; } unsigned Opcode = Orig -> getOpcode ( ) ; switch ( Opcode ) { default : { MachineInstr * MI = MBB . getParent ( ) -> CloneMachineInstr ( Orig ) ; MI -> getOperand ( 0 ) . setReg ( DestReg ) ; MBB . insert ( I , MI ) ; break ; } case ARM :: tLDRpci_pic : case ARM :: t2LDRpci_pic : { MachineFunction & MF = * MBB . getParent ( ) ; unsigned CPI = Orig -> getOperand ( 1 ) . getIndex ( ) ; unsigned PCLabelId = duplicateCPV ( MF , CPI ) ; MachineInstrBuilder MIB = BuildMI ( MBB , I , Orig -> getDebugLoc ( ) , get ( Opcode ) , DestReg ) . addConstantPoolIndex ( CPI ) . addImm ( PCLabelId ) ; ( * MIB ) . setMemRefs ( Orig -> memoperands_begin ( ) , Orig -> memoperands_end ( ) ) ; break ; } } MachineInstr * NewMI = prior ( I ) ; NewMI -> getOperand ( 0 ) . setSubReg ( SubIdx ) ; } </s>


<s>
void
ARMBaseInstrInfo
::
storeRegToStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
unsigned
SrcReg
,
bool
isKill
,
int
FI
,
const
TargetRegisterClass
*
RC
)
const
{
DebugLoc
DL
=
DebugLoc
::
getUnknownLoc
(
)
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
MachineFrameInfo
&
MFI
=
*
MF
.
getFrameInfo
(
)
;
unsigned
Align
=
MFI
.
getObjectAlignment
(
FI
)
;
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
PseudoSourceValue
::
getFixedStack
(
FI
)
,
MachineMemOperand
::
MOStore
,
0
,
MFI
.
getObjectSize
(
FI
)
,
Align
)
;
if
(
RC
==
ARM
::
tGPRRegisterClass
)
RC
=
ARM
::
GPRRegisterClass
;
if
(
RC
==
ARM
::
GPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
STR
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addReg
(
0
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
DPRRegisterClass
||
RC
==
ARM
::
DPR_VFP2RegisterClass
||
RC
==
ARM
::
DPR_8RegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VSTRD
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
SPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VSTRS
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
{
assert
(
(
RC
==
ARM
::
QPRRegisterClass
||
RC
==
ARM
::
QPR_VFP2RegisterClass
)
&&
"Unknown regclass!"
)
;
if
(
Align
>=
16
&&
(
getRegisterInfo
(
)
.
canRealignStack
(
MF
)
)
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VST1q64
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addImm
(
0
)
.
addImm
(
128
)
.
addMemOperand
(
MMO
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
)
;
}
else
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VSTRQ
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
}
}
</s>

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


<s>
bool
ARMBaseInstrInfo
::
analyzeBranch
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
*
&
TBB
,
MachineBasicBlock
*
&
FBB
,
SmallVectorImpl
<
MachineOperand
>
&
Cond
,
bool
AllowModify
)
const
{
TBB
=
nullptr
;
FBB
=
nullptr
;
MachineBasicBlock
::
instr_iterator
I
=
MBB
.
instr_end
(
)
;
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
while
(
isPredicated
(
*
I
)
||
I
->
isTerminator
(
)
||
I
->
isDebugValue
(
)
)
{
bool
CantAnalyze
=
false
;
while
(
I
->
isDebugInstr
(
)
||
!
I
->
isTerminator
(
)
)
{
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
}
if
(
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
CantAnalyze
=
true
;
}
else
if
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
}
else
if
(
isCondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
if
(
!
Cond
.
empty
(
)
)
return
true
;
assert
(
!
FBB
&&
"FBB should have been null."
)
;
FBB
=
TBB
;
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
Cond
.
push_back
(
I
->
getOperand
(
1
)
)
;
Cond
.
push_back
(
I
->
getOperand
(
2
)
)
;
}
else
if
(
I
->
isReturn
(
)
)
{
CantAnalyze
=
true
;
}
else
{
return
true
;
}
if
(
!
isPredicated
(
*
I
)
&&
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
||
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
||
I
->
isReturn
(
)
)
)
{
Cond
.
clear
(
)
;
FBB
=
nullptr
;
if
(
AllowModify
)
{
MachineBasicBlock
::
iterator
DI
=
std
::
next
(
I
)
;
while
(
DI
!=
MBB
.
instr_end
(
)
)
{
MachineInstr
&
InstToDelete
=
*
DI
;
++
DI
;
InstToDelete
.
eraseFromParent
(
)
;
}
}
}
if
(
CantAnalyze
)
{
if
(
AllowModify
&&
!
isPredicated
(
MBB
.
back
(
)
)
&&
isUncondBranchOpcode
(
MBB
.
back
(
)
.
getOpcode
(
)
)
&&
TBB
&&
MBB
.
isLayoutSuccessor
(
TBB
)
)
removeBranch
(
MBB
)
;
return
true
;
}
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
}
return
false
;
}
</s>

analyzeBranch - Analyze the branching code at the end of MBB , returning true if it can not be understood ( e.g .


<s> bool ARMBaseInstrInfo :: analyzeCompare ( const MachineInstr & MI , Register & SrcReg , Register & SrcReg2 , int & CmpMask , int & CmpValue ) const { switch ( MI . getOpcode ( ) ) { default : break ; case ARM :: CMPri : case ARM :: t2CMPri : case ARM :: tCMPi8 : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = ~ 0 ; CmpValue = MI . getOperand ( 1 ) . getImm ( ) ; return true ; case ARM :: CMPrr : case ARM :: t2CMPrr : case ARM :: tCMPr : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = MI . getOperand ( 1 ) . getReg ( ) ; CmpMask = ~ 0 ; CmpValue = 0 ; return true ; case ARM :: TSTri : case ARM :: t2TSTri : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = MI . getOperand ( 1 ) . getImm ( ) ; CmpValue = 0 ; 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> void ARMBaseInstrInfo :: buildOutlinedFrame ( MachineBasicBlock & MBB , MachineFunction & MF , const outliner :: OutlinedFunction & OF ) const { if ( OF . FrameConstructionID == MachineOutlinerThunk ) { MachineInstr * Call = & * -- MBB . instr_end ( ) ; bool isThumb = Subtarget . isThumb ( ) ; unsigned FuncOp = isThumb ? 2 : 0 ; unsigned Opc = Call -> getOperand ( FuncOp ) . isReg ( ) ? isThumb ? ARM :: tTAILJMPr : ARM :: TAILJMPr : isThumb ? Subtarget . isTargetMachO ( ) ? ARM :: tTAILJMPd : ARM :: tTAILJMPdND : ARM :: TAILJMPd ; MachineInstrBuilder MIB = BuildMI ( MBB , MBB . end ( ) , DebugLoc ( ) , get ( Opc ) ) . add ( Call -> getOperand ( FuncOp ) ) ; if ( isThumb && ! Call -> getOperand ( FuncOp ) . isReg ( ) ) MIB . add ( predOps ( ARMCC :: AL ) ) ; Call -> eraseFromParent ( ) ; } auto IsNonTailCall = [ ] ( MachineInstr & MI ) { return MI . isCall ( ) && ! MI . isReturn ( ) ; } ; if ( std :: any_of ( MBB . instr_begin ( ) , MBB . instr_end ( ) , IsNonTailCall ) ) { MachineBasicBlock :: iterator It = MBB . begin ( ) ; MachineBasicBlock :: iterator Et = MBB . end ( ) ; if ( OF . FrameConstructionID == MachineOutlinerTailCall || OF . FrameConstructionID == MachineOutlinerThunk ) Et = std :: prev ( MBB . end ( ) ) ; if ( ! MBB . isLiveIn ( ARM :: LR ) ) MBB . addLiveIn ( ARM :: LR ) ; saveLROnStack ( MBB , It ) ; unsigned StackAlignment = Subtarget . getStackAlignment ( ) . value ( ) ; const TargetSubtargetInfo & STI = MF . getSubtarget ( ) ; const MCRegisterInfo * MRI = STI . getRegisterInfo ( ) ; unsigned DwarfReg = MRI -> getDwarfRegNum ( ARM :: LR , true ) ; int64_t StackPosEntry = MF . addFrameInst ( MCCFIInstruction :: cfiDefCfaOffset ( nullptr , StackAlignment ) ) ; BuildMI ( MBB , It , DebugLoc ( ) , get ( ARM :: CFI_INSTRUCTION ) ) . addCFIIndex ( StackPosEntry ) . setMIFlags ( MachineInstr :: FrameSetup ) ; int64_t LRPosEntry = MF . addFrameInst ( MCCFIInstruction :: createOffset ( nullptr , DwarfReg , StackAlignment ) ) ; BuildMI ( MBB , It , DebugLoc ( ) , get ( ARM :: CFI_INSTRUCTION ) ) . addCFIIndex ( LRPosEntry ) . setMIFlags ( MachineInstr :: FrameSetup ) ; restoreLRFromStack ( MBB , Et ) ; } if ( OF . FrameConstructionID == MachineOutlinerTailCall || OF . FrameConstructionID == MachineOutlinerThunk ) return ; BuildMI ( MBB , MBB . end ( ) , DebugLoc ( ) , get ( Subtarget . getReturnOpcode ( ) ) ) . add ( predOps ( ARMCC :: AL ) ) ; } </s>

Insert a custom frame for outlined functions .

ARM ARM 2 0 ARM::tTAILJMPr ARM::TAILJMPr ARM::tTAILJMPd ARM::tTAILJMPdND ARM::TAILJMPd ARMCC::AL ARM::LR ARM::LR ARM::LR ARM::CFI_INSTRUCTION ARM::CFI_INSTRUCTION ARMCC::AL


<s> ScheduleHazardRecognizer * ARMBaseInstrInfo :: CreateTargetPostRAHazardRecognizer ( const InstrItineraryData * II , const ScheduleDAG * DAG ) const { if ( Subtarget . isThumb2 ( ) || Subtarget . hasVFP2Base ( ) ) return new ARMHazardRecognizer ( II , DAG ) ; return TargetInstrInfo :: CreateTargetPostRAHazardRecognizer ( II , DAG ) ; } </s>

Allocate and return a hazard recognizer to use for by non-scheduling passes .


<s>
MachineBasicBlock
::
iterator
ARMBaseInstrInfo
::
insertOutlinedCall
(
Module
&
M
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
&
It
,
MachineFunction
&
MF
,
const
outliner
::
Candidate
&
C
)
const
{
MachineInstrBuilder
MIB
;
MachineBasicBlock
::
iterator
CallPt
;
unsigned
Opc
;
bool
isThumb
=
Subtarget
.
isThumb
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerTailCall
)
{
Opc
=
isThumb
Subtarget
.
isTargetMachO
(
)
ARM
::
tTAILJMPd
:
ARM
::
tTAILJMPdND
:
ARM
::
TAILJMPd
;
MIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
isThumb
)
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
It
=
MBB
.
insert
(
It
,
MIB
)
;
return
It
;
}
Opc
=
isThumb
ARM
::
tBL
:
ARM
::
BL
;
MachineInstrBuilder
CallMIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
;
if
(
isThumb
)
CallMIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
CallMIB
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerNoLRSave
||
C
.
CallConstructionID
==
MachineOutlinerThunk
)
{
It
=
MBB
.
insert
(
It
,
CallMIB
)
;
return
It
;
}
if
(
C
.
CallConstructionID
==
MachineOutlinerRegSave
)
{
unsigned
Reg
=
findRegisterToSaveLRTo
(
C
)
;
assert
(
Reg
!=
0
&&
"No callee-saved register available?"
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
Reg
,
ARM
::
LR
,
true
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
ARM
::
LR
,
Reg
,
true
)
;
It
;
return
CallPt
;
}
saveLROnStack
(
MBB
,
It
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
restoreLRFromStack
(
MBB
,
It
)
;
It
;
return
CallPt
;
}
</s>

Insert a call to an outlined function into the program .

ARM
ARM
ARM::tTAILJMPd
ARM::tTAILJMPdND
ARM::TAILJMPd
ARMCC::AL
ARM::tBL
ARM::BL
ARMCC::AL
0
"No callee-saved register available?"
ARM::LR
ARM::LR


"Suitable Machine Function for outlining must track liveness"

Optional target hook that returns true if MBB is safe to outline from , and returns any target-specific information in Flags .


<s> bool ARMBaseInstrInfo :: shouldSink ( const MachineInstr & MI ) const { if ( isPredicated ( MI ) ) return true ; MachineBasicBlock :: const_iterator Next = & MI ; ++ Next ; Register SrcReg , SrcReg2 ; int CmpMask , CmpValue ; bool IsThumb1 ; if ( Next != MI . getParent ( ) -> end ( ) && analyzeCompare ( * Next , SrcReg , SrcReg2 , CmpMask , CmpValue ) && isRedundantFlagInstr ( & * Next , SrcReg , SrcReg2 , CmpValue , & MI , IsThumb1 ) ) return false ; return true ; } </s>


"Pseudo flag setting opcodes only exist in Selection DAG"

"Non-flag-setting Thumb1 mov is v6-only"

"Unsupported register in Thumb1 push/pop"


<s>
void
ARMBaseInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
DebugLoc
DL
,
unsigned
DestReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
bool
GPRDest
=
ARM
::
GPRRegClass
.
contains
(
DestReg
)
;
bool
GPRSrc
=
ARM
::
GPRRegClass
.
contains
(
SrcReg
)
;
if
(
GPRDest
&&
GPRSrc
)
{
AddDefaultCC
(
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
MOVr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
)
)
;
return
;
}
bool
SPRDest
=
ARM
::
SPRRegClass
.
contains
(
DestReg
)
;
bool
SPRSrc
=
ARM
::
SPRRegClass
.
contains
(
SrcReg
)
;
unsigned
Opc
;
if
(
SPRDest
&&
SPRSrc
)
Opc
=
ARM
::
VMOVS
;
else
if
(
GPRDest
&&
SPRSrc
)
Opc
=
ARM
::
VMOVRS
;
else
if
(
SPRDest
&&
GPRSrc
)
Opc
=
ARM
::
VMOVSR
;
else
if
(
ARM
::
DPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
Opc
=
ARM
::
VMOVD
;
else
if
(
ARM
::
QPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
Opc
=
ARM
::
VMOVQ
;
else
if
(
ARM
::
QQPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
Opc
=
ARM
::
VMOVQQ
;
else
if
(
ARM
::
QQQQPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
Opc
=
ARM
::
VMOVQQQQ
;
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
MachineInstrBuilder
MIB
=
BuildMI
(
MBB
,
I
,
DL
,
get
(
Opc
)
,
DestReg
)
;
MIB
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
if
(
Opc
!=
ARM
::
VMOVQQ
&&
Opc
!=
ARM
::
VMOVQQQQ
)
AddDefaultPred
(
MIB
)
;
}
</s>

ARM
ARM
ARM::GPRRegClass
ARM::GPRRegClass
ARM::MOVr
ARM::SPRRegClass
ARM::SPRRegClass
ARM::VMOVS
ARM::VMOVRS
ARM::VMOVSR
ARM::DPRRegClass
ARM::VMOVD
ARM::QPRRegClass
ARM::VMOVQ
ARM::QQPRRegClass
ARM::VMOVQQ
ARM::QQQQPRRegClass
ARM::VMOVQQQQ
"Impossible reg-to-reg copy"
ARM::VMOVQQ
ARM::VMOVQQQQ


<s> int ARMBaseInstrInfo :: getInstrLatency ( const InstrItineraryData * ItinData , SDNode * Node ) const { if ( ! Node -> isMachineOpcode ( ) ) return 1 ; if ( ! ItinData || ItinData -> isEmpty ( ) ) return 1 ; unsigned Opcode = Node -> getMachineOpcode ( ) ; switch ( Opcode ) { default : return ItinData -> getStageLatency ( get ( Opcode ) . getSchedClass ( ) ) ; case ARM :: VLDMQIA : case ARM :: VLDMQDB : case ARM :: VSTMQIA : case ARM :: VSTMQDB : return 2 ; } } </s>

Compute the instruction latency of a given instruction .

ARM ARM 1 1 ARM::VLDMQIA ARM::VLDMQDB ARM::VSTMQIA ARM::VSTMQDB 2


<s> int ARMBaseInstrInfo :: getOperandLatency ( const InstrItineraryData * ItinData , SDNode * DefNode , unsigned DefIdx , SDNode * UseNode , unsigned UseIdx ) const { if ( ! DefNode -> isMachineOpcode ( ) ) return 1 ; const TargetInstrDesc & DefTID = get ( DefNode -> getMachineOpcode ( ) ) ; if ( isZeroCost ( DefTID . Opcode ) ) return 0 ; if ( ! ItinData || ItinData -> isEmpty ( ) ) return DefTID . mayLoad ( ) ? 3 : 1 ; if ( ! UseNode -> isMachineOpcode ( ) ) { int Latency = ItinData -> getOperandCycle ( DefTID . getSchedClass ( ) , DefIdx ) ; if ( Subtarget . isCortexA9 ( ) ) return Latency <= 2 ? 1 : Latency - 1 ; else return Latency <= 3 ? 1 : Latency - 2 ; } const TargetInstrDesc & UseTID = get ( UseNode -> getMachineOpcode ( ) ) ; const MachineSDNode * DefMN = dyn_cast < MachineSDNode > ( DefNode ) ; unsigned DefAlign = ! DefMN -> memoperands_empty ( ) ? ( * DefMN -> memoperands_begin ( ) ) -> getAlignment ( ) : 0 ; const MachineSDNode * UseMN = dyn_cast < MachineSDNode > ( UseNode ) ; unsigned UseAlign = ! UseMN -> memoperands_empty ( ) ? ( * UseMN -> memoperands_begin ( ) ) -> getAlignment ( ) : 0 ; int Latency = getOperandLatency ( ItinData , DefTID , DefIdx , DefAlign , UseTID , UseIdx , UseAlign ) ; if ( Latency > 1 && ( Subtarget . isCortexA8 ( ) || Subtarget . isCortexA9 ( ) ) ) { switch ( DefTID . getOpcode ( ) ) { default : break ; case ARM :: LDRrs : case ARM :: LDRBrs : { unsigned ShOpVal = cast < ConstantSDNode > ( DefNode -> getOperand ( 2 ) ) -> getZExtValue ( ) ; unsigned ShImm = ARM_AM :: getAM2Offset ( ShOpVal ) ; if ( ShImm == 0 || ( ShImm == 2 && ARM_AM :: getAM2ShiftOpc ( ShOpVal ) == ARM_AM :: lsl ) ) -- Latency ; break ; } case ARM :: t2LDRs : case ARM :: t2LDRBs : case ARM :: t2LDRHs : case ARM :: t2LDRSHs : { unsigned ShAmt = cast < ConstantSDNode > ( DefNode -> getOperand ( 2 ) ) -> getZExtValue ( ) ; if ( ShAmt == 0 || ShAmt == 2 ) -- Latency ; break ; } } } return Latency ; } </s>

Compute and return the use operand latency of a given pair of def and use .


<s> unsigned ARMBaseInstrInfo :: isLoadFromStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { default : break ; case ARM :: LDRrs : case ARM :: t2LDRs : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isReg ( ) && MI -> getOperand ( 3 ) . isImm ( ) && MI -> getOperand ( 2 ) . getReg ( ) == 0 && MI -> getOperand ( 3 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: LDRi12 : case ARM :: t2LDRi12 : case ARM :: tRestore : case ARM :: VLDRD : case ARM :: VLDRS : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) && MI -> getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VLD1q64Pseudo : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 0 ) . getSubReg ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VLDMQIA : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 0 ) . getSubReg ( ) == 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> bool ARMBaseInstrInfo :: isPredicable ( MachineInstr * MI ) const { const TargetInstrDesc & TID = MI -> getDesc ( ) ; if ( ! TID . isPredicable ( ) ) return false ; if ( ( TID . TSFlags & ARMII :: DomainMask ) == ARMII :: DomainNEON ) { ARMFunctionInfo * AFI = MI -> getParent ( ) -> getParent ( ) -> getInfo < ARMFunctionInfo > ( ) ; return AFI -> isThumb2Function ( ) ; } return true ; } </s>

Return true if the specified instruction can be predicated .

ARM ARM ARMII::DomainMask ARMII::DomainNEON ARM ARM


<s> virtual bool isProfitableToDupForIfCvt ( MachineBasicBlock & MBB , unsigned NumCycles , const BranchProbability & Probability ) const { return NumCycles == 1 ; } </s>

Return true if it 's profitable for if-converter to duplicate instructions of specified accumulated instruction latencies in the specified MBB to enable if-conversion .


<s> bool ARMBaseInstrInfo :: isProfitableToIfCvt ( MachineBasicBlock & TMBB , unsigned TCycles , unsigned TExtra , MachineBasicBlock & FMBB , unsigned FCycles , unsigned FExtra , float Probability , float Confidence ) const { if ( ! TCycles || ! FCycles ) return false ; float UnpredCost = Probability * TCycles + ( 1.0 - Probability ) * FCycles ; UnpredCost += 1.0 ; UnpredCost += ( 1.0 - Confidence ) * Subtarget . getMispredictionPenalty ( ) ; return ( float ) ( TCycles + FCycles + TExtra + FExtra ) < UnpredCost ; } </s>


<s> unsigned ARMBaseInstrInfo :: isStoreToStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { default : break ; case ARM :: STRrs : case ARM :: t2STRs : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isReg ( ) && MI -> getOperand ( 3 ) . isImm ( ) && MI -> getOperand ( 2 ) . getReg ( ) == 0 && MI -> getOperand ( 3 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: STRi12 : case ARM :: t2STRi12 : case ARM :: tSpill : case ARM :: VSTRD : case ARM :: VSTRS : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 2 ) . isImm ( ) && MI -> getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; case ARM :: VST1q64Pseudo : if ( MI -> getOperand ( 0 ) . isFI ( ) && MI -> getOperand ( 2 ) . getSubReg ( ) == 0 ) { FrameIndex = MI -> getOperand ( 0 ) . getIndex ( ) ; return MI -> getOperand ( 2 ) . getReg ( ) ; } break ; case ARM :: VSTMQIA : if ( MI -> getOperand ( 1 ) . isFI ( ) && MI -> getOperand ( 0 ) . getSubReg ( ) == 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 ARMBaseInstrInfo :: reMaterialize ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator I , unsigned DestReg , unsigned SubIdx , const MachineInstr * Orig , const TargetRegisterInfo & TRI ) const { unsigned Opcode = Orig -> getOpcode ( ) ; switch ( Opcode ) { default : { MachineInstr * MI = MBB . getParent ( ) -> CloneMachineInstr ( Orig ) ; MI -> substituteRegister ( Orig -> getOperand ( 0 ) . getReg ( ) , DestReg , SubIdx , TRI ) ; MBB . insert ( I , MI ) ; break ; } case ARM :: tLDRpci_pic : case ARM :: t2LDRpci_pic : { MachineFunction & MF = * MBB . getParent ( ) ; unsigned CPI = Orig -> getOperand ( 1 ) . getIndex ( ) ; unsigned PCLabelId = duplicateCPV ( MF , CPI ) ; MachineInstrBuilder MIB = BuildMI ( MBB , I , Orig -> getDebugLoc ( ) , get ( Opcode ) , DestReg ) . addConstantPoolIndex ( CPI ) . addImm ( PCLabelId ) ; ( * MIB ) . setMemRefs ( Orig -> memoperands_begin ( ) , Orig -> memoperands_end ( ) ) ; break ; } } } </s>

Re-issue the specified 'original ' instruction at the specific location targeting a new destination register .


<s> MachineInstr * ARMBaseInstrInfo :: commuteInstructionImpl ( MachineInstr * MI , bool NewMI , unsigned OpIdx1 , unsigned OpIdx2 ) const { switch ( MI -> getOpcode ( ) ) { case ARM :: MOVCCr : case ARM :: t2MOVCCr : { unsigned PredReg = 0 ; ARMCC :: CondCodes CC = getInstrPredicate ( * MI , PredReg ) ; if ( CC == ARMCC :: AL || PredReg != ARM :: CPSR ) return nullptr ; MI = TargetInstrInfo :: commuteInstructionImpl ( MI , NewMI , OpIdx1 , OpIdx2 ) ; if ( ! MI ) return nullptr ; MI -> getOperand ( MI -> findFirstPredOperandIdx ( ) ) . setImm ( ARMCC :: getOppositeCondition ( CC ) ) ; return MI ; } } return TargetInstrInfo :: commuteInstructionImpl ( MI , NewMI , OpIdx1 , OpIdx2 ) ; } </s>

Commutes the operands in the given instruction by changing the operands order and/or changing the instruction 's opcode and/or the immediate value operand .

ARM ARM ARM::MOVCCr ARM::t2MOVCCr 0 ARMCC::CondCodes ARMCC::AL ARM::CPSR ARMCC::getOppositeCondition


<s> std :: pair < uint16_t , uint16_t > ARMBaseInstrInfo :: getExecutionDomain ( const MachineInstr * MI ) const { if ( Subtarget . hasNEON ( ) ) { if ( MI -> getOpcode ( ) == ARM :: VMOVD && ! isPredicated ( * MI ) ) return std :: make_pair ( ExeVFP , ( 1 << ExeVFP ) | ( 1 << ExeNEON ) ) ; if ( Subtarget . isCortexA9 ( ) && ! isPredicated ( * MI ) && ( MI -> getOpcode ( ) == ARM :: VMOVRS || MI -> getOpcode ( ) == ARM :: VMOVSR || MI -> getOpcode ( ) == ARM :: VMOVS ) ) return std :: make_pair ( ExeVFP , ( 1 << ExeVFP ) | ( 1 << ExeNEON ) ) ; } unsigned Domain = MI -> getDesc ( ) . TSFlags & ARMII :: DomainMask ; if ( Domain & ARMII :: DomainNEON ) return std :: make_pair ( ExeNEON , 0 ) ; if ( ( Domain & ARMII :: DomainNEONA8 ) && Subtarget . isCortexA8 ( ) ) return std :: make_pair ( ExeNEON , 0 ) ; if ( Domain & ARMII :: DomainVFP ) return std :: make_pair ( ExeVFP , 0 ) ; return std :: make_pair ( ExeGeneric , 0 ) ; } </s>

Return the current execution domain and bit mask of possible domains for instruction .


<s> unsigned ARMBaseInstrInfo :: extraSizeToPredicateInstructions ( const MachineFunction & MF , unsigned NumInsts ) const { return Subtarget . isThumb2 ( ) ? divideCeil ( NumInsts , 4 ) * 2 : 0 ; } </s>

Return the increase in code size needed to predicate a contiguous run of NumInsts instructions .


<s> void ARMBaseInstrInfo :: buildOutlinedFrame ( MachineBasicBlock & MBB , MachineFunction & MF , const outliner :: OutlinedFunction & OF ) const { if ( OF . FrameConstructionID == MachineOutlinerTailCall ) return ; if ( OF . FrameConstructionID == MachineOutlinerThunk ) { MachineInstr * Call = & * -- MBB . instr_end ( ) ; bool isThumb = Subtarget . isThumb ( ) ; unsigned FuncOp = isThumb ? 2 : 0 ; unsigned Opc = Call -> getOperand ( FuncOp ) . isReg ( ) ? isThumb ? ARM :: tTAILJMPr : ARM :: TAILJMPr : isThumb ? Subtarget . isTargetMachO ( ) ? ARM :: tTAILJMPd : ARM :: tTAILJMPdND : ARM :: TAILJMPd ; MachineInstrBuilder MIB = BuildMI ( MBB , MBB . end ( ) , DebugLoc ( ) , get ( Opc ) ) . add ( Call -> getOperand ( FuncOp ) ) ; if ( isThumb && ! Call -> getOperand ( FuncOp ) . isReg ( ) ) MIB . add ( predOps ( ARMCC :: AL ) ) ; Call -> eraseFromParent ( ) ; return ; } BuildMI ( MBB , MBB . end ( ) , DebugLoc ( ) , get ( Subtarget . getReturnOpcode ( ) ) ) . add ( predOps ( ARMCC :: AL ) ) ; } </s>

ARM ARM 2 0 ARM::tTAILJMPr ARM::TAILJMPr ARM::tTAILJMPd ARM::tTAILJMPdND ARM::TAILJMPd ARMCC::AL ARMCC::AL


<s>
MachineBasicBlock
::
iterator
ARMBaseInstrInfo
::
insertOutlinedCall
(
Module
&
M
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
&
It
,
MachineFunction
&
MF
,
const
outliner
::
Candidate
&
C
)
const
{
MachineInstrBuilder
MIB
;
MachineBasicBlock
::
iterator
CallPt
;
unsigned
Opc
;
bool
isThumb
=
Subtarget
.
isThumb
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerTailCall
)
{
Opc
=
isThumb
Subtarget
.
isTargetMachO
(
)
ARM
::
tTAILJMPd
:
ARM
::
tTAILJMPdND
:
ARM
::
TAILJMPd
;
MIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
isThumb
)
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
It
=
MBB
.
insert
(
It
,
MIB
)
;
return
It
;
}
Opc
=
isThumb
ARM
::
tBL
:
ARM
::
BL
;
MachineInstrBuilder
CallMIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
;
if
(
isThumb
)
CallMIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
CallMIB
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerRegSave
)
{
unsigned
Reg
=
findRegisterToSaveLRTo
(
C
)
;
assert
(
Reg
!=
0
&&
"No callee-saved register available?"
)
;
if
(
!
MBB
.
isLiveIn
(
ARM
::
LR
)
)
MBB
.
addLiveIn
(
ARM
::
LR
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
Reg
,
ARM
::
LR
,
true
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
ARM
::
LR
,
Reg
,
true
)
;
It
;
return
CallPt
;
}
It
=
MBB
.
insert
(
It
,
CallMIB
)
;
return
It
;
}
</s>

ARM
ARM
ARM::tTAILJMPd
ARM::tTAILJMPdND
ARM::TAILJMPd
ARMCC::AL
ARM::tBL
ARM::BL
ARMCC::AL
0
"No callee-saved register available?"
ARM::LR
ARM::LR
ARM::LR
ARM::LR


<s>
void
ARMBaseInstrInfo
::
buildOutlinedFrame
(
MachineBasicBlock
&
MBB
,
MachineFunction
&
MF
,
const
outliner
::
OutlinedFunction
&
OF
)
const
{
if
(
OF
.
FrameConstructionID
==
MachineOutlinerThunk
)
{
MachineInstr
*
Call
=
&
*
MBB
.
instr_end
(
)
;
bool
isThumb
=
Subtarget
.
isThumb
(
)
;
unsigned
FuncOp
=
isThumb
2
:
0
;
unsigned
Opc
=
Call
->
getOperand
(
FuncOp
)
.
isReg
(
)
isThumb
ARM
::
tTAILJMPr
:
ARM
::
TAILJMPr
:
isThumb
Subtarget
.
isTargetMachO
(
)
ARM
::
tTAILJMPd
:
ARM
::
tTAILJMPdND
:
ARM
::
TAILJMPd
;
MachineInstrBuilder
MIB
=
BuildMI
(
MBB
,
MBB
.
end
(
)
,
DebugLoc
(
)
,
get
(
Opc
)
)
.
add
(
Call
->
getOperand
(
FuncOp
)
)
;
if
(
isThumb
&&
!
Call
->
getOperand
(
FuncOp
)
.
isReg
(
)
)
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
Call
->
eraseFromParent
(
)
;
}
auto
IsNonTailCall
=
[
]
(
MachineInstr
&
MI
)
{
return
MI
.
isCall
(
)
&&
!
MI
.
isReturn
(
)
;
}
;
if
(
llvm
::
any_of
(
MBB
.
instrs
(
)
,
IsNonTailCall
)
)
{
MachineBasicBlock
::
iterator
It
=
MBB
.
begin
(
)
;
MachineBasicBlock
::
iterator
Et
=
MBB
.
end
(
)
;
if
(
OF
.
FrameConstructionID
==
MachineOutlinerTailCall
||
OF
.
FrameConstructionID
==
MachineOutlinerThunk
)
Et
=
std
::
prev
(
MBB
.
end
(
)
)
;
if
(
!
MBB
.
isLiveIn
(
ARM
::
LR
)
)
MBB
.
addLiveIn
(
ARM
::
LR
)
;
bool
Auth
=
OF
.
Candidates
.
front
(
)
.
getMF
(
)
->
getInfo
<
ARMFunctionInfo
>
(
)
->
shouldSignReturnAddress
(
true
)
;
saveLROnStack
(
MBB
,
It
,
true
,
Auth
)
;
assert
(
OF
.
FrameConstructionID
!=
MachineOutlinerDefault
&&
"Can only fix up stack references once"
)
;
fixupPostOutline
(
MBB
)
;
restoreLRFromStack
(
MBB
,
Et
,
true
,
Auth
)
;
}
if
(
OF
.
FrameConstructionID
==
MachineOutlinerTailCall
||
OF
.
FrameConstructionID
==
MachineOutlinerThunk
)
return
;
BuildMI
(
MBB
,
MBB
.
end
(
)
,
DebugLoc
(
)
,
get
(
Subtarget
.
getReturnOpcode
(
)
)
)
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
if
(
OF
.
FrameConstructionID
!=
MachineOutlinerDefault
&&
OF
.
Candidates
[
0
]
.
CallConstructionID
!=
MachineOutlinerDefault
)
return
;
fixupPostOutline
(
MBB
)
;
}
</s>

ARM
ARM
2
0
ARM::tTAILJMPr
ARM::TAILJMPr
ARM::tTAILJMPd
ARM::tTAILJMPdND
ARM::TAILJMPd
ARMCC::AL
ARM::LR
ARM::LR
ARM
"Can only fix up stack references once"
ARMCC::AL
0


<s> bool ARMBaseInstrInfo :: ClobbersPredicate ( MachineInstr & MI , std :: vector < MachineOperand > & Pred , bool SkipDead ) const { bool Found = false ; for ( const MachineOperand & MO : MI . operands ( ) ) { bool ClobbersCPSR = MO . isRegMask ( ) && MO . clobbersPhysReg ( ARM :: CPSR ) ; bool IsCPSR = MO . isReg ( ) && MO . isDef ( ) && MO . getReg ( ) == ARM :: CPSR ; if ( ClobbersCPSR || IsCPSR ) { const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( MCID . TSFlags & ARMII :: ThumbArithFlagSetting && MO . isDead ( ) && SkipDead ) continue ; Pred . push_back ( MO ) ; Found = true ; } } return Found ; } </s>

If the specified instruction defines any predicate or condition code register ( s ) used for predication , returns true as well as the definition predicate ( s ) by reference .

ARM ARM ARM::CPSR ARM::CPSR ARMII::ThumbArithFlagSetting


<s>
bool
ARMBaseInstrInfo
::
expandPostRAPseudo
(
MachineInstr
&
MI
)
const
{
if
(
MI
.
getOpcode
(
)
==
TargetOpcode
::
LOAD_STACK_GUARD
)
{
expandLoadStackGuard
(
MI
)
;
MI
.
getParent
(
)
->
erase
(
MI
)
;
return
true
;
}
if
(
MI
.
getOpcode
(
)
==
ARM
::
MEMCPY
)
{
expandMEMCPY
(
MI
)
;
return
true
;
}
if
(
!
MI
.
isCopy
(
)
||
Subtarget
.
dontWidenVMOVS
(
)
||
!
Subtarget
.
hasFP64
(
)
)
return
false
;
Register
DstRegS
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
Register
SrcRegS
=
MI
.
getOperand
(
1
)
.
getReg
(
)
;
if
(
!
ARM
::
SPRRegClass
.
contains
(
DstRegS
,
SrcRegS
)
)
return
false
;
const
TargetRegisterInfo
*
TRI
=
&
getRegisterInfo
(
)
;
unsigned
DstRegD
=
TRI
->
getMatchingSuperReg
(
DstRegS
,
ARM
::
ssub_0
,
&
ARM
::
DPRRegClass
)
;
unsigned
SrcRegD
=
TRI
->
getMatchingSuperReg
(
SrcRegS
,
ARM
::
ssub_0
,
&
ARM
::
DPRRegClass
)
;
if
(
!
DstRegD
||
!
SrcRegD
)
return
false
;
if
(
!
MI
.
definesRegister
(
DstRegD
,
TRI
)
||
MI
.
readsRegister
(
DstRegD
,
TRI
)
)
return
false
;
if
(
MI
.
getOperand
(
0
)
.
isDead
(
)
)
return
false
;
LLVM_DEBUG
(
dbgs
(
)
<<
"widening:    "
<<
MI
)
;
MachineInstrBuilder
MIB
(
*
MI
.
getParent
(
)
->
getParent
(
)
,
MI
)
;
int
ImpDefIdx
=
MI
.
findRegisterDefOperandIdx
(
DstRegD
)
;
if
(
ImpDefIdx
!=
1
)
MI
.
RemoveOperand
(
ImpDefIdx
)
;
MI
.
setDesc
(
get
(
ARM
::
VMOVD
)
)
;
MI
.
getOperand
(
0
)
.
setReg
(
DstRegD
)
;
MI
.
getOperand
(
1
)
.
setReg
(
SrcRegD
)
;
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
MI
.
getOperand
(
1
)
.
setIsUndef
(
)
;
MIB
.
addReg
(
SrcRegS
,
RegState
::
Implicit
)
;
if
(
MI
.
getOperand
(
1
)
.
isKill
(
)
)
{
MI
.
getOperand
(
1
)
.
setIsKill
(
false
)
;
MI
.
addRegisterKilled
(
SrcRegS
,
TRI
,
true
)
;
}
LLVM_DEBUG
(
dbgs
(
)
<<
"replaced by: "
<<
MI
)
;
return
true
;
}
</s>

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


<s>
MachineBasicBlock
::
iterator
ARMBaseInstrInfo
::
insertOutlinedCall
(
Module
&
M
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
&
It
,
MachineFunction
&
MF
,
const
outliner
::
Candidate
&
C
)
const
{
MachineInstrBuilder
MIB
;
MachineBasicBlock
::
iterator
CallPt
;
unsigned
Opc
;
bool
isThumb
=
Subtarget
.
isThumb
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerTailCall
)
{
Opc
=
isThumb
Subtarget
.
isTargetMachO
(
)
ARM
::
tTAILJMPd
:
ARM
::
tTAILJMPdND
:
ARM
::
TAILJMPd
;
MIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
isThumb
)
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
It
=
MBB
.
insert
(
It
,
MIB
)
;
return
It
;
}
Opc
=
isThumb
ARM
::
tBL
:
ARM
::
BL
;
MachineInstrBuilder
CallMIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
;
if
(
isThumb
)
CallMIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
CallMIB
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerNoLRSave
||
C
.
CallConstructionID
==
MachineOutlinerThunk
)
{
It
=
MBB
.
insert
(
It
,
CallMIB
)
;
return
It
;
}
const
ARMFunctionInfo
&
AFI
=
*
C
.
getMF
(
)
->
getInfo
<
ARMFunctionInfo
>
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerRegSave
)
{
unsigned
Reg
=
findRegisterToSaveLRTo
(
C
)
;
assert
(
Reg
!=
0
&&
"No callee-saved register available?"
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
Reg
,
ARM
::
LR
,
true
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRSaveToReg
(
MBB
,
It
,
Reg
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
ARM
::
LR
,
Reg
,
true
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRRestoreFromReg
(
MBB
,
It
)
;
It
;
return
CallPt
;
}
if
(
!
MBB
.
isLiveIn
(
ARM
::
LR
)
)
MBB
.
addLiveIn
(
ARM
::
LR
)
;
bool
Auth
=
!
AFI
.
isLRSpilled
(
)
&&
AFI
.
shouldSignReturnAddress
(
true
)
;
saveLROnStack
(
MBB
,
It
,
!
AFI
.
isLRSpilled
(
)
,
Auth
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
restoreLRFromStack
(
MBB
,
It
,
!
AFI
.
isLRSpilled
(
)
,
Auth
)
;
It
;
return
CallPt
;
}
</s>

ARM
ARM
ARM::tTAILJMPd
ARM::tTAILJMPdND
ARM::TAILJMPd
ARMCC::AL
ARM::tBL
ARM::BL
ARMCC::AL
ARM
ARM
0
"No callee-saved register available?"
ARM::LR
ARM::LR
ARM::LR
ARM::LR


<s> void ARMBaseInstrInfo :: mergeOutliningCandidateAttributes ( Function & F , std :: vector < outliner :: Candidate > & Candidates ) const { outliner :: Candidate & C = Candidates . front ( ) ; const Function & CFn = C . getMF ( ) -> getFunction ( ) ; if ( CFn . hasFnAttribute ( "branch-target-enforcement" ) ) F . addFnAttr ( CFn . getFnAttribute ( "branch-target-enforcement" ) ) ; ARMGenInstrInfo :: mergeOutliningCandidateAttributes ( F , Candidates ) ; } </s>

Optional target hook to create the LLVM IR attributes for the outlined function .

ARM ARM "branch-target-enforcement" "branch-target-enforcement" ARM


<s>
MachineInstr
*
ARMBaseInstrInfo
::
optimizeSelect
(
MachineInstr
&
MI
,
SmallPtrSetImpl
<
MachineInstr
*
>
&
SeenMIs
,
bool
PreferFalse
)
const
{
assert
(
(
MI
.
getOpcode
(
)
==
ARM
::
MOVCCr
||
MI
.
getOpcode
(
)
==
ARM
::
t2MOVCCr
)
&&
"Unknown select instruction"
)
;
MachineRegisterInfo
&
MRI
=
MI
.
getParent
(
)
->
getParent
(
)
->
getRegInfo
(
)
;
MachineInstr
*
DefMI
=
canFoldIntoMOVCC
(
MI
.
getOperand
(
2
)
.
getReg
(
)
,
MRI
,
this
)
;
bool
Invert
=
!
DefMI
;
if
(
!
DefMI
)
DefMI
=
canFoldIntoMOVCC
(
MI
.
getOperand
(
1
)
.
getReg
(
)
,
MRI
,
this
)
;
if
(
!
DefMI
)
return
nullptr
;
MachineOperand
FalseReg
=
MI
.
getOperand
(
Invert
2
:
1
)
;
MachineOperand
TrueReg
=
MI
.
getOperand
(
Invert
1
:
2
)
;
Register
DestReg
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
const
TargetRegisterClass
*
FalseClass
=
MRI
.
getRegClass
(
FalseReg
.
getReg
(
)
)
;
const
TargetRegisterClass
*
TrueClass
=
MRI
.
getRegClass
(
TrueReg
.
getReg
(
)
)
;
if
(
!
MRI
.
constrainRegClass
(
DestReg
,
FalseClass
)
)
return
nullptr
;
if
(
!
MRI
.
constrainRegClass
(
DestReg
,
TrueClass
)
)
return
nullptr
;
MachineInstrBuilder
NewMI
=
BuildMI
(
*
MI
.
getParent
(
)
,
MI
,
MI
.
getDebugLoc
(
)
,
DefMI
->
getDesc
(
)
,
DestReg
)
;
const
MCInstrDesc
&
DefDesc
=
DefMI
->
getDesc
(
)
;
for
(
unsigned
i
=
1
,
e
=
DefDesc
.
getNumOperands
(
)
;
i
!=
e
&&
!
DefDesc
.
OpInfo
[
i
]
.
isPredicate
(
)
;
++
i
)
NewMI
.
add
(
DefMI
->
getOperand
(
i
)
)
;
unsigned
CondCode
=
MI
.
getOperand
(
3
)
.
getImm
(
)
;
if
(
Invert
)
NewMI
.
addImm
(
ARMCC
::
getOppositeCondition
(
ARMCC
::
CondCodes
(
CondCode
)
)
)
;
else
NewMI
.
addImm
(
CondCode
)
;
NewMI
.
add
(
MI
.
getOperand
(
4
)
)
;
if
(
NewMI
->
hasOptionalDef
(
)
)
NewMI
.
add
(
condCodeOp
(
)
)
;
FalseReg
.
setImplicit
(
)
;
NewMI
.
add
(
FalseReg
)
;
NewMI
->
tieOperands
(
0
,
NewMI
->
getNumOperands
(
)
1
)
;
SeenMIs
.
insert
(
NewMI
)
;
SeenMIs
.
erase
(
DefMI
)
;
if
(
DefMI
->
getParent
(
)
!=
MI
.
getParent
(
)
)
NewMI
->
clearKillInfo
(
)
;
DefMI
->
eraseFromParent
(
)
;
return
NewMI
;
}
</s>

Given a select instruction that was understood by analyzeSelect and returned Optimizable = true , attempt to optimize MI by merging it with one of its operands .


"Pseudo flag setting opcodes only exist in Selection DAG"

"Non-flag-setting Thumb1 mov is v6-only"

"Unsupported register in Thumb1 push/pop"

"Incorrect array index for MVE_VMOV_q_rr"

Perform target-specific instruction verification .


<s> Optional < DestSourcePair > ARMBaseInstrInfo :: isAddImmediate ( const MachineInstr & MI , int64_t & Offset ) const { int Sign = 1 ; unsigned Opcode = MI . getOpcode ( ) ; if ( Opcode == ARM :: SUBri ) Sign = - 1 ; else if ( Opcode != ARM :: ADDri ) return None ; if ( ! MI . getOperand ( 0 ) . isReg ( ) || ! MI . getOperand ( 1 ) . isReg ( ) || ! MI . getOperand ( 2 ) . isImm ( ) ) return None ; Offset = MI . getOperand ( 2 ) . getImm ( ) * Sign ; return DestSourcePair { MI . getOperand ( 0 ) , MI . getOperand ( 1 ) } ; } </s>

If the specific machine instruction is an instruction that adds an immediate value and a register , and stores the result in the given register Reg , return a pair of the source register and the offset which has been added .


<s> MachineInstr * ARMBaseInstrInfo :: commuteInstruction ( MachineInstr * MI , bool NewMI ) const { switch ( MI -> getOpcode ( ) ) { case ARM :: MOVCCr : case ARM :: t2MOVCCr : { unsigned PredReg = 0 ; ARMCC :: CondCodes CC = getInstrPredicate ( MI , PredReg ) ; if ( CC == ARMCC :: AL || PredReg != ARM :: CPSR ) return NULL ; MI = TargetInstrInfoImpl :: commuteInstruction ( MI , NewMI ) ; if ( ! MI ) return NULL ; MI -> getOperand ( MI -> findFirstPredOperandIdx ( ) ) . setImm ( ARMCC :: getOppositeCondition ( CC ) ) ; return MI ; } } return TargetInstrInfoImpl :: commuteInstruction ( MI , NewMI ) ; } </s>

This method commutes the operands of the given machine instruction MI .


<s>
bool
ARMBaseInstrInfo
::
analyzeBranch
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
*
&
TBB
,
MachineBasicBlock
*
&
FBB
,
SmallVectorImpl
<
MachineOperand
>
&
Cond
,
bool
AllowModify
)
const
{
TBB
=
nullptr
;
FBB
=
nullptr
;
MachineBasicBlock
::
instr_iterator
I
=
MBB
.
instr_end
(
)
;
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
while
(
isPredicated
(
*
I
)
||
I
->
isTerminator
(
)
||
I
->
isDebugValue
(
)
)
{
bool
CantAnalyze
=
false
;
while
(
I
->
isDebugInstr
(
)
||
!
I
->
isTerminator
(
)
||
isSpeculationBarrierEndBBOpcode
(
I
->
getOpcode
(
)
)
)
{
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
}
if
(
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
CantAnalyze
=
true
;
}
else
if
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
}
else
if
(
isCondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
if
(
!
Cond
.
empty
(
)
)
return
true
;
assert
(
!
FBB
&&
"FBB should have been null."
)
;
FBB
=
TBB
;
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
Cond
.
push_back
(
I
->
getOperand
(
1
)
)
;
Cond
.
push_back
(
I
->
getOperand
(
2
)
)
;
}
else
if
(
I
->
isReturn
(
)
)
{
CantAnalyze
=
true
;
}
else
{
return
true
;
}
if
(
!
isPredicated
(
*
I
)
&&
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
||
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
||
I
->
isReturn
(
)
)
)
{
Cond
.
clear
(
)
;
FBB
=
nullptr
;
if
(
AllowModify
)
{
MachineBasicBlock
::
iterator
DI
=
std
::
next
(
I
)
;
while
(
DI
!=
MBB
.
instr_end
(
)
)
{
MachineInstr
&
InstToDelete
=
*
DI
;
++
DI
;
if
(
isSpeculationBarrierEndBBOpcode
(
InstToDelete
.
getOpcode
(
)
)
)
continue
;
InstToDelete
.
eraseFromParent
(
)
;
}
}
}
if
(
CantAnalyze
)
{
if
(
AllowModify
&&
!
isPredicated
(
MBB
.
back
(
)
)
&&
isUncondBranchOpcode
(
MBB
.
back
(
)
.
getOpcode
(
)
)
&&
TBB
&&
MBB
.
isLayoutSuccessor
(
TBB
)
)
removeBranch
(
MBB
)
;
return
true
;
}
if
(
I
==
MBB
.
instr_begin
(
)
)
return
false
;
I
;
}
return
false
;
}
</s>

analyzeBranch - Analyze the branching code at the end of MBB , returning true if it can not be understood ( e.g .


<s> void ARMBaseInstrInfo :: buildOutlinedFrame ( MachineBasicBlock & MBB , MachineFunction & MF , const outliner :: OutlinedFunction & OF ) const { if ( OF . FrameConstructionID == MachineOutlinerThunk ) { MachineInstr * Call = & * -- MBB . instr_end ( ) ; bool isThumb = Subtarget . isThumb ( ) ; unsigned FuncOp = isThumb ? 2 : 0 ; unsigned Opc = Call -> getOperand ( FuncOp ) . isReg ( ) ? isThumb ? ARM :: tTAILJMPr : ARM :: TAILJMPr : isThumb ? Subtarget . isTargetMachO ( ) ? ARM :: tTAILJMPd : ARM :: tTAILJMPdND : ARM :: TAILJMPd ; MachineInstrBuilder MIB = BuildMI ( MBB , MBB . end ( ) , DebugLoc ( ) , get ( Opc ) ) . add ( Call -> getOperand ( FuncOp ) ) ; if ( isThumb && ! Call -> getOperand ( FuncOp ) . isReg ( ) ) MIB . add ( predOps ( ARMCC :: AL ) ) ; Call -> eraseFromParent ( ) ; } auto IsNonTailCall = [ ] ( MachineInstr & MI ) { return MI . isCall ( ) && ! MI . isReturn ( ) ; } ; if ( llvm :: any_of ( MBB . instrs ( ) , IsNonTailCall ) ) { MachineBasicBlock :: iterator It = MBB . begin ( ) ; MachineBasicBlock :: iterator Et = MBB . end ( ) ; if ( OF . FrameConstructionID == MachineOutlinerTailCall || OF . FrameConstructionID == MachineOutlinerThunk ) Et = std :: prev ( MBB . end ( ) ) ; if ( ! MBB . isLiveIn ( ARM :: LR ) ) MBB . addLiveIn ( ARM :: LR ) ; saveLROnStack ( MBB , It ) ; emitCFIForLRSaveOnStack ( MBB , It ) ; restoreLRFromStack ( MBB , Et ) ; emitCFIForLRRestoreFromStack ( MBB , Et ) ; } if ( OF . FrameConstructionID == MachineOutlinerTailCall || OF . FrameConstructionID == MachineOutlinerThunk ) return ; BuildMI ( MBB , MBB . end ( ) , DebugLoc ( ) , get ( Subtarget . getReturnOpcode ( ) ) ) . add ( predOps ( ARMCC :: AL ) ) ; } </s>

Insert a custom frame for outlined functions .

ARM ARM 2 0 ARM::tTAILJMPr ARM::TAILJMPr ARM::tTAILJMPd ARM::tTAILJMPdND ARM::TAILJMPd ARMCC::AL ARM::LR ARM::LR ARMCC::AL


<s>
MachineBasicBlock
::
iterator
ARMBaseInstrInfo
::
insertOutlinedCall
(
Module
&
M
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
&
It
,
MachineFunction
&
MF
,
const
outliner
::
Candidate
&
C
)
const
{
MachineInstrBuilder
MIB
;
MachineBasicBlock
::
iterator
CallPt
;
unsigned
Opc
;
bool
isThumb
=
Subtarget
.
isThumb
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerTailCall
)
{
Opc
=
isThumb
Subtarget
.
isTargetMachO
(
)
ARM
::
tTAILJMPd
:
ARM
::
tTAILJMPdND
:
ARM
::
TAILJMPd
;
MIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
isThumb
)
MIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
It
=
MBB
.
insert
(
It
,
MIB
)
;
return
It
;
}
Opc
=
isThumb
ARM
::
tBL
:
ARM
::
BL
;
MachineInstrBuilder
CallMIB
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
Opc
)
)
;
if
(
isThumb
)
CallMIB
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
CallMIB
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerNoLRSave
||
C
.
CallConstructionID
==
MachineOutlinerThunk
)
{
It
=
MBB
.
insert
(
It
,
CallMIB
)
;
return
It
;
}
const
ARMFunctionInfo
&
AFI
=
*
C
.
getMF
(
)
->
getInfo
<
ARMFunctionInfo
>
(
)
;
if
(
C
.
CallConstructionID
==
MachineOutlinerRegSave
)
{
unsigned
Reg
=
findRegisterToSaveLRTo
(
C
)
;
assert
(
Reg
!=
0
&&
"No callee-saved register available?"
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
Reg
,
ARM
::
LR
,
true
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRSaveToReg
(
MBB
,
It
,
Reg
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
copyPhysReg
(
MBB
,
It
,
DebugLoc
(
)
,
ARM
::
LR
,
Reg
,
true
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRRestoreFromReg
(
MBB
,
It
)
;
It
;
return
CallPt
;
}
saveLROnStack
(
MBB
,
It
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRSaveOnStack
(
MBB
,
It
)
;
CallPt
=
MBB
.
insert
(
It
,
CallMIB
)
;
restoreLRFromStack
(
MBB
,
It
)
;
if
(
!
AFI
.
isLRSpilled
(
)
)
emitCFIForLRRestoreFromStack
(
MBB
,
It
)
;
It
;
return
CallPt
;
}
</s>

Insert a call to an outlined function into the program .

ARM
ARM
ARM::tTAILJMPd
ARM::tTAILJMPdND
ARM::TAILJMPd
ARMCC::AL
ARM::tBL
ARM::BL
ARMCC::AL
ARM
ARM
0
"No callee-saved register available?"
ARM::LR
ARM::LR


<s>
void
ARMBaseInstrInfo
::
loadRegFromStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
unsigned
DestReg
,
int
FI
,
const
TargetRegisterClass
*
RC
)
const
{
DebugLoc
DL
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
MachineFrameInfo
&
MFI
=
*
MF
.
getFrameInfo
(
)
;
unsigned
Align
=
MFI
.
getObjectAlignment
(
FI
)
;
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
PseudoSourceValue
::
getFixedStack
(
FI
)
,
MachineMemOperand
::
MOLoad
,
0
,
MFI
.
getObjectSize
(
FI
)
,
Align
)
;
if
(
RC
==
ARM
::
tGPRRegisterClass
)
RC
=
ARM
::
GPRRegisterClass
;
if
(
RC
==
ARM
::
GPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
LDR
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addReg
(
0
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
DPRRegisterClass
||
RC
==
ARM
::
DPR_VFP2RegisterClass
||
RC
==
ARM
::
DPR_8RegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLDRD
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
SPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLDRS
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
{
assert
(
(
RC
==
ARM
::
QPRRegisterClass
||
RC
==
ARM
::
QPR_VFP2RegisterClass
||
RC
==
ARM
::
QPR_8RegisterClass
)
&&
"Unknown regclass!"
)
;
if
(
Align
>=
16
&&
(
getRegisterInfo
(
)
.
canRealignStack
(
MF
)
)
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLD1q
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
128
)
.
addMemOperand
(
MMO
)
)
;
}
else
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VLDMQ
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
ARM_AM
::
getAM5Opc
(
ARM_AM
::
ia
,
4
)
)
.
addMemOperand
(
MMO
)
)
;
}
}
}
</s>

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


<s>
void
ARMBaseInstrInfo
::
storeRegToStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
unsigned
SrcReg
,
bool
isKill
,
int
FI
,
const
TargetRegisterClass
*
RC
)
const
{
DebugLoc
DL
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
MachineFrameInfo
&
MFI
=
*
MF
.
getFrameInfo
(
)
;
unsigned
Align
=
MFI
.
getObjectAlignment
(
FI
)
;
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
PseudoSourceValue
::
getFixedStack
(
FI
)
,
MachineMemOperand
::
MOStore
,
0
,
MFI
.
getObjectSize
(
FI
)
,
Align
)
;
if
(
RC
==
ARM
::
tGPRRegisterClass
)
RC
=
ARM
::
GPRRegisterClass
;
if
(
RC
==
ARM
::
GPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
STR
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addReg
(
0
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
DPRRegisterClass
||
RC
==
ARM
::
DPR_VFP2RegisterClass
||
RC
==
ARM
::
DPR_8RegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VSTRD
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
if
(
RC
==
ARM
::
SPRRegisterClass
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VSTRS
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
)
;
}
else
{
assert
(
(
RC
==
ARM
::
QPRRegisterClass
||
RC
==
ARM
::
QPR_VFP2RegisterClass
)
&&
"Unknown regclass!"
)
;
if
(
Align
>=
16
&&
(
getRegisterInfo
(
)
.
canRealignStack
(
MF
)
)
)
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VST1q
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
128
)
.
addMemOperand
(
MMO
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
)
;
}
else
{
AddDefaultPred
(
BuildMI
(
MBB
,
I
,
DL
,
get
(
ARM
::
VSTMQ
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
isKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
ARM_AM
::
getAM5Opc
(
ARM_AM
::
ia
,
4
)
)
.
addMemOperand
(
MMO
)
)
;
}
}
}
</s>

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


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

ARM ARM ARM "arm-got" "arm-sbrel" "arm-dllimport" "arm-secrel" "arm-nonlazy"


<s> bool ARMBaseInstrInfo :: isCopyInstr ( const MachineInstr & MI , const MachineOperand * & Src , const MachineOperand * & Dest ) const { if ( ! MI . isMoveReg ( ) || ( MI . getOpcode ( ) == ARM :: VORRq && MI . getOperand ( 1 ) . getReg ( ) != MI . getOperand ( 2 ) . getReg ( ) ) ) return false ; Dest = & MI . getOperand ( 0 ) ; Src = & MI . getOperand ( 1 ) ; return true ; } </s>

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


<s>
bool
ARMBaseInstrInfo
::
analyzeBranch
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
*
&
TBB
,
MachineBasicBlock
*
&
FBB
,
SmallVectorImpl
<
MachineOperand
>
&
Cond
,
bool
AllowModify
)
const
{
TBB
=
nullptr
;
FBB
=
nullptr
;
MachineBasicBlock
::
iterator
I
=
MBB
.
end
(
)
;
if
(
I
==
MBB
.
begin
(
)
)
return
false
;
I
;
while
(
isPredicated
(
*
I
)
||
I
->
isTerminator
(
)
||
I
->
isDebugValue
(
)
)
{
bool
CantAnalyze
=
false
;
while
(
I
->
isDebugInstr
(
)
||
!
I
->
isTerminator
(
)
)
{
if
(
I
==
MBB
.
begin
(
)
)
return
false
;
I
;
}
if
(
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
CantAnalyze
=
true
;
}
else
if
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
}
else
if
(
isCondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
if
(
!
Cond
.
empty
(
)
)
return
true
;
assert
(
!
FBB
&&
"FBB should have been null."
)
;
FBB
=
TBB
;
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
Cond
.
push_back
(
I
->
getOperand
(
1
)
)
;
Cond
.
push_back
(
I
->
getOperand
(
2
)
)
;
}
else
if
(
I
->
isReturn
(
)
)
{
CantAnalyze
=
!
isPredicated
(
*
I
)
;
}
else
{
return
true
;
}
if
(
!
isPredicated
(
*
I
)
&&
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
||
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
||
I
->
isReturn
(
)
)
)
{
Cond
.
clear
(
)
;
FBB
=
nullptr
;
if
(
AllowModify
)
{
MachineBasicBlock
::
iterator
DI
=
std
::
next
(
I
)
;
while
(
DI
!=
MBB
.
end
(
)
)
{
MachineInstr
&
InstToDelete
=
*
DI
;
++
DI
;
InstToDelete
.
eraseFromParent
(
)
;
}
}
}
if
(
CantAnalyze
)
return
true
;
if
(
I
==
MBB
.
begin
(
)
)
return
false
;
I
;
}
return
false
;
}
</s>


<s> bool ARMBaseInstrInfo :: analyzeCompare ( const MachineInstr & MI , unsigned & SrcReg , unsigned & SrcReg2 , int & CmpMask , int & CmpValue ) const { switch ( MI . getOpcode ( ) ) { default : break ; case ARM :: CMPri : case ARM :: t2CMPri : case ARM :: tCMPi8 : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = ~ 0 ; CmpValue = MI . getOperand ( 1 ) . getImm ( ) ; return true ; case ARM :: CMPrr : case ARM :: t2CMPrr : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = MI . getOperand ( 1 ) . getReg ( ) ; CmpMask = ~ 0 ; CmpValue = 0 ; return true ; case ARM :: TSTri : case ARM :: t2TSTri : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = MI . getOperand ( 1 ) . getImm ( ) ; CmpValue = 0 ; 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 .


"Can't break virtual register dependencies."

Insert a dependency-breaking instruction before MI to eliminate an unwanted dependency on OpNum .


<s> std :: pair < unsigned , unsigned > ARMBaseInstrInfo :: decomposeMachineOperandsTargetFlags ( unsigned TF ) const { const unsigned Mask = ARMII :: MO_OPTION_MASK ; return std :: make_pair ( TF & Mask , TF & ~ Mask ) ; } </s>

Decompose the machine operand 's target flags into two values - the direct target flag value and any of bit flags that are applied .


<s> MachineInstr & ARMBaseInstrInfo :: duplicate ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator InsertBefore , const MachineInstr & Orig ) const { MachineInstr & Cloned = TargetInstrInfo :: duplicate ( MBB , InsertBefore , Orig ) ; MachineBasicBlock :: instr_iterator I = Cloned . getIterator ( ) ; for ( ; ; ) { switch ( I -> getOpcode ( ) ) { case ARM :: tLDRpci_pic : case ARM :: t2LDRpci_pic : { MachineFunction & MF = * MBB . getParent ( ) ; unsigned CPI = I -> getOperand ( 1 ) . getIndex ( ) ; unsigned PCLabelId = duplicateCPV ( MF , CPI ) ; I -> getOperand ( 1 ) . setIndex ( CPI ) ; I -> getOperand ( 2 ) . setImm ( PCLabelId ) ; break ; } } if ( ! I -> isBundledWithSucc ( ) ) break ; ++ I ; } return Cloned ; } </s>

Clones instruction or the whole instruction bundle Orig and insert into MBB before InsertBefore .


"LOAD_STACK_GUARD currently supported only for MachO."

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


<s>
bool
ARMBaseInstrInfo
::
getExtractSubregLikeInputs
(
const
MachineInstr
&
MI
,
unsigned
DefIdx
,
RegSubRegPairAndIdx
&
InputReg
)
const
{
assert
(
DefIdx
<
MI
.
getDesc
(
)
.
getNumDefs
(
)
&&
"Invalid definition index"
)
;
assert
(
MI
.
isExtractSubregLike
(
)
&&
"Invalid kind of instruction"
)
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VMOVRRD
:
const
MachineOperand
&
MOReg
=
MI
.
getOperand
(
2
)
;
if
(
MOReg
.
isUndef
(
)
)
return
false
;
InputReg
.
Reg
=
MOReg
.
getReg
(
)
;
InputReg
.
SubReg
=
MOReg
.
getSubReg
(
)
;
InputReg
.
SubIdx
=
DefIdx
==
0
ARM
::
ssub_0
:
ARM
::
ssub_1
;
return
true
;
}
llvm_unreachable
(
"Target dependent opcode missing"
)
;
}
</s>

Target-dependent implementation of getExtractSubregInputs .


<s>
bool
ARMBaseInstrInfo
::
getInsertSubregLikeInputs
(
const
MachineInstr
&
MI
,
unsigned
DefIdx
,
RegSubRegPair
&
BaseReg
,
RegSubRegPairAndIdx
&
InsertedReg
)
const
{
assert
(
DefIdx
<
MI
.
getDesc
(
)
.
getNumDefs
(
)
&&
"Invalid definition index"
)
;
assert
(
MI
.
isInsertSubregLike
(
)
&&
"Invalid kind of instruction"
)
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VSETLNi32
:
const
MachineOperand
&
MOBaseReg
=
MI
.
getOperand
(
1
)
;
const
MachineOperand
&
MOInsertedReg
=
MI
.
getOperand
(
2
)
;
if
(
MOInsertedReg
.
isUndef
(
)
)
return
false
;
const
MachineOperand
&
MOIndex
=
MI
.
getOperand
(
3
)
;
BaseReg
.
Reg
=
MOBaseReg
.
getReg
(
)
;
BaseReg
.
SubReg
=
MOBaseReg
.
getSubReg
(
)
;
InsertedReg
.
Reg
=
MOInsertedReg
.
getReg
(
)
;
InsertedReg
.
SubReg
=
MOInsertedReg
.
getSubReg
(
)
;
InsertedReg
.
SubIdx
=
MOIndex
.
getImm
(
)
==
0
ARM
::
ssub_0
:
ARM
::
ssub_1
;
return
true
;
}
llvm_unreachable
(
"Target dependent opcode missing"
)
;
}
</s>

Target-dependent implementation of getInsertSubregInputs .


<s> unsigned ARMBaseInstrInfo :: getInstrLatency ( const InstrItineraryData * ItinData , const MachineInstr & MI , unsigned * PredCost ) const { if ( MI . isCopyLike ( ) || MI . isInsertSubreg ( ) || MI . isRegSequence ( ) || MI . isImplicitDef ( ) ) return 1 ; if ( MI . isBundle ( ) ) { unsigned Latency = 0 ; MachineBasicBlock :: const_instr_iterator I = MI . getIterator ( ) ; MachineBasicBlock :: const_instr_iterator E = MI . getParent ( ) -> instr_end ( ) ; while ( ++ I != E && I -> isInsideBundle ( ) ) { if ( I -> getOpcode ( ) != ARM :: t2IT ) Latency += getInstrLatency ( ItinData , * I , PredCost ) ; } return Latency ; } const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( PredCost && ( MCID . isCall ( ) || ( MCID . hasImplicitDefOfPhysReg ( ARM :: CPSR ) && ! Subtarget . cheapPredicableCPSRDef ( ) ) ) ) { * PredCost = 1 ; } if ( ! ItinData ) return MI . mayLoad ( ) ? 3 : 1 ; unsigned Class = MCID . getSchedClass ( ) ; if ( ! ItinData -> isEmpty ( ) && ItinData -> getNumMicroOps ( Class ) < 0 ) return getNumMicroOps ( ItinData , MI ) ; unsigned Latency = ItinData -> getStageLatency ( Class ) ; unsigned DefAlign = MI . hasOneMemOperand ( ) ? ( * MI . memoperands_begin ( ) ) -> getAlignment ( ) : 0 ; int Adj = adjustDefLatency ( Subtarget , MI , MCID , DefAlign ) ; if ( Adj >= 0 || ( int ) Latency > - Adj ) { return Latency + Adj ; } return Latency ; } </s>

Compute the instruction latency of a given instruction .


<s> unsigned ARMBaseInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { const MachineBasicBlock & MBB = * MI . getParent ( ) ; const MachineFunction * MF = MBB . getParent ( ) ; const MCAsmInfo * MAI = MF -> getTarget ( ) . getMCAsmInfo ( ) ; const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( MCID . getSize ( ) ) return MCID . getSize ( ) ; if ( MI . getOpcode ( ) == ARM :: INLINEASM ) { unsigned Size = getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * MAI ) ; if ( ! MF -> getInfo < ARMFunctionInfo > ( ) -> isThumbFunction ( ) ) Size = alignTo ( Size , 4 ) ; return Size ; } unsigned Opc = MI . getOpcode ( ) ; switch ( Opc ) { default : return 0 ; case TargetOpcode :: BUNDLE : return getInstBundleLength ( MI ) ; case ARM :: MOVi16_ga_pcrel : case ARM :: MOVTi16_ga_pcrel : case ARM :: t2MOVi16_ga_pcrel : case ARM :: t2MOVTi16_ga_pcrel : return 4 ; case ARM :: MOVi32imm : case ARM :: t2MOVi32imm : return 8 ; case ARM :: CONSTPOOL_ENTRY : case ARM :: JUMPTABLE_INSTS : case ARM :: JUMPTABLE_ADDRS : case ARM :: JUMPTABLE_TBB : case ARM :: JUMPTABLE_TBH : return MI . getOperand ( 2 ) . getImm ( ) ; case ARM :: Int_eh_sjlj_longjmp : return 16 ; case ARM :: tInt_eh_sjlj_longjmp : return 10 ; case ARM :: tInt_WIN_eh_sjlj_longjmp : return 12 ; case ARM :: Int_eh_sjlj_setjmp : case ARM :: Int_eh_sjlj_setjmp_nofp : return 20 ; case ARM :: tInt_eh_sjlj_setjmp : case ARM :: t2Int_eh_sjlj_setjmp : case ARM :: t2Int_eh_sjlj_setjmp_nofp : return 12 ; case ARM :: SPACE : return MI . getOperand ( 1 ) . getImm ( ) ; } } </s>

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


<s>
bool
ARMBaseInstrInfo
::
getRegSequenceLikeInputs
(
const
MachineInstr
&
MI
,
unsigned
DefIdx
,
SmallVectorImpl
<
RegSubRegPairAndIdx
>
&
InputRegs
)
const
{
assert
(
DefIdx
<
MI
.
getDesc
(
)
.
getNumDefs
(
)
&&
"Invalid definition index"
)
;
assert
(
MI
.
isRegSequenceLike
(
)
&&
"Invalid kind of instruction"
)
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VMOVDRR
:
const
MachineOperand
*
MOReg
=
&
MI
.
getOperand
(
1
)
;
if
(
!
MOReg
->
isUndef
(
)
)
InputRegs
.
push_back
(
RegSubRegPairAndIdx
(
MOReg
->
getReg
(
)
,
MOReg
->
getSubReg
(
)
,
ARM
::
ssub_0
)
)
;
MOReg
=
&
MI
.
getOperand
(
2
)
;
if
(
!
MOReg
->
isUndef
(
)
)
InputRegs
.
push_back
(
RegSubRegPairAndIdx
(
MOReg
->
getReg
(
)
,
MOReg
->
getSubReg
(
)
,
ARM
::
ssub_1
)
)
;
return
true
;
}
llvm_unreachable
(
"Target dependent opcode missing"
)
;
}
</s>

Target-dependent implementation of getRegSequenceInputs .


ARM ARM ARM "arm-coffstub" "arm-got" "arm-sbrel" "arm-dllimport" "arm-secrel" "arm-nonlazy"


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


"insertBranch must not be told to insert a fallthrough"

"ARM branch conditions have two components!"

Insert branch code into the end of the specified MachineBasicBlock .


<s> bool ARMBaseInstrInfo :: isCopyInstrImpl ( const MachineInstr & MI , const MachineOperand * & Src , const MachineOperand * & Dest ) const { if ( ! MI . isMoveReg ( ) || ( MI . getOpcode ( ) == ARM :: VORRq && MI . getOperand ( 1 ) . getReg ( ) != MI . getOperand ( 2 ) . getReg ( ) ) ) return false ; Dest = & MI . getOperand ( 0 ) ; Src = & MI . getOperand ( 1 ) ; return true ; } </s>