<s> bool ARMTargetLowering :: getPostIndexedAddressParts ( SDNode * N , SDNode * Op , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb ( ) ) return false ; MVT VT ; SDValue Ptr ; bool isSEXTLoad = false ; if ( LoadSDNode * LD = dyn_cast < LoadSDNode > ( N ) ) { VT = LD -> getMemoryVT ( ) ; isSEXTLoad = LD -> getExtensionType ( ) == ISD :: SEXTLOAD ; } else if ( StoreSDNode * ST = dyn_cast < StoreSDNode > ( N ) ) { VT = ST -> getMemoryVT ( ) ; } else return false ; bool isInc ; bool isLegal = getIndexedAddressParts ( Op , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; if ( isLegal ) { AM = isInc ? ISD :: POST_INC : ISD :: POST_DEC ; return true ; } return false ; } </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 ISD::POST_INC ISD::POST_DEC


<s> bool ARMTargetLowering :: getPreIndexedAddressParts ( SDNode * N , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb ( ) ) return false ; MVT 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 = getIndexedAddressParts ( Ptr . getNode ( ) , VT , isSEXTLoad , Base , Offset , isInc , DAG ) ; if ( isLegal ) { AM = isInc ? ISD :: PRE_INC : ISD :: PRE_DEC ; return true ; } return false ; } </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::PRE_INC ISD::PRE_DEC


<s> std :: pair < unsigned , const TargetRegisterClass * > ARMTargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'l' : case 'r' : return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'w' : if ( VT == MVT :: f32 ) return std :: make_pair ( 0U , ARM :: SPRRegisterClass ) ; if ( VT == MVT :: f64 ) return std :: make_pair ( 0U , ARM :: DPRRegisterClass ) ; break ; } } return TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<s> const char * ARMTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( Opcode ) { default : return 0 ; case ARMISD :: Wrapper : return "ARMISD::Wrapper" ; case ARMISD :: WrapperJT : return "ARMISD::WrapperJT" ; case ARMISD :: CALL : return "ARMISD::CALL" ; case ARMISD :: CALL_PRED : return "ARMISD::CALL_PRED" ; case ARMISD :: CALL_NOLINK : return "ARMISD::CALL_NOLINK" ; case ARMISD :: tCALL : return "ARMISD::tCALL" ; case ARMISD :: BRCOND : return "ARMISD::BRCOND" ; case ARMISD :: BR_JT : return "ARMISD::BR_JT" ; case ARMISD :: RET_FLAG : return "ARMISD::RET_FLAG" ; case ARMISD :: PIC_ADD : return "ARMISD::PIC_ADD" ; case ARMISD :: CMP : return "ARMISD::CMP" ; case ARMISD :: CMPNZ : return "ARMISD::CMPNZ" ; case ARMISD :: CMPFP : return "ARMISD::CMPFP" ; case ARMISD :: CMPFPw0 : return "ARMISD::CMPFPw0" ; case ARMISD :: FMSTAT : return "ARMISD::FMSTAT" ; case ARMISD :: CMOV : return "ARMISD::CMOV" ; case ARMISD :: CNEG : return "ARMISD::CNEG" ; case ARMISD :: FTOSI : return "ARMISD::FTOSI" ; case ARMISD :: FTOUI : return "ARMISD::FTOUI" ; case ARMISD :: SITOF : return "ARMISD::SITOF" ; case ARMISD :: UITOF : return "ARMISD::UITOF" ; case ARMISD :: SRL_FLAG : return "ARMISD::SRL_FLAG" ; case ARMISD :: SRA_FLAG : return "ARMISD::SRA_FLAG" ; case ARMISD :: RRX : return "ARMISD::RRX" ; case ARMISD :: FMRRD : return "ARMISD::FMRRD" ; case ARMISD :: FMDRR : return "ARMISD::FMDRR" ; case ARMISD :: THREAD_POINTER : return "ARMISD::THREAD_POINTER" ; } } </s>

getTargetNodeName - This method returns the name of a target specific

ARM ARM 0 ARMISD::Wrapper "ARMISD::Wrapper" ARMISD::WrapperJT "ARMISD::WrapperJT" ARMISD::CALL "ARMISD::CALL" ARMISD::CALL_PRED "ARMISD::CALL_PRED" ARMISD::CALL_NOLINK "ARMISD::CALL_NOLINK" ARMISD::tCALL "ARMISD::tCALL" ARMISD::BRCOND "ARMISD::BRCOND" ARMISD::BR_JT "ARMISD::BR_JT" ARMISD::RET_FLAG "ARMISD::RET_FLAG" ARMISD::PIC_ADD "ARMISD::PIC_ADD" ARMISD::CMP "ARMISD::CMP" ARMISD::CMPNZ "ARMISD::CMPNZ" ARMISD::CMPFP "ARMISD::CMPFP" ARMISD::CMPFPw0 "ARMISD::CMPFPw0" ARMISD::FMSTAT "ARMISD::FMSTAT" ARMISD::CMOV "ARMISD::CMOV" ARMISD::CNEG "ARMISD::CNEG" ARMISD::FTOSI "ARMISD::FTOSI" ARMISD::FTOUI "ARMISD::FTOUI" ARMISD::SITOF "ARMISD::SITOF" ARMISD::UITOF "ARMISD::UITOF" ARMISD::SRL_FLAG "ARMISD::SRL_FLAG" ARMISD::SRA_FLAG "ARMISD::SRA_FLAG" ARMISD::RRX "ARMISD::RRX" ARMISD::FMRRD "ARMISD::FMRRD" ARMISD::FMDRR "ARMISD::FMDRR" ARMISD::THREAD_POINTER "ARMISD::THREAD_POINTER"


<s> bool ARMTargetLowering :: isLegalAddressingMode ( const AddrMode & AM , const Type * Ty ) const { if ( ! isLegalAddressImmediate ( AM . BaseOffs , getValueType ( Ty , true ) , Subtarget ) ) return false ; if ( AM . BaseGV ) return false ; switch ( AM . Scale ) { case 0 : break ; case 1 : if ( Subtarget -> isThumb ( ) ) return false ; default : if ( AM . BaseOffs ) return false ; int Scale = AM . Scale ; switch ( getValueType ( Ty ) . getSimpleVT ( ) ) { default : return false ; case MVT :: i1 : case MVT :: i8 : case MVT :: i32 : case MVT :: i64 : if ( Scale < 0 ) Scale = - Scale ; if ( Scale == 1 ) return true ; return isPowerOf2_32 ( Scale & ~ 1 ) ; case MVT :: i16 : if ( ( ( unsigned ) AM . HasBaseReg + Scale ) <= 2 ) return true ; return false ; case MVT :: isVoid : if ( AM . Scale & 1 ) return false ; return isPowerOf2_32 ( AM . Scale ) ; } break ; } 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>
SDValue
ARMTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
assert
(
0
&&
"Don't know how to custom lower this!"
)
;
abort
(
)
;
case
ISD
::
ConstantPool
:
return
LowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
Subtarget
->
isTargetDarwin
(
)
LowerGlobalAddressDarwin
(
Op
,
DAG
)
:
LowerGlobalAddressELF
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
LowerGlobalTLSAddress
(
Op
,
DAG
)
;
case
ISD
::
CALL
:
return
LowerCALL
(
Op
,
DAG
)
;
case
ISD
::
RET
:
return
LowerRET
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BR_JT
:
return
LowerBR_JT
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
LowerVASTART
(
Op
,
DAG
,
VarArgsFrameIndex
)
;
case
ISD
::
SINT_TO_FP
:
case
ISD
::
UINT_TO_FP
:
return
LowerINT_TO_FP
(
Op
,
DAG
)
;
case
ISD
::
FP_TO_SINT
:
case
ISD
::
FP_TO_UINT
:
return
LowerFP_TO_INT
(
Op
,
DAG
)
;
case
ISD
::
FCOPYSIGN
:
return
LowerFCOPYSIGN
(
Op
,
DAG
)
;
case
ISD
::
FORMAL_ARGUMENTS
:
return
LowerFORMAL_ARGUMENTS
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
break
;
case
ISD
::
FRAMEADDR
:
break
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
return
LowerGLOBAL_OFFSET_TABLE
(
Op
,
DAG
)
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
LowerINTRINSIC_WO_CHAIN
(
Op
,
DAG
)
;
case
ISD
::
BIT_CONVERT
:
return
ExpandBIT_CONVERT
(
Op
.
getNode
(
)
,
DAG
)
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
return
ExpandSRx
(
Op
.
getNode
(
)
,
DAG
,
Subtarget
)
;
}
return
SDValue
(
)
;
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .


<s> SDValue ARMTargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { switch ( N -> getOpcode ( ) ) { default : break ; case ISD :: ADD : return PerformADDCombine ( N , DCI ) ; case ISD :: SUB : return PerformSUBCombine ( N , DCI ) ; case ARMISD :: FMRRD : return PerformFMRRDCombine ( N , DCI ) ; } return SDValue ( ) ; } </s>

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


