<s> bool ARMTargetLowering :: mayBeEmittedAsTailCall ( CallInst * CI ) const { if ( ! Subtarget -> supportsTailCall ( ) ) return false ; auto Attr = CI -> getParent ( ) -> getParent ( ) -> getFnAttribute ( "disable-tail-calls" ) ; if ( ! CI -> isTailCall ( ) || Attr . getValueAsString ( ) == "true" ) return false ; return true ; } </s>

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


<s> SDValue ARMTargetLowering :: PerformCMOVCombine ( SDNode * N , SelectionDAG & DAG ) const { SDValue Cmp = N -> getOperand ( 4 ) ; if ( Cmp . getOpcode ( ) != ARMISD :: CMPZ ) return SDValue ( ) ; EVT VT = N -> getValueType ( 0 ) ; SDLoc dl ( N ) ; SDValue LHS = Cmp . getOperand ( 0 ) ; SDValue RHS = Cmp . getOperand ( 1 ) ; SDValue FalseVal = N -> getOperand ( 0 ) ; SDValue TrueVal = N -> getOperand ( 1 ) ; SDValue ARMcc = N -> getOperand ( 2 ) ; ARMCC :: CondCodes CC = ( ARMCC :: CondCodes ) cast < ConstantSDNode > ( ARMcc ) -> getZExtValue ( ) ; if ( ! Subtarget -> isThumb1Only ( ) && Subtarget -> hasV6T2Ops ( ) ) { SDValue R = PerformCMOVToBFICombine ( N , DAG ) ; if ( R ) return R ; } SDValue Res ; if ( CC == ARMCC :: NE && FalseVal == RHS && FalseVal != LHS ) { Res = DAG . getNode ( ARMISD :: CMOV , dl , VT , LHS , TrueVal , ARMcc , N -> getOperand ( 3 ) , Cmp ) ; } else if ( CC == ARMCC :: EQ && TrueVal == RHS ) { SDValue ARMcc ; SDValue NewCmp = getARMCmp ( LHS , RHS , ISD :: SETNE , ARMcc , DAG , dl ) ; Res = DAG . getNode ( ARMISD :: CMOV , dl , VT , LHS , FalseVal , ARMcc , N -> getOperand ( 3 ) , NewCmp ) ; } if ( Res . getNode ( ) ) { APInt KnownZero , KnownOne ; DAG . computeKnownBits ( SDValue ( N , 0 ) , KnownZero , KnownOne ) ; if ( KnownZero == 0xfffffffe ) Res = DAG . getNode ( ISD :: AssertZext , dl , MVT :: i32 , Res , DAG . getValueType ( MVT :: i1 ) ) ; else if ( KnownZero == 0xffffff00 ) Res = DAG . getNode ( ISD :: AssertZext , dl , MVT :: i32 , Res , DAG . getValueType ( MVT :: i8 ) ) ; else if ( KnownZero == 0xffff0000 ) Res = DAG . getNode ( ISD :: AssertZext , dl , MVT :: i32 , Res , DAG . getValueType ( MVT :: i16 ) ) ; } return Res ; } </s>

PerformCMOVCombine - Target-specific DAG combining for ARMISD : :CMOV .


<s>
void
ARMTargetLowering
::
ReplaceNodeResults
(
SDNode
*
N
,
SmallVectorImpl
<
SDValue
>
&
Results
,
SelectionDAG
&
DAG
)
const
{
SDValue
Res
;
switch
(
N
->
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom expand this!"
)
;
case
ISD
::
READ_REGISTER
:
ExpandREAD_REGISTER
(
N
,
Results
,
DAG
)
;
break
;
case
ISD
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
SREM
:
case
ISD
::
UREM
:
Res
=
LowerREM
(
N
,
DAG
)
;
break
;
case
ISD
::
READCYCLECOUNTER
:
ReplaceREADCYCLECOUNTER
(
N
,
Results
,
DAG
,
Subtarget
)
;
return
;
case
ISD
::
UDIV
:
case
ISD
::
SDIV
:
assert
(
Subtarget
->
isTargetWindows
(
)
&&
"can only expand DIV on Windows"
)
;
return
ExpandDIV_Windows
(
SDValue
(
N
,
0
)
,
DAG
,
N
->
getOpcode
(
)
==
ISD
::
SDIV
,
Results
)
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>

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

ARM
ARM
"Don't know how to custom expand this!"
ISD::READ_REGISTER
ISD::BITCAST
ISD::SRL
ISD::SRA
ISD::SREM
ISD::UREM
ISD::READCYCLECOUNTER
ISD::UDIV
ISD::SDIV
"can only expand DIV on Windows"
0
ISD::SDIV


<s> bool ARMTargetLowering :: shouldAlignPointerArgs ( CallInst * CI , unsigned & MinSize , unsigned & PrefAlign ) const { if ( ! isa < MemIntrinsic > ( CI ) ) return false ; MinSize = 8 ; PrefAlign = ( Subtarget -> hasV6Ops ( ) && ! Subtarget -> isMClass ( ) ? 8 : 4 ) ; return true ; } </s>

Return true if the pointer arguments to CI should be aligned by aligning the object whose address is being passed .


<s> bool ARMTargetLowering :: shouldExpandAtomicCmpXchgInIR ( AtomicCmpXchgInst * AI ) const { return true ; } </s>

Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass .


<s> TargetLowering :: AtomicExpansionKind ARMTargetLowering :: shouldExpandAtomicLoadInIR ( LoadInst * LI ) const { unsigned Size = LI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; return ( ( Size == 64 ) && ! Subtarget -> isMClass ( ) ) ? AtomicExpansionKind :: LLOnly : AtomicExpansionKind :: None ; } </s>

Returns how the given ( atomic ) load should be expanded by the IR-level AtomicExpand pass .


<s> TargetLowering :: AtomicExpansionKind ARMTargetLowering :: shouldExpandAtomicRMWInIR ( AtomicRMWInst * AI ) const { unsigned Size = AI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; return ( Size <= ( Subtarget -> isMClass ( ) ? 32U : 64U ) ) ? AtomicExpansionKind :: LLSC : AtomicExpansionKind :: None ; } </s>

Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW , if at all .


<s> bool ARMTargetLowering :: shouldExpandAtomicStoreInIR ( StoreInst * SI ) const { unsigned Size = SI -> getValueOperand ( ) -> getType ( ) -> getPrimitiveSizeInBits ( ) ; return ( Size == 64 ) && ! Subtarget -> isMClass ( ) ; } </s>

Returns how the given ( atomic ) store should be expanded by the IR-level AtomicExpand pass into .


<s> bool ARMTargetLowering :: useLoadStackGuardNode ( ) const { return Subtarget -> isTargetMachO ( ) ; } </s>

If this function returns true , SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering Intrinsic : :stackprotector .


"converted opcode should be the same except for cc_out"

"expect uninitialized optional cc_out operand"

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


<s> bool ARMTargetLowering :: allowsMisalignedMemoryAccesses ( EVT VT , unsigned , unsigned , bool * Fast ) const { bool AllowsUnaligned = Subtarget -> allowsUnalignedMem ( ) ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { default : return false ; case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : { if ( AllowsUnaligned ) { if ( Fast ) * Fast = Subtarget -> hasV7Ops ( ) ; return true ; } return false ; } case MVT :: f64 : case MVT :: v2f64 : { if ( Subtarget -> hasNEON ( ) && ( AllowsUnaligned || isLittleEndian ( ) ) ) { if ( Fast ) * Fast = true ; return true ; } return false ; } } } </s>

Returns true if the target allows unaligned memory accesses of the specified type .


<s> Value * ARMTargetLowering :: emitStoreConditional ( IRBuilder < > & Builder , Value * Val , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; bool IsRelease = isAtLeastRelease ( Ord ) ; if ( Val -> getType ( ) -> getPrimitiveSizeInBits ( ) == 64 ) { Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlexd : Intrinsic :: arm_strexd ; Function * Strex = Intrinsic :: getDeclaration ( M , Int ) ; Type * Int32Ty = Type :: getInt32Ty ( M -> getContext ( ) ) ; Value * Lo = Builder . CreateTrunc ( Val , Int32Ty , "lo" ) ; Value * Hi = Builder . CreateTrunc ( Builder . CreateLShr ( Val , 32 ) , Int32Ty , "hi" ) ; if ( ! Subtarget -> isLittle ( ) ) std :: swap ( Lo , Hi ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; return Builder . CreateCall3 ( Strex , Lo , Hi , Addr ) ; } Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlex : Intrinsic :: arm_strex ; Type * Tys [ ] = { Addr -> getType ( ) } ; Function * Strex = Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateCall2 ( Strex , Builder . CreateZExtOrBitCast ( Val , Strex -> getFunctionType ( ) -> getParamType ( 0 ) ) , Addr ) ; } </s>

Perform a store-conditional operation to Addr .


Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calling convention CallConv .


<s> EVT ARMTargetLowering :: getOptimalMemOpType ( uint64_t Size , unsigned DstAlign , unsigned SrcAlign , bool IsMemset , bool ZeroMemset , bool MemcpyStrSrc , MachineFunction & MF ) const { const Function * F = MF . getFunction ( ) ; if ( ( ! IsMemset || ZeroMemset ) && Subtarget -> hasNEON ( ) && ! F -> getAttributes ( ) . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: NoImplicitFloat ) ) { bool Fast ; if ( Size >= 16 && ( memOpAlign ( SrcAlign , DstAlign , 16 ) || ( allowsMisalignedMemoryAccesses ( MVT :: v2f64 , 0 , 1 , & Fast ) && Fast ) ) ) { return MVT :: v2f64 ; } else if ( Size >= 8 && ( memOpAlign ( SrcAlign , DstAlign , 8 ) || ( allowsMisalignedMemoryAccesses ( MVT :: f64 , 0 , 1 , & Fast ) && Fast ) ) ) { return MVT :: f64 ; } } if ( Size >= 4 ) return MVT :: i32 ; else if ( Size >= 2 ) return MVT :: i16 ; return MVT :: Other ; } </s>

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


<s> RCPair ARMTargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: tGPRRegClass ) ; return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'h' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: hGPRRegClass ) ; break ; case 'r' : if ( Subtarget -> isThumb1Only ( ) ) return RCPair ( 0U , & ARM :: tGPRRegClass ) ; return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'w' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPRRegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPRRegClass ) ; break ; case 'x' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPR_8RegClass ) ; break ; case 't' : if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; break ; } } if ( StringRef ( "{cc}" ) . equals_lower ( Constraint ) ) return std :: make_pair ( unsigned ( ARM :: CPSR ) , & ARM :: CCRRegClass ) ; return TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<s> bool ARMTargetLowering :: shouldExpandAtomicLoadInIR ( LoadInst * LI ) const { unsigned Size = LI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; return ( Size == 64 ) && ! Subtarget -> isMClass ( ) ; } </s>


<s> bool ARMTargetLowering :: shouldExpandAtomicRMWInIR ( AtomicRMWInst * AI ) const { unsigned Size = AI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; return Size <= ( Subtarget -> isMClass ( ) ? 32U : 64U ) ; } </s>


<s> bool ARMTargetLowering :: alignLoopsWithOptSize ( ) const { return Subtarget -> isMClass ( ) ; } </s>

Should loops be aligned even when the function is marked OptSize ( but not MinSize ) .


<s> bool ARMTargetLowering :: allowsMisalignedMemoryAccesses ( EVT VT , unsigned , Align Alignment , MachineMemOperand :: Flags , bool * Fast ) const { if ( ! VT . isSimple ( ) ) return false ; bool AllowsUnaligned = Subtarget -> allowsUnalignedMem ( ) ; auto Ty = VT . getSimpleVT ( ) . SimpleTy ; if ( Ty == MVT :: i8 || Ty == MVT :: i16 || Ty == MVT :: i32 ) { if ( AllowsUnaligned ) { if ( Fast ) * Fast = Subtarget -> hasV7Ops ( ) ; return true ; } } if ( Ty == MVT :: f64 || Ty == MVT :: v2f64 ) { if ( Subtarget -> hasNEON ( ) && ( AllowsUnaligned || Subtarget -> isLittle ( ) ) ) { if ( Fast ) * Fast = true ; return true ; } } if ( ! Subtarget -> hasMVEIntegerOps ( ) ) return false ; if ( ( Ty == MVT :: v16i1 || Ty == MVT :: v8i1 || Ty == MVT :: v4i1 ) ) { if ( Fast ) * Fast = true ; return true ; } if ( ( Ty == MVT :: v4i8 || Ty == MVT :: v8i8 || Ty == MVT :: v4i16 ) && Alignment >= VT . getScalarSizeInBits ( ) / 8 ) { if ( Fast ) * Fast = true ; return true ; } if ( Ty == MVT :: v16i8 || Ty == MVT :: v8i16 || Ty == MVT :: v8f16 || Ty == MVT :: v4i32 || Ty == MVT :: v4f32 || Ty == MVT :: v2i64 || Ty == MVT :: v2f64 ) { if ( Fast ) * Fast = true ; return true ; } return false ; } </s>


<s> SDValue ARMTargetLowering :: BuildSDIVPow2 ( SDNode * N , const APInt & Divisor , SelectionDAG & DAG , SmallVectorImpl < SDNode * > & Created ) const { if ( N -> getOpcode ( ) != ISD :: SDIV ) return SDValue ( ) ; const auto & ST = static_cast < const ARMSubtarget & > ( DAG . getSubtarget ( ) ) ; const bool MinSize = ST . hasMinSize ( ) ; const bool HasDivide = ST . isThumb ( ) ? ST . hasDivideInThumbMode ( ) : ST . hasDivideInARMMode ( ) ; if ( N -> getOperand ( 0 ) . getValueType ( ) . isVector ( ) ) return SDValue ( ) ; if ( ! ( MinSize && HasDivide ) ) return SDValue ( ) ; if ( ! ST . isThumb ( ) ) return SDValue ( N , 0 ) ; if ( Divisor . sgt ( 128 ) ) return SDValue ( ) ; return SDValue ( N , 0 ) ; } </s>