<s>
void
ARMTargetLowering
::
ReplaceNodeResults
(
SDNode
*
N
,
SmallVectorImpl
<
SDValue
>
&
Results
,
SelectionDAG
&
DAG
)
{
switch
(
N
->
getOpcode
(
)
)
{
default
:
assert
(
0
&&
"Don't know how to custom expand this!"
)
;
return
;
case
ISD
::
BIT_CONVERT
:
Results
.
push_back
(
ExpandBIT_CONVERT
(
N
,
DAG
)
)
;
return
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
{
SDValue
Res
=
ExpandSRx
(
N
,
DAG
,
Subtarget
)
;
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
return
;
}
}
}
</s>

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

ARM
ARM
0
"Don't know how to custom expand this!"
ISD::BIT_CONVERT
ISD::SRL
ISD::SRA


<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
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
READCYCLECOUNTER
:
ReplaceREADCYCLECOUNTER
(
N
,
Results
,
DAG
,
Subtarget
)
;
return
;
case
ISD
::
ATOMIC_STORE
:
case
ISD
::
ATOMIC_LOAD
:
case
ISD
::
ATOMIC_LOAD_ADD
:
case
ISD
::
ATOMIC_LOAD_AND
:
case
ISD
::
ATOMIC_LOAD_NAND
:
case
ISD
::
ATOMIC_LOAD_OR
:
case
ISD
::
ATOMIC_LOAD_SUB
:
case
ISD
::
ATOMIC_LOAD_XOR
:
case
ISD
::
ATOMIC_SWAP
:
case
ISD
::
ATOMIC_CMP_SWAP
:
case
ISD
::
ATOMIC_LOAD_MIN
:
case
ISD
::
ATOMIC_LOAD_UMIN
:
case
ISD
::
ATOMIC_LOAD_MAX
:
case
ISD
::
ATOMIC_LOAD_UMAX
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
)
;
return
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>


<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 || Ty == MVT :: v2i1 ) ) { 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 .


<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 ) ; CallInst * CI = Builder . CreateCall ( Ldrex , Addr ) ; CI -> addParamAttr ( 0 , Attribute :: get ( M -> getContext ( ) , Attribute :: ElementType , ValueTy ) ) ; return Builder . CreateTruncOrBitCast ( CI , 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 ) ; CallInst * CI = Builder . CreateCall ( Strex , { Builder . CreateZExtOrBitCast ( Val , Strex -> getFunctionType ( ) -> getParamType ( 0 ) ) , Addr } ) ; CI -> addParamAttr ( 1 , Attribute :: get ( M -> getContext ( ) , Attribute :: ElementType , Val -> getType ( ) ) ) ; return CI ; } </s>

Perform a store-conditional operation to Addr .


<s> EVT ARMTargetLowering :: getSetCCResultType ( const DataLayout & DL , LLVMContext & , EVT VT ) const { if ( ! VT . isVector ( ) ) return getPointerTy ( DL ) ; if ( ( Subtarget -> hasMVEIntegerOps ( ) && ( VT == MVT :: v2i64 || VT == MVT :: v4i32 || VT == MVT :: v8i16 || VT == MVT :: v16i8 ) ) || ( Subtarget -> hasMVEFloatOps ( ) && ( VT == MVT :: v2f64 || 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> bool ARMTargetLowering :: isMulAddWithConstProfitable ( SDValue AddNode , 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 :: 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 * U : VMov -> uses ( ) ) { if ( U -> getOpcode ( ) != ISD :: CopyToReg ) return false ; Copies . insert ( U ) ; } if ( Copies . size ( ) > 2 ) return false ; for ( SDNode * U : VMov -> uses ( ) ) { SDValue UseChain = U -> getOperand ( 0 ) ; if ( Copies . count ( UseChain . getNode ( ) ) ) Copy = U ; else { if ( U -> getOperand ( U -> getNumOperands ( ) - 1 ) . getValueType ( ) == MVT :: Glue ) return false ; 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 ; if ( Copy -> getOperand ( Copy -> getNumOperands ( ) - 1 ) . getValueType ( ) == MVT :: Glue ) return false ; TCChain = Copy -> getOperand ( 0 ) ; } else { return false ; } bool HasRet = false ; for ( const SDNode * U : Copy -> uses ( ) ) { if ( U -> getOpcode ( ) != ARMISD :: RET_FLAG && U -> 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>
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
::
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>


<s> bool ARMTargetLowering :: shouldConvertFpToSat ( unsigned Op , EVT FPVT , EVT VT ) const { if ( ! isOperationLegalOrCustom ( Op , VT ) || ! FPVT . isSimple ( ) ) return false ; switch ( FPVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: f16 : return Subtarget -> hasVFP2Base ( ) ; case MVT :: f32 : return Subtarget -> hasVFP2Base ( ) ; case MVT :: f64 : return Subtarget -> hasFP64 ( ) ; case MVT :: v4f32 : case MVT :: v8f16 : return Subtarget -> hasMVEFloatOps ( ) ; default : return false ; } } </s>

Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min ( max ( fptoi ) ) saturation patterns .


<s> TargetLowering :: AtomicExpansionKind ARMTargetLowering :: shouldExpandAtomicCmpXchgInIR ( AtomicCmpXchgInst * AI ) const { unsigned Size = AI -> getOperand ( 1 ) -> getType ( ) -> getPrimitiveSizeInBits ( ) ; bool HasAtomicCmpXchg ; if ( Subtarget -> isMClass ( ) ) HasAtomicCmpXchg = Subtarget -> hasV8MBaselineOps ( ) ; else if ( Subtarget -> isThumb ( ) ) HasAtomicCmpXchg = Subtarget -> hasV7Ops ( ) ; else HasAtomicCmpXchg = Subtarget -> hasV6Ops ( ) ; 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 :: shouldExpandAtomicLoadInIR ( LoadInst * LI ) const { bool has64BitAtomicLoad ; if ( Subtarget -> isMClass ( ) ) has64BitAtomicLoad = false ; else if ( Subtarget -> isThumb ( ) ) has64BitAtomicLoad = Subtarget -> hasV7Ops ( ) ; else has64BitAtomicLoad = Subtarget -> hasV6Ops ( ) ; unsigned Size = LI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; return ( Size == 64 && has64BitAtomicLoad ) ? 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 { if ( AI -> isFloatingPointOperation ( ) ) return AtomicExpansionKind :: CmpXChg ; unsigned Size = AI -> getType ( ) -> getPrimitiveSizeInBits ( ) ; bool hasAtomicRMW ; if ( Subtarget -> isMClass ( ) ) hasAtomicRMW = Subtarget -> hasV8MBaselineOps ( ) ; else if ( Subtarget -> isThumb ( ) ) hasAtomicRMW = Subtarget -> hasV7Ops ( ) ; else hasAtomicRMW = Subtarget -> hasV6Ops ( ) ; if ( Size <= ( Subtarget -> isMClass ( ) ? 32U : 64U ) && hasAtomicRMW ) { if ( getTargetMachine ( ) . getOptLevel ( ) == CodeGenOpt :: None ) return AtomicExpansionKind :: CmpXChg ; return AtomicExpansionKind :: LLSC ; } return 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 { bool has64BitAtomicStore ; if ( Subtarget -> isMClass ( ) ) has64BitAtomicStore = false ; else if ( Subtarget -> isThumb ( ) ) has64BitAtomicStore = Subtarget -> hasV7Ops ( ) ; else has64BitAtomicStore = Subtarget -> hasV6Ops ( ) ; unsigned Size = SI -> getValueOperand ( ) -> getType ( ) -> getPrimitiveSizeInBits ( ) ; return Size == 64 && has64BitAtomicStore ; } </s>

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


<s> bool ARMTargetLowering :: useLoadStackGuardNode ( ) const { return true ; } </s>

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


<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
)
{
const
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 < unsigned , const TargetRegisterClass * > ARMTargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , EVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb ( ) ) return std :: make_pair ( 0U , ARM :: tGPRRegisterClass ) ; else return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'r' : return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'w' : if ( VT == MVT :: f32 ) return std :: make_pair ( 0U , ARM :: SPRRegisterClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return std :: make_pair ( 0U , ARM :: DPRRegisterClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return std :: make_pair ( 0U , ARM :: QPRRegisterClass ) ; break ; } } if ( StringRef ( "{cc}" ) . equals_lower ( Constraint ) ) return std :: make_pair ( unsigned ( ARM :: CPSR ) , ARM :: CCRRegisterClass ) ; return TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<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 :: Latency ; } if ( ! N -> isMachineOpcode ( ) ) return Sched :: RegPressure ; const TargetInstrInfo * TII = getTargetMachine ( ) . getInstrInfo ( ) ; const TargetInstrDesc & TID = TII -> get ( N -> getMachineOpcode ( ) ) ; if ( TID . getNumDefs ( ) == 0 ) return Sched :: RegPressure ; if ( ! Itins -> isEmpty ( ) && Itins -> getOperandCycle ( TID . getSchedClass ( ) , 0 ) > 2 ) return Sched :: Latency ; return Sched :: RegPressure ; } </s>


<s> TargetLowering :: ConstraintWeight ARMTargetLowering :: getSingleConstraintMatchWeight ( AsmOperandInfo & info , const char * constraint ) const { ConstraintWeight weight = CW_Invalid ; Value * CallOperandVal = info . CallOperandVal ; if ( CallOperandVal == NULL ) return CW_Default ; const 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> bool ARMTargetLowering :: getTgtMemIntrinsic ( IntrinsicInfo & Info , const CallInst & I , unsigned Intrinsic ) const { switch ( Intrinsic ) { case Intrinsic :: arm_neon_vld1 : case Intrinsic :: arm_neon_vld2 : case Intrinsic :: arm_neon_vld3 : case Intrinsic :: arm_neon_vld4 : case Intrinsic :: arm_neon_vld2lane : case Intrinsic :: arm_neon_vld3lane : case Intrinsic :: arm_neon_vld4lane : { Info . opc = ISD :: INTRINSIC_W_CHAIN ; uint64_t NumElts = getTargetData ( ) -> getTypeAllocSize ( I . getType ( ) ) / 8 ; Info . memVT = EVT :: getVectorVT ( I . getType ( ) -> getContext ( ) , MVT :: i64 , NumElts ) ; Info . ptrVal = I . getArgOperand ( 0 ) ; Info . offset = 0 ; Value * AlignArg = I . getArgOperand ( I . getNumArgOperands ( ) - 1 ) ; Info . align = cast < ConstantInt > ( AlignArg ) -> getZExtValue ( ) ; Info . vol = false ; Info . readMem = true ; Info . writeMem = false ; return true ; } case Intrinsic :: arm_neon_vst1 : case Intrinsic :: arm_neon_vst2 : case Intrinsic :: arm_neon_vst3 : case Intrinsic :: arm_neon_vst4 : case Intrinsic :: arm_neon_vst2lane : case Intrinsic :: arm_neon_vst3lane : case Intrinsic :: arm_neon_vst4lane : { Info . opc = ISD :: INTRINSIC_VOID ; unsigned NumElts = 0 ; for ( unsigned ArgI = 1 , ArgE = I . getNumArgOperands ( ) ; ArgI < ArgE ; ++ ArgI ) { const Type * ArgTy = I . getArgOperand ( ArgI ) -> getType ( ) ; if ( ! ArgTy -> isVectorTy ( ) ) break ; NumElts += getTargetData ( ) -> getTypeAllocSize ( ArgTy ) / 8 ; } Info . memVT = EVT :: getVectorVT ( I . getType ( ) -> getContext ( ) , MVT :: i64 , NumElts ) ; Info . ptrVal = I . getArgOperand ( 0 ) ; Info . offset = 0 ; Value * AlignArg = I . getArgOperand ( I . getNumArgOperands ( ) - 1 ) ; Info . align = cast < ConstantInt > ( AlignArg ) -> getZExtValue ( ) ; Info . vol = false ; Info . readMem = false ; Info . writeMem = true ; return true ; } default : break ; } return false ; } </s>

Given an intrinsic , checks if on the target the intrinsic will need to map to a MemIntrinsicNode ( touches memory ) .


<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 ) || 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 ) ) ; } </s>

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


<s> SDValue ARMTargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { switch ( N -> getOpcode ( ) ) { default : break ; case ISD :: ADD : return PerformADDCombine ( N , DCI ) ; case ISD :: SUB : return PerformSUBCombine ( N , DCI ) ; case ISD :: MUL : return PerformMULCombine ( N , DCI , Subtarget ) ; case ISD :: OR : return PerformORCombine ( N , DCI , Subtarget ) ; case ISD :: AND : return PerformANDCombine ( N , DCI ) ; case ARMISD :: BFI : return PerformBFICombine ( N , DCI ) ; case ARMISD :: VMOVRRD : return PerformVMOVRRDCombine ( N , DCI ) ; case ARMISD :: VMOVDRR : return PerformVMOVDRRCombine ( N , DCI . DAG ) ; case ISD :: STORE : return PerformSTORECombine ( N , DCI ) ; case ISD :: BUILD_VECTOR : return PerformBUILD_VECTORCombine ( N , DCI ) ; case ISD :: INSERT_VECTOR_ELT : return PerformInsertEltCombine ( N , DCI ) ; case ISD :: VECTOR_SHUFFLE : return PerformVECTOR_SHUFFLECombine ( N , DCI . DAG ) ; case ARMISD :: VDUPLANE : return PerformVDUPLANECombine ( N , DCI ) ; case ISD :: INTRINSIC_WO_CHAIN : return PerformIntrinsicCombine ( N , DCI . DAG ) ; case ISD :: SHL : case ISD :: SRA : case ISD :: SRL : return PerformShiftCombine ( N , DCI . DAG , Subtarget ) ; case ISD :: SIGN_EXTEND : case ISD :: ZERO_EXTEND : case ISD :: ANY_EXTEND : return PerformExtendCombine ( N , DCI . DAG , Subtarget ) ; case ISD :: SELECT_CC : return PerformSELECT_CCCombine ( N , DCI . DAG , Subtarget ) ; case ARMISD :: VLD2DUP : case ARMISD :: VLD3DUP : case ARMISD :: VLD4DUP : return CombineBaseUpdate ( N , DCI ) ; case ISD :: INTRINSIC_VOID : case ISD :: INTRINSIC_W_CHAIN : switch ( cast < ConstantSDNode > ( N -> getOperand ( 1 ) ) -> getZExtValue ( ) ) { case Intrinsic :: arm_neon_vld1 : case Intrinsic :: arm_neon_vld2 : case Intrinsic :: arm_neon_vld3 : case Intrinsic :: arm_neon_vld4 : case Intrinsic :: arm_neon_vld2lane : case Intrinsic :: arm_neon_vld3lane : case Intrinsic :: arm_neon_vld4lane : case Intrinsic :: arm_neon_vst1 : case Intrinsic :: arm_neon_vst2 : case Intrinsic :: arm_neon_vst3 : case Intrinsic :: arm_neon_vst4 : case Intrinsic :: arm_neon_vst2lane : case Intrinsic :: arm_neon_vst3lane : case Intrinsic :: arm_neon_vst4lane : return CombineBaseUpdate ( N , DCI ) ; default : break ; } break ; } return SDValue ( ) ; } </s>

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


<s>
void
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!"
)
;
break
;
case
ISD
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
Expand64BitShift
(
N
,
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 .

ARM
ARM
"Don't know how to custom expand this!"
ISD::BITCAST
ISD::SRL
ISD::SRA


<s> RCPair ARMTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , 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 ( TRI , Constraint , VT ) ; } </s>


<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
(
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> bool ARMTargetLowering :: isLegalAddressingMode ( const AddrMode & AM , Type * Ty , unsigned AS ) 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>
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
::
READCYCLECOUNTER
:
ReplaceREADCYCLECOUNTER
(
N
,
Results
,
DAG
,
Subtarget
)
;
return
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>

ARM
ARM
"Don't know how to custom expand this!"
ISD::READ_REGISTER
ISD::BITCAST
ISD::SRL
ISD::SRA
ISD::READCYCLECOUNTER


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


"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> 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 ( ) . getSubtargetImpl ( ) -> 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> 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 . getScalarSizeInBits ( ) ; 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 .


"Unmatched number of shufflevectors and indices"

Lower interleaved load ( s ) into target specific instructions/intrinsics .


<s>
bool
ARMTargetLowering
::
lowerInterleavedStore
(
StoreInst
*
SI
,
ShuffleVectorInst
*
SVI
,
unsigned
Factor
)
const
{
assert
(
Factor
>=
2
&&
Factor
<=
getMaxSupportedInterleaveFactor
(
)
&&
"Invalid interleave factor"
)
;
VectorType
*
VecTy
=
SVI
->
getType
(
)
;
assert
(
VecTy
->
getVectorNumElements
(
)
%
Factor
==
0
&&
"Invalid interleaved store"
)
;
unsigned
NumSubElts
=
VecTy
->
getVectorNumElements
(
)
/
Factor
;
Type
*
EltTy
=
VecTy
->
getVectorElementType
(
)
;
VectorType
*
SubVecTy
=
VectorType
::
get
(
EltTy
,
NumSubElts
)
;
const
DataLayout
&
DL
=
SI
->
getModule
(
)
->
getDataLayout
(
)
;
unsigned
SubVecSize
=
DL
.
getTypeAllocSizeInBits
(
SubVecTy
)
;
bool
EltIs64Bits
=
DL
.
getTypeAllocSizeInBits
(
EltTy
)
==
64
;
if
(
(
SubVecSize
!=
64
&&
SubVecSize
!=
128
)
||
EltIs64Bits
)
return
false
;
Value
*
Op0
=
SVI
->
getOperand
(
0
)
;
Value
*
Op1
=
SVI
->
getOperand
(
1
)
;
IRBuilder
<
>
Builder
(
SI
)
;
if
(
EltTy
->
isPointerTy
(
)
)
{
Type
*
IntTy
=
DL
.
getIntPtrType
(
EltTy
)
;
Type
*
IntVecTy
=
VectorType
::
get
(
IntTy
,
Op0
->
getType
(
)
->
getVectorNumElements
(
)
)
;
Op0
=
Builder
.
CreatePtrToInt
(
Op0
,
IntVecTy
)
;
Op1
=
Builder
.
CreatePtrToInt
(
Op1
,
IntVecTy
)
;
SubVecTy
=
VectorType
::
get
(
IntTy
,
NumSubElts
)
;
}
static
Intrinsic
::
ID
StoreInts
[
3
]
=
{
Intrinsic
::
arm_neon_vst2
,
Intrinsic
::
arm_neon_vst3
,
Intrinsic
::
arm_neon_vst4
}
;
Function
*
VstNFunc
=
Intrinsic
::
getDeclaration
(
SI
->
getModule
(
)
,
StoreInts
[
Factor
2
]
,
SubVecTy
)
;
SmallVector
<
Value
*
,
6
>
Ops
;
Type
*
Int8Ptr
=
Builder
.
getInt8PtrTy
(
SI
->
getPointerAddressSpace
(
)
)
;
Ops
.
push_back
(
Builder
.
CreateBitCast
(
SI
->
getPointerOperand
(
)
,
Int8Ptr
)
)
;
for
(
unsigned
i
=
0
;
i
<
Factor
;
i
++
)
Ops
.
push_back
(
Builder
.
CreateShuffleVector
(
Op0
,
Op1
,
getSequentialMask
(
Builder
,
NumSubElts
*
i
,
NumSubElts
)
)
)
;
Ops
.
push_back
(
Builder
.
getInt32
(
SI
->
getAlignment
(
)
)
)
;
Builder
.
CreateCall
(
VstNFunc
,
Ops
)
;
return
true
;
}
</s>

Lower interleaved store ( s ) into target specific instructions/intrinsics .


<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 ! Subtarget -> isThumb1Only ( ) ; } </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
)
;
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
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>

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


"Stack offset for byval regs doesn't introduced anymore?"

Target-specific cleanup for formal ByVal parameters .


<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
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
)
;
break
;
case
ISD
::
SIGN_EXTEND
:
case
ISD
::
ZERO_EXTEND
:
Res
=
ExpandVectorExtension
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
ATOMIC_LOAD_ADD
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMADD64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_AND
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMAND64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_NAND
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMNAND64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_OR
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMOR64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_SUB
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMSUB64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_XOR
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMXOR64_DAG
)
;
return
;
case
ISD
::
ATOMIC_SWAP
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMSWAP64_DAG
)
;
return
;
case
ISD
::
ATOMIC_CMP_SWAP
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMCMPXCHG64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_MIN
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMMIN64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_UMIN
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMUMIN64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_MAX
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMMAX64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_UMAX
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMUMAX64_DAG
)
;
return
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>