Targets may override this function to provide custom SDIV lowering for power-of-2 denominators .


<s>
bool
ARMTargetLowering
::
canCombineStoreAndExtract
(
Type
*
VectorTy
,
Value
*
Idx
,
unsigned
&
Cost
)
const
{
if
(
!
Subtarget
->
hasNEON
(
)
)
return
false
;
if
(
VectorTy
->
isFPOrFPVectorTy
(
)
)
return
false
;
if
(
!
isa
<
ConstantInt
>
(
Idx
)
)
return
false
;
assert
(
VectorTy
->
isVectorTy
(
)
&&
"VectorTy is not a vector type"
)
;
unsigned
BitWidth
=
VectorTy
->
getPrimitiveSizeInBits
(
)
.
getFixedSize
(
)
;
if
(
BitWidth
==
64
||
BitWidth
==
128
)
{
Cost
=
0
;
return
true
;
}
return
false
;
}
</s>

Return true if the target can combine store ( extractelement VectorTy , Idx ) .


<s> bool ARMTargetLowering :: CanLowerReturn ( CallingConv :: ID CallConv , MachineFunction & MF , bool isVarArg , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) const { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , isVarArg , MF , RVLocs , Context ) ; return CCInfo . CheckReturn ( Outs , CCAssignFnForReturn ( CallConv , isVarArg ) ) ; } </s>

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


<s> CCAssignFn * ARMTargetLowering :: CCAssignFnForCall ( CallingConv :: ID CC , bool isVarArg ) const { return CCAssignFnForNode ( CC , false , isVarArg ) ; } </s>

Selects the correct CCAssignFn for a given CallingConvention value .


<s> CCAssignFn * ARMTargetLowering :: CCAssignFnForReturn ( CallingConv :: ID CC , bool isVarArg ) const { return CCAssignFnForNode ( CC , true , isVarArg ) ; } </s>


"Unknown fence ordering in emitLeadingFence"


<s> Value * ARMTargetLowering :: emitLoadLinked ( IRBuilderBase & Builder , Type * ValueTy , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; bool IsAcquire = isAcquireOrStronger ( Ord ) ; if ( ValueTy -> getPrimitiveSizeInBits ( ) == 64 ) { Intrinsic :: ID Int = IsAcquire ? Intrinsic :: arm_ldaexd : Intrinsic :: arm_ldrexd ; Function * Ldrex = Intrinsic :: getDeclaration ( M , Int ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; Value * LoHi = Builder . CreateCall ( Ldrex , Addr , "lohi" ) ; Value * Lo = Builder . CreateExtractValue ( LoHi , 0 , "lo" ) ; Value * Hi = Builder . CreateExtractValue ( LoHi , 1 , "hi" ) ; if ( ! Subtarget -> isLittle ( ) ) std :: swap ( Lo , Hi ) ; Lo = Builder . CreateZExt ( Lo , ValueTy , "lo64" ) ; Hi = Builder . CreateZExt ( Hi , ValueTy , "hi64" ) ; return Builder . CreateOr ( Lo , Builder . CreateShl ( Hi , ConstantInt :: get ( ValueTy , 32 ) ) , "val64" ) ; } Type * Tys [ ] = { Addr -> getType ( ) } ; Intrinsic :: ID Int = IsAcquire ? Intrinsic :: arm_ldaex : Intrinsic :: arm_ldrex ; Function * Ldrex = Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateTruncOrBitCast ( Builder . CreateCall ( Ldrex , Addr ) , ValueTy ) ; } </s>

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


<s> Value * ARMTargetLowering :: emitStoreConditional ( IRBuilderBase & Builder , Value * Val , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; bool IsRelease = isReleaseOrStronger ( Ord ) ; if ( Val -> getType ( ) -> getPrimitiveSizeInBits ( ) == 64 ) { Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlexd : Intrinsic :: arm_strexd ; Function * Strex = Intrinsic :: getDeclaration ( M , Int ) ; Type * Int32Ty = Type :: getInt32Ty ( M -> getContext ( ) ) ; Value * Lo = Builder . CreateTrunc ( Val , Int32Ty , "lo" ) ; Value * Hi = Builder . CreateTrunc ( Builder . CreateLShr ( Val , 32 ) , Int32Ty , "hi" ) ; if ( ! Subtarget -> isLittle ( ) ) std :: swap ( Lo , Hi ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; return Builder . CreateCall ( Strex , { Lo , Hi , Addr } ) ; } Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlex : Intrinsic :: arm_strex ; Type * Tys [ ] = { Addr -> getType ( ) } ; Function * Strex = Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateCall ( Strex , { Builder . CreateZExtOrBitCast ( Val , Strex -> getFunctionType ( ) -> getParamType ( 0 ) ) , Addr } ) ; } </s>


<s>
bool
ARMTargetLowering
::
ExpandInlineAsm
(
CallInst
*
CI
)
const
{
if
(
!
Subtarget
->
hasV6Ops
(
)
)
return
false
;
InlineAsm
*
IA
=
cast
<
InlineAsm
>
(
CI
->
getCalledOperand
(
)
)
;
std
::
string
AsmStr
=
IA
->
getAsmString
(
)
;
SmallVector
<
StringRef
,
4
>
AsmPieces
;
SplitString
(
AsmStr
,
AsmPieces
,
";\n"
)
;
switch
(
AsmPieces
.
size
(
)
)
{
default
:
return
false
;
case
1
:
AsmStr
=
std
::
string
(
AsmPieces
[
0
]
)
;
AsmPieces
.
clear
(
)
;
SplitString
(
AsmStr
,
AsmPieces
,
" \t,"
)
;
if
(
AsmPieces
.
size
(
)
==
3
&&
AsmPieces
[
0
]
==
"rev"
&&
AsmPieces
[
1
]
==
"$0"
&&
AsmPieces
[
2
]
==
"$1"
&&
IA
->
getConstraintString
(
)
.
compare
(
0
,
4
,
"=l,l"
)
==
0
)
{
IntegerType
*
Ty
=
dyn_cast
<
IntegerType
>
(
CI
->
getType
(
)
)
;
if
(
Ty
&&
Ty
->
getBitWidth
(
)
==
32
)
return
IntrinsicLowering
::
LowerToByteSwap
(
CI
)
;
}
break
;
}
return
false
;
}
</s>

This hook allows the target to expand an inline asm call to be explicit llvm code if it wants to .


<s> void ARMTargetLowering :: finalizeLowering ( MachineFunction & MF ) const { MF . getFrameInfo ( ) . computeMaxCallFrameSize ( MF ) ; TargetLoweringBase :: finalizeLowering ( MF ) ; } </s>

Execute target specific actions to finalize target lowering .


<s> Align ARMTargetLowering :: getABIAlignmentForCallingConv ( Type * ArgTy , const DataLayout & DL ) const { const Align ABITypeAlign = DL . getABITypeAlign ( ArgTy ) ; if ( ! ArgTy -> isVectorTy ( ) ) return ABITypeAlign ; return std :: min ( ABITypeAlign , DL . getStackAlignment ( ) ) ; } </s>

Return the correct alignment for the current calling convention .


<s> ARMTargetLowering :: ConstraintType ARMTargetLowering :: getConstraintType ( StringRef Constraint ) const { unsigned S = Constraint . size ( ) ; if ( S == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'l' : return C_RegisterClass ; case 'w' : return C_RegisterClass ; case 'h' : return C_RegisterClass ; case 'x' : return C_RegisterClass ; case 't' : return C_RegisterClass ; case 'j' : return C_Immediate ; case 'Q' : return C_Memory ; } } else if ( S == 2 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'T' : return C_RegisterClass ; case 'U' : return C_Memory ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

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


<s> Register ARMTargetLowering :: getExceptionPointerRegister ( const Constant * PersonalityFn ) const { return Subtarget -> useSjLjEH ( ) ? Register ( ) : ARM :: R0 ; } </s>

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


<s> Register ARMTargetLowering :: getExceptionSelectorRegister ( const Constant * PersonalityFn ) const { return Subtarget -> useSjLjEH ( ) ? Register ( ) : ARM :: R1 ; } </s>

If a physical register , this returns the register that receives the exception typeid on entry to a landing pad .


<s> unsigned ARMTargetLowering :: getMaxSupportedInterleaveFactor ( ) const { if ( Subtarget -> hasNEON ( ) ) return 4 ; if ( Subtarget -> hasMVEIntegerOps ( ) ) return MVEMaxSupportedInterleaveFactor ; return TargetLoweringBase :: getMaxSupportedInterleaveFactor ( ) ; } </s>

Get the maximum supported factor for interleaved memory accesses .


<s> unsigned ARMTargetLowering :: getNumInterleavedAccesses ( VectorType * VecTy , const DataLayout & DL ) const { return ( DL . getTypeSizeInBits ( VecTy ) + 127 ) / 128 ; } </s>

Returns the number of interleaved accesses that will be generated when lowering accesses of the given type .


<s> EVT ARMTargetLowering :: getOptimalMemOpType ( const MemOp & Op , const AttributeList & FuncAttributes ) const { if ( ( Op . isMemcpy ( ) || Op . isZeroMemset ( ) ) && Subtarget -> hasNEON ( ) && ! FuncAttributes . hasFnAttr ( Attribute :: NoImplicitFloat ) ) { bool Fast ; if ( Op . size ( ) >= 16 && ( Op . isAligned ( Align ( 16 ) ) || ( allowsMisalignedMemoryAccesses ( MVT :: v2f64 , 0 , Align ( 1 ) , MachineMemOperand :: MONone , & Fast ) && Fast ) ) ) { return MVT :: v2f64 ; } else if ( Op . size ( ) >= 8 && ( Op . isAligned ( Align ( 8 ) ) || ( allowsMisalignedMemoryAccesses ( MVT :: f64 , 0 , Align ( 1 ) , MachineMemOperand :: MONone , & Fast ) && Fast ) ) ) { return MVT :: f64 ; } } return MVT :: Other ; } </s>


<s> bool ARMTargetLowering :: getPreIndexedAddressParts ( SDNode * N , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb1Only ( ) ) return false ; EVT VT ; SDValue Ptr ; Align Alignment ; bool isSEXTLoad = false ; bool IsMasked = false ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { Ptr = LD -> getBasePtr ( ) ; VT = LD -> getMemoryVT ( ) ; Alignment = LD -> getAlign ( ) ; isSEXTLoad = LD -> getExtensionType ( ) == ISD :: SEXTLOAD ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { Ptr = ST -> getBasePtr ( ) ; VT = ST -> getMemoryVT ( ) ; Alignment = ST -> getAlign ( ) ; } else if ( MaskedLoadSDNode * LD = dyn_cast < MaskedLoadSDNode > ( N ) ) { Ptr = LD -> getBasePtr ( ) ; VT = LD -> getMemoryVT ( ) ; Alignment = LD -> getAlign ( ) ; isSEXTLoad = LD -> getExtensionType ( ) == ISD :: SEXTLOAD ; IsMasked = true ; } else if ( MaskedStoreSDNode * ST = dyn_cast < MaskedStoreSDNode > ( N ) ) { Ptr = ST -> getBasePtr ( ) ; VT = ST -> getMemoryVT ( ) ; Alignment = ST -> getAlign ( ) ; IsMasked = true ; } else return false ; bool isInc ; bool isLegal = false ; if ( VT . isVector ( ) ) isLegal = Subtarget -> hasMVEIntegerOps ( ) && getMVEIndexedAddressParts ( Ptr . getNode ( ) , VT , Alignment , isSEXTLoad , IsMasked , Subtarget -> isLittle ( ) , Base , Offset , isInc , DAG ) ; else { if ( Subtarget -> isThumb2 ( ) ) isLegal = getT2IndexedAddressParts ( Ptr . getNode ( ) , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; else isLegal = getARMIndexedAddressParts ( Ptr . getNode ( ) , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; } if ( ! isLegal ) return false ; AM = isInc ? ISD :: PRE_INC : ISD :: PRE_DEC ; return true ; } </s>

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

ARM ARM ISD::MemIndexedMode ISD::SEXTLOAD ISD::SEXTLOAD ARM ISD::PRE_INC ISD::PRE_DEC


<s> const TargetRegisterClass * ARMTargetLowering :: getRegClassFor ( MVT VT , bool isDivergent ) const { ( void ) isDivergent ; if ( Subtarget -> hasNEON ( ) ) { if ( VT == MVT :: v4i64 ) return & ARM :: QQPRRegClass ; if ( VT == MVT :: v8i64 ) return & ARM :: QQQQPRRegClass ; } if ( Subtarget -> hasMVEIntegerOps ( ) ) { if ( VT == MVT :: v4i64 ) return & ARM :: MQQPRRegClass ; if ( VT == MVT :: v8i64 ) return & ARM :: MQQQQPRRegClass ; } return TargetLowering :: getRegClassFor ( VT ) ; } </s>

Return the register class that should be used for the specified value type .


<s> RCPair ARMTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { switch ( Constraint . size ( ) ) { case 1 : switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: tGPRRegClass ) ; return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'h' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: hGPRRegClass ) ; break ; case 'r' : if ( Subtarget -> isThumb1Only ( ) ) return RCPair ( 0U , & ARM :: tGPRRegClass ) ; return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'w' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPRRegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPRRegClass ) ; break ; case 'x' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPR_8RegClass ) ; break ; case 't' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 || VT == MVT :: i32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPR_VFP2RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPR_VFP2RegClass ) ; break ; } break ; case 2 : if ( Constraint [ 0 ] == 'T' ) { switch ( Constraint [ 1 ] ) { default : break ; case 'e' : return RCPair ( 0U , & ARM :: tGPREvenRegClass ) ; case 'o' : return RCPair ( 0U , & ARM :: tGPROddRegClass ) ; } } break ; default : break ; } if ( StringRef ( "{cc}" ) . equals_insensitive ( Constraint ) ) return std :: make_pair ( unsigned ( ARM :: CPSR ) , & ARM :: CCRRegClass ) ; return TargetLowering :: getRegForInlineAsmConstraint ( TRI , Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<s>
Register
ARMTargetLowering
::
getRegisterByName
(
const
char
*
RegName
,
LLT
VT
,
const
MachineFunction
&
MF
)
const
{
Register
Reg
=
StringSwitch
<
unsigned
>
(
RegName
)
.
Case
(
"sp"
,
ARM
::
SP
)
.
Default
(
0
)
;
if
(
Reg
)
return
Reg
;
report_fatal_error
(
Twine
(
"Invalid register name \""
+
StringRef
(
RegName
)
+
"\"."
)
)
;
}
</s>

Return the register ID of the name passed in .

ARM
ARM
"sp"
ARM::SP
0
"Invalid register name \""
"\"."


<s> InstructionCost ARMTargetLowering :: getScalingFactorCost ( const DataLayout & DL , const AddrMode & AM , Type * Ty , unsigned AS ) const { if ( isLegalAddressingMode ( DL , AM , Ty , AS ) ) { if ( Subtarget -> hasFPAO ( ) ) return AM . Scale < 0 ? 1 : 0 ; return 0 ; } return - 1 ; } </s>

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


<s> Value * ARMTargetLowering :: getSDagStackGuard ( const Module & M ) const { if ( Subtarget -> getTargetTriple ( ) . isWindowsMSVCEnvironment ( ) ) return M . getGlobalVariable ( "__security_cookie" ) ; return TargetLowering :: getSDagStackGuard ( M ) ; } </s>

Return the variable that 's previously inserted by insertSSPDeclarations , if any , otherwise return nullptr .


<s> EVT ARMTargetLowering :: getSetCCResultType ( const DataLayout & DL , LLVMContext & , EVT VT ) const { if ( ! VT . isVector ( ) ) return getPointerTy ( DL ) ; if ( ( Subtarget -> hasMVEIntegerOps ( ) && ( VT == MVT :: v4i32 || VT == MVT :: v8i16 || VT == MVT :: v16i8 ) ) || ( Subtarget -> hasMVEFloatOps ( ) && ( VT == MVT :: v4f32 || VT == MVT :: v8f16 ) ) ) return MVT :: getVectorVT ( MVT :: i1 , VT . getVectorElementCount ( ) ) ; return VT . changeVectorElementTypeToInteger ( ) ; } </s>

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


<s> Function * ARMTargetLowering :: getSSPStackGuardCheck ( const Module & M ) const { if ( Subtarget -> getTargetTriple ( ) . isWindowsMSVCEnvironment ( ) ) return M . getFunction ( "__security_check_cookie" ) ; return TargetLowering :: getSSPStackGuardCheck ( M ) ; } </s>

If the target has a standard stack protection check function that performs validation and error handling , returns the function .


<s> void ARMTargetLowering :: HandleByVal ( CCState * State , unsigned & Size , Align Alignment ) const { Alignment = std :: max ( Alignment , Align ( 4 ) ) ; unsigned Reg = State -> AllocateReg ( GPRArgRegs ) ; if ( ! Reg ) return ; unsigned AlignInRegs = Alignment . value ( ) / 4 ; unsigned Waste = ( ARM :: R4 - Reg ) % AlignInRegs ; for ( unsigned i = 0 ; i < Waste ; ++ i ) Reg = State -> AllocateReg ( GPRArgRegs ) ; if ( ! Reg ) return ; unsigned Excess = 4 * ( ARM :: R4 - Reg ) ; const unsigned NSAAOffset = State -> getNextStackOffset ( ) ; if ( NSAAOffset != 0 && Size > Excess ) { while ( State -> AllocateReg ( GPRArgRegs ) ) ; return ; } unsigned ByValRegBegin = Reg ; unsigned ByValRegEnd = std :: min < unsigned > ( Reg + Size / 4 , ARM :: R4 ) ; State -> addInRegsParamInfo ( ByValRegBegin , ByValRegEnd ) ; for ( unsigned i = Reg + 1 ; i != ByValRegEnd ; ++ i ) State -> AllocateReg ( GPRArgRegs ) ; Size = std :: max < int > ( Size - Excess , 0 ) ; } </s>

Target-specific cleanup for formal ByVal parameters .


<s> void ARMTargetLowering :: initializeSplitCSR ( MachineBasicBlock * Entry ) const { ARMFunctionInfo * AFI = Entry -> getParent ( ) -> getInfo < ARMFunctionInfo > ( ) ; AFI -> setIsSplitCSR ( true ) ; } </s>

Perform necessary initialization to handle a subset of CSRs explicitly via copies .


"Unexpected register class in CSRsViaCopy!"

"Function should be nounwind in insertCopiesSplitCSR!"

Insert explicit copies in entry and exit blocks .


<s> void ARMTargetLowering :: insertSSPDeclarations ( Module & M ) const { if ( ! Subtarget -> getTargetTriple ( ) . isWindowsMSVCEnvironment ( ) ) return TargetLowering :: insertSSPDeclarations ( M ) ; M . getOrInsertGlobal ( "__security_cookie" , Type :: getInt8PtrTy ( M . getContext ( ) ) ) ; FunctionCallee SecurityCheckCookie = M . getOrInsertFunction ( "__security_check_cookie" , Type :: getVoidTy ( M . getContext ( ) ) , Type :: getInt8PtrTy ( M . getContext ( ) ) ) ; if ( Function * F = dyn_cast < Function > ( SecurityCheckCookie . getCallee ( ) ) ) F -> addParamAttr ( 0 , Attribute :: AttrKind :: InReg ) ; } </s>

Inserts necessary declarations for SSP ( stack protection ) purpose .


<s> bool ARMTargetLowering :: isDesirableToCommuteWithShift ( const SDNode * N , CombineLevel Level ) const { if ( Level == BeforeLegalizeTypes ) return true ; if ( N -> getOpcode ( ) != ISD :: SHL ) return true ; if ( Subtarget -> isThumb1Only ( ) ) { if ( N -> getOpcode ( ) != ISD :: SHL ) return true ; SDValue N1 = N -> getOperand ( 0 ) ; if ( N1 -> getOpcode ( ) != ISD :: ADD && N1 -> getOpcode ( ) != ISD :: AND && N1 -> getOpcode ( ) != ISD :: OR && N1 -> getOpcode ( ) != ISD :: XOR ) return true ; if ( auto * Const = dyn_cast < ConstantSDNode > ( N1 -> getOperand ( 1 ) ) ) { if ( Const -> getAPIntValue ( ) . ult ( 256 ) ) return false ; if ( N1 -> getOpcode ( ) == ISD :: ADD && Const -> getAPIntValue ( ) . slt ( 0 ) && Const -> getAPIntValue ( ) . sgt ( - 256 ) ) return false ; } return true ; } return false ; } </s>

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


<s> bool ARMTargetLowering :: isExtractSubvectorCheap ( EVT ResVT , EVT SrcVT , unsigned Index ) const { if ( ! isOperationLegalOrCustom ( ISD :: EXTRACT_SUBVECTOR , ResVT ) ) return false ; return ( Index == 0 || Index == ResVT . getVectorNumElements ( ) ) ; } </s>

Return true if EXTRACT_SUBVECTOR is cheap for this result type with this index .


<s> bool ARMTargetLowering :: isFMAFasterThanFMulAndFAdd ( const MachineFunction & MF , EVT VT ) const { if ( ! VT . isSimple ( ) ) return false ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { case MVT :: v4f32 : case MVT :: v8f16 : return Subtarget -> hasMVEFloatOps ( ) ; case MVT :: f16 : return Subtarget -> useFPVFMx16 ( ) ; case MVT :: f32 : return Subtarget -> useFPVFMx ( ) ; case MVT :: f64 : return Subtarget -> useFPVFMx64 ( ) ; default : break ; } return false ; } </s>

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


<s> bool ARMTargetLowering :: isFNegFree ( EVT VT ) const { if ( ! VT . isSimple ( ) ) return false ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { default : break ; case MVT :: f16 : return Subtarget -> hasFullFP16 ( ) ; } return false ; } </s>

Return true if an fneg operation is free to the point where it is never worthwhile to replace it with a bitwise operation .


<s> bool ARMTargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT , bool ForCodeSize ) const { if ( ! Subtarget -> hasVFP3Base ( ) ) return false ; if ( VT == MVT :: f16 && Subtarget -> hasFullFP16 ( ) ) return ARM_AM :: getFP16Imm ( Imm ) != - 1 ; if ( VT == MVT :: f32 && Subtarget -> hasFullFP16 ( ) && ARM_AM :: getFP32FP16Imm ( Imm ) != - 1 ) return true ; if ( VT == MVT :: f32 ) return ARM_AM :: getFP32Imm ( Imm ) != - 1 ; if ( VT == MVT :: f64 && Subtarget -> hasFP64 ( ) ) return ARM_AM :: getFP64Imm ( Imm ) != - 1 ; return false ; } </s>

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