<s> EVT ARMTargetLowering :: getOptimalMemOpType ( uint64_t Size , unsigned DstAlign , unsigned SrcAlign , bool IsZeroVal , bool MemcpyStrSrc , MachineFunction & MF ) const { const Function * F = MF . getFunction ( ) ; if ( IsZeroVal && ! F -> getFnAttributes ( ) . hasNoImplicitFloatAttr ( ) && Subtarget -> hasNEON ( ) ) { if ( memOpAlign ( SrcAlign , DstAlign , 16 ) && Size >= 16 ) { return MVT :: v4i32 ; } else if ( memOpAlign ( SrcAlign , DstAlign , 8 ) && Size >= 8 ) { return MVT :: v2i32 ; } } 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 :: 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 :: v16i8 && Ty != MVT :: v8i16 && Ty != MVT :: v8f16 && Ty != MVT :: v4i32 && Ty != MVT :: v4f32 && Ty != MVT :: v2i64 && Ty != MVT :: v2f64 && Ty != MVT :: v4i8 && Ty != MVT :: v8i8 && Ty != MVT :: v4i16 ) return false ; if ( Subtarget -> isLittle ( ) ) { if ( Fast ) * Fast = true ; return true ; } else { if ( Ty == MVT :: v16i8 || ( ( Ty == MVT :: v8i16 || Ty == MVT :: v8f16 ) && Alignment >= 2 ) || ( ( Ty == MVT :: v4i32 || Ty == MVT :: v4f32 ) && Alignment >= 4 ) ) { if ( Fast ) * Fast = true ; return true ; } } return false ; } </s>

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


<s> ARMTargetLowering :: ConstraintType ARMTargetLowering :: getConstraintType ( StringRef 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 '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> bool ARMTargetLowering :: allowsMisalignedMemoryAccesses ( EVT VT , unsigned , unsigned , MachineMemOperand :: Flags , bool * Fast ) const { if ( ! VT . isSimple ( ) ) return false ; 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 || Subtarget -> isLittle ( ) ) ) { if ( Fast ) * Fast = true ; return true ; } return false ; } } } </s>


<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
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
ATOMIC_LOAD_ADD
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMADD64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_AND
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMAND64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_NAND
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMNAND64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_OR
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMOR64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_SUB
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMSUB64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_XOR
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMXOR64_DAG
)
;
return
;
case
ISD
::
ATOMIC_SWAP
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMSWAP64_DAG
)
;
return
;
case
ISD
::
ATOMIC_CMP_SWAP
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMCMPXCHG64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_MIN
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMMIN64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_UMIN
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMUMIN64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_MAX
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMMAX64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_UMAX
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMUMAX64_DAG
)
;
return
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>


<s> static void computeKnownBits ( SelectionDAG & DAG , SDValue Op , APInt & KnownZero , APInt & KnownOne ) { if ( Op . getOpcode ( ) == ARMISD :: BFI ) { computeKnownBits ( DAG , Op . getOperand ( 0 ) , KnownZero , KnownOne ) ; ConstantSDNode * CI = cast < ConstantSDNode > ( Op . getOperand ( 2 ) ) ; const APInt & Mask = CI -> getAPIntValue ( ) ; KnownZero &= Mask ; KnownOne &= Mask ; return ; } if ( Op . getOpcode ( ) == ARMISD :: CMOV ) { APInt KZ2 ( KnownZero . getBitWidth ( ) , 0 ) ; APInt KO2 ( KnownOne . getBitWidth ( ) , 0 ) ; computeKnownBits ( DAG , Op . getOperand ( 0 ) , KnownZero , KnownOne ) ; computeKnownBits ( DAG , Op . getOperand ( 1 ) , KZ2 , KO2 ) ; KnownZero &= KZ2 ; KnownOne &= KO2 ; return ; } return DAG . computeKnownBits ( Op , KnownZero , KnownOne ) ; } </s>

Determine which bits of Op are known to be either zero or one and return them in Known .


<s> void ARMTargetLowering :: computeKnownBitsForTargetNode ( const SDValue Op , APInt & KnownZero , APInt & KnownOne , const APInt & DemandedElts , 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 . getScalarSizeInBits ( ) ; KnownZero |= APInt :: getHighBitsSet ( BitWidth , BitWidth - MemBits ) ; return ; } } } } } </s>


<s> static unsigned getNumInterleavedAccesses ( VectorType * VecTy , const DataLayout & DL ) { 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> void ARMTargetLowering :: computeKnownBitsForTargetNode ( const SDValue Op , KnownBits & Known , const APInt & DemandedElts , const SelectionDAG & DAG , unsigned Depth ) const { unsigned BitWidth = Known . getBitWidth ( ) ; Known . resetAll ( ) ; switch ( Op . getOpcode ( ) ) { default : break ; case ARMISD :: ADDC : case ARMISD :: ADDE : case ARMISD :: SUBC : case ARMISD :: SUBE : if ( Op . getResNo ( ) == 0 ) { SDValue LHS = Op . getOperand ( 0 ) ; SDValue RHS = Op . getOperand ( 1 ) ; if ( Op -> getOpcode ( ) == ARMISD :: ADDE && isNullConstant ( LHS ) && isNullConstant ( RHS ) ) { Known . Zero |= APInt :: getHighBitsSet ( BitWidth , BitWidth - 1 ) ; return ; } } break ; case ARMISD :: CMOV : { Known = DAG . computeKnownBits ( Op . getOperand ( 0 ) , Depth + 1 ) ; if ( Known . isUnknown ( ) ) return ; KnownBits KnownRHS = DAG . computeKnownBits ( Op . getOperand ( 1 ) , Depth + 1 ) ; Known . Zero &= KnownRHS . Zero ; Known . One &= KnownRHS . One ; 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 . getScalarSizeInBits ( ) ; Known . Zero |= APInt :: getHighBitsSet ( BitWidth , BitWidth - MemBits ) ; return ; } } } case ARMISD :: BFI : { Known = DAG . computeKnownBits ( Op . getOperand ( 0 ) , Depth + 1 ) ; ConstantSDNode * CI = cast < ConstantSDNode > ( Op . getOperand ( 2 ) ) ; const APInt & Mask = CI -> getAPIntValue ( ) ; Known . Zero &= Mask ; Known . One &= Mask ; return ; } } } </s>


"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"


<s>
void
ARMTargetLowering
::
emitLeadingFence
(
IRBuilder
<
>
&
Builder
,
AtomicOrdering
Ord
,
bool
IsStore
,
bool
IsLoad
)
const
{
if
(
!
getInsertFencesForAtomic
(
)
)
return
;
switch
(
Ord
)
{
case
NotAtomic
:
case
Unordered
:
llvm_unreachable
(
"Invalid fence: unordered/non-atomic"
)
;
case
Monotonic
:
case
Acquire
:
return
;
case
SequentiallyConsistent
:
if
(
!
IsStore
)
return
;
case
Release
:
case
AcquireRelease
:
if
(
Subtarget
->
isSwift
(
)
)
makeDMB
(
Builder
,
ARM_MB
::
ISHST
)
;
else
makeDMB
(
Builder
,
ARM_MB
::
ISH
)
;
return
;
}
}
</s>


<s> bool ARMTargetLowering :: useLoadStackGuardNode ( ) const { return Subtarget -> getTargetTriple ( ) . getObjectFormat ( ) == Triple :: MachO ; } </s>

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


<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
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
)
;
break
;
case
ISD
::
SIGN_EXTEND
:
case
ISD
::
ZERO_EXTEND
:
Res
=
ExpandVectorExtension
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
READCYCLECOUNTER
:
ReplaceREADCYCLECOUNTER
(
N
,
Results
,
DAG
,
Subtarget
)
;
return
;
case
ISD
::
ATOMIC_STORE
:
case
ISD
::
ATOMIC_LOAD
:
case
ISD
::
ATOMIC_LOAD_ADD
:
case
ISD
::
ATOMIC_LOAD_AND
:
case
ISD
::
ATOMIC_LOAD_NAND
:
case
ISD
::
ATOMIC_LOAD_OR
:
case
ISD
::
ATOMIC_LOAD_SUB
:
case
ISD
::
ATOMIC_LOAD_XOR
:
case
ISD
::
ATOMIC_SWAP
:
case
ISD
::
ATOMIC_CMP_SWAP
:
case
ISD
::
ATOMIC_LOAD_MIN
:
case
ISD
::
ATOMIC_LOAD_UMIN
:
case
ISD
::
ATOMIC_LOAD_MAX
:
case
ISD
::
ATOMIC_LOAD_UMAX
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
)
;
return
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>


<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 :: Latency ; } 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 :: Latency ; return Sched :: RegPressure ; } </s>


<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 ) ; } break ; } return true ; } </s>


<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!"
)
;
break
;
case
ISD
::
BITCAST
:
Res
=
ExpandBITCAST
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
Expand64BitShift
(
N
,
DAG
,
Subtarget
)
;
break
;
case
ISD
::
ATOMIC_LOAD_ADD
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMADD64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_AND
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMAND64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_NAND
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMNAND64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_OR
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMOR64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_SUB
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMSUB64_DAG
)
;
return
;
case
ISD
::
ATOMIC_LOAD_XOR
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMXOR64_DAG
)
;
return
;
case
ISD
::
ATOMIC_SWAP
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMSWAP64_DAG
)
;
return
;
case
ISD
::
ATOMIC_CMP_SWAP
:
ReplaceATOMIC_OP_64
(
N
,
Results
,
DAG
,
ARMISD
::
ATOMCMPXCHG64_DAG
)
;
return
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>


<s> unsigned ARMTargetLowering :: getJumpTableEncoding ( ) const { if ( Subtarget -> useInlineJumpTables ( ) ) { return MachineJumpTableInfo :: EK_Inline ; } else { return TargetLowering :: getJumpTableEncoding ( ) ; } } </s>

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


<s> bool ARMTargetLowering :: getPostIndexedAddressParts ( SDNode * N , SDNode * Op , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb1Only ( ) ) return false ; const bool restrict_addressing_modes_for_nacl = Subtarget -> isTargetNaCl ( ) && ( N -> getOpcode ( ) == ISD :: LOAD || N -> getOpcode ( ) == ISD :: STORE ) ; if ( restrict_addressing_modes_for_nacl ) { 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::LOAD ISD::STORE 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 ; const bool restrict_addressing_modes_for_nacl = Subtarget -> isTargetNaCl ( ) && ( N -> getOpcode ( ) == ISD :: LOAD || N -> getOpcode ( ) == ISD :: STORE ) ; if ( restrict_addressing_modes_for_nacl ) { 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::LOAD ISD::STORE ISD::SEXTLOAD ARM ISD::PRE_INC ISD::PRE_DEC


<s>
SDValue
ARMTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom lower this!"
)
;
case
ISD
::
ConstantPool
:
return
LowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
LowerBlockAddress
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
Subtarget
->
isTargetDarwin
(
)
LowerGlobalAddressDarwin
(
Op
,
DAG
)
:
LowerGlobalAddressELF
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
LowerGlobalTLSAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
)
;
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
)
;
case
ISD
::
BR_JT
:
return
LowerBR_JT
(
Op
,
DAG
)
;
case
ISD
::
DYNAMIC_STACKALLOC
:
return
LowerDYNAMIC_STACKALLOC
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
LowerVASTART
(
Op
,
DAG
,
VarArgsFrameIndex
)
;
case
ISD
::
MEMBARRIER
:
return
LowerMEMBARRIER
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
FP16_TO_FP32
:
case
ISD
::
SINT_TO_FP
:
case
ISD
::
UINT_TO_FP
:
return
LowerINT_TO_FP
(
Op
,
DAG
)
;
case
ISD
::
FP32_TO_FP16
:
case
ISD
::
FP_TO_SINT
:
case
ISD
::
FP_TO_UINT
:
return
LowerFP_TO_INT
(
Op
,
DAG
)
;
case
ISD
::
FCOPYSIGN
:
return
LowerFCOPYSIGN
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
break
;
case
ISD
::
FRAMEADDR
:
return
LowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
return
LowerGLOBAL_OFFSET_TABLE
(
Op
,
DAG
)
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
LowerINTRINSIC_WO_CHAIN
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BIT_CONVERT
:
return
ExpandBIT_CONVERT
(
Op
.
getNode
(
)
,
DAG
)
;
case
ISD
::
SHL
:
case
ISD
::
SRL
:
case
ISD
::
SRA
:
return
LowerShift
(
Op
.
getNode
(
)
,
DAG
,
Subtarget
)
;
case
ISD
::
SHL_PARTS
:
return
LowerShiftLeftParts
(
Op
,
DAG
)
;
case
ISD
::
SRL_PARTS
:
case
ISD
::
SRA_PARTS
:
return
LowerShiftRightParts
(
Op
,
DAG
)
;
case
ISD
::
CTTZ
:
return
LowerCTTZ
(
Op
.
getNode
(
)
,
DAG
,
Subtarget
)
;
case
ISD
::
VSETCC
:
return
LowerVSETCC
(
Op
,
DAG
)
;
case
ISD
::
BUILD_VECTOR
:
return
LowerBUILD_VECTOR
(
Op
,
DAG
)
;
case
ISD
::
VECTOR_SHUFFLE
:
return
LowerVECTOR_SHUFFLE
(
Op
,
DAG
)
;
case
ISD
::
EXTRACT_VECTOR_ELT
:
return
LowerEXTRACT_VECTOR_ELT
(
Op
,
DAG
)
;
case
ISD
::
CONCAT_VECTORS
:
return
LowerCONCAT_VECTORS
(
Op
,
DAG
)
;
}
return
SDValue
(
)
;
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .


<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 . optForMinSize ( ) ; 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 :: isFPImmLegal ( const APFloat & Imm , EVT VT , bool ForCodeSize ) const { if ( ! Subtarget -> hasVFP3 ( ) ) 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 -> isFPOnlySP ( ) ) 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 :: isUsedByReturnOnly ( SDNode * N ) const { if ( N -> getNumValues ( ) != 1 ) return false ; if ( ! N -> hasNUsesOfValue ( 1 , 0 ) ) return false ; unsigned NumCopies = 0 ; SDNode * Copies [ 2 ] = { 0 , 0 } ; SDNode * Use = * N -> use_begin ( ) ; if ( Use -> getOpcode ( ) == ISD :: CopyToReg ) { Copies [ NumCopies ++ ] = Use ; } else if ( Use -> getOpcode ( ) == ARMISD :: VMOVRRD ) { for ( SDNode :: use_iterator UI = Use -> use_begin ( ) , UE = Use -> use_end ( ) ; UI != UE ; ++ UI ) { if ( UI -> getOpcode ( ) != ISD :: CopyToReg ) return false ; Copies [ UI . getUse ( ) . getResNo ( ) ] = * UI ; ++ NumCopies ; } } else if ( Use -> getOpcode ( ) == ISD :: BITCAST ) { if ( ! Use -> hasNUsesOfValue ( 1 , 0 ) ) return false ; Use = * Use -> use_begin ( ) ; if ( Use -> getOpcode ( ) != ISD :: CopyToReg || ! Use -> hasNUsesOfValue ( 1 , 0 ) ) return false ; Copies [ NumCopies ++ ] = Use ; } else { return false ; } if ( NumCopies != 1 && NumCopies != 2 ) return false ; bool HasRet = false ; for ( unsigned i = 0 ; i < NumCopies ; ++ i ) { SDNode * Copy = Copies [ i ] ; for ( SDNode :: use_iterator UI = Copy -> use_begin ( ) , UE = Copy -> use_end ( ) ; UI != UE ; ++ UI ) { if ( UI -> getOpcode ( ) == ISD :: CopyToReg ) { SDNode * Use = * UI ; if ( Use == Copies [ 0 ] || ( ( NumCopies == 2 ) && ( Use == Copies [ 1 ] ) ) ) continue ; return false ; } if ( UI -> getOpcode ( ) != ARMISD :: RET_FLAG ) return false ; HasRet = true ; } } return HasRet ; } </s>

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