<s> bool ARMTargetLowering :: isLegalAddressingMode ( const DataLayout & DL , const AddrMode & AM , Type * Ty , unsigned AS , Instruction * I ) const { EVT VT = getValueType ( DL , Ty , true ) ; if ( ! isLegalAddressImmediate ( AM . BaseOffs , VT , Subtarget ) ) return false ; if ( AM . BaseGV ) return false ; switch ( AM . Scale ) { case 0 : break ; default : if ( AM . BaseOffs ) return false ; if ( ! VT . isSimple ( ) ) return false ; if ( Subtarget -> isThumb1Only ( ) ) return isLegalT1ScaledAddressingMode ( AM , VT ) ; if ( Subtarget -> isThumb2 ( ) ) return isLegalT2ScaledAddressingMode ( AM , VT ) ; int Scale = AM . Scale ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { default : return false ; case MVT :: i1 : case MVT :: i8 : case MVT :: i32 : if ( Scale < 0 ) Scale = - Scale ; if ( Scale == 1 ) return true ; return isPowerOf2_32 ( Scale & ~ 1 ) ; case MVT :: i16 : case MVT :: i64 : if ( Scale == 1 || ( AM . HasBaseReg && Scale == - 1 ) ) return true ; if ( ! AM . HasBaseReg && Scale == 2 ) return true ; return false ; case MVT :: isVoid : if ( Scale & 1 ) return false ; return isPowerOf2_32 ( Scale ) ; } } return true ; } </s>

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


<s> bool ARMTargetLowering :: isLegalICmpImmediate ( int64_t Imm ) const { if ( ! Subtarget -> isThumb ( ) ) return ARM_AM :: getSOImmVal ( ( uint32_t ) Imm ) != - 1 || ARM_AM :: getSOImmVal ( - ( uint32_t ) Imm ) != - 1 ; if ( Subtarget -> isThumb2 ( ) ) return ARM_AM :: getT2SOImmVal ( ( uint32_t ) Imm ) != - 1 || ARM_AM :: getT2SOImmVal ( - ( uint32_t ) Imm ) != - 1 ; return Imm >= 0 && Imm <= 255 ; } </s>

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


<s> bool ARMTargetLowering :: isLegalInterleavedAccessType ( unsigned Factor , FixedVectorType * VecTy , Align Alignment , const DataLayout & DL ) const { unsigned VecSize = DL . getTypeSizeInBits ( VecTy ) ; unsigned ElSize = DL . getTypeSizeInBits ( VecTy -> getElementType ( ) ) ; if ( ! Subtarget -> hasNEON ( ) && ! Subtarget -> hasMVEIntegerOps ( ) ) return false ; if ( Subtarget -> hasNEON ( ) && VecTy -> getElementType ( ) -> isHalfTy ( ) ) return false ; if ( Subtarget -> hasMVEIntegerOps ( ) && Factor == 3 ) return false ; if ( VecTy -> getNumElements ( ) < 2 ) return false ; if ( ElSize != 8 && ElSize != 16 && ElSize != 32 ) return false ; if ( Subtarget -> hasMVEIntegerOps ( ) && Alignment < ElSize / 8 ) return false ; if ( Subtarget -> hasNEON ( ) && VecSize == 64 ) return true ; return VecSize % 128 == 0 ; } </s>

Returns whether or not generating a interleaved load/store intrinsic for this type will be legal .


<s> bool ARMTargetLowering :: isLegalT1ScaledAddressingMode ( const AddrMode & AM , EVT VT ) const { const int Scale = AM . Scale ; if ( Scale < 0 ) return false ; return ( Scale == 1 ) || ( ! AM . HasBaseReg && Scale == 2 ) ; } </s>

Returns true if the addressing mode representing by AM is legal for the Thumb1 target , for a load/store of the specified type .


<s> bool ARMTargetLowering :: isMulAddWithConstProfitable ( const SDValue & AddNode , const SDValue & ConstNode ) const { const EVT VT = AddNode . getValueType ( ) ; if ( VT . isVector ( ) || VT . getScalarSizeInBits ( ) > 32 ) return true ; const ConstantSDNode * C0Node = cast < ConstantSDNode > ( AddNode . getOperand ( 1 ) ) ; const ConstantSDNode * C1Node = cast < ConstantSDNode > ( ConstNode ) ; const int64_t C0 = C0Node -> getSExtValue ( ) ; APInt CA = C0Node -> getAPIntValue ( ) * C1Node -> getAPIntValue ( ) ; if ( ! isLegalAddImmediate ( C0 ) || isLegalAddImmediate ( CA . getSExtValue ( ) ) ) return true ; if ( ConstantMaterializationCost ( ( unsigned ) CA . getZExtValue ( ) , Subtarget ) > 1 ) return false ; return true ; } </s>