<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
=
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> std :: pair < unsigned , const TargetRegisterClass * > ARMTargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , EVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb ( ) ) return std :: make_pair ( 0U , ARM :: tGPRRegisterClass ) ; else return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'r' : return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'w' : if ( VT == MVT :: f32 ) return std :: make_pair ( 0U , ARM :: SPRRegisterClass ) ; if ( VT . getSizeInBits ( ) == 64 ) return std :: make_pair ( 0U , ARM :: DPRRegisterClass ) ; if ( VT . getSizeInBits ( ) == 128 ) return std :: make_pair ( 0U , ARM :: QPRRegisterClass ) ; break ; } } if ( StringRef ( "{cc}" ) . equals_lower ( Constraint ) ) return std :: make_pair ( 0U , ARM :: CCRRegisterClass ) ; return TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<s>
void
ARMTargetLowering
::
ReplaceNodeResults
(
SDNode
*
N
,
SmallVectorImpl
<
SDValue
>
&
Results
,
SelectionDAG
&
DAG
)
{
SDValue
Res
;
switch
(
N
->
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom expand this!"
)
;
break
;
case
ISD
::
BIT_CONVERT
:
Res
=
ExpandBIT_CONVERT
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
LowerShift
(
N
,
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 .

ARM
ARM
"Don't know how to custom expand this!"
ISD::BIT_CONVERT
ISD::SRL
ISD::SRA


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

Get the maximum supported factor for interleaved memory accesses .


<s>
Register
ARMTargetLowering
::
getRegisterByName
(
const
char
*
RegName
,
EVT
VT
,
const
MachineFunction
&
MF
)
const
{
Register
Reg
=
StringSwitch
<
unsigned
>
(
RegName
)
.
Case
(
"r6"
,
ARM
::
R6
)
.
Case
(
"r7"
,
ARM
::
R7
)
.
Case
(
"r8"
,
ARM
::
R8
)
.
Case
(
"r9"
,
ARM
::
R9
)
.
Case
(
"r10"
,
ARM
::
R10
)
.
Case
(
"r11"
,
ARM
::
R11
)
.
Case
(
"sp"
,
ARM
::
SP
)
.
Default
(
ARM
::
NoRegister
)
;
if
(
Reg
!=
ARM
::
NoRegister
)
return
Reg
;
report_fatal_error
(
Twine
(
"Invalid register name \""
+
StringRef
(
RegName
)
+
"\"."
)
)
;
}
</s>

Return the register ID of the name passed in .


"Unmatched number of shufflevectors and indices"

Lower interleaved load ( s ) into target specific instructions/intrinsics .


<s> bool canMergeStoresTo ( unsigned AddressSpace , EVT MemVT ) const override { return ( MemVT . getSizeInBits ( ) <= 32 ) ; } </s>

Returns if it 's reasonable to merge stores to MemVT size .


<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
::
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
::
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>

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


<s> std :: pair < unsigned , const TargetRegisterClass * > ARMTargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , EVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb1Only ( ) ) return std :: make_pair ( 0U , ARM :: tGPRRegisterClass ) ; else return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'r' : return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'w' : if ( VT == MVT :: f32 ) return std :: make_pair ( 0U , ARM :: SPRRegisterClass ) ; if ( VT == MVT :: f64 ) return std :: make_pair ( 0U , ARM :: DPRRegisterClass ) ; break ; } } return TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; } </s>


<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 ; return ( ShuffleVectorSDNode :: isSplatMask ( & M [ 0 ] , VT ) || isVREVMask ( M , VT , 64 ) || isVREVMask ( M , VT , 32 ) || isVREVMask ( M , VT , 16 ) || isVEXTMask ( M , VT , ReverseVEXT , Imm ) || isVTRNMask ( M , VT , WhichResult ) || isVUZPMask ( M , VT , WhichResult ) || isVZIPMask ( M , VT , WhichResult ) ) ; } </s>

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


<s>
SDValue
ARMTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom lower this!"
)
;
case
ISD
::
ConstantPool
:
return
LowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
Subtarget
->
isTargetDarwin
(
)
LowerGlobalAddressDarwin
(
Op
,
DAG
)
:
LowerGlobalAddressELF
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
LowerGlobalTLSAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BR_JT
:
return
LowerBR_JT
(
Op
,
DAG
)
;
case
ISD
::
DYNAMIC_STACKALLOC
:
return
LowerDYNAMIC_STACKALLOC
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
LowerVASTART
(
Op
,
DAG
,
VarArgsFrameIndex
)
;
case
ISD
::
SINT_TO_FP
:
case
ISD
::
UINT_TO_FP
:
return
LowerINT_TO_FP
(
Op
,
DAG
)
;
case
ISD
::
FP_TO_SINT
:
case
ISD
::
FP_TO_UINT
:
return
LowerFP_TO_INT
(
Op
,
DAG
)
;
case
ISD
::
FCOPYSIGN
:
return
LowerFCOPYSIGN
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
break
;
case
ISD
::
FRAMEADDR
:
return
LowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
return
LowerGLOBAL_OFFSET_TABLE
(
Op
,
DAG
)
;
case
ISD
::
INTRINSIC_VOID
:
case
ISD
::
INTRINSIC_W_CHAIN
:
return
LowerINTRINSIC_W_CHAIN
(
Op
,
DAG
)
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
LowerINTRINSIC_WO_CHAIN
(
Op
,
DAG
)
;
case
ISD
::
BIT_CONVERT
:
return
ExpandBIT_CONVERT
(
Op
.
getNode
(
)
,
DAG
)
;
case
ISD
::
SHL
:
case
ISD
::
SRL
:
case
ISD
::
SRA
:
return
LowerShift
(
Op
.
getNode
(
)
,
DAG
,
Subtarget
)
;
case
ISD
::
VSETCC
:
return
LowerVSETCC
(
Op
,
DAG
)
;
case
ISD
::
BUILD_VECTOR
:
return
LowerBUILD_VECTOR
(
Op
,
DAG
)
;
case
ISD
::
VECTOR_SHUFFLE
:
return
LowerVECTOR_SHUFFLE
(
Op
,
DAG
)
;
case
ISD
::
SCALAR_TO_VECTOR
:
return
LowerSCALAR_TO_VECTOR
(
Op
,
DAG
)
;
case
ISD
::
EXTRACT_VECTOR_ELT
:
return
LowerEXTRACT_VECTOR_ELT
(
Op
,
DAG
)
;
case
ISD
::
CONCAT_VECTORS
:
return
LowerCONCAT_VECTORS
(
Op
,
DAG
)
;
}
return
SDValue
(
)
;
}
</s>


<s> SDValue ARMTargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { switch ( N -> getOpcode ( ) ) { default : break ; case ISD :: ADD : return PerformADDCombine ( N , DCI ) ; case ISD :: SUB : return PerformSUBCombine ( N , DCI ) ; case ARMISD :: FMRRD : return PerformFMRRDCombine ( N , DCI ) ; case ISD :: INTRINSIC_WO_CHAIN : return PerformIntrinsicCombine ( N , DCI . DAG ) ; case ISD :: SHL : case ISD :: SRA : case ISD :: SRL : return PerformShiftCombine ( N , DCI . DAG , Subtarget ) ; case ISD :: SIGN_EXTEND : case ISD :: ZERO_EXTEND : case ISD :: ANY_EXTEND : return PerformExtendCombine ( N , DCI . DAG , Subtarget ) ; } return SDValue ( ) ; } </s>

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

ARM ARM ISD::ADD ISD::SUB ARMISD::FMRRD ISD::INTRINSIC_WO_CHAIN ISD::SHL ISD::SRA ISD::SRL ISD::SIGN_EXTEND ISD::ZERO_EXTEND ISD::ANY_EXTEND


<s> bool ARMTargetLowering :: getPostIndexedAddressParts ( SDNode * N , SDNode * Op , SDValue & Base , SDValue & Offset , ISD :: MemIndexedMode & AM , SelectionDAG & DAG ) const { if ( Subtarget -> isThumb1Only ( ) ) return false ; const bool restrict_addressing_modes_for_nacl = Subtarget -> isTargetNaCl ( ) && isa < MemSDNode > ( N ) ; if ( restrict_addressing_modes_for_nacl ) { 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>

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 ; const bool restrict_addressing_modes_for_nacl = Subtarget -> isTargetNaCl ( ) && isa < MemSDNode > ( N ) ; if ( restrict_addressing_modes_for_nacl ) { 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>

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


<s> void ARMTargetLowering :: computeKnownBitsForTargetNode ( const SDValue Op , APInt & KnownZero , APInt & KnownOne , const APInt & DemandedElts , 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 . getScalarSizeInBits ( ) ; KnownZero |= APInt :: getHighBitsSet ( BitWidth , BitWidth - MemBits ) ; return ; } } } case ARMISD :: BFI : { DAG . computeKnownBits ( Op . getOperand ( 0 ) , KnownZero , KnownOne , Depth + 1 ) ; ConstantSDNode * CI = cast < ConstantSDNode > ( Op . getOperand ( 2 ) ) ; const APInt & Mask = CI -> getAPIntValue ( ) ; KnownZero &= Mask ; KnownOne &= Mask ; 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> std :: pair < const TargetRegisterClass * , uint8_t > ARMTargetLowering :: findRepresentativeClass ( EVT VT ) const { const TargetRegisterClass * RRC = 0 ; uint8_t Cost = 1 ; switch ( VT . getSimpleVT ( ) . 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 :: DPRRegisterClass ; break ; case MVT :: v16i8 : case MVT :: v8i16 : case MVT :: v4i32 : case MVT :: v2i64 : case MVT :: v4f32 : case MVT :: v2f64 : RRC = ARM :: DPRRegisterClass ; Cost = 2 ; break ; case MVT :: v4i64 : RRC = ARM :: DPRRegisterClass ; Cost = 4 ; break ; case MVT :: v8i64 : RRC = ARM :: DPRRegisterClass ; 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 '' .


<s> unsigned ARMTargetLowering :: getRegPressureLimit ( const TargetRegisterClass * RC , MachineFunction & MF ) const { switch ( RC -> getID ( ) ) { default : return 0 ; case ARM :: tGPRRegClassID : return RegInfo -> hasFP ( MF ) ? 4 : 5 ; case ARM :: GPRRegClassID : { unsigned FP = RegInfo -> hasFP ( MF ) ? 1 : 0 ; return 10 - FP - ( Subtarget -> isR9Reserved ( ) ? 1 : 0 ) ; } case ARM :: SPRRegClassID : case ARM :: DPRRegClassID : return 32 - 10 ; } } </s>

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


<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 . isFloatingPoint ( ) || VT . isVector ( ) ) return Sched :: Latency ; } if ( ! N -> isMachineOpcode ( ) ) return Sched :: RegPressure ; const TargetInstrInfo * TII = getTargetMachine ( ) . getInstrInfo ( ) ; const TargetInstrDesc & TID = TII -> get ( N -> getMachineOpcode ( ) ) ; if ( TID . mayLoad ( ) ) return Sched :: Latency ; const InstrItineraryData & Itins = getTargetMachine ( ) . getInstrItineraryData ( ) ; if ( ! Itins . isEmpty ( ) && Itins . getStageLatency ( TID . getSchedClass ( ) ) > 2 ) return Sched :: Latency ; return Sched :: RegPressure ; } </s>


<s>
SDValue
ARMTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Don't know how to custom lower this!"
)
;
case
ISD
::
ConstantPool
:
return
LowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
LowerBlockAddress
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
Subtarget
->
isTargetDarwin
(
)
LowerGlobalAddressDarwin
(
Op
,
DAG
)
:
LowerGlobalAddressELF
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
LowerGlobalTLSAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT
:
return
LowerSELECT
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
)
;
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
)
;
case
ISD
::
BR_JT
:
return
LowerBR_JT
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
LowerVASTART
(
Op
,
DAG
)
;
case
ISD
::
MEMBARRIER
:
return
LowerMEMBARRIER
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
SINT_TO_FP
:
case
ISD
::
UINT_TO_FP
:
return
LowerINT_TO_FP
(
Op
,
DAG
)
;
case
ISD
::
FP_TO_SINT
:
case
ISD
::
FP_TO_UINT
:
return
LowerFP_TO_INT
(
Op
,
DAG
)
;
case
ISD
::
FCOPYSIGN
:
return
LowerFCOPYSIGN
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
return
LowerRETURNADDR
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
LowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
return
LowerGLOBAL_OFFSET_TABLE
(
Op
,
DAG
)
;
case
ISD
::
EH_SJLJ_SETJMP
:
return
LowerEH_SJLJ_SETJMP
(
Op
,
DAG
)
;
case
ISD
::
EH_SJLJ_LONGJMP
:
return
LowerEH_SJLJ_LONGJMP
(
Op
,
DAG
)
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
LowerINTRINSIC_WO_CHAIN
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BIT_CONVERT
:
return
ExpandBIT_CONVERT
(
Op
.
getNode
(
)
,
DAG
)
;
case
ISD
::
SHL
:
case
ISD
::
SRL
:
case
ISD
::
SRA
:
return
LowerShift
(
Op
.
getNode
(
)
,
DAG
,
Subtarget
)
;
case
ISD
::
SHL_PARTS
:
return
LowerShiftLeftParts
(
Op
,
DAG
)
;
case
ISD
::
SRL_PARTS
:
case
ISD
::
SRA_PARTS
:
return
LowerShiftRightParts
(
Op
,
DAG
)
;
case
ISD
::
CTTZ
:
return
LowerCTTZ
(
Op
.
getNode
(
)
,
DAG
,
Subtarget
)
;
case
ISD
::
VSETCC
:
return
LowerVSETCC
(
Op
,
DAG
)
;
case
ISD
::
BUILD_VECTOR
:
return
LowerBUILD_VECTOR
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
VECTOR_SHUFFLE
:
return
LowerVECTOR_SHUFFLE
(
Op
,
DAG
)
;
case
ISD
::
EXTRACT_VECTOR_ELT
:
return
LowerEXTRACT_VECTOR_ELT
(
Op
,
DAG
)
;
case
ISD
::
CONCAT_VECTORS
:
return
LowerCONCAT_VECTORS
(
Op
,
DAG
)
;
case
ISD
::
FLT_ROUNDS_
:
return
LowerFLT_ROUNDS_
(
Op
,
DAG
)
;
case
ISD
::
MUL
:
return
LowerMUL
(
Op
,
DAG
)
;
}
return
SDValue
(
)
;
}
</s>


<s> SDValue ARMTargetLowering :: PerformDAGCombine ( SDNode * N , DAGCombinerInfo & DCI ) const { switch ( N -> getOpcode ( ) ) { default : break ; case ISD :: ADD : return PerformADDCombine ( N , DCI ) ; case ISD :: SUB : return PerformSUBCombine ( N , DCI ) ; case ISD :: MUL : return PerformMULCombine ( N , DCI , Subtarget ) ; case ISD :: OR : return PerformORCombine ( N , DCI , Subtarget ) ; case ARMISD :: VMOVRRD : return PerformVMOVRRDCombine ( N , DCI ) ; case ARMISD :: VDUPLANE : return PerformVDUPLANECombine ( N , DCI ) ; case ISD :: INTRINSIC_WO_CHAIN : return PerformIntrinsicCombine ( N , DCI . DAG ) ; case ISD :: SHL : case ISD :: SRA : case ISD :: SRL : return PerformShiftCombine ( N , DCI . DAG , Subtarget ) ; case ISD :: SIGN_EXTEND : case ISD :: ZERO_EXTEND : case ISD :: ANY_EXTEND : return PerformExtendCombine ( N , DCI . DAG , Subtarget ) ; case ISD :: SELECT_CC : return PerformSELECT_CCCombine ( N , DCI . DAG , Subtarget ) ; } return SDValue ( ) ; } </s>

ARM ARM ISD::ADD ISD::SUB ISD::MUL ISD::OR ARMISD::VMOVRRD ARMISD::VDUPLANE ISD::INTRINSIC_WO_CHAIN ISD::SHL ISD::SRA ISD::SRL ISD::SIGN_EXTEND ISD::ZERO_EXTEND ISD::ANY_EXTEND ISD::SELECT_CC


<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!"
)
;
break
;
case
ISD
::
BIT_CONVERT
:
Res
=
ExpandBIT_CONVERT
(
N
,
DAG
)
;
break
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
Res
=
LowerShift
(
N
,
DAG
,
Subtarget
)
;
break
;
}
if
(
Res
.
getNode
(
)
)
Results
.
push_back
(
Res
)
;
}
</s>


<s> std :: pair < unsigned , const TargetRegisterClass * > ARMTargetLowering :: getRegForInlineAsmConstraint ( const std :: string & Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'l' : if ( Subtarget -> isThumb ( ) ) return std :: make_pair ( 0U , ARM :: tGPRRegisterClass ) ; else return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'r' : return std :: make_pair ( 0U , ARM :: GPRRegisterClass ) ; case 'w' : if ( VT == MVT :: f32 ) return std :: make_pair ( 0U , ARM :: SPRRegisterClass ) ; if ( VT == MVT :: f64 ) return std :: make_pair ( 0U , ARM :: DPRRegisterClass ) ; break ; } } return TargetLowering :: getRegForInlineAsmConstraint ( Constraint , VT ) ; } </s>