Return true if it may be profitable to transform ( mul ( add x , c1 ) , c2 ) - > ( add ( mul x , c2 ) , c1 * c2 ) .


<s> bool ARMTargetLowering :: isShuffleMaskLegal ( ArrayRef < int > M , EVT VT ) const { if ( VT . getVectorNumElements ( ) == 4 && ( VT . is128BitVector ( ) || VT . is64BitVector ( ) ) ) { unsigned PFIndexes [ 4 ] ; for ( unsigned i = 0 ; i != 4 ; ++ i ) { if ( M [ i ] < 0 ) PFIndexes [ i ] = 8 ; else PFIndexes [ i ] = M [ i ] ; } unsigned PFTableIndex = PFIndexes [ 0 ] * 9 * 9 * 9 + PFIndexes [ 1 ] * 9 * 9 + PFIndexes [ 2 ] * 9 + PFIndexes [ 3 ] ; unsigned PFEntry = PerfectShuffleTable [ PFTableIndex ] ; unsigned Cost = ( PFEntry >> 30 ) ; if ( Cost <= 4 && ( Subtarget -> hasNEON ( ) || isLegalMVEShuffleOp ( PFEntry ) ) ) return true ; } bool ReverseVEXT , isV_UNDEF ; unsigned Imm , WhichResult ; unsigned EltSize = VT . getScalarSizeInBits ( ) ; if ( EltSize >= 32 || ShuffleVectorSDNode :: isSplatMask ( & M [ 0 ] , VT ) || ShuffleVectorInst :: isIdentityMask ( M ) || isVREVMask ( M , VT , 64 ) || isVREVMask ( M , VT , 32 ) || isVREVMask ( M , VT , 16 ) ) return true ; else if ( Subtarget -> hasNEON ( ) && ( isVEXTMask ( M , VT , ReverseVEXT , Imm ) || isVTBLMask ( M , VT ) || isNEONTwoResultShuffleMask ( M , VT , WhichResult , isV_UNDEF ) ) ) return true ; else if ( ( VT == MVT :: v8i16 || VT == MVT :: v8f16 || VT == MVT :: v16i8 ) && isReverseMask ( M , VT ) ) return true ; else if ( Subtarget -> hasMVEIntegerOps ( ) && ( isVMOVNMask ( M , VT , true , false ) || isVMOVNMask ( M , VT , false , false ) || isVMOVNMask ( M , VT , true , true ) ) ) return true ; else return false ; } </s>

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


<s> bool ARMTargetLowering :: isTruncateFree ( EVT SrcVT , EVT DstVT ) const { if ( SrcVT . isVector ( ) || DstVT . isVector ( ) || ! SrcVT . isInteger ( ) || ! DstVT . isInteger ( ) ) return false ; unsigned SrcBits = SrcVT . getSizeInBits ( ) ; unsigned DestBits = DstVT . getSizeInBits ( ) ; return ( SrcBits == 64 && DestBits == 32 ) ; } </s>

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


<s> bool ARMTargetLowering :: isVectorLoadExtDesirable ( SDValue ExtVal ) const { EVT VT = ExtVal . getValueType ( ) ; if ( ! isTypeLegal ( VT ) ) return false ; if ( auto * Ld = dyn_cast < MaskedLoadSDNode > ( ExtVal . getOperand ( 0 ) ) ) { if ( Ld -> isExpandingLoad ( ) ) return false ; } if ( Subtarget -> hasMVEIntegerOps ( ) ) return true ; if ( ExtVal -> use_empty ( ) || ! ExtVal -> use_begin ( ) -> isOnlyUserOf ( ExtVal . getNode ( ) ) ) return true ; SDNode * U = * ExtVal -> use_begin ( ) ; if ( ( U -> getOpcode ( ) == ISD :: ADD || U -> getOpcode ( ) == ISD :: SUB || U -> getOpcode ( ) == ISD :: SHL || U -> getOpcode ( ) == ARMISD :: VSHLIMM ) ) return false ; return true ; } </s>

Return true if folding a vector load into ExtVal ( a sign , zero , or any extend node ) is profitable .

ARM ARM 0 ISD::ADD ISD::SUB ISD::SHL ARMISD::VSHLIMM


<s> SDValue ARMTargetLowering :: joinRegisterPartsIntoValue ( SelectionDAG & DAG , const SDLoc & DL , const SDValue * Parts , unsigned NumParts , MVT PartVT , EVT ValueVT , Optional < CallingConv :: ID > CC ) const { bool IsABIRegCopy = CC . hasValue ( ) ; if ( IsABIRegCopy && ( ValueVT == MVT :: f16 || ValueVT == MVT :: bf16 ) && PartVT == MVT :: f32 ) { unsigned ValueBits = ValueVT . getSizeInBits ( ) ; unsigned PartBits = PartVT . getSizeInBits ( ) ; SDValue Val = Parts [ 0 ] ; Val = DAG . getNode ( ISD :: BITCAST , DL , MVT :: getIntegerVT ( PartBits ) , Val ) ; Val = DAG . getNode ( ISD :: TRUNCATE , DL , MVT :: getIntegerVT ( ValueBits ) , Val ) ; Val = DAG . getNode ( ISD :: BITCAST , DL , ValueVT , Val ) ; return Val ; } return SDValue ( ) ; } </s>

Target-specific combining of register parts into its original value .


<s> const char * ARMTargetLowering :: LowerXConstraint ( EVT ConstraintVT ) const { if ( ! Subtarget -> hasVFP2Base ( ) ) return "r" ; if ( ConstraintVT . isFloatingPoint ( ) ) return "w" ; if ( ConstraintVT . isVector ( ) && Subtarget -> hasNEON ( ) && ( ConstraintVT . getSizeInBits ( ) == 64 || ConstraintVT . getSizeInBits ( ) == 128 ) ) return "w" ; return "r" ; } </s>

Try to replace an X constraint , which matches anything , with another that has more specific requirements based on the type of the corresponding operand .


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

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


<s> SDValue ARMTargetLowering :: PerformBRCONDCombine ( SDNode * N , SelectionDAG & DAG ) const { SDValue Cmp = N -> getOperand ( 4 ) ; if ( Cmp . getOpcode ( ) != ARMISD :: CMPZ ) return SDValue ( ) ; EVT VT = N -> getValueType ( 0 ) ; SDLoc dl ( N ) ; SDValue LHS = Cmp . getOperand ( 0 ) ; SDValue RHS = Cmp . getOperand ( 1 ) ; SDValue Chain = N -> getOperand ( 0 ) ; SDValue BB = N -> getOperand ( 1 ) ; SDValue ARMcc = N -> getOperand ( 2 ) ; ARMCC :: CondCodes CC = ( ARMCC :: CondCodes ) cast < ConstantSDNode > ( ARMcc ) -> getZExtValue ( ) ; if ( CC == ARMCC :: NE && LHS . getOpcode ( ) == ISD :: AND && LHS -> hasOneUse ( ) && LHS -> getOperand ( 0 ) -> getOpcode ( ) == ARMISD :: CMOV && LHS -> getOperand ( 0 ) -> hasOneUse ( ) ) { auto * LHS00C = dyn_cast < ConstantSDNode > ( LHS -> getOperand ( 0 ) -> getOperand ( 0 ) ) ; auto * LHS01C = dyn_cast < ConstantSDNode > ( LHS -> getOperand ( 0 ) -> getOperand ( 1 ) ) ; auto * LHS1C = dyn_cast < ConstantSDNode > ( LHS -> getOperand ( 1 ) ) ; auto * RHSC = dyn_cast < ConstantSDNode > ( RHS ) ; if ( ( LHS00C && LHS00C -> getZExtValue ( ) == 0 ) && ( LHS01C && LHS01C -> getZExtValue ( ) == 1 ) && ( LHS1C && LHS1C -> getZExtValue ( ) == 1 ) && ( RHSC && RHSC -> getZExtValue ( ) == 0 ) ) { return DAG . getNode ( ARMISD :: BRCOND , dl , VT , Chain , BB , LHS -> getOperand ( 0 ) -> getOperand ( 2 ) , LHS -> getOperand ( 0 ) -> getOperand ( 3 ) , LHS -> getOperand ( 0 ) -> getOperand ( 4 ) ) ; } } return SDValue ( ) ; } </s>

PerformBRCONDCombine - Target-specific DAG combining for ARMISD : :BRCOND .


<s> bool ARMTargetLowering :: preferIncOfAddToSubOfNot ( EVT VT ) const { if ( ! Subtarget -> hasNEON ( ) ) { if ( Subtarget -> isThumb1Only ( ) ) return VT . getScalarSizeInBits ( ) <= 32 ; return true ; } return VT . isScalarInteger ( ) ; } </s>

These two forms are equivalent : sub y , ( xor x , -1 ) add ( add x , 1 ) , y The variant with two add 's is IR-canonical .


<s>
void
ARMTargetLowering
::
ReplaceNodeResults
(
SDNode
*
N
,
SmallVectorImpl
<
SDValue
>
&
Results
,
SelectionDAG
&
DAG
)
const
{
SDValue
Res
;
switch
(
N
->
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom expand this!"
)
;
case
ISD
::
READ_REGISTER
:
ExpandREAD_REGISTER
(
N
,
Results
,
DAG
)
;
break
;
case
ISD
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
case
ISD
::
SHL
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
SREM
:
case
ISD
::
UREM
:
Res
=
LowerREM
(
N
,
DAG
)
;
break
;
case
ISD
::
SDIVREM
:
case
ISD
::
UDIVREM
:
Res
=
LowerDivRem
(
SDValue
(
N
,
0
)
,
DAG
)
;
assert
(
Res
.
getNumOperands
(
)
==
2
&&
"DivRem needs two values"
)
;
Results
.
push_back
(
Res
.
getValue
(
0
)
)
;
Results
.
push_back
(
Res
.
getValue
(
1
)
)
;
return
;
case
ISD
::
SADDSAT
:
case
ISD
::
SSUBSAT
:
case
ISD
::
UADDSAT
:
case
ISD
::
USUBSAT
:
Res
=
LowerADDSUBSAT
(
SDValue
(
N
,
0
)
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
READCYCLECOUNTER
:
ReplaceREADCYCLECOUNTER
(
N
,
Results
,
DAG
,
Subtarget
)
;
return
;
case
ISD
::
UDIV
:
case
ISD
::
SDIV
:
assert
(
Subtarget
->
isTargetWindows
(
)
&&
"can only expand DIV on Windows"
)
;
return
ExpandDIV_Windows
(
SDValue
(
N
,
0
)
,
DAG
,
N
->
getOpcode
(
)
==
ISD
::
SDIV
,
Results
)
;
case
ISD
::
ATOMIC_CMP_SWAP
:
ReplaceCMP_SWAP_64Results
(
N
,
Results
,
DAG
)
;
return
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
ReplaceLongIntrinsic
(
N
,
Results
,
DAG
)
;
case
ISD
::
ABS
:
lowerABS
(
N
,
Results
,
DAG
)
;
return
;
case
ISD
::
LOAD
:
LowerLOAD
(
N
,
Results
,
DAG
)
;
break
;
case
ISD
::
TRUNCATE
:
Res
=
LowerTruncate
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
SIGN_EXTEND
:
case
ISD
::
ZERO_EXTEND
:
Res
=
LowerVectorExtend
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
FP_TO_SINT_SAT
:
case
ISD
::
FP_TO_UINT_SAT
:
Res
=
LowerFP_TO_INT_SAT
(
SDValue
(
N
,
0
)
,
DAG
,
Subtarget
)
;
break
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>

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


<s> Type * ARMTargetLowering :: shouldConvertSplatType ( ShuffleVectorInst * SVI ) const { if ( ! Subtarget -> hasMVEIntegerOps ( ) ) return nullptr ; Type * SVIType = SVI -> getType ( ) ; Type * ScalarType = SVIType -> getScalarType ( ) ; if ( ScalarType -> isFloatTy ( ) ) return Type :: getInt32Ty ( SVIType -> getContext ( ) ) ; if ( ScalarType -> isHalfTy ( ) ) return Type :: getInt16Ty ( SVIType -> getContext ( ) ) ; return nullptr ; } </s>

Given a shuffle vector SVI representing a vector splat , return a new scalar type of size equal to SVI 's scalar type if the new type is more profitable .


<s> TargetLowering :: AtomicExpansionKind ARMTargetLowering :: shouldExpandAtomicCmpXchgInIR ( AtomicCmpXchgInst * AI ) const { unsigned Size = AI -> getOperand ( 1 ) -> getType ( ) -> getPrimitiveSizeInBits ( ) ; bool HasAtomicCmpXchg = ! Subtarget -> isThumb ( ) || Subtarget -> hasV8MBaselineOps ( ) ; if ( getTargetMachine ( ) . getOptLevel ( ) != 0 && HasAtomicCmpXchg && Size <= ( Subtarget -> isMClass ( ) ? 32U : 64U ) ) return AtomicExpansionKind :: LLSC ; return AtomicExpansionKind :: None ; } </s>

Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass .


<s> TargetLowering :: AtomicExpansionKind ARMTargetLowering :: shouldExpandAtomicRMWInIR ( AtomicRMWInst * AI ) const { if ( AI -> isFloatingPointOperation ( ) ) return AtomicExpansionKind :: CmpXChg ; if ( getTargetMachine ( ) . getOptLevel ( ) == CodeGenOpt :: None ) return AtomicExpansionKind :: CmpXChg ; unsigned Size = AI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; bool hasAtomicRMW = ! Subtarget -> isThumb ( ) || Subtarget -> hasV8MBaselineOps ( ) ; return ( Size <= ( Subtarget -> isMClass ( ) ? 32U : 64U ) && hasAtomicRMW ) ? AtomicExpansionKind :: LLSC : AtomicExpansionKind :: None ; } </s>

Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW , if at all .


<s> bool ARMTargetLowering :: shouldFoldConstantShiftPairToMask ( const SDNode * N , CombineLevel Level ) const { if ( ! Subtarget -> isThumb1Only ( ) ) return true ; if ( Level == BeforeLegalizeTypes ) return true ; return false ; } </s>

Return true if it is profitable to fold a pair of shifts into a mask .


<s> bool ARMTargetLowering :: shouldInsertFencesForAtomic ( const Instruction * I ) const { return InsertFencesForAtomic ; } </s>

Helper functions for atomic operations .


<s> bool ARMTargetLowering :: SimplifyDemandedBitsForTargetNode ( SDValue Op , const APInt & OriginalDemandedBits , const APInt & OriginalDemandedElts , KnownBits & Known , TargetLoweringOpt & TLO , unsigned Depth ) const { unsigned Opc = Op . getOpcode ( ) ; switch ( Opc ) { case ARMISD :: ASRL : case ARMISD :: LSRL : { if ( Op . getResNo ( ) == 0 && ! Op -> hasAnyUseOfValue ( 1 ) && isa < ConstantSDNode > ( Op -> getOperand ( 2 ) ) ) { unsigned ShAmt = Op -> getConstantOperandVal ( 2 ) ; if ( ShAmt < 32 && OriginalDemandedBits . isSubsetOf ( APInt :: getAllOnes ( 32 ) << ( 32 - ShAmt ) ) ) return TLO . CombineTo ( Op , TLO . DAG . getNode ( ISD :: SHL , SDLoc ( Op ) , MVT :: i32 , Op . getOperand ( 1 ) , TLO . DAG . getConstant ( 32 - ShAmt , SDLoc ( Op ) , MVT :: i32 ) ) ) ; } break ; } } return TargetLowering :: SimplifyDemandedBitsForTargetNode ( Op , OriginalDemandedBits , OriginalDemandedElts , Known , TLO , Depth ) ; } </s>

Attempt to simplify any target nodes based on the demanded bits/elts , returning true on success .


<s> bool ARMTargetLowering :: splitValueIntoRegisterParts ( SelectionDAG & DAG , const SDLoc & DL , SDValue Val , SDValue * Parts , unsigned NumParts , MVT PartVT , Optional < CallingConv :: ID > CC ) const { bool IsABIRegCopy = CC . hasValue ( ) ; EVT ValueVT = Val . getValueType ( ) ; if ( IsABIRegCopy && ( ValueVT == MVT :: f16 || ValueVT == MVT :: bf16 ) && PartVT == MVT :: f32 ) { unsigned ValueBits = ValueVT . getSizeInBits ( ) ; unsigned PartBits = PartVT . getSizeInBits ( ) ; Val = DAG . getNode ( ISD :: BITCAST , DL , MVT :: getIntegerVT ( ValueBits ) , Val ) ; Val = DAG . getNode ( ISD :: ANY_EXTEND , DL , MVT :: getIntegerVT ( PartBits ) , Val ) ; Val = DAG . getNode ( ISD :: BITCAST , DL , PartVT , Val ) ; Parts [ 0 ] = Val ; return true ; } return false ; } </s>

Target-specific splitting of values into parts that fit a register storing a legal type .


<s> bool ARMTargetLowering :: allowsMisalignedMemoryAccesses ( EVT VT , unsigned , unsigned Alignment , MachineMemOperand :: Flags , bool * Fast ) const { if ( ! VT . isSimple ( ) ) return false ; bool AllowsUnaligned = Subtarget -> allowsUnalignedMem ( ) ; auto Ty = VT . getSimpleVT ( ) . SimpleTy ; if ( Ty == MVT :: i8 || Ty == MVT :: i16 || Ty == MVT :: i32 ) { if ( AllowsUnaligned ) { if ( Fast ) * Fast = Subtarget -> hasV7Ops ( ) ; return true ; } } if ( Ty == MVT :: f64 || Ty == MVT :: v2f64 ) { if ( Subtarget -> hasNEON ( ) && ( AllowsUnaligned || Subtarget -> isLittle ( ) ) ) { if ( Fast ) * Fast = true ; return true ; } } if ( ! Subtarget -> hasMVEIntegerOps ( ) ) return false ; if ( ( Ty == MVT :: v16i1 || Ty == MVT :: v8i1 || Ty == MVT :: v4i1 ) ) { if ( Fast ) * Fast = true ; return true ; } if ( ( Ty == MVT :: v4i8 || Ty == MVT :: v8i8 || Ty == MVT :: v4i16 ) && Alignment >= VT . getScalarSizeInBits ( ) / 8 ) { if ( Fast ) * Fast = true ; return true ; } if ( Ty == MVT :: v16i8 || Ty == MVT :: v8i16 || Ty == MVT :: v8f16 || Ty == MVT :: v4i32 || Ty == MVT :: v4f32 || Ty == MVT :: v2i64 || Ty == MVT :: v2f64 ) { if ( Fast ) * Fast = true ; return true ; } return false ; } </s>

Returns true if the target allows unaligned memory accesses of the specified type .


"Unknown fence ordering in emitLeadingFence"


<s> Value * ARMTargetLowering :: emitLoadLinked ( IRBuilder < > & Builder , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; Type * ValTy = cast < PointerType > ( Addr -> getType ( ) ) -> getElementType ( ) ; bool IsAcquire = isAcquireOrStronger ( Ord ) ; if ( ValTy -> getPrimitiveSizeInBits ( ) == 64 ) { Intrinsic :: ID Int = IsAcquire ? Intrinsic :: arm_ldaexd : Intrinsic :: arm_ldrexd ; Function * Ldrex = Intrinsic :: getDeclaration ( M , Int ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; Value * LoHi = Builder . CreateCall ( Ldrex , Addr , "lohi" ) ; Value * Lo = Builder . CreateExtractValue ( LoHi , 0 , "lo" ) ; Value * Hi = Builder . CreateExtractValue ( LoHi , 1 , "hi" ) ; if ( ! Subtarget -> isLittle ( ) ) std :: swap ( Lo , Hi ) ; Lo = Builder . CreateZExt ( Lo , ValTy , "lo64" ) ; Hi = Builder . CreateZExt ( Hi , ValTy , "hi64" ) ; return Builder . CreateOr ( Lo , Builder . CreateShl ( Hi , ConstantInt :: get ( ValTy , 32 ) ) , "val64" ) ; } Type * Tys [ ] = { Addr -> getType ( ) } ; Intrinsic :: ID Int = IsAcquire ? Intrinsic :: arm_ldaex : Intrinsic :: arm_ldrex ; Function * Ldrex = Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateTruncOrBitCast ( Builder . CreateCall ( Ldrex , Addr ) , cast < PointerType > ( Addr -> getType ( ) ) -> getElementType ( ) ) ; } </s>

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


<s> Value * ARMTargetLowering :: emitStoreConditional ( IRBuilder < > & Builder , Value * Val , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; bool IsRelease = isReleaseOrStronger ( Ord ) ; if ( Val -> getType ( ) -> getPrimitiveSizeInBits ( ) == 64 ) { Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlexd : Intrinsic :: arm_strexd ; Function * Strex = Intrinsic :: getDeclaration ( M , Int ) ; Type * Int32Ty = Type :: getInt32Ty ( M -> getContext ( ) ) ; Value * Lo = Builder . CreateTrunc ( Val , Int32Ty , "lo" ) ; Value * Hi = Builder . CreateTrunc ( Builder . CreateLShr ( Val , 32 ) , Int32Ty , "hi" ) ; if ( ! Subtarget -> isLittle ( ) ) std :: swap ( Lo , Hi ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; return Builder . CreateCall ( Strex , { Lo , Hi , Addr } ) ; } Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlex : Intrinsic :: arm_strex ; Type * Tys [ ] = { Addr -> getType ( ) } ; Function * Strex = Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateCall ( Strex , { Builder . CreateZExtOrBitCast ( Val , Strex -> getFunctionType ( ) -> getParamType ( 0 ) ) , Addr } ) ; } </s>

Perform a store-conditional operation to Addr .


Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calling convention CallConv .


<s> Align ARMTargetLowering :: getABIAlignmentForCallingConv ( Type * ArgTy , DataLayout DL ) const { const Align ABITypeAlign ( DL . getABITypeAlignment ( ArgTy ) ) ; if ( ! ArgTy -> isVectorTy ( ) ) return ABITypeAlign ; return std :: min ( ABITypeAlign , DL . getStackAlignment ( ) ) ; } </s>

Return the correct alignment for the current calling convention .


<s> EVT ARMTargetLowering :: getOptimalMemOpType ( uint64_t Size , unsigned DstAlign , unsigned SrcAlign , bool IsMemset , bool ZeroMemset , bool MemcpyStrSrc , const AttributeList & FuncAttributes ) const { if ( ( ! IsMemset || ZeroMemset ) && Subtarget -> hasNEON ( ) && ! FuncAttributes . hasFnAttribute ( Attribute :: NoImplicitFloat ) ) { bool Fast ; if ( Size >= 16 && ( memOpAlign ( SrcAlign , DstAlign , 16 ) || ( allowsMisalignedMemoryAccesses ( MVT :: v2f64 , 0 , 1 , MachineMemOperand :: MONone , & Fast ) && Fast ) ) ) { return MVT :: v2f64 ; } else if ( Size >= 8 && ( memOpAlign ( SrcAlign , DstAlign , 8 ) || ( allowsMisalignedMemoryAccesses ( MVT :: f64 , 0 , 1 , MachineMemOperand :: MONone , & Fast ) && Fast ) ) ) { return MVT :: f64 ; } } return MVT :: Other ; } </s>

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


<s> bool ARMTargetLowering :: getPreIndexedAddressParts ( SDNode * N , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb1Only ( ) ) return false ; EVT VT ; SDValue Ptr ; unsigned Align ; bool isSEXTLoad = false ; bool IsMasked = false ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { Ptr = LD -> getBasePtr ( ) ; VT = LD -> getMemoryVT ( ) ; Align = LD -> getAlignment ( ) ; isSEXTLoad = LD -> getExtensionType ( ) == ISD :: SEXTLOAD ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { Ptr = ST -> getBasePtr ( ) ; VT = ST -> getMemoryVT ( ) ; Align = ST -> getAlignment ( ) ; } else if ( MaskedLoadSDNode * LD = dyn_cast < MaskedLoadSDNode > ( N ) ) { Ptr = LD -> getBasePtr ( ) ; VT = LD -> getMemoryVT ( ) ; Align = LD -> getAlignment ( ) ; isSEXTLoad = LD -> getExtensionType ( ) == ISD :: SEXTLOAD ; IsMasked = true ; } else if ( MaskedStoreSDNode * ST = dyn_cast < MaskedStoreSDNode > ( N ) ) { Ptr = ST -> getBasePtr ( ) ; VT = ST -> getMemoryVT ( ) ; Align = ST -> getAlignment ( ) ; IsMasked = true ; } else return false ; bool isInc ; bool isLegal = false ; if ( VT . isVector ( ) ) isLegal = Subtarget -> hasMVEIntegerOps ( ) && getMVEIndexedAddressParts ( Ptr . getNode ( ) , VT , Align , isSEXTLoad , IsMasked , Subtarget -> isLittle ( ) , Base , Offset , isInc , DAG ) ; else { if ( Subtarget -> isThumb2 ( ) ) isLegal = getT2IndexedAddressParts ( Ptr . getNode ( ) , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; else isLegal = getARMIndexedAddressParts ( Ptr . getNode ( ) , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; } if ( ! isLegal ) return false ; AM = isInc ? ISD :: PRE_INC : ISD :: PRE_DEC ; return true ; } </s>

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


<s> const TargetRegisterClass * ARMTargetLowering :: getRegClassFor ( MVT VT , bool isDivergent ) const { ( void ) isDivergent ; if ( Subtarget -> hasNEON ( ) || Subtarget -> hasMVEIntegerOps ( ) ) { if ( VT == MVT :: v4i64 ) return & ARM :: QQPRRegClass ; if ( VT == MVT :: v8i64 ) return & ARM :: QQQQPRRegClass ; } return TargetLowering :: getRegClassFor ( VT ) ; } </s>

Return the register class that should be used for the specified value type .

ARM ARM MVT::v4i64 ARM::QQPRRegClass MVT::v8i64 ARM::QQQQPRRegClass


<s> RCPair ARMTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { switch ( Constraint . size ( ) ) { case 1 : switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: tGPRRegClass ) ; return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'h' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: hGPRRegClass ) ; break ; case 'r' : if ( Subtarget -> isThumb1Only ( ) ) return RCPair ( 0U , & ARM :: tGPRRegClass ) ; return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'w' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPRRegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPRRegClass ) ; break ; case 'x' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPR_8RegClass ) ; break ; case 't' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 || VT == MVT :: i32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPR_VFP2RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPR_VFP2RegClass ) ; break ; } break ; case 2 : if ( Constraint [ 0 ] == 'T' ) { switch ( Constraint [ 1 ] ) { default : break ; case 'e' : return RCPair ( 0U , & ARM :: tGPREvenRegClass ) ; case 'o' : return RCPair ( 0U , & ARM :: tGPROddRegClass ) ; } } break ; default : break ; } if ( StringRef ( "{cc}" ) . equals_lower ( Constraint ) ) return std :: make_pair ( unsigned ( ARM :: CPSR ) , & ARM :: CCRRegClass ) ; return TargetLowering :: getRegForInlineAsmConstraint ( TRI , Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<s>
Register
ARMTargetLowering
::
getRegisterByName
(
const
char
*
RegName
,
EVT
VT
,
const
MachineFunction
&
MF
)
const
{
Register
Reg
=
StringSwitch
<
unsigned
>
(
RegName
)
.
Case
(
"sp"
,
ARM
::
SP
)
.
Default
(
0
)
;
if
(
Reg
)
return
Reg
;
report_fatal_error
(
Twine
(
"Invalid register name \""
+
StringRef
(
RegName
)
+
"\"."
)
)
;
}
</s>

Return the register ID of the name passed in .


<s> int ARMTargetLowering :: getScalingFactorCost ( const DataLayout & DL , const AddrMode & AM , Type * Ty , unsigned AS ) const { if ( isLegalAddressingMode ( DL , AM , Ty , AS ) ) { if ( Subtarget -> hasFPAO ( ) ) return AM . Scale < 0 ? 1 : 0 ; return 0 ; } return - 1 ; } </s>

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


<s> EVT ARMTargetLowering :: getSetCCResultType ( const DataLayout & DL , LLVMContext & , EVT VT ) const { if ( ! VT . isVector ( ) ) return getPointerTy ( DL ) ; if ( Subtarget -> hasMVEIntegerOps ( ) && ( VT == MVT :: v4i32 || VT == MVT :: v8i16 || VT == MVT :: v16i8 ) ) return MVT :: getVectorVT ( MVT :: i1 , VT . getVectorElementCount ( ) ) ; return VT . changeVectorElementTypeToInteger ( ) ; } </s>

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


<s> void ARMTargetLowering :: HandleByVal ( CCState * State , unsigned & Size , unsigned Align ) const { Align = std :: max ( Align , 4U ) ; unsigned Reg = State -> AllocateReg ( GPRArgRegs ) ; if ( ! Reg ) return ; unsigned AlignInRegs = Align / 4 ; unsigned Waste = ( ARM :: R4 - Reg ) % AlignInRegs ; for ( unsigned i = 0 ; i < Waste ; ++ i ) Reg = State -> AllocateReg ( GPRArgRegs ) ; if ( ! Reg ) return ; unsigned Excess = 4 * ( ARM :: R4 - Reg ) ; const unsigned NSAAOffset = State -> getNextStackOffset ( ) ; if ( NSAAOffset != 0 && Size > Excess ) { while ( State -> AllocateReg ( GPRArgRegs ) ) ; return ; } unsigned ByValRegBegin = Reg ; unsigned ByValRegEnd = std :: min < unsigned > ( Reg + Size / 4 , ARM :: R4 ) ; State -> addInRegsParamInfo ( ByValRegBegin , ByValRegEnd ) ; for ( unsigned i = Reg + 1 ; i != ByValRegEnd ; ++ i ) State -> AllocateReg ( GPRArgRegs ) ; Size = std :: max < int > ( Size - Excess , 0 ) ; } </s>

Target-specific cleanup for formal ByVal parameters .


<s> void ARMTargetLowering :: insertSSPDeclarations ( Module & M ) const { if ( ! Subtarget -> getTargetTriple ( ) . isWindowsMSVCEnvironment ( ) ) return TargetLowering :: insertSSPDeclarations ( M ) ; M . getOrInsertGlobal ( "__security_cookie" , Type :: getInt8PtrTy ( M . getContext ( ) ) ) ; FunctionCallee SecurityCheckCookie = M . getOrInsertFunction ( "__security_check_cookie" , Type :: getVoidTy ( M . getContext ( ) ) , Type :: getInt8PtrTy ( M . getContext ( ) ) ) ; if ( Function * F = dyn_cast < Function > ( SecurityCheckCookie . getCallee ( ) ) ) F -> addAttribute ( 1 , Attribute :: AttrKind :: InReg ) ; } </s>

Inserts necessary declarations for SSP ( stack protection ) purpose .


<s> bool ARMTargetLowering :: isFMAFasterThanFMulAndFAdd ( const MachineFunction & MF , EVT VT ) const { if ( ! Subtarget -> hasMVEFloatOps ( ) ) return false ; if ( ! VT . isSimple ( ) ) return false ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { case MVT :: v4f32 : case MVT :: v8f16 : return true ; default : break ; } return false ; } </s>

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


<s> bool ARMTargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT , bool ForCodeSize ) const { if ( ! Subtarget -> hasVFP3Base ( ) ) return false ; if ( VT == MVT :: f16 && Subtarget -> hasFullFP16 ( ) ) return ARM_AM :: getFP16Imm ( Imm ) != - 1 ; if ( VT == MVT :: f32 ) return ARM_AM :: getFP32Imm ( Imm ) != - 1 ; if ( VT == MVT :: f64 && Subtarget -> hasFP64 ( ) ) return ARM_AM :: getFP64Imm ( Imm ) != - 1 ; return false ; } </s>

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


<s> bool ARMTargetLowering :: isLegalInterleavedAccessType ( unsigned Factor , VectorType * VecTy , const DataLayout & DL ) const { unsigned VecSize = DL . getTypeSizeInBits ( VecTy ) ; unsigned ElSize = DL . getTypeSizeInBits ( VecTy -> getElementType ( ) ) ; if ( ! Subtarget -> hasNEON ( ) && ! Subtarget -> hasMVEIntegerOps ( ) ) return false ; if ( Subtarget -> hasNEON ( ) && VecTy -> getElementType ( ) -> isHalfTy ( ) ) return false ; if ( Subtarget -> hasMVEIntegerOps ( ) && Factor == 3 ) return false ; if ( VecTy -> getNumElements ( ) < 2 ) return false ; if ( ElSize != 8 && ElSize != 16 && ElSize != 32 ) return false ; if ( Subtarget -> hasNEON ( ) && VecSize == 64 ) return true ; return VecSize % 128 == 0 ; } </s>

Returns whether or not generating a interleaved load/store intrinsic for this type will be legal .


<s> bool ARMTargetLowering :: isShuffleMaskLegal ( ArrayRef < int > M , EVT VT ) const { if ( VT . getVectorNumElements ( ) == 4 && ( VT . is128BitVector ( ) || VT . is64BitVector ( ) ) ) { unsigned PFIndexes [ 4 ] ; for ( unsigned i = 0 ; i != 4 ; ++ i ) { if ( M [ i ] < 0 ) PFIndexes [ i ] = 8 ; else PFIndexes [ i ] = M [ i ] ; } unsigned PFTableIndex = PFIndexes [ 0 ] * 9 * 9 * 9 + PFIndexes [ 1 ] * 9 * 9 + PFIndexes [ 2 ] * 9 + PFIndexes [ 3 ] ; unsigned PFEntry = PerfectShuffleTable [ PFTableIndex ] ; unsigned Cost = ( PFEntry >> 30 ) ; if ( Cost <= 4 && ( Subtarget -> hasNEON ( ) || isLegalMVEShuffleOp ( PFEntry ) ) ) return true ; } bool ReverseVEXT , isV_UNDEF ; unsigned Imm , WhichResult ; unsigned EltSize = VT . getScalarSizeInBits ( ) ; if ( EltSize >= 32 || ShuffleVectorSDNode :: isSplatMask ( & M [ 0 ] , VT ) || ShuffleVectorInst :: isIdentityMask ( M ) || isVREVMask ( M , VT , 64 ) || isVREVMask ( M , VT , 32 ) || isVREVMask ( M , VT , 16 ) ) return true ; else if ( Subtarget -> hasNEON ( ) && ( isVEXTMask ( M , VT , ReverseVEXT , Imm ) || isVTBLMask ( M , VT ) || isNEONTwoResultShuffleMask ( M , VT , WhichResult , isV_UNDEF ) ) ) return true ; else if ( Subtarget -> hasNEON ( ) && ( VT == MVT :: v8i16 || VT == MVT :: v16i8 ) && isReverseMask ( M , VT ) ) return true ; else if ( Subtarget -> hasMVEIntegerOps ( ) && ( isVMOVNMask ( M , VT , 0 ) || isVMOVNMask ( M , VT , 1 ) ) ) return true ; else return false ; } </s>

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


<s> bool ARMTargetLowering :: isVectorLoadExtDesirable ( SDValue ExtVal ) const { EVT VT = ExtVal . getValueType ( ) ; if ( ! isTypeLegal ( VT ) ) return false ; if ( auto * Ld = dyn_cast < MaskedLoadSDNode > ( ExtVal . getOperand ( 0 ) ) ) { if ( Ld -> isExpandingLoad ( ) ) return false ; } if ( ExtVal -> use_empty ( ) || ! ExtVal -> use_begin ( ) -> isOnlyUserOf ( ExtVal . getNode ( ) ) ) return true ; SDNode * U = * ExtVal -> use_begin ( ) ; if ( ( U -> getOpcode ( ) == ISD :: ADD || U -> getOpcode ( ) == ISD :: SUB || U -> getOpcode ( ) == ISD :: SHL || U -> getOpcode ( ) == ARMISD :: VSHLIMM ) ) return false ; return true ; } </s>

Return true if folding a vector load into ExtVal ( a sign , zero , or any extend node ) is profitable .


<s> bool ARMTargetLowering :: mayBeEmittedAsTailCall ( const CallInst * CI ) const { if ( ! Subtarget -> supportsTailCall ( ) ) return false ; auto Attr = CI -> getParent ( ) -> getParent ( ) -> getFnAttribute ( "disable-tail-calls" ) ; if ( ! CI -> isTailCall ( ) || Attr . getValueAsString ( ) == "true" ) return false ; return true ; } </s>

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


<s>
void
ARMTargetLowering
::
ReplaceNodeResults
(
SDNode
*
N
,
SmallVectorImpl
<
SDValue
>
&
Results
,
SelectionDAG
&
DAG
)
const
{
SDValue
Res
;
switch
(
N
->
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom expand this!"
)
;
case
ISD
::
READ_REGISTER
:
ExpandREAD_REGISTER
(
N
,
Results
,
DAG
)
;
break
;
case
ISD
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
case
ISD
::
SHL
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
SREM
:
case
ISD
::
UREM
:
Res
=
LowerREM
(
N
,
DAG
)
;
break
;
case
ISD
::
SDIVREM
:
case
ISD
::
UDIVREM
:
Res
=
LowerDivRem
(
SDValue
(
N
,
0
)
,
DAG
)
;
assert
(
Res
.
getNumOperands
(
)
==
2
&&
"DivRem needs two values"
)
;
Results
.
push_back
(
Res
.
getValue
(
0
)
)
;
Results
.
push_back
(
Res
.
getValue
(
1
)
)
;
return
;
case
ISD
::
SADDSAT
:
case
ISD
::
SSUBSAT
:
Res
=
LowerSADDSUBSAT
(
SDValue
(
N
,
0
)
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
READCYCLECOUNTER
:
ReplaceREADCYCLECOUNTER
(
N
,
Results
,
DAG
,
Subtarget
)
;
return
;
case
ISD
::
UDIV
:
case
ISD
::
SDIV
:
assert
(
Subtarget
->
isTargetWindows
(
)
&&
"can only expand DIV on Windows"
)
;
return
ExpandDIV_Windows
(
SDValue
(
N
,
0
)
,
DAG
,
N
->
getOpcode
(
)
==
ISD
::
SDIV
,
Results
)
;
case
ISD
::
ATOMIC_CMP_SWAP
:
ReplaceCMP_SWAP_64Results
(
N
,
Results
,
DAG
)
;
return
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
ReplaceLongIntrinsic
(
N
,
Results
,
DAG
)
;
case
ISD
::
ABS
:
lowerABS
(
N
,
Results
,
DAG
)
;
return
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>

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

ARM
ARM
"Don't know how to custom expand this!"
ISD::READ_REGISTER
ISD::BITCAST
ISD::SRL
ISD::SRA
ISD::SHL
ISD::SREM
ISD::UREM
ISD::SDIVREM
ISD::UDIVREM
0
2
"DivRem needs two values"
0
1
ISD::SADDSAT
ISD::SSUBSAT
0
ISD::READCYCLECOUNTER
ISD::UDIV
ISD::SDIV
"can only expand DIV on Windows"
0
ISD::SDIV
ISD::ATOMIC_CMP_SWAP
ISD::INTRINSIC_WO_CHAIN
ISD::ABS


<s> TargetLowering :: AtomicExpansionKind ARMTargetLowering :: shouldExpandAtomicCmpXchgInIR ( AtomicCmpXchgInst * AI ) const { bool HasAtomicCmpXchg = ! Subtarget -> isThumb ( ) || Subtarget -> hasV8MBaselineOps ( ) ; if ( getTargetMachine ( ) . getOptLevel ( ) != 0 && HasAtomicCmpXchg ) return AtomicExpansionKind :: LLSC ; return AtomicExpansionKind :: None ; } </s>

Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass .


<s> TargetLowering :: AtomicExpansionKind ARMTargetLowering :: shouldExpandAtomicRMWInIR ( AtomicRMWInst * AI ) const { if ( AI -> isFloatingPointOperation ( ) ) return AtomicExpansionKind :: CmpXChg ; unsigned Size = AI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; bool hasAtomicRMW = ! Subtarget -> isThumb ( ) || Subtarget -> hasV8MBaselineOps ( ) ; return ( Size <= ( Subtarget -> isMClass ( ) ? 32U : 64U ) && hasAtomicRMW ) ? AtomicExpansionKind :: LLSC : AtomicExpansionKind :: None ; } </s>

Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW , if at all .


<s> bool ARMTargetLowering :: shouldSinkOperands ( Instruction * I , SmallVectorImpl < Use * > & Ops ) const { if ( ! I -> getType ( ) -> isVectorTy ( ) ) return false ; if ( Subtarget -> hasNEON ( ) ) { switch ( I -> getOpcode ( ) ) { case Instruction :: Sub : case Instruction :: Add : { if ( ! areExtractExts ( I -> getOperand ( 0 ) , I -> getOperand ( 1 ) ) ) return false ; Ops . push_back ( & I -> getOperandUse ( 0 ) ) ; Ops . push_back ( & I -> getOperandUse ( 1 ) ) ; return true ; } default : return false ; } } if ( ! Subtarget -> hasMVEIntegerOps ( ) ) return false ; auto IsSinker = [ ] ( Instruction * I , int Operand ) { switch ( I -> getOpcode ( ) ) { case Instruction :: Add : case Instruction :: Mul : return true ; case Instruction :: Sub : case Instruction :: Shl : case Instruction :: LShr : case Instruction :: AShr : return Operand == 1 ; default : return false ; } } ; int Op = 0 ; if ( ! isa < ShuffleVectorInst > ( I -> getOperand ( Op ) ) ) Op = 1 ; if ( ! IsSinker ( I , Op ) ) return false ; if ( ! match ( I -> getOperand ( Op ) , m_ShuffleVector ( m_InsertElement ( m_Undef ( ) , m_Value ( ) , m_ZeroInt ( ) ) , m_Undef ( ) , m_Zero ( ) ) ) ) { return false ; } Instruction * Shuffle = cast < Instruction > ( I -> getOperand ( Op ) ) ; for ( Use & U : Shuffle -> uses ( ) ) { Instruction * Insn = cast < Instruction > ( U . getUser ( ) ) ; if ( ! IsSinker ( Insn , U . getOperandNo ( ) ) ) return false ; } Ops . push_back ( & Shuffle -> getOperandUse ( 0 ) ) ; Ops . push_back ( & I -> getOperandUse ( Op ) ) ; return true ; } </s>

Return true if sinking I 's operands to the same basic block as I is profitable , e.g .


"Pseudo flag-setting opcodes must be marked with 'hasPostISelHook'"

"converted opcode should be the same except for cc_out"

"expect uninitialized optional cc_out operand"

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


<s>
bool
ARMTargetLowering
::
allowTruncateForTailCall
(
Type
*
Ty1
,
Type
*
Ty2
)
const
{
if
(
!
Ty1
->
isIntegerTy
(
)
||
!
Ty2
->
isIntegerTy
(
)
)
return
false
;
if
(
!
isTypeLegal
(
EVT
::
getEVT
(
Ty1
)
)
)
return
false
;
assert
(
Ty1
->
getPrimitiveSizeInBits
(
)
<=
64
&&
"i128 is probably not a noop"
)
;
return
true
;
}
</s>

Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail position .

ARM
ARM
64
"i128 is probably not a noop"


<s> bool ARMTargetLowering :: CanLowerReturn ( CallingConv :: ID CallConv , MachineFunction & MF , bool isVarArg , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) const { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , isVarArg , MF , getTargetMachine ( ) , RVLocs , Context ) ; return CCInfo . CheckReturn ( Outs , CCAssignFnForNode ( CallConv , true , isVarArg ) ) ; } </s>

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


<s> void ARMTargetLowering :: computeKnownBitsForTargetNode ( const SDValue Op , APInt & KnownZero , APInt & KnownOne , const SelectionDAG & DAG , unsigned Depth ) const { unsigned BitWidth = KnownOne . getBitWidth ( ) ; KnownZero = KnownOne = APInt ( BitWidth , 0 ) ; switch ( Op . getOpcode ( ) ) { default : break ; case ARMISD :: ADDC : case ARMISD :: ADDE : case ARMISD :: SUBC : case ARMISD :: SUBE : if ( Op . getResNo ( ) == 0 ) break ; KnownZero |= APInt :: getHighBitsSet ( BitWidth , BitWidth - 1 ) ; break ; case ARMISD :: CMOV : { DAG . computeKnownBits ( Op . getOperand ( 0 ) , KnownZero , KnownOne , Depth + 1 ) ; if ( KnownZero == 0 && KnownOne == 0 ) return ; APInt KnownZeroRHS , KnownOneRHS ; DAG . computeKnownBits ( Op . getOperand ( 1 ) , KnownZeroRHS , KnownOneRHS , Depth + 1 ) ; KnownZero &= KnownZeroRHS ; KnownOne &= KnownOneRHS ; return ; } case ISD :: INTRINSIC_W_CHAIN : { ConstantSDNode * CN = cast < ConstantSDNode > ( Op -> getOperand ( 1 ) ) ; Intrinsic :: ID IntID = static_cast < Intrinsic :: ID > ( CN -> getZExtValue ( ) ) ; switch ( IntID ) { default : return ; case Intrinsic :: arm_ldaex : case Intrinsic :: arm_ldrex : { EVT VT = cast < MemIntrinsicSDNode > ( Op ) -> getMemoryVT ( ) ; unsigned MemBits = VT . getScalarType ( ) . getSizeInBits ( ) ; KnownZero |= APInt :: getHighBitsSet ( BitWidth , BitWidth - MemBits ) ; return ; } } } } } </s>

Determine which of the bits specified in Mask are known to be either zero or one and return them in the KnownZero/KnownOne bitsets .


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

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


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

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


<s> Value * ARMTargetLowering :: emitStoreConditional ( IRBuilder < > & Builder , Value * Val , Value * Addr , AtomicOrdering Ord ) const { Module * M = Builder . GetInsertBlock ( ) -> getParent ( ) -> getParent ( ) ; bool IsRelease = Ord == Release || Ord == AcquireRelease || Ord == SequentiallyConsistent ; if ( Val -> getType ( ) -> getPrimitiveSizeInBits ( ) == 64 ) { Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlexd : Intrinsic :: arm_strexd ; Function * Strex = Intrinsic :: getDeclaration ( M , Int ) ; Type * Int32Ty = Type :: getInt32Ty ( M -> getContext ( ) ) ; Value * Lo = Builder . CreateTrunc ( Val , Int32Ty , "lo" ) ; Value * Hi = Builder . CreateTrunc ( Builder . CreateLShr ( Val , 32 ) , Int32Ty , "hi" ) ; if ( ! Subtarget -> isLittle ( ) ) std :: swap ( Lo , Hi ) ; Addr = Builder . CreateBitCast ( Addr , Type :: getInt8PtrTy ( M -> getContext ( ) ) ) ; return Builder . CreateCall3 ( Strex , Lo , Hi , Addr ) ; } Intrinsic :: ID Int = IsRelease ? Intrinsic :: arm_stlex : Intrinsic :: arm_strex ; Type * Tys [ ] = { Addr -> getType ( ) } ; Function * Strex = Intrinsic :: getDeclaration ( M , Int , Tys ) ; return Builder . CreateCall2 ( Strex , Builder . CreateZExtOrBitCast ( Val , Strex -> getFunctionType ( ) -> getParamType ( 0 ) ) , Addr ) ; } </s>

Perform a store-conditional operation to Addr .


<s>
bool
ARMTargetLowering
::
ExpandInlineAsm
(
CallInst
*
CI
)
const
{
if
(
!
Subtarget
->
hasV6Ops
(
)
)
return
false
;
InlineAsm
*
IA
=
cast
<
InlineAsm
>
(
CI
->
getCalledValue
(
)
)
;
std
::
string
AsmStr
=
IA
->
getAsmString
(
)
;
SmallVector
<
StringRef
,
4
>
AsmPieces
;
SplitString
(
AsmStr
,
AsmPieces
,
";\n"
)
;
switch
(
AsmPieces
.
size
(
)
)
{
default
:
return
false
;
case
1
:
AsmStr
=
AsmPieces
[
0
]
;
AsmPieces
.
clear
(
)
;
SplitString
(
AsmStr
,
AsmPieces
,
" \t,"
)
;
if
(
AsmPieces
.
size
(
)
==
3
&&
AsmPieces
[
0
]
==
"rev"
&&
AsmPieces
[
1
]
==
"$0"
&&
AsmPieces
[
2
]
==
"$1"
&&
IA
->
getConstraintString
(
)
.
compare
(
0
,
4
,
"=l,l"
)
==
0
)
{
IntegerType
*
Ty
=
dyn_cast
<
IntegerType
>
(
CI
->
getType
(
)
)
;
if
(
Ty
&&
Ty
->
getBitWidth
(
)
==
32
)
return
IntrinsicLowering
::
LowerToByteSwap
(
CI
)
;
}
break
;
}
return
false
;
}
</s>

This hook allows the target to expand an inline asm call to be explicit llvm code if it wants to .


<s> std :: pair < const TargetRegisterClass * , uint8_t > ARMTargetLowering :: findRepresentativeClass ( MVT VT ) const { const TargetRegisterClass * RRC = nullptr ; uint8_t Cost = 1 ; switch ( VT . SimpleTy ) { default : return TargetLowering :: findRepresentativeClass ( VT ) ; case MVT :: f32 : case MVT :: f64 : case MVT :: v8i8 : case MVT :: v4i16 : case MVT :: v2i32 : case MVT :: v1i64 : case MVT :: v2f32 : RRC = & ARM :: DPRRegClass ; if ( Subtarget -> useNEONForSinglePrecisionFP ( ) ) Cost = 2 ; break ; case MVT :: v16i8 : case MVT :: v8i16 : case MVT :: v4i32 : case MVT :: v2i64 : case MVT :: v4f32 : case MVT :: v2f64 : RRC = & ARM :: DPRRegClass ; Cost = 2 ; break ; case MVT :: v4i64 : RRC = & ARM :: DPRRegClass ; Cost = 4 ; break ; case MVT :: v8i64 : RRC = & ARM :: DPRRegClass ; Cost = 8 ; break ; } return std :: make_pair ( RRC , Cost ) ; } </s>

Return the largest legal super-reg register class of the register class for the specified type and its associated `` cost '' .


Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calling convention CallConv .


<s> ARMTargetLowering :: ConstraintType ARMTargetLowering :: getConstraintType ( const std :: string & Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'l' : return C_RegisterClass ; case 'w' : return C_RegisterClass ; case 'h' : return C_RegisterClass ; case 'x' : return C_RegisterClass ; case 't' : return C_RegisterClass ; case 'j' : return C_Other ; case 'Q' : return C_Memory ; } } else if ( Constraint . size ( ) == 2 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'U' : return C_Memory ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

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


<s> unsigned ARMTargetLowering :: getJumpTableEncoding ( ) const { return MachineJumpTableInfo :: EK_Inline ; } </s>

Return the entry encoding for a jump table in the current function .


<s> EVT ARMTargetLowering :: getOptimalMemOpType ( uint64_t Size , unsigned DstAlign , unsigned SrcAlign , bool IsMemset , bool ZeroMemset , bool MemcpyStrSrc , MachineFunction & MF ) const { const Function * F = MF . getFunction ( ) ; if ( ( ! IsMemset || ZeroMemset ) && Subtarget -> hasNEON ( ) && ! F -> getAttributes ( ) . hasAttribute ( AttributeSet :: FunctionIndex , Attribute :: NoImplicitFloat ) ) { bool Fast ; if ( Size >= 16 && ( memOpAlign ( SrcAlign , DstAlign , 16 ) || ( allowsUnalignedMemoryAccesses ( MVT :: v2f64 , 0 , & Fast ) && Fast ) ) ) { return MVT :: v2f64 ; } else if ( Size >= 8 && ( memOpAlign ( SrcAlign , DstAlign , 8 ) || ( allowsUnalignedMemoryAccesses ( MVT :: f64 , 0 , & Fast ) && Fast ) ) ) { return MVT :: f64 ; } } if ( Size >= 4 ) return MVT :: i32 ; else if ( Size >= 2 ) return MVT :: i16 ; return MVT :: Other ; } </s>

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


<s> bool ARMTargetLowering :: getPostIndexedAddressParts ( SDNode * N , SDNode * Op , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb1Only ( ) ) return false ; EVT VT ; SDValue Ptr ; bool isSEXTLoad = false ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { VT = LD -> getMemoryVT ( ) ; Ptr = LD -> getBasePtr ( ) ; isSEXTLoad = LD -> getExtensionType ( ) == ISD :: SEXTLOAD ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { VT = ST -> getMemoryVT ( ) ; Ptr = ST -> getBasePtr ( ) ; } else return false ; bool isInc ; bool isLegal = false ; if ( Subtarget -> isThumb2 ( ) ) isLegal = getT2IndexedAddressParts ( Op , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; else isLegal = getARMIndexedAddressParts ( Op , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; if ( ! isLegal ) return false ; if ( Ptr != Base ) { if ( Ptr == Offset && Op -> getOpcode ( ) == ISD :: ADD && ! Subtarget -> isThumb2 ( ) ) std :: swap ( Base , Offset ) ; if ( Ptr != Base ) return false ; } AM = isInc ? ISD :: POST_INC : ISD :: POST_DEC ; return true ; } </s>

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

ARM ARM ISD::MemIndexedMode ISD::SEXTLOAD ARM ISD::ADD ISD::POST_INC ISD::POST_DEC


<s> bool ARMTargetLowering :: getPreIndexedAddressParts ( SDNode * N , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb1Only ( ) ) return false ; EVT VT ; SDValue Ptr ; bool isSEXTLoad = false ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { Ptr = LD -> getBasePtr ( ) ; VT = LD -> getMemoryVT ( ) ; isSEXTLoad = LD -> getExtensionType ( ) == ISD :: SEXTLOAD ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { Ptr = ST -> getBasePtr ( ) ; VT = ST -> getMemoryVT ( ) ; } else return false ; bool isInc ; bool isLegal = false ; if ( Subtarget -> isThumb2 ( ) ) isLegal = getT2IndexedAddressParts ( Ptr . getNode ( ) , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; else isLegal = getARMIndexedAddressParts ( Ptr . getNode ( ) , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; if ( ! isLegal ) return false ; AM = isInc ? ISD :: PRE_INC : ISD :: PRE_DEC ; return true ; } </s>

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

ARM ARM ISD::MemIndexedMode ISD::SEXTLOAD ARM ISD::PRE_INC ISD::PRE_DEC


<s> const TargetRegisterClass * ARMTargetLowering :: getRegClassFor ( MVT VT ) const { if ( Subtarget -> hasNEON ( ) ) { if ( VT == MVT :: v4i64 ) return & ARM :: QQPRRegClass ; if ( VT == MVT :: v8i64 ) return & ARM :: QQQQPRRegClass ; } return TargetLowering :: getRegClassFor ( VT ) ; } </s>

Return the register class that should be used for the specified value type .


<s> RCPair ARMTargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: tGPRRegClass ) ; return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'h' : if ( Subtarget -> isThumb ( ) ) return RCPair ( 0U , & ARM :: hGPRRegClass ) ; break ; case 'r' : return RCPair ( 0U , & ARM :: GPRRegClass ) ; case 'w' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPRRegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPRRegClass ) ; break ; case 'x' : if ( VT == MVT :: Other ) break ; if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return RCPair ( 0U , & ARM :: DPR_8RegClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return RCPair ( 0U , & ARM :: QPR_8RegClass ) ; break ; case 't' : if ( VT == MVT :: f32 ) return RCPair ( 0U , & ARM :: SPRRegClass ) ; break ; } } if ( StringRef ( "{cc}" ) . equals_lower ( Constraint ) ) return std :: make_pair ( unsigned ( ARM :: CPSR ) , & ARM :: CCRRegClass ) ; return TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


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

Return the register ID of the name passed in .

ARM
ARM
"sp"
ARM::SP
0
"Invalid register name global variable"


<s> Sched :: Preference ARMTargetLowering :: getSchedulingPreference ( SDNode * N ) const { unsigned NumVals = N -> getNumValues ( ) ; if ( ! NumVals ) return Sched :: RegPressure ; for ( unsigned i = 0 ; i != NumVals ; ++ i ) { EVT VT = N -> getValueType ( i ) ; if ( VT == MVT :: Glue || VT == MVT :: Other ) continue ; if ( VT . isFloatingPoint ( ) || VT . isVector ( ) ) return Sched :: ILP ; } if ( ! N -> isMachineOpcode ( ) ) return Sched :: RegPressure ; const TargetInstrInfo * TII = getTargetMachine ( ) . getInstrInfo ( ) ; const MCInstrDesc & MCID = TII -> get ( N -> getMachineOpcode ( ) ) ; if ( MCID . getNumDefs ( ) == 0 ) return Sched :: RegPressure ; if ( ! Itins -> isEmpty ( ) && Itins -> getOperandCycle ( MCID . getSchedClass ( ) , 0 ) > 2 ) return Sched :: ILP ; return Sched :: RegPressure ; } </s>


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

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


<s> TargetLowering :: ConstraintWeight ARMTargetLowering :: getSingleConstraintMatchWeight ( AsmOperandInfo & info , const char * constraint ) const { ConstraintWeight weight = CW_Invalid ; Value * CallOperandVal = info . CallOperandVal ; if ( ! CallOperandVal ) return CW_Default ; Type * type = CallOperandVal -> getType ( ) ; switch ( * constraint ) { default : weight = TargetLowering :: getSingleConstraintMatchWeight ( info , constraint ) ; break ; case 'l' : if ( type -> isIntegerTy ( ) ) { if ( Subtarget -> isThumb ( ) ) weight = CW_SpecificReg ; else weight = CW_Register ; } break ; case 'w' : if ( type -> isFloatingPointTy ( ) ) weight = CW_Register ; break ; } return weight ; } </s>

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


<s>
void
ARMTargetLowering
::
HandleByVal
(
CCState
*
State
,
unsigned
&
size
,
unsigned
Align
)
const
{
unsigned
reg
=
State
->
AllocateReg
(
GPRArgRegs
,
4
)
;
assert
(
(
State
->
getCallOrPrologue
(
)
==
Prologue
||
State
->
getCallOrPrologue
(
)
==
Call
)
&&
"unhandled ParmContext"
)
;
if
(
(
ARM
::
R0
<=
reg
)
&&
(
reg
<=
ARM
::
R3
)
)
{
if
(
Subtarget
->
isAAPCS_ABI
(
)
&&
Align
>
4
)
{
unsigned
AlignInRegs
=
Align
/
4
;
unsigned
Waste
=
(
ARM
::
R4
reg
)
%
AlignInRegs
;
for
(
unsigned
i
=
0
;
i
<
Waste
;
++
i
)
reg
=
State
->
AllocateReg
(
GPRArgRegs
,
4
)
;
}
if
(
reg
!=
0
)
{
unsigned
excess
=
4
*
(
ARM
::
R4
reg
)
;
const
unsigned
NSAAOffset
=
State
->
getNextStackOffset
(
)
;
if
(
Subtarget
->
isAAPCS_ABI
(
)
&&
NSAAOffset
!=
0
&&
size
>
excess
)
{
while
(
State
->
AllocateReg
(
GPRArgRegs
,
4
)
)
;
return
;
}
unsigned
ByValRegBegin
=
reg
;
unsigned
ByValRegEnd
=
(
size
<
excess
)
reg
+
size
/
4
:
(
unsigned
)
ARM
::
R4
;
State
->
addInRegsParamInfo
(
ByValRegBegin
,
ByValRegEnd
)
;
for
(
unsigned
i
=
reg
+
1
;
i
!=
ByValRegEnd
;
++
i
)
State
->
AllocateReg
(
GPRArgRegs
,
4
)
;
if
(
size
<
excess
)
size
=
0
;
else
size
-=
excess
;
}
}
}
</s>

Target-specific cleanup for formal ByVal parameters .


<s> bool ARMTargetLowering :: isDesirableToTransformToIntegerOp ( unsigned Opc , EVT VT ) const { return ( VT == MVT :: f32 ) && ( Opc == ISD :: LOAD || Opc == ISD :: STORE ) ; } </s>

Return true if it is profitable for dag combiner to transform a floating point op of specified opcode to a equivalent op of an integer type .


<s> bool ARMTargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT ) const { if ( ! Subtarget -> hasVFP3 ( ) ) return false ; if ( VT == MVT :: f32 ) return ARM_AM :: getFP32Imm ( Imm ) != - 1 ; if ( VT == MVT :: f64 ) return ARM_AM :: getFP64Imm ( Imm ) != - 1 ; return false ; } </s>

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


<s> bool ARMTargetLowering :: isLegalAddImmediate ( int64_t Imm ) const { int64_t AbsImm = llvm :: abs64 ( Imm ) ; if ( ! Subtarget -> isThumb ( ) ) return ARM_AM :: getSOImmVal ( AbsImm ) != - 1 ; if ( Subtarget -> isThumb2 ( ) ) return ARM_AM :: getT2SOImmVal ( AbsImm ) != - 1 ; return AbsImm >= 0 && AbsImm <= 255 ; } </s>

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


<s> bool ARMTargetLowering :: isLegalAddressingMode ( const AddrMode & AM , Type * Ty ) const { EVT VT = getValueType ( Ty , true ) ; if ( ! isLegalAddressImmediate ( AM . BaseOffs , VT , Subtarget ) ) return false ; if ( AM . BaseGV ) return false ; switch ( AM . Scale ) { case 0 : break ; case 1 : if ( Subtarget -> isThumb1Only ( ) ) return false ; default : if ( AM . BaseOffs ) return false ; if ( ! VT . isSimple ( ) ) return false ; if ( Subtarget -> isThumb2 ( ) ) return isLegalT2ScaledAddressingMode ( AM , VT ) ; int Scale = AM . Scale ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { default : return false ; case MVT :: i1 : case MVT :: i8 : case MVT :: i32 : if ( Scale < 0 ) Scale = - Scale ; if ( Scale == 1 ) return true ; return isPowerOf2_32 ( Scale & ~ 1 ) ; case MVT :: i16 : case MVT :: i64 : if ( ( ( unsigned ) AM . HasBaseReg + Scale ) <= 2 ) return true ; return false ; case MVT :: isVoid : if ( Scale & 1 ) return false ; return isPowerOf2_32 ( Scale ) ; } } return true ; } </s>

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


<s> bool ARMTargetLowering :: isLegalICmpImmediate ( int64_t Imm ) const { if ( ! Subtarget -> isThumb ( ) ) return ARM_AM :: getSOImmVal ( llvm :: abs64 ( Imm ) ) != - 1 ; if ( Subtarget -> isThumb2 ( ) ) return ARM_AM :: getT2SOImmVal ( llvm :: abs64 ( Imm ) ) != - 1 ; return Imm >= 0 && Imm <= 255 ; } </s>

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


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

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


<s> static bool isReverseMask ( ArrayRef < int > M , EVT VT ) { unsigned NumElts = VT . getVectorNumElements ( ) ; if ( NumElts != M . size ( ) ) return false ; for ( unsigned i = 0 ; i != NumElts ; ++ i ) if ( M [ i ] >= 0 && M [ i ] != ( int ) ( NumElts - 1 - i ) ) return false ; return true ; } </s>

Return true if this shuffle mask swaps the order of elements from exactly one source vector .


<s> bool ARMTargetLowering :: isShuffleMaskLegal ( const SmallVectorImpl < int > & M , EVT VT ) const { if ( VT . getVectorNumElements ( ) == 4 && ( VT . is128BitVector ( ) || VT . is64BitVector ( ) ) ) { unsigned PFIndexes [ 4 ] ; for ( unsigned i = 0 ; i != 4 ; ++ i ) { if ( M [ i ] < 0 ) PFIndexes [ i ] = 8 ; else PFIndexes [ i ] = M [ i ] ; } unsigned PFTableIndex = PFIndexes [ 0 ] * 9 * 9 * 9 + PFIndexes [ 1 ] * 9 * 9 + PFIndexes [ 2 ] * 9 + PFIndexes [ 3 ] ; unsigned PFEntry = PerfectShuffleTable [ PFTableIndex ] ; unsigned Cost = ( PFEntry >> 30 ) ; if ( Cost <= 4 ) return true ; } bool ReverseVEXT ; unsigned Imm , WhichResult ; unsigned EltSize = VT . getVectorElementType ( ) . getSizeInBits ( ) ; return ( EltSize >= 32 || ShuffleVectorSDNode :: isSplatMask ( & M [ 0 ] , VT ) || isVREVMask ( M , VT , 64 ) || isVREVMask ( M , VT , 32 ) || isVREVMask ( M , VT , 16 ) || isVEXTMask ( M , VT , ReverseVEXT , Imm ) || isVTBLMask ( M , VT ) || isVTRNMask ( M , VT , WhichResult ) || isVUZPMask ( M , VT , WhichResult ) || isVZIPMask ( M , VT , WhichResult ) || isVTRN_v_undef_Mask ( M , VT , WhichResult ) || isVUZP_v_undef_Mask ( M , VT , WhichResult ) || isVZIP_v_undef_Mask ( M , VT , WhichResult ) || ( ( VT == MVT :: v8i16 || VT == MVT :: v16i8 ) && isReverseMask ( M , VT ) ) ) ; } </s>

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


<s> bool ARMTargetLowering :: isUsedByReturnOnly ( SDNode * N , SDValue & Chain ) const { if ( N -> getNumValues ( ) != 1 ) return false ; if ( ! N -> hasNUsesOfValue ( 1 , 0 ) ) return false ; SDValue TCChain = Chain ; SDNode * Copy = * N -> use_begin ( ) ; if ( Copy -> getOpcode ( ) == ISD :: CopyToReg ) { if ( Copy -> getOperand ( Copy -> getNumOperands ( ) - 1 ) . getValueType ( ) == MVT :: Glue ) return false ; TCChain = Copy -> getOperand ( 0 ) ; } else if ( Copy -> getOpcode ( ) == ARMISD :: VMOVRRD ) { SDNode * VMov = Copy ; SmallPtrSet < SDNode * , 2 > Copies ; for ( SDNode :: use_iterator UI = VMov -> use_begin ( ) , UE = VMov -> use_end ( ) ; UI != UE ; ++ UI ) { if ( UI -> getOpcode ( ) != ISD :: CopyToReg ) return false ; Copies . insert ( * UI ) ; } if ( Copies . size ( ) > 2 ) return false ; for ( SDNode :: use_iterator UI = VMov -> use_begin ( ) , UE = VMov -> use_end ( ) ; UI != UE ; ++ UI ) { SDValue UseChain = UI -> getOperand ( 0 ) ; if ( Copies . count ( UseChain . getNode ( ) ) ) Copy = * UI ; else TCChain = UseChain ; } } else if ( Copy -> getOpcode ( ) == ISD :: BITCAST ) { if ( ! Copy -> hasOneUse ( ) ) return false ; Copy = * Copy -> use_begin ( ) ; if ( Copy -> getOpcode ( ) != ISD :: CopyToReg || ! Copy -> hasNUsesOfValue ( 1 , 0 ) ) return false ; TCChain = Copy -> getOperand ( 0 ) ; } else { return false ; } bool HasRet = false ; for ( SDNode :: use_iterator UI = Copy -> use_begin ( ) , UE = Copy -> use_end ( ) ; UI != UE ; ++ UI ) { if ( UI -> getOpcode ( ) != ARMISD :: RET_FLAG && UI -> getOpcode ( ) != ARMISD :: INTRET_FLAG ) return false ; HasRet = true ; } if ( ! HasRet ) return false ; Chain = TCChain ; return true ; } </s>

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


<s> bool ARMTargetLowering :: isZExtFree ( SDValue Val , EVT VT2 ) const { if ( Val . getOpcode ( ) != ISD :: LOAD ) return false ; EVT VT1 = Val . getValueType ( ) ; if ( ! VT1 . isSimple ( ) || ! VT1 . isInteger ( ) || ! VT2 . isSimple ( ) || ! VT2 . isInteger ( ) ) return false ; switch ( VT1 . getSimpleVT ( ) . SimpleTy ) { default : break ; case MVT :: i1 : case MVT :: i8 : case MVT :: i16 : return true ; } return false ; } </s>

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


<s> bool ARMTargetLowering :: mayBeEmittedAsTailCall ( CallInst * CI ) const { if ( ! Subtarget -> supportsTailCall ( ) ) return false ; if ( ! CI -> isTailCall ( ) || getTargetMachine ( ) . Options . DisableTailCalls ) return false ; return ! Subtarget -> isThumb1Only ( ) ; } </s>

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