<s> bool ARMTargetLowering :: isLegalAddressingMode ( const AddrMode & AM , const Type * Ty ) const { MVT 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 -> isThumb ( ) ) return false ; default : if ( AM . BaseOffs ) return false ; if ( ! VT . isSimple ( ) ) return false ; int Scale = AM . Scale ; switch ( VT . getSimpleVT ( ) ) { default : return false ; case MVT :: i1 : case MVT :: i8 : case MVT :: i32 : case MVT :: i64 : if ( Scale < 0 ) Scale = - Scale ; if ( Scale == 1 ) return true ; return isPowerOf2_32 ( Scale & ~ 1 ) ; case MVT :: i16 : if ( ( ( unsigned ) AM . HasBaseReg + Scale ) <= 2 ) return true ; return false ; case MVT :: isVoid : if ( AM . Scale & 1 ) return false ; return isPowerOf2_32 ( AM . Scale ) ; } break ; } 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> void ARMTargetLowering :: LowerAsmOperandForConstraint ( SDValue Op , char Constraint , bool hasMemory , std :: vector < SDValue > & Ops , SelectionDAG & DAG ) const { SDValue Result ( 0 , 0 ) ; switch ( Constraint ) { default : break ; case 'I' : case 'J' : case 'K' : case 'L' : case 'M' : case 'N' : case 'O' : ConstantSDNode * C = dyn_cast < ConstantSDNode > ( Op ) ; if ( ! C ) return ; int64_t CVal64 = C -> getSExtValue ( ) ; int CVal = ( int ) CVal64 ; if ( CVal != CVal64 ) return ; switch ( Constraint ) { case 'I' : if ( Subtarget -> isThumb ( ) ) { if ( CVal >= 0 && CVal <= 255 ) break ; } else { if ( ARM_AM :: getSOImmVal ( CVal ) != - 1 ) break ; } return ; case 'J' : if ( Subtarget -> isThumb ( ) ) { if ( CVal >= - 255 && CVal <= - 1 ) break ; } else { if ( CVal >= - 4095 && CVal <= 4095 ) break ; } return ; case 'K' : if ( Subtarget -> isThumb ( ) ) { if ( CVal != 0 && ARM_AM :: isThumbImmShiftedVal ( CVal ) ) break ; } else { if ( ARM_AM :: getSOImmVal ( ~ CVal ) != - 1 ) break ; } return ; case 'L' : if ( Subtarget -> isThumb ( ) ) { if ( CVal >= - 7 && CVal < 7 ) break ; } else { if ( ARM_AM :: getSOImmVal ( - CVal ) != - 1 ) break ; } return ; case 'M' : if ( Subtarget -> isThumb ( ) ) { if ( ( CVal >= 0 && CVal <= 1020 ) && ( ( CVal & 3 ) == 0 ) ) break ; } else { if ( ( CVal >= 0 && CVal <= 32 ) || ( ( CVal & ( CVal - 1 ) ) == 0 ) ) break ; } return ; case 'N' : if ( Subtarget -> isThumb ( ) ) { if ( CVal >= 0 && CVal <= 31 ) break ; } return ; case 'O' : if ( Subtarget -> isThumb ( ) ) { if ( ( CVal >= - 508 && CVal <= 508 ) && ( ( CVal & 3 ) == 0 ) ) break ; } return ; } Result = DAG . getTargetConstant ( CVal , Op . getValueType ( ) ) ; break ; } if ( Result . getNode ( ) ) { Ops . push_back ( Result ) ; return ; } return TargetLowering :: LowerAsmOperandForConstraint ( Op , Constraint , hasMemory , Ops , DAG ) ; } </s>

Lower the specified operand into the Ops vector .


<s>
SDNode
*
ARMTargetLowering
::
LowerCallResult
(
SDValue
Chain
,
SDValue
InFlag
,
CallSDNode
*
TheCall
,
unsigned
CallingConv
,
SelectionDAG
&
DAG
)
{
DebugLoc
dl
=
TheCall
->
getDebugLoc
(
)
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
bool
isVarArg
=
TheCall
->
isVarArg
(
)
;
CCState
CCInfo
(
CallingConv
,
isVarArg
,
getTargetMachine
(
)
,
RVLocs
)
;
CCInfo
.
AnalyzeCallResult
(
TheCall
,
RetCC_ARM
)
;
SmallVector
<
SDValue
,
8
>
ResultVals
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
VA
=
RVLocs
[
i
]
;
SDValue
Val
;
if
(
VA
.
needsCustom
(
)
)
{
SDValue
Lo
=
DAG
.
getCopyFromReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
MVT
::
i32
,
InFlag
)
;
Chain
=
Lo
.
getValue
(
1
)
;
InFlag
=
Lo
.
getValue
(
2
)
;
VA
=
RVLocs
[
++
i
]
;
SDValue
Hi
=
DAG
.
getCopyFromReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
MVT
::
i32
,
InFlag
)
;
Chain
=
Hi
.
getValue
(
1
)
;
InFlag
=
Hi
.
getValue
(
2
)
;
Val
=
DAG
.
getNode
(
ARMISD
::
FMDRR
,
dl
,
MVT
::
f64
,
Lo
,
Hi
)
;
}
else
{
Val
=
DAG
.
getCopyFromReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
,
InFlag
)
;
Chain
=
Val
.
getValue
(
1
)
;
InFlag
=
Val
.
getValue
(
2
)
;
}
switch
(
VA
.
getLocInfo
(
)
)
{
default
:
assert
(
0
&&
"Unknown loc info!"
)
;
case
CCValAssign
::
Full
:
break
;
case
CCValAssign
::
BCvt
:
Val
=
DAG
.
getNode
(
ISD
::
BIT_CONVERT
,
dl
,
VA
.
getValVT
(
)
,
Val
)
;
break
;
}
ResultVals
.
push_back
(
Val
)
;
}
ResultVals
.
push_back
(
Chain
)
;
return
DAG
.
getNode
(
ISD
::
MERGE_VALUES
,
dl
,
TheCall
->
getVTList
(
)
,
&
ResultVals
[
0
]
,
ResultVals
.
size
(
)
)
.
getNode
(
)
;
}
</s>

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


<s>
SDValue
ARMTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
assert
(
0
&&
"Don't know how to custom lower this!"
)
;
abort
(
)
;
case
ISD
::
ConstantPool
:
return
LowerConstantPool
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
Subtarget
->
isTargetDarwin
(
)
LowerGlobalAddressDarwin
(
Op
,
DAG
)
:
LowerGlobalAddressELF
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
LowerGlobalTLSAddress
(
Op
,
DAG
)
;
case
ISD
::
CALL
:
return
LowerCALL
(
Op
,
DAG
)
;
case
ISD
::
RET
:
return
LowerRET
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
,
Subtarget
)
;
case
ISD
::
BR_JT
:
return
LowerBR_JT
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
LowerVASTART
(
Op
,
DAG
,
VarArgsFrameIndex
)
;
case
ISD
::
SINT_TO_FP
:
case
ISD
::
UINT_TO_FP
:
return
LowerINT_TO_FP
(
Op
,
DAG
)
;
case
ISD
::
FP_TO_SINT
:
case
ISD
::
FP_TO_UINT
:
return
LowerFP_TO_INT
(
Op
,
DAG
)
;
case
ISD
::
FCOPYSIGN
:
return
LowerFCOPYSIGN
(
Op
,
DAG
)
;
case
ISD
::
FORMAL_ARGUMENTS
:
return
LowerFORMAL_ARGUMENTS
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
break
;
case
ISD
::
FRAMEADDR
:
return
LowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
return
LowerGLOBAL_OFFSET_TABLE
(
Op
,
DAG
)
;
case
ISD
::
INTRINSIC_WO_CHAIN
:
return
LowerINTRINSIC_WO_CHAIN
(
Op
,
DAG
)
;
case
ISD
::
BIT_CONVERT
:
return
ExpandBIT_CONVERT
(
Op
.
getNode
(
)
,
DAG
)
;
case
ISD
::
SRL
:
case
ISD
::
SRA
:
return
ExpandSRx
(
Op
.
getNode
(
)
,
DAG
,
Subtarget
)
;
}
return
SDValue
(
)
;
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .


<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 return false ; } </s>


<s> unsigned ARMTargetLowering :: getRegPressureLimit ( const TargetRegisterClass * RC , MachineFunction & MF ) const { const TargetFrameInfo * TFI = MF . getTarget ( ) . getFrameInfo ( ) ; switch ( RC -> getID ( ) ) { default : return 0 ; case ARM :: tGPRRegClassID : return TFI -> hasFP ( MF ) ? 4 : 5 ; case ARM :: GPRRegClassID : { unsigned FP = TFI -> hasFP ( MF ) ? 1 : 0 ; return 10 - FP - ( Subtarget -> isR9Reserved ( ) ? 1 : 0 ) ; } case ARM :: SPRRegClassID : case ARM :: DPRRegClassID : return 32 - 10 ; } } </s>