<s>
bool
MipsAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
SmallVectorImpl
<
MCParsedAsmOperand
*
>
&
Operands
)
{
if
(
!
mnemonicIsValid
(
Name
,
0
)
)
{
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
NameLoc
,
"Unknown instruction"
)
;
}
Operands
.
push_back
(
MipsOperand
::
CreateToken
(
Name
,
NameLoc
)
)
;
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
if
(
ParseOperand
(
Operands
,
Name
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token in argument list"
)
;
}
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
Parser
.
Lex
(
)
;
if
(
ParseOperand
(
Operands
,
Name
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token in argument list"
)
;
}
}
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
Parser
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token in argument list"
)
;
}
Parser
.
Lex
(
)
;
return
false
;
}
</s>

ParseInstruction - Parse one assembly instruction .

Mips
Mips
0
"Unknown instruction"
MipsOperand::CreateToken
"unexpected token in argument list"
"unexpected token in argument list"
"unexpected token in argument list"


"C++ constructor pointer had zero size!"

"C++ constructor pointer was not a GlobalValue!"

Targets can override this to change how global constants that are part of a C++ static/global constructor list are emitted .


"Instr doesn't have FrameIndex operand!"

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


"sh_try_split_insn_simple n = %d i = \n"

Given an rtx x , which is assumed to be some expression that has been matched by the 'treg_set_expr ' predicate before , split and emit the insns that are necessary to calculate the expression and store the result in the T bit . The splitting is done recursively similar to 'try_split ' in emit-rt.c . Unfortunately we ca n't use 'try_split ' here directly , as it tries to invoke 'delete_insn ' which then causes the DF parts to bail out , because we currently are inside another gen_split * function and would invoke 'try_split ' in a reentrant way .


<s> static rtx_insn * rs6000_md_asm_adjust ( vec < rtx > & , vec < rtx > & , vec < const char * > & , vec < rtx > & clobbers , HARD_REG_SET & clobbered_regs ) { clobbers . safe_push ( gen_rtx_REG ( SImode , CA_REGNO ) ) ; SET_HARD_REG_BIT ( clobbered_regs , CA_REGNO ) ; return NULL ; } </s>

Implement TARGET_MD_ASM_ADJUST . All asm statements are considered to clobber the XER [ CA ] bit because clobbering that bit without telling the compiler worked just fine with versions of GCC before GCC 5 , and breaking a lot of older code in ways that are hard to track down is not such a great idea .


<s> bool AArch64FastISel :: optimizeSelect ( const SelectInst * SI ) { if ( ! SI -> getType ( ) -> isIntegerTy ( 1 ) ) return false ; const Value * Src1Val , * Src2Val ; unsigned Opc = 0 ; bool NeedExtraOp = false ; if ( auto * CI = dyn_cast < ConstantInt > ( SI -> getTrueValue ( ) ) ) { if ( CI -> isOne ( ) ) { Src1Val = SI -> getCondition ( ) ; Src2Val = SI -> getFalseValue ( ) ; Opc = AArch64 :: ORRWrr ; } else { assert ( CI -> isZero ( ) ) ; Src1Val = SI -> getFalseValue ( ) ; Src2Val = SI -> getCondition ( ) ; Opc = AArch64 :: BICWrr ; } } else if ( auto * CI = dyn_cast < ConstantInt > ( SI -> getFalseValue ( ) ) ) { if ( CI -> isOne ( ) ) { Src1Val = SI -> getCondition ( ) ; Src2Val = SI -> getTrueValue ( ) ; Opc = AArch64 :: ORRWrr ; NeedExtraOp = true ; } else { assert ( CI -> isZero ( ) ) ; Src1Val = SI -> getCondition ( ) ; Src2Val = SI -> getTrueValue ( ) ; Opc = AArch64 :: ANDWrr ; } } if ( ! Opc ) return false ; Register Src1Reg = getRegForValue ( Src1Val ) ; if ( ! Src1Reg ) return false ; Register Src2Reg = getRegForValue ( Src2Val ) ; if ( ! Src2Reg ) return false ; if ( NeedExtraOp ) Src1Reg = emitLogicalOp_ri ( ISD :: XOR , MVT :: i32 , Src1Reg , 1 ) ; Register ResultReg = fastEmitInst_rr ( Opc , & AArch64 :: GPR32RegClass , Src1Reg , Src2Reg ) ; updateValueMap ( SI , ResultReg ) ; return true ; } </s>

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


<s>
const
MCFixupKindInfo
&
getFixupKindInfo
(
MCFixupKind
Kind
)
const
override
{
const
static
MCFixupKindInfo
Infos
[
UPT
::
NumTargetFixupKinds
]
=
{
{
"fixup_upt_mov_hi16_pcrel"
,
0
,
32
,
MCFixupKindInfo
::
FKF_IsPCRel
}
,
{
"fixup_upt_mov_lo16_pcrel"
,
0
,
32
,
MCFixupKindInfo
::
FKF_IsPCRel
}
,
}
;
if
(
Kind
<
FirstTargetFixupKind
)
{
return
MCAsmBackend
::
getFixupKindInfo
(
Kind
)
;
}
assert
(
unsigned
(
Kind
FirstTargetFixupKind
)
<
getNumFixupKinds
(
)
&&
"Invalid kind!"
)
;
return
Infos
[
Kind
FirstTargetFixupKind
]
;
}
</s>


<s> static bool pru_hard_regno_scratch_ok ( unsigned int regno ) { if ( ( ! reload_completed || frame_pointer_needed ) && ( IN_RANGE ( regno , HARD_FRAME_POINTER_REGNUM , HARD_FRAME_POINTER_REGNUM + 3 ) || IN_RANGE ( regno , FRAME_POINTER_REGNUM , FRAME_POINTER_REGNUM + 3 ) ) ) return false ; return true ; } </s>

Implement ` TARGET_HARD_REGNO_SCRATCH_OK ' . Returns true if REGNO is safe to be allocated as a scratch register ( for a define_peephole2 ) in the current function .


<s> SDNode * SparcDAGToDAGISel :: Select ( SDNode * N ) { SDLoc dl ( N ) ; if ( N -> isMachineOpcode ( ) ) return NULL ; switch ( N -> getOpcode ( ) ) { default : break ; case SPISD :: GLOBAL_BASE_REG : return getGlobalBaseReg ( ) ; case ISD :: SDIV : case ISD :: UDIV : { if ( N -> getValueType ( 0 ) == MVT :: i64 ) break ; SDValue DivLHS = N -> getOperand ( 0 ) ; SDValue DivRHS = N -> getOperand ( 1 ) ; SDValue TopPart ; if ( N -> getOpcode ( ) == ISD :: SDIV ) { TopPart = SDValue ( CurDAG -> getMachineNode ( SP :: SRAri , dl , MVT :: i32 , DivLHS , CurDAG -> getTargetConstant ( 31 , MVT :: i32 ) ) , 0 ) ; } else { TopPart = CurDAG -> getRegister ( SP :: G0 , MVT :: i32 ) ; } TopPart = SDValue ( CurDAG -> getMachineNode ( SP :: WRYrr , dl , MVT :: Glue , TopPart , CurDAG -> getRegister ( SP :: G0 , MVT :: i32 ) ) , 0 ) ; unsigned Opcode = N -> getOpcode ( ) == ISD :: SDIV ? SP :: SDIVrr : SP :: UDIVrr ; return CurDAG -> SelectNodeTo ( N , Opcode , MVT :: i32 , DivLHS , DivRHS , TopPart ) ; } case ISD :: MULHU : case ISD :: MULHS : { SDValue MulLHS = N -> getOperand ( 0 ) ; SDValue MulRHS = N -> getOperand ( 1 ) ; unsigned Opcode = N -> getOpcode ( ) == ISD :: MULHU ? SP :: UMULrr : SP :: SMULrr ; SDNode * Mul = CurDAG -> getMachineNode ( Opcode , dl , MVT :: i32 , MVT :: Glue , MulLHS , MulRHS ) ; return CurDAG -> SelectNodeTo ( N , SP :: RDY , MVT :: i32 , SDValue ( Mul , 1 ) ) ; } } return SelectCode ( N ) ; } </s>

Main hook for targets to transform nodes into machine nodes .


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

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


<s> bool PPCTargetLowering :: isFPImmLegal ( const APFloat & Imm , EVT VT , bool ForCodeSize ) const { if ( ! VT . isSimple ( ) || ! Subtarget . hasVSX ( ) ) return false ; switch ( VT . getSimpleVT ( ) . SimpleTy ) { default : return false ; case MVT :: f32 : case MVT :: f64 : case MVT :: ppcf128 : return Imm . isPosZero ( ) ; } } </s>

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


<s> EVT MipsTargetLowering :: getSetCCResultType ( EVT VT ) const { return MVT :: i32 ; } </s>

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


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

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


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

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


<s> MCELFStreamer & SHUXITargetELFStreamer :: getStreamer ( ) { return static_cast < MCELFStreamer & > ( Streamer ) ; } </s>

Return the output streamer for the assembler .


<s> void rs6000_asm_output_opcode ( FILE * stream ) { if ( prepend_p_to_next_insn ) { fprintf ( stream , "p" ) ; prepend_p_to_next_insn = false ; } return ; } </s>

Define ASM_OUTPUT_OPCODE to do anything special before emitting an opcode . We use it to emit a ' p ' for prefixed insns that is set in FINAL_PRESCAN_INSN .


<s> bool MipsInstrInfo :: HasForbiddenSlot ( const MachineInstr & MI ) const { return ( MI . getDesc ( ) . TSFlags & MipsII :: HasForbiddenSlot ) != 0 ; } </s>

Predicate to determine if an instruction has a forbidden slot .


<s> void CAHPFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const CAHPRegisterInfo * RI = STI . getRegisterInfo ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; uint64_t StackAlign = RI -> needsStackRealignment ( MF ) ? MFI . getMaxAlignment ( ) : getStackAlignment ( ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; } </s>

Determine the frame layout but do not update the machine function .


"MIPS: Optimize calls to math library functions."

getPassName - Return a nice clean name for a pass .


<s> static void mt_emit_save_restore ( enum save_direction direction , rtx reg , rtx mem , int stack_offset ) { if ( direction == FROM_PROCESSOR_TO_MEM ) { rtx insn ; insn = emit_move_insn ( mem , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_FRAME_RELATED_EXPR , gen_rtx_SET ( VOIDmode , gen_rtx_MEM ( SImode , gen_rtx_PLUS ( SImode , stack_pointer_rtx , GEN_INT ( stack_offset ) ) ) , reg ) , REG_NOTES ( insn ) ) ; } else emit_move_insn ( reg , mem ) ; } </s>

Emit code to save REG in stack offset pointed to by MEM . STACK_OFFSET is the offset from the SP where the save will happen . This function sets the REG_FRAME_RELATED_EXPR note accordingly .


<s>
SDValue
CAHPTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
report_fatal_error
(
"unimplemented operand"
)
;
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
LowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT
:
return
LowerSELECT
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
LowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
return
LowerRETURNADDR
(
Op
,
DAG
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .

CAHP
CAHP
"unimplemented operand"
ISD::BR_CC
ISD::GlobalAddress
ISD::SELECT
ISD::FRAMEADDR
ISD::RETURNADDR


<s> static bool loongarch_valid_offset_p ( rtx x , machine_mode mode ) { if ( ! ( const_arith_operand ( x , Pmode ) || ( ( mode == E_SImode || mode == E_DImode ) && const_imm16_operand ( x , Pmode ) && ( loongarch_signed_immediate_p ( INTVAL ( x ) , 14 , 2 ) ) ) ) ) return false ; if ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD && ! IMM12_OPERAND ( INTVAL ( x ) + GET_MODE_SIZE ( mode ) - UNITS_PER_WORD ) ) return false ; return true ; } </s>

Return true if , for every base register BASE_REG , ( plus BASE_REG X ) can address a value of mode MODE .


<s>
static
const
char
*
rs6000_call_template_1
(
rtx
*
operands
,
unsigned
int
funop
,
bool
sibcall
)
{
gcc_assert
(
funop
<=
MAX_RECOG_OPERANDS
)
;
char
arg
[
12
]
;
arg
[
0
]
=
0
;
if
(
TARGET_TLS_MARKERS
&&
GET_CODE
(
operands
[
funop
+
1
]
)
==
UNSPEC
)
{
if
(
XINT
(
operands
[
funop
+
1
]
,
1
)
==
UNSPEC_TLSGD
)
sprintf
(
arg
,
"(%%%u@tlsgd)"
,
funop
+
1
)
;
else
if
(
XINT
(
operands
[
funop
+
1
]
,
1
)
==
UNSPEC_TLSLD
)
sprintf
(
arg
,
"(%%&@tlsld)"
)
;
else
gcc_unreachable
(
)
;
}
char
z
[
11
]
;
sprintf
(
z
,
"%%z%u%s"
,
funop
,
(
DEFAULT_ABI
==
ABI_V4
&&
TARGET_SECURE_PLT
&&
flag_pic
==
2
"+32768"
:
""
)
)
;
static
char
str
[
32
]
;
if
(
DEFAULT_ABI
==
ABI_AIX
||
DEFAULT_ABI
==
ABI_ELFv2
)
sprintf
(
str
,
"b%s %s%s%s"
,
sibcall
""
:
"l"
,
z
,
arg
,
sibcall
""
:
"\n\tnop"
)
;
else
if
(
DEFAULT_ABI
==
ABI_V4
)
sprintf
(
str
,
"b%s %s%s%s"
,
sibcall
""
:
"l"
,
z
,
arg
,
flag_pic
"@plt"
:
""
)
;
else
if
(
DEFAULT_ABI
==
ABI_DARWIN
)
{
gcc_checking_assert
(
GET_CODE
(
operands
[
funop
+
2
]
)
==
CONST_INT
)
;
int
cookie
=
INTVAL
(
operands
[
funop
+
2
]
)
;
if
(
cookie
&
CALL_LONG
)
{
tree
funname
=
get_identifier
(
XSTR
(
operands
[
funop
]
,
0
)
)
;
tree
labelname
=
get_prev_label
(
funname
)
;
gcc_checking_assert
(
labelname
&&
!
sibcall
)
;
sprintf
(
str
,
"jbsr %%z%u,%.10s"
,
funop
,
IDENTIFIER_POINTER
(
labelname
)
)
;
}
else
sprintf
(
str
,
"b%s %s%s"
,
sibcall
""
:
"l"
,
z
,
arg
)
;
}
else
gcc_unreachable
(
)
;
return
str
;
}
</s>

Return a template string for assembly to emit when making an external call . FUNOP is the call mem argument operand number .


<s>
bool
isNoTOCCallInstr
(
unsigned
Opcode
)
const
{
if
(
!
get
(
Opcode
)
.
isCall
(
)
)
return
false
;
switch
(
Opcode
)
{
default
:
llvm_unreachable
(
"Unknown call opcode"
)
;
return
false
;
case
PPC
::
BL8_NOTOC
:
case
PPC
::
BL8_NOTOC_TLS
:
case
PPC
::
BL8_NOTOC_RM
:
return
true
;
case
PPC
::
BL8
:
case
PPC
::
BL
:
case
PPC
::
BL8_TLS
:
case
PPC
::
BL_TLS
:
case
PPC
::
BLA8
:
case
PPC
::
BLA
:
case
PPC
::
BCCL
:
case
PPC
::
BCCLA
:
case
PPC
::
BCL
:
case
PPC
::
BCLn
:
case
PPC
::
BL8_NOP
:
case
PPC
::
BL_NOP
:
case
PPC
::
BL8_NOP_TLS
:
case
PPC
::
BLA8_NOP
:
case
PPC
::
BCTRL8
:
case
PPC
::
BCTRL
:
case
PPC
::
BCCCTRL8
:
case
PPC
::
BCCCTRL
:
case
PPC
::
BCCTRL8
:
case
PPC
::
BCCTRL
:
case
PPC
::
BCCTRL8n
:
case
PPC
::
BCCTRLn
:
case
PPC
::
BL8_RM
:
case
PPC
::
BLA8_RM
:
case
PPC
::
BL8_NOP_RM
:
case
PPC
::
BLA8_NOP_RM
:
case
PPC
::
BCTRL8_RM
:
case
PPC
::
BCTRL8_LDinto_toc
:
case
PPC
::
BCTRL8_LDinto_toc_RM
:
case
PPC
::
BL8_TLS_
:
case
PPC
::
TCRETURNdi8
:
case
PPC
::
TCRETURNai8
:
case
PPC
::
TCRETURNri8
:
case
PPC
::
TAILBCTR8
:
case
PPC
::
TAILB8
:
case
PPC
::
TAILBA8
:
case
PPC
::
BCLalways
:
case
PPC
::
BLRL
:
case
PPC
::
BCCLRL
:
case
PPC
::
BCLRL
:
case
PPC
::
BCLRLn
:
case
PPC
::
BDZL
:
case
PPC
::
BDNZL
:
case
PPC
::
BDZLA
:
case
PPC
::
BDNZLA
:
case
PPC
::
BDZLp
:
case
PPC
::
BDNZLp
:
case
PPC
::
BDZLAp
:
case
PPC
::
BDNZLAp
:
case
PPC
::
BDZLm
:
case
PPC
::
BDNZLm
:
case
PPC
::
BDZLAm
:
case
PPC
::
BDNZLAm
:
case
PPC
::
BDZLRL
:
case
PPC
::
BDNZLRL
:
case
PPC
::
BDZLRLp
:
case
PPC
::
BDNZLRLp
:
case
PPC
::
BDZLRLm
:
case
PPC
::
BDNZLRLm
:
case
PPC
::
BL_RM
:
case
PPC
::
BLA_RM
:
case
PPC
::
BL_NOP_RM
:
case
PPC
::
BCTRL_RM
:
case
PPC
::
TCRETURNdi
:
case
PPC
::
TCRETURNai
:
case
PPC
::
TCRETURNri
:
case
PPC
::
BCTRL_LWZinto_toc
:
case
PPC
::
BCTRL_LWZinto_toc_RM
:
case
PPC
::
TAILBCTR
:
case
PPC
::
TAILB
:
case
PPC
::
TAILBA
:
return
false
;
}
}
</s>

Check if Opcode corresponds to a call instruction that should be marked with the NOTOC relocation .


<s> static void rs6000_init_hard_regno_mode_ok ( void ) { int r , m ; for ( r = 0 ; r < FIRST_PSEUDO_REGISTER ; ++ r ) for ( m = 0 ; m < NUM_MACHINE_MODES ; ++ m ) if ( rs6000_hard_regno_mode_ok ( r , m ) ) rs6000_hard_regno_mode_ok_p [ m ] [ r ] = true ; } </s>

Initialize rs6000_hard_regno_mode_ok_p table .


<s> unsigned PPCFastISel :: fastEmitInst_rr ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , bool Op0IsKill , unsigned Op1 , bool Op1IsKill ) { const TargetRegisterClass * UseRC = ( RC == & PPC :: GPRCRegClass ? & PPC :: GPRC_and_GPRC_NOR0RegClass : ( RC == & PPC :: G8RCRegClass ? & PPC :: G8RC_and_G8RC_NOX0RegClass : RC ) ) ; return FastISel :: fastEmitInst_rr ( MachineInstOpcode , UseRC , Op0 , Op0IsKill , Op1 , Op1IsKill ) ; } </s>

Emit a MachineInstr with two register operands and a result register in the given register class .


<s> InstructionCost getArithmeticInstrCost ( unsigned Opcode , Type * Ty , TTI :: TargetCostKind CostKind , TTI :: OperandValueKind Opd1Info = TTI :: OK_AnyValue , TTI :: OperandValueKind Opd2Info = TTI :: OK_AnyValue , TTI :: OperandValueProperties Opd1PropInfo = TTI :: OP_None , TTI :: OperandValueProperties Opd2PropInfo = TTI :: OP_None , ArrayRef < const Value * > Args = ArrayRef < const Value * > ( ) , const Instruction * CxtI = nullptr ) { int ISD = TLI -> InstructionOpcodeToISD ( Opcode ) ; switch ( ISD ) { default : return BaseT :: getArithmeticInstrCost ( Opcode , Ty , CostKind , Opd1Info , Opd2Info , Opd1PropInfo , Opd2PropInfo ) ; case ISD :: MUL : case ISD :: SDIV : case ISD :: UDIV : case ISD :: UREM : return 64 * BaseT :: getArithmeticInstrCost ( Opcode , Ty , CostKind , Opd1Info , Opd2Info , Opd1PropInfo , Opd2PropInfo ) ; } } </s>

This is an approximation of reciprocal throughput of a math/logic op .

Lanai ISD::MUL ISD::SDIV ISD::UDIV ISD::UREM 64


<s> static enum loongarch_symbol_type loongarch_classify_symbolic_expression ( rtx x ) { rtx offset ; split_const ( x , & x , & offset ) ; if ( UNSPEC_ADDRESS_P ( x ) ) return UNSPEC_ADDRESS_TYPE ( x ) ; return loongarch_classify_symbol ( x ) ; } </s>

Classify the base of symbolic expression X , given that X appears in context CONTEXT .


<s> static void aarch64_emit_atomic_swap ( machine_mode mode , rtx dst , rtx value , rtx mem , rtx model ) { rtx ( * gen ) ( rtx , rtx , rtx , rtx ) ; switch ( mode ) { case QImode : gen = gen_aarch64_atomic_swpqi ; break ; case HImode : gen = gen_aarch64_atomic_swphi ; break ; case SImode : gen = gen_aarch64_atomic_swpsi ; break ; case DImode : gen = gen_aarch64_atomic_swpdi ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen ( dst , mem , value , model ) ) ; } </s>


<s>
static
void
rs6000_print_options_internal
(
FILE
*
file
,
int
indent
,
const
char
*
string
,
HOST_WIDE_INT
flags
,
const
char
*
prefix
,
const
struct
rs6000_opt_mask
*
opts
,
size_t
num_elements
)
{
size_t
i
;
size_t
start_column
=
0
;
size_t
cur_column
;
size_t
max_column
=
120
;
size_t
prefix_len
=
strlen
(
prefix
)
;
size_t
comma_len
=
0
;
const
char
*
comma
=
""
;
if
(
indent
)
start_column
+=
fprintf
(
file
,
"%*s"
,
indent
,
""
)
;
if
(
!
flags
)
{
fprintf
(
stderr
,
DEBUG_FMT_S
,
string
,
"<none>"
)
;
return
;
}
start_column
+=
fprintf
(
stderr
,
DEBUG_FMT_WX
,
string
,
flags
)
;
cur_column
=
start_column
;
for
(
i
=
0
;
i
<
num_elements
;
i
++
)
{
bool
invert
=
opts
[
i
]
.
invert
;
const
char
*
name
=
opts
[
i
]
.
name
;
const
char
*
no_str
=
""
;
HOST_WIDE_INT
mask
=
opts
[
i
]
.
mask
;
size_t
len
=
comma_len
+
prefix_len
+
strlen
(
name
)
;
if
(
!
invert
)
{
if
(
(
flags
&
mask
)
==
0
)
{
no_str
=
"no-"
;
len
+=
strlen
(
"no-"
)
;
}
flags
&=
~
mask
;
}
else
{
if
(
(
flags
&
mask
)
!=
0
)
{
no_str
=
"no-"
;
len
+=
strlen
(
"no-"
)
;
}
flags
|=
mask
;
}
cur_column
+=
len
;
if
(
cur_column
>
max_column
)
{
fprintf
(
stderr
,
", \\\n%*s"
,
(
int
)
start_column
,
""
)
;
cur_column
=
start_column
+
len
;
comma
=
""
;
}
fprintf
(
file
,
"%s%s%s%s"
,
comma
,
prefix
,
no_str
,
name
)
;
comma
=
", "
;
comma_len
=
strlen
(
", "
)
;
}
fputs
(
"\n"
,
file
)
;
}
</s>

Helper function to print the current isa or misc options on a line .


<s> void X86DAGToDAGISel :: PreprocessISelDAG ( ) { OptForSize = MF -> getFunction ( ) -> hasFnAttr ( Attribute :: OptimizeForSize ) ; for ( SelectionDAG :: allnodes_iterator I = CurDAG -> allnodes_begin ( ) , E = CurDAG -> allnodes_end ( ) ; I != E ; ) { SDNode * N = I ++ ; if ( OptLevel != CodeGenOpt :: None && N -> getOpcode ( ) == X86ISD :: CALL ) { SDValue Chain = N -> getOperand ( 0 ) ; SDValue Load = N -> getOperand ( 1 ) ; if ( ! isCalleeLoad ( Load , Chain ) ) continue ; MoveBelowCallSeqStart ( CurDAG , Load , SDValue ( N , 0 ) , Chain ) ; ++ NumLoadMoved ; continue ; } if ( N -> getOpcode ( ) != ISD :: FP_ROUND && N -> getOpcode ( ) != ISD :: FP_EXTEND ) continue ; EVT SrcVT = N -> getOperand ( 0 ) . getValueType ( ) ; EVT DstVT = N -> getValueType ( 0 ) ; bool SrcIsSSE = X86Lowering . isScalarFPTypeInSSEReg ( SrcVT ) ; bool DstIsSSE = X86Lowering . isScalarFPTypeInSSEReg ( DstVT ) ; if ( SrcIsSSE && DstIsSSE ) continue ; if ( ! SrcIsSSE && ! DstIsSSE ) { if ( N -> getOpcode ( ) == ISD :: FP_EXTEND ) continue ; if ( N -> getConstantOperandVal ( 1 ) ) continue ; } EVT MemVT ; if ( N -> getOpcode ( ) == ISD :: FP_ROUND ) MemVT = DstVT ; else MemVT = SrcIsSSE ? SrcVT : DstVT ; SDValue MemTmp = CurDAG -> CreateStackTemporary ( MemVT ) ; DebugLoc dl = N -> getDebugLoc ( ) ; SDValue Store = CurDAG -> getTruncStore ( CurDAG -> getEntryNode ( ) , dl , N -> getOperand ( 0 ) , MemTmp , NULL , 0 , MemVT , false , false , 0 ) ; SDValue Result = CurDAG -> getExtLoad ( ISD :: EXTLOAD , dl , DstVT , Store , MemTmp , NULL , 0 , MemVT , false , false , 0 ) ; -- I ; CurDAG -> ReplaceAllUsesOfValueWith ( SDValue ( N , 0 ) , Result ) ; ++ I ; CurDAG -> DeleteNode ( N ) ; } } </s>

PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts .


<s> void ARMPassConfig :: addPreEmitPass ( ) { addPass ( createThumb2SizeReductionPass ( ) ) ; addPass ( createUnpackMachineBundles ( [ ] ( const MachineFunction & MF ) { return MF . getSubtarget < ARMSubtarget > ( ) . isThumb2 ( ) ; } ) ) ; if ( getOptLevel ( ) != CodeGenOpt :: None ) addPass ( createARMOptimizeBarriersPass ( ) ) ; addPass ( createARMConstantIslandPass ( ) ) ; addPass ( createARMLowOverheadLoopsPass ( ) ) ; if ( TM -> getTargetTriple ( ) . isOSWindows ( ) ) addPass ( createCFGuardLongjmpPass ( ) ) ; } </s>

This pass may be implemented by targets that want to run passes immediately before machine code is emitted .


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

Inserts necessary declarations for SSP ( stack protection ) purpose .


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

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


<s> int shl_sext_kind ( rtx left_rtx , rtx size_rtx , int * costp ) { int left , size , insize , ext ; int cost = 0 , best_cost ; int kind ; left = INTVAL ( left_rtx ) ; size = INTVAL ( size_rtx ) ; insize = size - left ; gcc_assert ( insize > 0 ) ; kind = 0 ; best_cost = shift_insns [ 32 - insize ] + ashiftrt_insns [ 32 - size ] ; if ( size <= 16 ) { cost = shift_insns [ 16 - insize ] + 1 + ashiftrt_insns [ 16 - size ] ; if ( cost < best_cost ) { kind = 5 ; best_cost = cost ; } } for ( ext = 16 ; ext >= insize ; ext -= 8 ) { if ( ext <= size ) { cost = ext_shift_insns [ ext - insize ] + 1 + shift_insns [ size - ext ] ; if ( cost < best_cost ) { kind = ext / ( unsigned ) 8 ; best_cost = cost ; } } if ( EXT_SHIFT_SIGNED ( size - ext ) ) cost = ext_shift_insns [ ext - insize ] + ext_shift_insns [ size - ext ] + 1 ; else if ( size <= 16 ) cost = ext_shift_insns [ ext - insize ] + 1 + ext_shift_insns [ size > ext ? size - ext : ext - size ] + 1 ; else continue ; if ( cost < best_cost ) { kind = ext / ( unsigned ) 8 + 2 ; best_cost = cost ; } } if ( insize < 8 ) { cost = 3 + shift_insns [ left ] ; if ( cost < best_cost ) { kind = 6 ; best_cost = cost ; } if ( left < 31 ) { cost = 3 + ext_shift_insns [ left + 1 ] + 1 ; if ( cost < best_cost ) { kind = 7 ; best_cost = cost ; } } } if ( TARGET_SH3 ) { cost = shift_insns [ 32 - insize ] + 1 + SH_DYNAMIC_SHIFT_COST ; if ( cost < best_cost ) { kind = 0 ; best_cost = cost ; } } if ( costp ) * costp = cost ; return kind ; } </s>

Try to find a good way to implement the combiner pattern [ ( set ( match_operand : SI 0 `` register_operand '' `` =r '' ) ( sign_extract : SI ( ashift : SI ( match_operand : SI 1 `` register_operand '' `` r '' ) ( match_operand : SI 2 `` const_int_operand '' `` n '' ) ( match_operand : SI 3 `` const_int_operand '' `` n '' ) ( const_int 0 ) ) ) ( clobber ( reg : SI T_REG ) ) ] LEFT_RTX is operand 2 in the above pattern , and SIZE_RTX is operand 3. return 0 for simple left / right shift combination . return 1 for left shift / 8 bit sign extend / left shift . return 2 for left shift / 16 bit sign extend / left shift . return 3 for left shift / 8 bit sign extend / shift / sign extend . return 4 for left shift / 16 bit sign extend / shift / sign extend . return 5 for left shift / 16 bit sign extend / right shift return 6 for < 8 bit sign extend / left shift . return 7 for < 8 bit sign extend / left shift / single right shift . If COSTP is nonzero , assign the calculated cost to * COSTP .


<s> rtx mips_subword_at_byte ( rtx op , unsigned int byte ) { machine_mode mode ; mode = GET_MODE ( op ) ; if ( mode == VOIDmode ) mode = TImode ; gcc_assert ( ! FP_REG_RTX_P ( op ) ) ; if ( MEM_P ( op ) ) return mips_rewrite_small_data ( adjust_address ( op , word_mode , byte ) ) ; return simplify_gen_subreg ( word_mode , op , mode , byte ) ; } </s>

Return one word of 128-bit value OP , taking into account the fixed endianness of certain registers . BYTE selects from the byte address .


<s> void AArch64TTIImpl :: getUnrollingPreferences ( Loop * L , ScalarEvolution & SE , TTI :: UnrollingPreferences & UP ) { BaseT :: getUnrollingPreferences ( L , SE , UP ) ; if ( L -> getLoopDepth ( ) > 1 ) UP . PartialThreshold *= 2 ; UP . PartialOptSizeThreshold = 0 ; if ( ST -> getProcFamily ( ) == AArch64Subtarget :: Falkor && EnableFalkorHWPFUnrollFix ) getFalkorUnrollingPreferences ( L , SE , UP ) ; for ( auto * BB : L -> getBlocks ( ) ) { for ( auto & I : * BB ) { if ( I . getType ( ) -> isVectorTy ( ) ) return ; if ( isa < CallInst > ( I ) || isa < InvokeInst > ( I ) ) { if ( const Function * F = cast < CallBase > ( I ) . getCalledFunction ( ) ) { if ( ! isLoweredToCall ( F ) ) continue ; } return ; } } } if ( ST -> getProcFamily ( ) != AArch64Subtarget :: Others && ! ST -> getSchedModel ( ) . isOutOfOrder ( ) ) { UP . Runtime = true ; UP . Partial = true ; UP . UpperBound = true ; UP . UnrollRemainder = true ; UP . DefaultUnrollRuntimeCount = 4 ; } } </s>

Get target-customized preferences for the generic loop unrolling transformation .


<s> static bool aarch64_cheap_mult_shift_p ( rtx x ) { rtx op0 , op1 ; op0 = XEXP ( x , 0 ) ; op1 = XEXP ( x , 1 ) ; if ( ! ( aarch64_tune_params . extra_tuning_flags & AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND ) ) return false ; if ( GET_CODE ( op0 ) == SIGN_EXTEND ) return false ; if ( GET_CODE ( x ) == ASHIFT && CONST_INT_P ( op1 ) && UINTVAL ( op1 ) <= 4 ) return true ; if ( GET_CODE ( x ) != MULT || ! CONST_INT_P ( op1 ) ) return false ; HOST_WIDE_INT l2 = exact_log2 ( INTVAL ( op1 ) ) ; if ( l2 > 0 && l2 <= 4 ) return true ; return false ; } </s>

Return true iff X is a cheap shift without a sign extend .


<s>
static
const
char
*
shift_op
(
rtx
op
,
HOST_WIDE_INT
*
amountp
)
{
const
char
*
mnem
;
enum
rtx_code
code
=
GET_CODE
(
op
)
;
switch
(
code
)
{
case
ROTATE
:
if
(
!
CONST_INT_P
(
XEXP
(
op
,
1
)
)
)
{
output_operand_lossage
(
"invalid shift operand"
)
;
return
;
}
code
=
ROTATERT
;
*
amountp
=
32
INTVAL
(
XEXP
(
op
,
1
)
)
;
mnem
=
"ror"
;
break
;
case
ASHIFT
:
case
ASHIFTRT
:
case
LSHIFTRT
:
case
ROTATERT
:
mnem
=
arm_shift_nmem
(
code
)
;
if
(
CONST_INT_P
(
XEXP
(
op
,
1
)
)
)
{
*
amountp
=
INTVAL
(
XEXP
(
op
,
1
)
)
;
}
else
if
(
REG_P
(
XEXP
(
op
,
1
)
)
)
{
*
amountp
=
1
;
return
mnem
;
}
else
{
output_operand_lossage
(
"invalid shift operand"
)
;
return
;
}
break
;
case
MULT
:
if
(
!
CONST_INT_P
(
XEXP
(
op
,
1
)
)
)
{
output_operand_lossage
(
"invalid shift operand"
)
;
return
;
}
*
amountp
=
INTVAL
(
XEXP
(
op
,
1
)
)
&
0xFFFFFFFF
;
if
(
*
amountp
&
(
*
amountp
1
)
)
{
output_operand_lossage
(
"invalid shift operand"
)
;
return
;
}
*
amountp
=
exact_log2
(
*
amountp
)
;
gcc_assert
(
IN_RANGE
(
*
amountp
,
0
,
31
)
)
;
return
ARM_LSL_NAME
;
default
:
output_operand_lossage
(
"invalid shift operand"
)
;
return
;
}
if
(
code
==
ROTATERT
)
*
amountp
&=
31
;
else
if
(
*
amountp
!=
(
*
amountp
&
31
)
)
{
if
(
code
==
ASHIFT
)
mnem
=
"lsr"
;
*
amountp
=
32
;
}
if
(
*
amountp
==
0
)
return
;
return
mnem
;
}
</s>

Ensure valid constant shifts and return the appropriate shift mnemonic for the operation code . The returned result should not be overwritten . OP is the rtx code of the shift . On exit , * AMOUNTP will be -1 if the shift is by a register , or a constant shift .


<s>
void
SystemZPostRASchedStrategy
::
enterMBB
(
MachineBasicBlock
*
NextMBB
)
{
assert
(
(
SchedStates
.
find
(
NextMBB
)
==
SchedStates
.
end
(
)
)
&&
"Entering MBB twice?"
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"** Entering "
<<
printMBBReference
(
*
NextMBB
)
)
;
MBB
=
NextMBB
;
HazardRec
=
SchedStates
[
MBB
]
=
new
SystemZHazardRecognizer
(
TII
,
&
SchedModel
)
;
LLVM_DEBUG
(
const
MachineLoop
*
Loop
=
MLI
->
getLoopFor
(
MBB
)
;
if
(
Loop
&&
Loop
->
getHeader
(
)
==
MBB
)
dbgs
(
)
<<
" (Loop header)"
;
dbgs
(
)
<<
":\n"
;
)
;
MachineBasicBlock
*
SinglePredMBB
=
getSingleSchedPred
(
MBB
,
MLI
->
getLoopFor
(
MBB
)
)
;
if
(
SinglePredMBB
==
nullptr
||
SchedStates
.
find
(
SinglePredMBB
)
==
SchedStates
.
end
(
)
)
return
;
LLVM_DEBUG
(
dbgs
(
)
<<
"** Continued scheduling from "
<<
printMBBReference
(
*
SinglePredMBB
)
<<
"\n"
;
)
;
HazardRec
->
copyState
(
SchedStates
[
SinglePredMBB
]
)
;
LLVM_DEBUG
(
HazardRec
->
dumpState
(
)
;
)
;
for
(
MachineBasicBlock
::
iterator
I
=
SinglePredMBB
->
getFirstTerminator
(
)
;
I
!=
SinglePredMBB
->
end
(
)
;
I
++
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"** Emitting incoming branch: "
;
I
->
dump
(
)
;
)
;
bool
TakenBranch
=
(
I
->
isBranch
(
)
&&
(
TII
->
getBranchInfo
(
*
I
)
.
isIndirect
(
)
||
TII
->
getBranchInfo
(
*
I
)
.
getMBBTarget
(
)
==
MBB
)
)
;
HazardRec
->
emitInstruction
(
&
*
I
,
TakenBranch
)
;
if
(
TakenBranch
)
break
;
}
}
</s>

Tell the strategy that MBB is about to be processed .

SystemZ
SystemZ
"Entering MBB twice?"
"** Entering "
SystemZ
" (Loop header)"
":\n"
"** Continued scheduling from "
"\n"
"** Emitting incoming branch: "


<s> static enum machine_mode rs6000_eh_return_filter_mode ( void ) { return TARGET_32BIT ? SImode : word_mode ; } </s>


<s> bool DLXRegisterInfo :: trackLivenessAfterRegAlloc ( const MachineFunction & ) const { return true ; } </s>

Returns true if the live-ins should be tracked after register allocation .


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


<s> void Thumb2InstrInfo :: ReplaceTailWithBranchTo ( MachineBasicBlock :: iterator Tail , MachineBasicBlock * NewDest ) const { MachineBasicBlock * MBB = Tail -> getParent ( ) ; ARMFunctionInfo * AFI = MBB -> getParent ( ) -> getInfo < ARMFunctionInfo > ( ) ; if ( ! AFI -> hasITBlocks ( ) || Tail -> isBranch ( ) ) { TargetInstrInfo :: ReplaceTailWithBranchTo ( Tail , NewDest ) ; return ; } unsigned PredReg = 0 ; ARMCC :: CondCodes CC = getInstrPredicate ( * Tail , PredReg ) ; MachineBasicBlock :: iterator MBBI = Tail ; if ( CC != ARMCC :: AL ) -- MBBI ; TargetInstrInfo :: ReplaceTailWithBranchTo ( Tail , NewDest ) ; if ( CC != ARMCC :: AL ) { MachineBasicBlock :: iterator E = MBB -> begin ( ) ; unsigned Count = 4 ; while ( Count && MBBI != E ) { if ( MBBI -> isDebugInstr ( ) ) { -- MBBI ; continue ; } if ( MBBI -> getOpcode ( ) == ARM :: t2IT ) { unsigned Mask = MBBI -> getOperand ( 1 ) . getImm ( ) ; if ( Count == 4 ) MBBI -> eraseFromParent ( ) ; else { unsigned MaskOn = 1 << Count ; unsigned MaskOff = ~ ( MaskOn - 1 ) ; MBBI -> getOperand ( 1 ) . setImm ( ( Mask & MaskOff ) | MaskOn ) ; } return ; } -- MBBI ; -- Count ; } } } </s>

Delete the instruction OldInst and everything after it , replacing it with an unconditional branch to NewDest .


<s> AArch64Subtarget & AArch64Subtarget :: initializeSubtargetDependencies ( StringRef FS , StringRef CPUString ) { if ( CPUString . empty ( ) ) CPUString = "generic" ; ParseSubtargetFeatures ( CPUString , FS ) ; initializeProperties ( ) ; return * this ; } </s>

initializeSubtargetDependencies - Initializes using a CPU , a TuneCPU , and feature string so that we can use initializer lists for subtarget initialization .


<s> bool enableShrinkWrapping ( const MachineFunction & MF ) const override { return true ; } </s>

Returns true if the target will correctly handle shrink wrapping .


<s> void function_expander :: add_ptrue_hint ( unsigned int argno , machine_mode pred_mode ) { rtx pred = gen_lowpart ( pred_mode , args [ argno ] ) ; int hint = ( pred == CONSTM1_RTX ( pred_mode ) ? SVE_KNOWN_PTRUE : SVE_MAYBE_NOT_PTRUE ) ; args . quick_insert ( argno + 1 , gen_int_mode ( hint , SImode ) ) ; } </s>

Add a dummy argument to indicate whether predicate argument ARGNO is all-true when interpreted in mode PRED_MODE . The hint goes immediately after ARGNO .


<s> static void d30v_add_gc_roots ( ) { ggc_add_rtx_root ( & d30v_compare_op0 , 1 ) ; ggc_add_rtx_root ( & d30v_compare_op1 , 1 ) ; } </s>

Called to register all of our global variables with the garbage collector .


<s> static bool r10k_protected_bb_p ( basic_block bb , sbitmap protected_bbs ) { edge_iterator ei ; edge e ; FOR_EACH_EDGE ( e , ei , bb -> preds ) if ( ! single_succ_p ( e -> src ) || ! bitmap_bit_p ( protected_bbs , e -> src -> index ) || ( e -> flags & EDGE_COMPLEX ) != 0 ) return false ; return true ; } </s>

Return true if BB is only reached by blocks in PROTECTED_BBS and if every edge is unconditional .


<s> void AArch64PreLegalizerCombiner :: getAnalysisUsage ( AnalysisUsage & AU ) const { AU . addRequired < TargetPassConfig > ( ) ; AU . setPreservesCFG ( ) ; getSelectionDAGFallbackAnalysisUsage ( AU ) ; AU . addRequired < GISelKnownBitsAnalysis > ( ) ; AU . addPreserved < GISelKnownBitsAnalysis > ( ) ; AU . addRequired < MachineDominatorTree > ( ) ; AU . addPreserved < MachineDominatorTree > ( ) ; AU . addRequired < GISelCSEAnalysisWrapperPass > ( ) ; AU . addPreserved < GISelCSEAnalysisWrapperPass > ( ) ; MachineFunctionPass :: getAnalysisUsage ( AU ) ; } </s>

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


<s> static HOST_WIDE_INT rounded_frame_size ( int pushed ) { HOST_WIDE_INT size = get_frame_size ( ) ; HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT ; if ( ACCUMULATE_OUTGOING_ARGS ) size += crtl -> outgoing_args_size ; return ( ( size + pushed + align - 1 ) & - align ) - pushed ; } </s>

PUSHED is the number of bytes that are bing pushed on the stack for register saves . Return the frame size , padded appropriately so that the stack stays properly aligned .


<s> void Thumb1RegisterInfo :: emitLoadConstPool ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator & MBBI , DebugLoc dl , unsigned DestReg , unsigned SubIdx , int Val , ARMCC :: CondCodes Pred , unsigned PredReg ) const { MachineFunction & MF = * MBB . getParent ( ) ; MachineConstantPool * ConstantPool = MF . getConstantPool ( ) ; Constant * C = ConstantInt :: get ( Type :: getInt32Ty ( MBB . getParent ( ) -> getFunction ( ) -> getContext ( ) ) , Val ) ; unsigned Idx = ConstantPool -> getConstantPoolIndex ( C , 4 ) ; BuildMI ( MBB , MBBI , dl , TII . get ( ARM :: tLDRcp ) ) . addReg ( DestReg , getDefRegState ( true ) , SubIdx ) . addConstantPoolIndex ( Idx ) . addImm ( Pred ) . addReg ( PredReg ) ; } </s>

emitLoadConstPool - Emits a load from constpool to materialize the specified immediate .


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

Selects the correct CCAssignFn for a given CallingConvention value .


<s> bool X86PassConfig :: addILPOpts ( ) { addPass ( & EarlyIfConverterID ) ; if ( EnableMachineCombinerPass ) addPass ( & MachineCombinerID ) ; addPass ( createX86CmovConverterPass ( ) ) ; return true ; } </s>

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


<s> StringRef getPassName ( ) const override { return AVOIDCALL_DESC ; } </s>

getPassName - Return a nice clean name for a pass .


<s>
unsigned
X86TTI
::
getArithmeticInstrCost
(
unsigned
Opcode
,
Type
*
Ty
)
const
{
std
::
pair
<
unsigned
,
MVT
>
LT
=
TLI
->
getTypeLegalizationCost
(
Ty
)
;
int
ISD
=
TLI
->
InstructionOpcodeToISD
(
Opcode
)
;
assert
(
ISD
&&
"Invalid opcode"
)
;
static
const
CostTblEntry
<
MVT
>
AVX1CostTable
[
]
=
{
{
ISD
::
MUL
,
MVT
::
v8i32
,
4
}
,
{
ISD
::
SUB
,
MVT
::
v8i32
,
4
}
,
{
ISD
::
ADD
,
MVT
::
v8i32
,
4
}
,
{
ISD
::
MUL
,
MVT
::
v4i64
,
4
}
,
{
ISD
::
SUB
,
MVT
::
v4i64
,
4
}
,
{
ISD
::
ADD
,
MVT
::
v4i64
,
4
}
,
}
;
if
(
ST
->
hasAVX
(
)
)
{
int
Idx
=
CostTableLookup
<
MVT
>
(
AVX1CostTable
,
array_lengthof
(
AVX1CostTable
)
,
ISD
,
LT
.
second
)
;
if
(
Idx
!=
1
)
return
LT
.
first
*
AVX1CostTable
[
Idx
]
.
Cost
;
}
return
TargetTransformInfo
::
getArithmeticInstrCost
(
Opcode
,
Ty
)
;
}
</s>

This is an approximation of reciprocal throughput of a math/logic op .


<s> void X86PassConfig :: addPreRegAlloc ( ) { if ( getOptLevel ( ) != CodeGenOpt :: None ) { addPass ( createX86FixupSetCC ( ) ) ; addPass ( createX86OptimizeLEAs ( ) ) ; } addPass ( createX86CallFrameOptimization ( ) ) ; addPass ( createX86WinAllocaExpander ( ) ) ; } </s>

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


"  num_insn = %d, num_uops = %d, window_size = %d\n"

"  num_imm = %d, num_imm_32 = %d, num_imm_64 = %d, imm_size = %d\n"

"    group[%d] = %s, insn[%d] = %p, path[%d] = %d byte_len[%d] = %d, imm_bytes[%d] = %d\n"

Print the dispatch window , WINDOW_NUM , to FILE .


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

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


<s> AArch64TargetMachine :: AArch64TargetMachine ( const Target & T , const Triple & TT , StringRef CPU , StringRef FS , const TargetOptions & Options , Optional < Reloc :: Model > RM , Optional < CodeModel :: Model > CM , CodeGenOpt :: Level OL , bool JIT , bool LittleEndian ) : LLVMTargetMachine ( T , computeDataLayout ( TT , Options . MCOptions , LittleEndian ) , TT , CPU , FS , Options , getEffectiveRelocModel ( TT , RM ) , getEffectiveCodeModel ( TT , CM , JIT ) , OL ) , TLOF ( createTLOF ( getTargetTriple ( ) ) ) , isLittle ( LittleEndian ) { initAsmInfo ( ) ; if ( TT . isOSBinFormatMachO ( ) ) { this -> Options . TrapUnreachable = true ; this -> Options . NoTrapAfterNoreturn = true ; } if ( getOptLevel ( ) <= EnableGlobalISelAtO ) setGlobalISel ( true ) ; setMachineOutliner ( true ) ; setSupportsDefaultOutlining ( true ) ; } </s>


<s> static void loongarch_print_operand_address ( FILE * file , machine_mode , rtx x ) { struct loongarch_address_info addr ; if ( loongarch_classify_address ( & addr , x , word_mode , true ) ) switch ( addr . type ) { case ADDRESS_REG : fprintf ( file , "%s," , reg_names [ REGNO ( addr . reg ) ] ) ; loongarch_print_operand ( file , addr . offset , 0 ) ; return ; case ADDRESS_REG_REG : fprintf ( file , "%s,%s" , reg_names [ REGNO ( addr . reg ) ] , reg_names [ REGNO ( addr . offset ) ] ) ; return ; case ADDRESS_CONST_INT : fprintf ( file , "%s," , reg_names [ GP_REG_FIRST ] ) ; output_addr_const ( file , x ) ; return ; case ADDRESS_SYMBOLIC : output_addr_const ( file , loongarch_strip_unspec_address ( x ) ) ; return ; } if ( CONST_INT_P ( x ) ) output_addr_const ( file , x ) ; else gcc_unreachable ( ) ; } </s>


<s> static rtx gen_push ( rtx arg ) { struct machine_function * m = cfun -> machine ; if ( m -> fs . cfa_reg == stack_pointer_rtx ) m -> fs . cfa_offset += UNITS_PER_WORD ; m -> fs . sp_offset += UNITS_PER_WORD ; if ( REG_P ( arg ) && GET_MODE ( arg ) != word_mode ) arg = gen_rtx_REG ( word_mode , REGNO ( arg ) ) ; return gen_rtx_SET ( gen_rtx_MEM ( word_mode , gen_rtx_PRE_DEC ( Pmode , stack_pointer_rtx ) ) , arg ) ; } </s>

Code to generate prologue and epilogue sequences


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"OR1K Delay Slot Filler"
;
}
</s>


<s> static rtx pru_function_value ( const_tree ret_type , const_tree fn ATTRIBUTE_UNUSED , bool outgoing ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( TYPE_MODE ( ret_type ) , FIRST_RETVAL_REGNUM ) ; } </s>


<s> static void mips_print_operand_address ( FILE * file , rtx x ) { struct mips_address_info addr ; if ( mips_classify_address ( & addr , x , word_mode , true ) ) switch ( addr . type ) { case ADDRESS_REG : mips_print_operand ( file , addr . offset , 0 ) ; fprintf ( file , "(%s)" , reg_names [ REGNO ( addr . reg ) ] ) ; return ; case ADDRESS_LO_SUM : mips_print_operand_reloc ( file , addr . offset , SYMBOL_CONTEXT_MEM , mips_lo_relocs ) ; fprintf ( file , "(%s)" , reg_names [ REGNO ( addr . reg ) ] ) ; return ; case ADDRESS_CONST_INT : output_addr_const ( file , x ) ; fprintf ( file , "(%s)" , reg_names [ GP_REG_FIRST ] ) ; return ; case ADDRESS_SYMBOLIC : output_addr_const ( file , mips_strip_unspec_address ( x ) ) ; return ; } gcc_unreachable ( ) ; } </s>


<s> static void aarch64_save_callee_saves ( machine_mode mode , HOST_WIDE_INT start_offset , unsigned start , unsigned limit , bool skip_wb ) { rtx_insn * insn ; rtx ( * gen_mem_ref ) ( machine_mode , rtx ) = ( frame_pointer_needed ? gen_frame_mem : gen_rtx_MEM ) ; unsigned regno ; unsigned regno2 ; for ( regno = aarch64_next_callee_save ( start , limit ) ; regno <= limit ; regno = aarch64_next_callee_save ( regno + 1 , limit ) ) { rtx reg , mem ; HOST_WIDE_INT offset ; if ( skip_wb && ( regno == cfun -> machine -> frame . wb_candidate1 || regno == cfun -> machine -> frame . wb_candidate2 ) ) continue ; reg = gen_rtx_REG ( mode , regno ) ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno ] ; mem = gen_mem_ref ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; regno2 = aarch64_next_callee_save ( regno + 1 , limit ) ; if ( regno2 <= limit && ( ( cfun -> machine -> frame . reg_offset [ regno ] + UNITS_PER_WORD ) == cfun -> machine -> frame . reg_offset [ regno2 ] ) ) { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; rtx mem2 ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno2 ] ; mem2 = gen_mem_ref ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; insn = emit_insn ( aarch64_gen_store_pair ( mode , mem , reg , mem2 , reg2 ) ) ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 1 ) ) = 1 ; regno = regno2 ; } else insn = emit_move_insn ( mem , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Emit code to save the callee-saved registers from register number START to LIMIT to the stack at the location starting at offset START_OFFSET , skipping any write-back candidates if SKIP_WB is true .


<s> static void iq2000_va_start ( tree valist , rtx nextarg ) { int int_arg_words ; int gpr_save_area_size ; int_arg_words = crtl -> args . info . arg_words ; if ( int_arg_words < 8 ) gpr_save_area_size = ( 8 - int_arg_words ) * UNITS_PER_WORD ; else gpr_save_area_size = 0 ; nextarg = plus_constant ( Pmode , nextarg , - gpr_save_area_size ) ; std_expand_builtin_va_start ( valist , nextarg ) ; } </s>


<s> int ia64_register_move_cost ( enum machine_mode mode , enum reg_class from , enum reg_class to ) { if ( to == ADDL_REGS ) to = GR_REGS ; if ( from == ADDL_REGS ) from = GR_REGS ; if ( from < to ) { enum reg_class tmp = to ; to = from , from = tmp ; } if ( mode == XFmode || mode == RFmode ) { if ( to != GR_REGS || from != GR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; else return 3 ; } switch ( to ) { case PR_REGS : if ( from == PR_REGS ) return 3 ; if ( from != GR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; break ; case BR_REGS : if ( from != GR_REGS && from != GR_AND_BR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; break ; case AR_I_REGS : case AR_M_REGS : if ( from != GR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; break ; case GR_REGS : case FR_REGS : case FP_REGS : case GR_AND_FR_REGS : case GR_AND_BR_REGS : case ALL_REGS : break ; default : gcc_unreachable ( ) ; } return 2 ; } </s>

Calulate the cost of moving data from a register in class FROM to one in class TO , using MODE .


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

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


<s> bool mips_split_move_p ( rtx dest , rtx src , enum mips_split_type split_type ) { if ( mips_mult_move_p ( dest , src , split_type ) ) return false ; unsigned int size = GET_MODE_SIZE ( GET_MODE ( dest ) ) ; if ( size == 8 && FP_REG_RTX_P ( src ) && FP_REG_RTX_P ( dest ) ) return false ; if ( size == 8 && ISA_HAS_LDC1_SDC1 ) { if ( FP_REG_RTX_P ( dest ) && MEM_P ( src ) ) return false ; if ( FP_REG_RTX_P ( src ) && MEM_P ( dest ) ) return false ; } if ( MSA_SUPPORTED_MODE_P ( GET_MODE ( dest ) ) ) return mips_split_128bit_move_p ( dest , src ) ; return size > UNITS_PER_WORD ; } </s>

Return true if a move from SRC to DEST should be split into two . SPLIT_TYPE describes the split condition .


<s> virtual unsigned int execute ( function * ) { return mips_machine_reorg2 ( ) ; } </s>


<s> bool ix86_expand_fp_movcc ( rtx operands [ ] ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; enum rtx_code code = GET_CODE ( operands [ 1 ] ) ; rtx tmp , compare_op ; rtx op0 = XEXP ( operands [ 1 ] , 0 ) ; rtx op1 = XEXP ( operands [ 1 ] , 1 ) ; if ( TARGET_SSE_MATH && SSE_FLOAT_MODE_P ( mode ) ) { machine_mode cmode ; cmode = GET_MODE ( op0 ) ; if ( cmode == VOIDmode ) cmode = GET_MODE ( op1 ) ; if ( cmode != mode ) return false ; code = ix86_prepare_sse_fp_compare_args ( operands [ 0 ] , code , & op0 , & op1 ) ; if ( code == UNKNOWN ) return false ; if ( ix86_expand_sse_fp_minmax ( operands [ 0 ] , code , op0 , op1 , operands [ 2 ] , operands [ 3 ] ) ) return true ; tmp = ix86_expand_sse_cmp ( operands [ 0 ] , code , op0 , op1 , operands [ 2 ] , operands [ 3 ] ) ; ix86_expand_sse_movcc ( operands [ 0 ] , tmp , operands [ 2 ] , operands [ 3 ] ) ; return true ; } if ( GET_MODE ( op0 ) == TImode || ( GET_MODE ( op0 ) == DImode && ! TARGET_64BIT ) ) return false ; compare_op = ix86_expand_compare ( code , op0 , op1 ) ; if ( ! fcmov_comparison_operator ( compare_op , VOIDmode ) ) { tmp = gen_reg_rtx ( QImode ) ; ix86_expand_setcc ( tmp , code , op0 , op1 ) ; compare_op = ix86_expand_compare ( NE , tmp , const0_rtx ) ; } emit_insn ( gen_rtx_SET ( VOIDmode , operands [ 0 ] , gen_rtx_IF_THEN_ELSE ( mode , compare_op , operands [ 2 ] , operands [ 3 ] ) ) ) ; return true ; } </s>

Expand a floating-point conditional move . Return true if successful .


"invalid id value for interrupt attribute"

FIXME : FOR BACKWARD COMPATIBILITY , we need to support following patterns : __attribute__ ( ( interrupt ( `` XXX ; YYY ; id=ZZZ '' ) ) ) __attribute__ ( ( exception ( `` XXX ; YYY ; id=ZZZ '' ) ) ) __attribute__ ( ( reset ( `` vectors=XXX ; nmi_func=YYY ; warm_func=ZZZ '' ) ) ) We provide several functions to parse the strings .


<s> rtx swap_endian_selector_for_mode ( machine_mode mode ) { unsigned int swap1 [ 16 ] = { 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 } ; unsigned int swap2 [ 16 ] = { 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 } ; unsigned int swap4 [ 16 ] = { 3 , 2 , 1 , 0 , 7 , 6 , 5 , 4 , 11 , 10 , 9 , 8 , 15 , 14 , 13 , 12 } ; unsigned int swap8 [ 16 ] = { 1 , 0 , 3 , 2 , 5 , 4 , 7 , 6 , 9 , 8 , 11 , 10 , 13 , 12 , 15 , 14 } ; unsigned int * swaparray , i ; rtx perm [ 16 ] ; switch ( mode ) { case E_V1TImode : swaparray = swap1 ; break ; case E_V2DFmode : case E_V2DImode : swaparray = swap2 ; break ; case E_V4SFmode : case E_V4SImode : swaparray = swap4 ; break ; case E_V8HImode : swaparray = swap8 ; break ; default : gcc_unreachable ( ) ; } for ( i = 0 ; i < 16 ; ++ i ) if ( BYTES_BIG_ENDIAN ) perm [ i ] = GEN_INT ( swaparray [ i ] ) ; else perm [ i ] = GEN_INT ( ~ swaparray [ i ] & 0x0000001f ) ; return force_reg ( V16QImode , gen_rtx_CONST_VECTOR ( V16QImode , gen_rtvec_v ( 16 , perm ) ) ) ; } </s>

Return the permutation index for the swapping on the given vector mode . Note that the permutation index is correspondingly generated by endianness , it should be used by direct vector permutation .


<s> bool PPCPassConfig :: addPreEmitPass ( ) { PM -> add ( createPPCBranchSelectionPass ( ) ) ; return false ; } </s>

This pass may be implemented by targets that want to run passes immediately before machine code is emitted .


<s>
void
A57ChainingConstraint
::
apply
(
PBQPRAGraph
&
G
)
{
const
MachineFunction
&
MF
=
G
.
getMetadata
(
)
.
MF
;
LiveIntervals
&
LIs
=
G
.
getMetadata
(
)
.
LIS
;
TRI
=
MF
.
getTarget
(
)
.
getSubtargetImpl
(
)
->
getRegisterInfo
(
)
;
DEBUG
(
MF
.
dump
(
)
)
;
for
(
const
auto
&
MBB
:
MF
)
{
Chains
.
clear
(
)
;
for
(
const
auto
&
MI
:
MBB
)
{
for
(
auto
r
:
Chains
)
{
SmallVector
<
unsigned
,
8
>
toDel
;
if
(
regJustKilledBefore
(
LIs
,
r
,
MI
)
)
{
DEBUG
(
dbgs
(
)
<<
"Killing chain "
<<
PrintReg
(
r
,
TRI
)
<<
" at "
;
MI
.
print
(
dbgs
(
)
)
;
)
;
toDel
.
push_back
(
r
)
;
}
while
(
!
toDel
.
empty
(
)
)
{
Chains
.
remove
(
toDel
.
back
(
)
)
;
toDel
.
pop_back
(
)
;
}
}
switch
(
MI
.
getOpcode
(
)
)
{
case
AArch64
::
FMSUBSrrr
:
case
AArch64
::
FMADDSrrr
:
case
AArch64
::
FNMSUBSrrr
:
case
AArch64
::
FNMADDSrrr
:
case
AArch64
::
FMSUBDrrr
:
case
AArch64
::
FMADDDrrr
:
case
AArch64
::
FNMSUBDrrr
:
case
AArch64
::
FNMADDDrrr
:
{
unsigned
Rd
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
unsigned
Ra
=
MI
.
getOperand
(
3
)
.
getReg
(
)
;
if
(
addIntraChainConstraint
(
G
,
Rd
,
Ra
)
)
addInterChainConstraint
(
G
,
Rd
,
Ra
)
;
break
;
}
case
AArch64
::
FMLAv2f32
:
case
AArch64
::
FMLSv2f32
:
{
unsigned
Rd
=
MI
.
getOperand
(
0
)
.
getReg
(
)
;
addInterChainConstraint
(
G
,
Rd
,
Rd
)
;
break
;
}
default
:
break
;
}
}
}
}
</s>

Apply the profile inference algorithm for a given function .


<s> static bool sparc_handle_option ( size_t code , const char * arg , int value ATTRIBUTE_UNUSED ) { switch ( code ) { case OPT_mfpu : case OPT_mhard_float : case OPT_msoft_float : fpu_option_set = true ; break ; case OPT_mcpu_ : sparc_select [ 1 ] . string = arg ; break ; case OPT_mtune_ : sparc_select [ 2 ] . string = arg ; break ; } return true ; } </s>


<s> static const uint16_t * lookup ( unsigned opcode , unsigned domain ) { for ( const uint16_t ( & Row ) [ 3 ] : ReplaceableInstrs ) if ( Row [ domain - 1 ] == opcode ) return Row ; return nullptr ; } </s>

This method finds the value with the given Name in the the symbol table .


<s> static bool aapcs_vfp_is_call_or_return_candidate ( enum arm_pcs pcs_variant , machine_mode mode , const_tree type , machine_mode * base_mode , int * count ) { machine_mode new_mode = VOIDmode ; if ( type ) { int ag_count = aapcs_vfp_sub_candidate ( type , & new_mode ) ; if ( ag_count > 0 && ag_count <= 4 ) * count = ag_count ; else return false ; } else if ( GET_MODE_CLASS ( mode ) == MODE_FLOAT || GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT || GET_MODE_CLASS ( mode ) == MODE_VECTOR_FLOAT ) { * count = 1 ; new_mode = mode ; } else if ( GET_MODE_CLASS ( mode ) == MODE_COMPLEX_FLOAT ) { * count = 2 ; new_mode = ( mode == DCmode ? DFmode : SFmode ) ; } else return false ; if ( ! use_vfp_abi ( pcs_variant , ARM_NUM_REGS ( new_mode ) > 1 ) ) return false ; * base_mode = new_mode ; return true ; } </s>

Return true if an argument whose type is TYPE , or mode is MODE , is suitable for passing or returning in VFP registers for the PCS variant selected . If it is , then * BASE_MODE is updated to contain a machine mode describing each element of the argument 's type and * COUNT to hold the number of such elements .


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

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


<s> unsigned MipsTargetLowering :: getNumRegistersForCallingConv ( LLVMContext & Context , CallingConv :: ID CC , EVT VT ) const { if ( VT . isVector ( ) ) return std :: max ( ( VT . getSizeInBits ( ) / ( Subtarget . isABI_O32 ( ) ? 32 : 64 ) ) , 1U ) ; return MipsTargetLowering :: getNumRegisters ( Context , VT ) ; } </s>

Certain targets require unusual breakdowns of certain types .


<s> static tree rs6000_fold_builtin ( tree fndecl , int n_args ATTRIBUTE_UNUSED , tree * args , bool ignore ATTRIBUTE_UNUSED ) { if ( DECL_BUILT_IN_CLASS ( fndecl ) == BUILT_IN_MD ) { enum rs6000_builtins fn_code = ( enum rs6000_builtins ) DECL_FUNCTION_CODE ( fndecl ) ; switch ( fn_code ) { case RS6000_BUILTIN_NANQ : case RS6000_BUILTIN_NANSQ : { tree type = TREE_TYPE ( TREE_TYPE ( fndecl ) ) ; const char * str = c_getstr ( * args ) ; int quiet = fn_code == RS6000_BUILTIN_NANQ ; REAL_VALUE_TYPE real ; if ( str && real_nan ( & real , str , quiet , TYPE_MODE ( type ) ) ) return build_real ( type , real ) ; return NULL_TREE ; } case RS6000_BUILTIN_INFQ : case RS6000_BUILTIN_HUGE_VALQ : { tree type = TREE_TYPE ( TREE_TYPE ( fndecl ) ) ; REAL_VALUE_TYPE inf ; real_inf ( & inf ) ; return build_real ( type , inf ) ; } default : break ; } } return SUBTARGET_FOLD_BUILTIN ( fndecl , n_args , args , ignore ) ; return NULL_TREE ; } </s>

Target hook for early folding of built-ins , shamelessly stolen from ia64.cc .


<s> bool AArch64AsmParser :: ParseDirective ( AsmToken DirectiveID ) { const MCObjectFileInfo :: Environment Format = getContext ( ) . getObjectFileInfo ( ) -> getObjectFileType ( ) ; bool IsMachO = Format == MCObjectFileInfo :: IsMachO ; bool IsCOFF = Format == MCObjectFileInfo :: IsCOFF ; StringRef IDVal = DirectiveID . getIdentifier ( ) ; SMLoc Loc = DirectiveID . getLoc ( ) ; if ( IDVal == ".arch" ) return parseDirectiveArch ( Loc ) ; if ( IDVal == ".cpu" ) return parseDirectiveCPU ( Loc ) ; if ( IDVal == ".hword" ) return parseDirectiveWord ( 2 , Loc ) ; if ( IDVal == ".word" ) return parseDirectiveWord ( 4 , Loc ) ; if ( IDVal == ".xword" ) return parseDirectiveWord ( 8 , Loc ) ; if ( IDVal == ".tlsdesccall" ) return parseDirectiveTLSDescCall ( Loc ) ; if ( IDVal == ".ltorg" || IDVal == ".pool" ) return parseDirectiveLtorg ( Loc ) ; if ( IDVal == ".unreq" ) return parseDirectiveUnreq ( Loc ) ; if ( ! IsMachO && ! IsCOFF ) { if ( IDVal == ".inst" ) return parseDirectiveInst ( Loc ) ; } return parseDirectiveLOH ( IDVal , Loc ) ; } </s>

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


<s> SDNode * PPCDAGToDAGISel :: getGlobalBaseReg ( ) { if ( ! GlobalBaseReg ) { const TargetInstrInfo & TII = * PPCSubTarget -> getInstrInfo ( ) ; MachineBasicBlock & FirstMBB = MF -> front ( ) ; MachineBasicBlock :: iterator MBBI = FirstMBB . begin ( ) ; const Module * M = MF -> getFunction ( ) -> getParent ( ) ; DebugLoc dl ; if ( PPCLowering -> getPointerTy ( CurDAG -> getDataLayout ( ) ) == MVT :: i32 ) { if ( PPCSubTarget -> isTargetELF ( ) ) { GlobalBaseReg = PPC :: R30 ; if ( M -> getPICLevel ( ) == PICLevel :: SmallPIC ) { BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MoveGOTtoLR ) ) ; BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MFLR ) , GlobalBaseReg ) ; MF -> getInfo < PPCFunctionInfo > ( ) -> setUsesPICBase ( true ) ; } else { BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MovePCtoLR ) ) ; BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MFLR ) , GlobalBaseReg ) ; unsigned TempReg = RegInfo -> createVirtualRegister ( & PPC :: GPRCRegClass ) ; BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: UpdateGBR ) , GlobalBaseReg ) . addReg ( TempReg , RegState :: Define ) . addReg ( GlobalBaseReg ) ; MF -> getInfo < PPCFunctionInfo > ( ) -> setUsesPICBase ( true ) ; } } else { GlobalBaseReg = RegInfo -> createVirtualRegister ( & PPC :: GPRC_NOR0RegClass ) ; BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MovePCtoLR ) ) ; BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MFLR ) , GlobalBaseReg ) ; } } else { GlobalBaseReg = RegInfo -> createVirtualRegister ( & PPC :: G8RC_NOX0RegClass ) ; BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MovePCtoLR8 ) ) ; BuildMI ( FirstMBB , MBBI , dl , TII . get ( PPC :: MFLR8 ) , GlobalBaseReg ) ; } } return CurDAG -> getRegister ( GlobalBaseReg , PPCLowering -> getPointerTy ( CurDAG -> getDataLayout ( ) ) ) . getNode ( ) ; } </s>

getGlobalBaseReg - Return a virtual register initialized with the the global base register value .

PowerPC PPC PPC PPC MVT::i32 PPC PPC::R30 PPC::MoveGOTtoLR PPC::MFLR PPC PPC::MovePCtoLR PPC::MFLR PPC::GPRCRegClass PPC::UpdateGBR PPC PPC::GPRC_NOR0RegClass PPC::MovePCtoLR PPC::MFLR PPC::G8RC_NOX0RegClass PPC::MovePCtoLR8 PPC::MFLR8 PPC


<s> bool X86FrameLowering :: assignCalleeSavedSpillSlots ( MachineFunction & MF , const TargetRegisterInfo * TRI , std :: vector < CalleeSavedInfo > & CSI ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; X86MachineFunctionInfo * X86FI = MF . getInfo < X86MachineFunctionInfo > ( ) ; unsigned CalleeSavedFrameSize = 0 ; int SpillSlotOffset = getOffsetOfLocalArea ( ) + X86FI -> getTCReturnAddrDelta ( ) ; if ( hasFP ( MF ) ) { SpillSlotOffset -= SlotSize ; MFI . CreateFixedSpillStackObject ( SlotSize , SpillSlotOffset ) ; unsigned FPReg = TRI -> getFrameRegister ( MF ) ; for ( unsigned i = 0 ; i < CSI . size ( ) ; ++ i ) { if ( TRI -> regsOverlap ( CSI [ i ] . getReg ( ) , FPReg ) ) { CSI . erase ( CSI . begin ( ) + i ) ; break ; } } } for ( unsigned i = CSI . size ( ) ; i != 0 ; -- i ) { unsigned Reg = CSI [ i - 1 ] . getReg ( ) ; if ( ! X86 :: GR64RegClass . contains ( Reg ) && ! X86 :: GR32RegClass . contains ( Reg ) ) continue ; SpillSlotOffset -= SlotSize ; CalleeSavedFrameSize += SlotSize ; int SlotIndex = MFI . CreateFixedSpillStackObject ( SlotSize , SpillSlotOffset ) ; CSI [ i - 1 ] . setFrameIdx ( SlotIndex ) ; } X86FI -> setCalleeSavedFrameSize ( CalleeSavedFrameSize ) ; for ( unsigned i = CSI . size ( ) ; i != 0 ; -- i ) { unsigned Reg = CSI [ i - 1 ] . getReg ( ) ; if ( X86 :: GR64RegClass . contains ( Reg ) || X86 :: GR32RegClass . contains ( Reg ) ) continue ; const TargetRegisterClass * RC = TRI -> getMinimalPhysRegClass ( Reg ) ; SpillSlotOffset -= std :: abs ( SpillSlotOffset ) % RC -> getAlignment ( ) ; SpillSlotOffset -= RC -> getSize ( ) ; int SlotIndex = MFI . CreateFixedSpillStackObject ( RC -> getSize ( ) , SpillSlotOffset ) ; CSI [ i - 1 ] . setFrameIdx ( SlotIndex ) ; MFI . ensureMaxAlignment ( RC -> getAlignment ( ) ) ; } return true ; } </s>

This function will assign callee saved gprs to volatile vector registers for prologue spills when applicable .


<s> bool reg_unused_after ( rtx reg , rtx_insn * insn ) { rtx set = single_set ( insn ) ; if ( set && ! MEM_P ( SET_DEST ( set ) ) && reg_overlap_mentioned_p ( reg , SET_DEST ( set ) ) ) return true ; while ( ( insn = NEXT_INSN ( insn ) ) ) { if ( ! INSN_P ( insn ) ) continue ; rtx_code code = GET_CODE ( insn ) ; if ( code == CODE_LABEL ) return 1 ; if ( code == JUMP_INSN ) return false ; else if ( code == INSN && GET_CODE ( PATTERN ( insn ) ) == SEQUENCE ) { rtx_sequence * seq = as_a < rtx_sequence * > ( PATTERN ( insn ) ) ; bool retval = false ; for ( int i = 0 ; i < seq -> len ( ) ; i ++ ) { rtx_insn * this_insn = seq -> insn ( i ) ; rtx set = single_set ( this_insn ) ; if ( CALL_P ( this_insn ) ) code = CALL_INSN ; else if ( JUMP_P ( this_insn ) ) { if ( INSN_ANNULLED_BRANCH_P ( this_insn ) ) return false ; code = JUMP_INSN ; } if ( set && reg_overlap_mentioned_p ( reg , SET_SRC ( set ) ) ) return false ; if ( set && reg_overlap_mentioned_p ( reg , SET_DEST ( set ) ) ) { if ( ! MEM_P ( SET_DEST ( set ) ) ) retval = true ; else return false ; } if ( set == NULL_RTX && reg_overlap_mentioned_p ( reg , PATTERN ( this_insn ) ) ) return false ; } if ( retval ) return true ; else if ( code == JUMP_INSN ) return false ; } rtx set = single_set ( insn ) ; if ( set && reg_overlap_mentioned_p ( reg , SET_SRC ( set ) ) ) return false ; if ( set && reg_overlap_mentioned_p ( reg , SET_DEST ( set ) ) ) return ! MEM_P ( SET_DEST ( set ) ) ; if ( set == NULL && reg_overlap_mentioned_p ( reg , PATTERN ( insn ) ) ) return false ; if ( code == CALL_INSN && call_really_used_regs [ REGNO ( reg ) ] ) return true ; } return true ; } </s>

Return nonzero if REG is not used after INSN . We assume REG is a reload reg , and therefore does not live past labels or calls or jumps .


<s> static void aarch64_save_callee_saves ( machine_mode mode , poly_int64 start_offset , unsigned start , unsigned limit , bool skip_wb ) { rtx_insn * insn ; unsigned regno ; unsigned regno2 ; for ( regno = aarch64_next_callee_save ( start , limit ) ; regno <= limit ; regno = aarch64_next_callee_save ( regno + 1 , limit ) ) { rtx reg , mem ; poly_int64 offset ; int offset_diff ; if ( skip_wb && ( regno == cfun -> machine -> frame . wb_candidate1 || regno == cfun -> machine -> frame . wb_candidate2 ) ) continue ; if ( cfun -> machine -> reg_is_wrapped_separately [ regno ] ) continue ; reg = gen_rtx_REG ( mode , regno ) ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno ] ; mem = gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; regno2 = aarch64_next_callee_save ( regno + 1 , limit ) ; offset_diff = cfun -> machine -> frame . reg_offset [ regno2 ] - cfun -> machine -> frame . reg_offset [ regno ] ; if ( regno2 <= limit && ! cfun -> machine -> reg_is_wrapped_separately [ regno2 ] && known_eq ( GET_MODE_SIZE ( mode ) , offset_diff ) ) { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; rtx mem2 ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno2 ] ; mem2 = gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; insn = emit_insn ( aarch64_gen_store_pair ( mode , mem , reg , mem2 , reg2 ) ) ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 1 ) ) = 1 ; regno = regno2 ; } else insn = emit_move_insn ( mem , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Emit code to save the callee-saved registers from register number START to LIMIT to the stack at the location starting at offset START_OFFSET , skipping any write-back candidates if SKIP_WB is true .


<s>
bool
ThumbDisassembler
::
getInstruction
(
MCInst
&
MI
,
uint64_t
&
Size
,
const
MemoryObject
&
Region
,
uint64_t
Address
,
raw_ostream
&
os
)
const
{
uint32_t
insn
=
0
;
uint16_t
insn1
=
0
;
uint8_t
bytes
[
2
]
;
if
(
Region
.
readBytes
(
Address
,
2
,
(
uint8_t
*
)
bytes
,
)
==
1
)
return
false
;
insn
=
(
bytes
[
1
]
<<
8
)
|
bytes
[
0
]
;
unsigned
bits15_11
=
slice
(
insn
,
15
,
11
)
;
bool
IsThumb2
=
false
;
if
(
bits15_11
==
0x1D
||
bits15_11
==
0x1E
||
bits15_11
==
0x1F
)
{
IsThumb2
=
true
;
if
(
Region
.
readBytes
(
Address
+
2
,
2
,
(
uint8_t
*
)
bytes
,
)
==
1
)
return
false
;
insn1
=
(
bytes
[
1
]
<<
8
)
|
bytes
[
0
]
;
insn
=
(
insn
<<
16
|
insn1
)
;
}
unsigned
Opcode
=
decodeThumbSideEffect
(
IsThumb2
,
insn
)
;
if
(
Thumb2PreloadOpcodeNoPCI
(
Opcode
)
&&
slice
(
insn
,
19
,
16
)
==
15
)
Opcode
=
T2Morph2Preload2PCI
(
Opcode
)
;
ARMFormat
Format
=
ARMFormats
[
Opcode
]
;
Size
=
IsThumb2
4
:
2
;
DEBUG
(
{
errs
(
)
<<
"Opcode="
<<
Opcode
<<
" Name="
<<
ARMUtils
::
OpcodeName
(
Opcode
)
<<
" Format="
<<
stringForARMFormat
(
Format
)
<<
'('
<<
(
int
)
Format
<<
")\n"
;
showBitVector
(
errs
(
)
,
insn
)
;
}
)
;
ARMBasicMCBuilder
*
Builder
=
CreateMCBuilder
(
Opcode
,
Format
)
;
Builder
->
SetSession
(
const_cast
<
Session
*
>
(
&
SO
)
)
;
if
(
!
Builder
)
return
false
;
if
(
!
Builder
->
Build
(
MI
,
insn
)
)
return
false
;
delete
Builder
;
return
true
;
}
</s>

Returns the disassembly of a single instruction .


<s> void Thumb2InstrInfo :: ReplaceTailWithBranchTo ( MachineBasicBlock :: iterator Tail , MachineBasicBlock * NewDest ) const { MachineBasicBlock * MBB = Tail -> getParent ( ) ; ARMFunctionInfo * AFI = MBB -> getParent ( ) -> getInfo < ARMFunctionInfo > ( ) ; if ( ! AFI -> hasITBlocks ( ) ) { TargetInstrInfo :: ReplaceTailWithBranchTo ( Tail , NewDest ) ; return ; } unsigned PredReg = 0 ; ARMCC :: CondCodes CC = getInstrPredicate ( * Tail , PredReg ) ; MachineBasicBlock :: iterator MBBI = Tail ; if ( CC != ARMCC :: AL ) -- MBBI ; TargetInstrInfo :: ReplaceTailWithBranchTo ( Tail , NewDest ) ; if ( CC != ARMCC :: AL ) { MachineBasicBlock :: iterator E = MBB -> begin ( ) ; unsigned Count = 4 ; while ( Count && MBBI != E ) { if ( MBBI -> isDebugValue ( ) ) { -- MBBI ; continue ; } if ( MBBI -> getOpcode ( ) == ARM :: t2IT ) { unsigned Mask = MBBI -> getOperand ( 1 ) . getImm ( ) ; if ( Count == 4 ) MBBI -> eraseFromParent ( ) ; else { unsigned MaskOn = 1 << Count ; unsigned MaskOff = ~ ( MaskOn - 1 ) ; MBBI -> getOperand ( 1 ) . setImm ( ( Mask & MaskOff ) | MaskOn ) ; } return ; } -- MBBI ; -- Count ; } } } </s>

Delete the instruction OldInst and everything after it , replacing it with an unconditional branch to NewDest .


<s> bool ARMSubtarget :: enablePostRAScheduler ( ) const { if ( disablePostRAScheduler ( ) ) return false ; return ! isThumb1Only ( ) ; } </s>

True if the subtarget should run a scheduler after register allocation .


<s> static bool rs6000_scalar_mode_supported_p ( machine_mode mode ) { if ( TARGET_32BIT && mode == TImode ) return false ; if ( DECIMAL_FLOAT_MODE_P ( mode ) ) return default_decimal_float_supported_p ( ) ; else return default_scalar_mode_supported_p ( mode ) ; } </s>

Target hook for scalar_mode_supported_p .


<s> MachineBasicBlock :: iterator CJGFrameLowering :: eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator I ) const { const CJGInstrInfo & TII = * static_cast < const CJGInstrInfo * > ( MF . getSubtarget ( ) . getInstrInfo ( ) ) ; unsigned StackAlign = getStackAlignment ( ) ; if ( ! hasReservedCallFrame ( MF ) ) { MachineInstr & Old = * I ; uint64_t Amount = Old . getOperand ( 0 ) . getImm ( ) ; if ( Amount != 0 ) { Amount = ( Amount + StackAlign - 1 ) / StackAlign * StackAlign ; MachineInstr * New = nullptr ; if ( Old . getOpcode ( ) == TII . getCallFrameSetupOpcode ( ) ) { New = BuildMI ( MF , Old . getDebugLoc ( ) , TII . get ( CJG :: SUBri ) , CJG :: SP ) . addReg ( CJG :: SP ) . addImm ( Amount ) ; } else { assert ( Old . getOpcode ( ) == TII . getCallFrameDestroyOpcode ( ) ) ; uint64_t CalleeAmt = Old . getOperand ( 1 ) . getImm ( ) ; Amount -= CalleeAmt ; if ( Amount ) New = BuildMI ( MF , Old . getDebugLoc ( ) , TII . get ( CJG :: ADDri ) , CJG :: SP ) . addReg ( CJG :: SP ) . addImm ( Amount ) ; } if ( New ) { New -> getOperand ( 3 ) . setIsDead ( ) ; MBB . insert ( I , New ) ; } } } else if ( I -> getOpcode ( ) == TII . getCallFrameDestroyOpcode ( ) ) { if ( uint64_t CalleeAmt = I -> getOperand ( 1 ) . getImm ( ) ) { MachineInstr & Old = * I ; MachineInstr * New = BuildMI ( MF , Old . getDebugLoc ( ) , TII . get ( CJG :: SUBri ) , CJG :: SP ) . addReg ( CJG :: SP ) . addImm ( CalleeAmt ) ; New -> getOperand ( 3 ) . setIsDead ( ) ; MBB . insert ( I , New ) ; } } return MBB . erase ( I ) ; } </s>

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


<s>
void
SystemZMCAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
,
const
MCSubtargetInfo
*
STI
)
const
{
MCFixupKind
Kind
=
Fixup
.
getKind
(
)
;
if
(
Kind
>=
FirstLiteralRelocationKind
)
return
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
unsigned
BitSize
=
getFixupKindInfo
(
Kind
)
.
TargetSize
;
unsigned
Size
=
(
BitSize
+
7
)
/
8
;
assert
(
Offset
+
Size
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
Value
=
extractBitsForFixup
(
Kind
,
Value
)
;
if
(
BitSize
<
64
)
Value
&=
(
(
uint64_t
)
1
<<
BitSize
)
1
;
unsigned
ShiftValue
=
(
Size
*
8
)
8
;
for
(
unsigned
I
=
0
;
I
!=
Size
;
++
I
)
{
Data
[
Offset
+
I
]
|=
uint8_t
(
Value
>>
ShiftValue
)
;
ShiftValue
-=
8
;
}
}
</s>

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


<s> static bool arm_output_addr_const_extra ( FILE * fp , rtx x ) { if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) == UNSPEC_TLS ) return arm_emit_tls_decoration ( fp , x ) ; else if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) == UNSPEC_PIC_LABEL ) { char label [ 256 ] ; int labelno = INTVAL ( XVECEXP ( x , 0 , 0 ) ) ; ASM_GENERATE_INTERNAL_LABEL ( label , "LPIC" , labelno ) ; assemble_name_raw ( fp , label ) ; return TRUE ; } else if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) == UNSPEC_GOTSYM_OFF ) { assemble_name ( fp , "_GLOBAL_OFFSET_TABLE_" ) ; if ( GOT_PCREL ) fputs ( "+." , fp ) ; fputs ( "-(" , fp ) ; output_addr_const ( fp , XVECEXP ( x , 0 , 0 ) ) ; fputc ( ')' , fp ) ; return TRUE ; } else if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) == UNSPEC_SYMBOL_OFFSET ) { output_addr_const ( fp , XVECEXP ( x , 0 , 0 ) ) ; if ( GOT_PCREL ) fputs ( "+." , fp ) ; fputs ( "-(" , fp ) ; output_addr_const ( fp , XVECEXP ( x , 0 , 1 ) ) ; fputc ( ')' , fp ) ; return TRUE ; } else if ( GET_CODE ( x ) == CONST_VECTOR ) return arm_emit_vector_const ( fp , x ) ; return FALSE ; } </s>


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


<s> bool LoongArchPassConfig :: addInstSelector ( ) { addPass ( createLoongArchISelDag ( getLoongArchTargetMachine ( ) ) ) ; return false ; } </s>

addInstSelector - This method should install an instruction selector pass , which converts from LLVM code to machine instructions .


<s> rtx sparc_legitimize_reload_address ( rtx x , machine_mode mode , int opnum , int type , int ind_levels ATTRIBUTE_UNUSED , int * win ) { if ( CONSTANT_P ( x ) && ( mode != TFmode || TARGET_ARCH64 ) && GET_MODE ( x ) == SImode && GET_CODE ( x ) != LO_SUM && GET_CODE ( x ) != HIGH && sparc_cmodel <= CM_MEDLOW && ! ( flag_pic && ( symbolic_operand ( x , Pmode ) || pic_address_needs_scratch ( x ) ) ) ) { x = gen_rtx_LO_SUM ( GET_MODE ( x ) , gen_rtx_HIGH ( GET_MODE ( x ) , x ) , x ) ; push_reload ( XEXP ( x , 0 ) , NULL_RTX , & XEXP ( x , 0 ) , NULL , BASE_REG_CLASS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , ( enum reload_type ) type ) ; * win = 1 ; return x ; } if ( GET_CODE ( x ) == LO_SUM && GET_CODE ( XEXP ( x , 0 ) ) == HIGH ) { push_reload ( XEXP ( x , 0 ) , NULL_RTX , & XEXP ( x , 0 ) , NULL , BASE_REG_CLASS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , ( enum reload_type ) type ) ; * win = 1 ; return x ; } * win = 0 ; return x ; } </s>

SPARC implementation of LEGITIMIZE_RELOAD_ADDRESS . Returns a value to replace the input X , or the original X if no replacement is called for . The output parameter * WIN is 1 if the calling macro should goto WIN , 0 if it should not . For SPARC , we wish to handle addresses by splitting them into HIGH+LO_SUM pairs , retaining the LO_SUM in the memory reference . This cuts the number of extra insns by one . Do nothing when generating PIC code and the address is a symbolic operand or requires a scratch register .


<s> void AArch64PassConfig :: addPreLegalizeMachineIR ( ) { addPass ( createAArch64PreLegalizeCombiner ( ) ) ; } </s>

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


<s> static int rs6000_variable_issue_1 ( rtx_insn * insn , int more ) { last_scheduled_insn = insn ; if ( GET_CODE ( PATTERN ( insn ) ) == USE || GET_CODE ( PATTERN ( insn ) ) == CLOBBER ) { cached_can_issue_more = more ; return cached_can_issue_more ; } if ( insn_terminates_group_p ( insn , current_group ) ) { cached_can_issue_more = 0 ; return cached_can_issue_more ; } if ( recog_memoized ( insn ) < 0 ) return more ; if ( rs6000_sched_groups ) { if ( is_microcoded_insn ( insn ) ) cached_can_issue_more = 0 ; else if ( is_cracked_insn ( insn ) ) cached_can_issue_more = more > 2 ? more - 2 : 0 ; else cached_can_issue_more = more - 1 ; return cached_can_issue_more ; } if ( rs6000_cpu_attr == CPU_CELL && is_nonpipeline_insn ( insn ) ) return 0 ; cached_can_issue_more = more - 1 ; return cached_can_issue_more ; } </s>

Power4 load update and store update instructions are cracked into a load or store and an integer insn which are executed in the same cycle . Branches have their own dispatch slot which does not count against the GCC issue rate , but it changes the program flow so there are no other instructions to issue in this cycle .


"SPARC DAG->DAG Pattern Instruction Selection"

getPassName - Return a nice clean name for a pass .


<s>
MachineBasicBlock
::
iterator
AArch64InstrInfo
::
insertOutlinedCall
(
Module
&
M
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
&
It
,
MachineFunction
&
MF
,
const
outliner
::
Candidate
&
C
)
const
{
if
(
C
.
CallConstructionID
==
MachineOutlinerTailCall
)
{
It
=
MBB
.
insert
(
It
,
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
AArch64
::
TCRETURNdi
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
.
addImm
(
0
)
)
;
return
It
;
}
if
(
C
.
CallConstructionID
==
MachineOutlinerNoLRSave
||
C
.
CallConstructionID
==
MachineOutlinerThunk
)
{
It
=
MBB
.
insert
(
It
,
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
AArch64
::
BL
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
)
;
return
It
;
}
MachineBasicBlock
::
iterator
CallPt
;
MachineInstr
*
Save
;
MachineInstr
*
Restore
;
if
(
C
.
CallConstructionID
==
MachineOutlinerRegSave
)
{
unsigned
Reg
=
findRegisterToSaveLRTo
(
C
)
;
assert
(
Reg
!=
0
&&
"No callee-saved register available?"
)
;
Save
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
AArch64
::
ORRXrs
)
,
Reg
)
.
addReg
(
AArch64
::
XZR
)
.
addReg
(
AArch64
::
LR
)
.
addImm
(
0
)
;
Restore
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
AArch64
::
ORRXrs
)
,
AArch64
::
LR
)
.
addReg
(
AArch64
::
XZR
)
.
addReg
(
Reg
)
.
addImm
(
0
)
;
}
else
{
Save
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
AArch64
::
STRXpre
)
)
.
addReg
(
AArch64
::
SP
,
RegState
::
Define
)
.
addReg
(
AArch64
::
LR
)
.
addReg
(
AArch64
::
SP
)
.
addImm
(
16
)
;
Restore
=
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
AArch64
::
LDRXpost
)
)
.
addReg
(
AArch64
::
SP
,
RegState
::
Define
)
.
addReg
(
AArch64
::
LR
,
RegState
::
Define
)
.
addReg
(
AArch64
::
SP
)
.
addImm
(
16
)
;
}
It
=
MBB
.
insert
(
It
,
Save
)
;
It
++
;
It
=
MBB
.
insert
(
It
,
BuildMI
(
MF
,
DebugLoc
(
)
,
get
(
AArch64
::
BL
)
)
.
addGlobalAddress
(
M
.
getNamedValue
(
MF
.
getName
(
)
)
)
)
;
CallPt
=
It
;
It
++
;
It
=
MBB
.
insert
(
It
,
Restore
)
;
return
CallPt
;
}
</s>

Insert a call to an outlined function into the program .


<s>
const
char
*
output_v9branch
(
rtx
op
,
rtx
dest
,
int
reg
,
int
label
,
int
reversed
,
int
annul
,
rtx
insn
)
{
static
char
string
[
64
]
;
enum
rtx_code
code
=
GET_CODE
(
op
)
;
enum
machine_mode
mode
=
GET_MODE
(
XEXP
(
op
,
0
)
)
;
rtx
note
;
int
far
;
char
*
p
;
far
=
get_attr_length
(
insn
)
>=
3
;
if
(
reversed
^
far
)
code
=
reverse_condition
(
code
)
;
gcc_assert
(
mode
==
DImode
)
;
switch
(
code
)
{
case
NE
:
strcpy
(
string
,
"brnz"
)
;
break
;
case
EQ
:
strcpy
(
string
,
"brz"
)
;
break
;
case
GE
:
strcpy
(
string
,
"brgez"
)
;
break
;
case
LT
:
strcpy
(
string
,
"brlz"
)
;
break
;
case
LE
:
strcpy
(
string
,
"brlez"
)
;
break
;
case
GT
:
strcpy
(
string
,
"brgz"
)
;
break
;
default
:
gcc_unreachable
(
)
;
}
p
=
strchr
(
string
,
'\0'
)
;
if
(
annul
&&
!
far
)
{
strcpy
(
p
,
",a"
)
;
p
+=
2
;
}
if
(
insn
&&
(
note
=
find_reg_note
(
insn
,
REG_BR_PROB
,
NULL_RTX
)
)
)
{
strcpy
(
p
,
(
(
INTVAL
(
XEXP
(
note
,
0
)
)
>=
REG_BR_PROB_BASE
/
2
)
^
far
)
",pt"
:
",pn"
)
;
p
+=
3
;
}
*
p
=
p
<
string
+
8
'\t'
:
' '
;
p
++
;
*
p
++
=
'%'
;
*
p
++
=
'0'
+
reg
;
*
p
++
=
','
;
*
p
++
=
' '
;
if
(
far
)
{
int
veryfar
=
1
,
delta
;
if
(
INSN_ADDRESSES_SET_P
(
)
)
{
delta
=
(
INSN_ADDRESSES
(
INSN_UID
(
dest
)
)
INSN_ADDRESSES
(
INSN_UID
(
insn
)
)
)
;
if
(
delta
>=
260000
&&
delta
<
260000
)
veryfar
=
0
;
}
strcpy
(
p
,
".+12\n\t nop\n\t"
)
;
if
(
annul
||
!
final_sequence
)
p
[
3
]
=
'6'
;
p
+=
12
;
if
(
veryfar
)
{
strcpy
(
p
,
"b\t"
)
;
p
+=
2
;
}
else
{
strcpy
(
p
,
"ba,pt\t%%xcc, "
)
;
p
+=
13
;
}
}
*
p
++
=
'%'
;
*
p
++
=
'l'
;
*
p
++
=
'0'
+
label
;
*
p
++
=
'%'
;
*
p
++
=
'#'
;
*
p
=
'\0'
;
return
string
;
}
</s>

Return the string to output a conditional branch to LABEL , testing register REG . LABEL is the operand number of the label ; REG is the operand number of the reg . OP is the conditional expression . The mode of REG says what kind of comparison we made . REVERSED is non-zero if we should reverse the sense of the comparison . ANNUL is non-zero if we should generate an annulling branch . NOOP is non-zero if we have to follow this branch by a noop .


<s> void FixupLEAPass :: processInstruction ( MachineBasicBlock :: iterator & I , MachineFunction :: iterator MFI ) { MachineInstr * MI = I ; int opcode = MI -> getOpcode ( ) ; const MCInstrDesc & Desc = MI -> getDesc ( ) ; int AddrOffset = X86II :: getMemoryOperandNo ( Desc . TSFlags , opcode ) ; if ( AddrOffset >= 0 ) { AddrOffset += X86II :: getOperandBias ( Desc ) ; MachineOperand & p = MI -> getOperand ( AddrOffset + X86 :: AddrBaseReg ) ; if ( p . isReg ( ) && p . getReg ( ) != X86 :: ESP ) { seekLEAFixup ( p , I , MFI ) ; } MachineOperand & q = MI -> getOperand ( AddrOffset + X86 :: AddrIndexReg ) ; if ( q . isReg ( ) && q . getReg ( ) != X86 :: ESP ) { seekLEAFixup ( q , I , MFI ) ; } } } </s>

Process a single instruction and collect debug info anchors .


<s> static bool arm_const_not_ok_for_debug_p ( rtx p ) { tree decl_op0 = NULL ; tree decl_op1 = NULL ; if ( GET_CODE ( p ) == MINUS ) { if ( GET_CODE ( XEXP ( p , 1 ) ) == SYMBOL_REF ) { decl_op1 = SYMBOL_REF_DECL ( XEXP ( p , 1 ) ) ; if ( decl_op1 && GET_CODE ( XEXP ( p , 0 ) ) == SYMBOL_REF && ( decl_op0 = SYMBOL_REF_DECL ( XEXP ( p , 0 ) ) ) ) { if ( ( VAR_P ( decl_op1 ) || TREE_CODE ( decl_op1 ) == CONST_DECL ) && ( VAR_P ( decl_op0 ) || TREE_CODE ( decl_op0 ) == CONST_DECL ) ) return ( get_variable_section ( decl_op1 , false ) != get_variable_section ( decl_op0 , false ) ) ; if ( TREE_CODE ( decl_op1 ) == LABEL_DECL && TREE_CODE ( decl_op0 ) == LABEL_DECL ) return ( DECL_CONTEXT ( decl_op1 ) != DECL_CONTEXT ( decl_op0 ) ) ; } return true ; } } return false ; } </s>

This is a temporary fix for PR60655 . Ideally we need to handle most of these cases in the generic part but currently we reject minus ( .. ) ( sym_ref ) . We try to ameliorate the case with minus ( sym_ref1 ) ( sym_ref2 ) where they are in the same section .


<s> bool X86InstrInfo :: areLoadsFromSameBasePtr ( SDNode * Load1 , SDNode * Load2 , int64_t & Offset1 , int64_t & Offset2 ) const { if ( ! Load1 -> isMachineOpcode ( ) || ! Load2 -> isMachineOpcode ( ) ) return false ; unsigned Opc1 = Load1 -> getMachineOpcode ( ) ; unsigned Opc2 = Load2 -> getMachineOpcode ( ) ; switch ( Opc1 ) { default : return false ; case X86 :: MOV8rm : case X86 :: MOV16rm : case X86 :: MOV32rm : case X86 :: MOV64rm : case X86 :: LD_Fp32m : case X86 :: LD_Fp64m : case X86 :: LD_Fp80m : case X86 :: MOVSSrm : case X86 :: MOVSDrm : case X86 :: MMX_MOVD64rm : case X86 :: MMX_MOVQ64rm : case X86 :: FsMOVAPSrm : case X86 :: FsMOVAPDrm : case X86 :: MOVAPSrm : case X86 :: MOVUPSrm : case X86 :: MOVUPSrm_Int : case X86 :: MOVAPDrm : case X86 :: MOVDQArm : case X86 :: MOVDQUrm : case X86 :: MOVDQUrm_Int : break ; } switch ( Opc2 ) { default : return false ; case X86 :: MOV8rm : case X86 :: MOV16rm : case X86 :: MOV32rm : case X86 :: MOV64rm : case X86 :: LD_Fp32m : case X86 :: LD_Fp64m : case X86 :: LD_Fp80m : case X86 :: MOVSSrm : case X86 :: MOVSDrm : case X86 :: MMX_MOVD64rm : case X86 :: MMX_MOVQ64rm : case X86 :: FsMOVAPSrm : case X86 :: FsMOVAPDrm : case X86 :: MOVAPSrm : case X86 :: MOVUPSrm : case X86 :: MOVUPSrm_Int : case X86 :: MOVAPDrm : case X86 :: MOVDQArm : case X86 :: MOVDQUrm : case X86 :: MOVDQUrm_Int : break ; } if ( Load1 -> getOperand ( 0 ) != Load2 -> getOperand ( 0 ) || Load1 -> getOperand ( 5 ) != Load2 -> getOperand ( 5 ) ) return false ; if ( Load1 -> getOperand ( 4 ) != Load2 -> getOperand ( 4 ) ) return false ; if ( Load1 -> getOperand ( 1 ) == Load2 -> getOperand ( 1 ) && Load1 -> getOperand ( 2 ) == Load2 -> getOperand ( 2 ) ) { if ( cast < ConstantSDNode > ( Load1 -> getOperand ( 1 ) ) -> getZExtValue ( ) != 1 ) return false ; SDValue Op2 = Load1 -> getOperand ( 2 ) ; if ( ! isa < RegisterSDNode > ( Op2 ) || cast < RegisterSDNode > ( Op2 ) -> getReg ( ) != 0 ) return 0 ; if ( isa < ConstantSDNode > ( Load1 -> getOperand ( 3 ) ) && isa < ConstantSDNode > ( Load2 -> getOperand ( 3 ) ) ) { Offset1 = cast < ConstantSDNode > ( Load1 -> getOperand ( 3 ) ) -> getSExtValue ( ) ; Offset2 = cast < ConstantSDNode > ( Load2 -> getOperand ( 3 ) ) -> getSExtValue ( ) ; return true ; } } return false ; } </s>

areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to determine if two loads are loading from the same base address .


<s> void Finish ( ) { const size_t ContentsSize = Contents . size ( ) ; const size_t VendorHeaderSize = 4 + CurrentVendor . size ( ) + 1 ; const size_t TagHeaderSize = 1 + 4 ; Streamer . EmitIntValue ( VendorHeaderSize + TagHeaderSize + ContentsSize , 4 ) ; Streamer . EmitBytes ( CurrentVendor , 0 ) ; Streamer . EmitIntValue ( 0 , 1 ) ; Streamer . EmitIntValue ( ARMBuildAttrs :: File , 1 ) ; Streamer . EmitIntValue ( TagHeaderSize + ContentsSize , 4 ) ; Streamer . EmitBytes ( Contents , 0 ) ; Contents . clear ( ) ; } </s>

Finish - Do final processing and write the object to the output stream .


<s> bool sh_vector_mode_supported_p ( machine_mode mode ) { if ( TARGET_SHMEDIA_FPU && ( ( mode == V2SFmode ) || ( mode == V4SFmode ) || ( mode == V16SFmode ) ) ) return true ; else if ( TARGET_SHMEDIA && ( ( mode == V8QImode ) || ( mode == V2HImode ) || ( mode == V4HImode ) || ( mode == V2SImode ) ) ) return true ; return false ; } </s>

Implements target hook vector_mode_supported_p .


<s> BitVector DLXRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { BitVector Reserved ( getNumRegs ( ) ) ; Reserved . set ( DLX :: RA ) ; Reserved . set ( DLX :: FP ) ; Reserved . set ( DLX :: SP ) ; if ( hasBasePointer ( MF ) ) Reserved . set ( getBaseRegister ( ) ) ; return Reserved ; } </s>

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


<s>
void
X86AsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
,
const
MCSubtargetInfo
*
STI
)
const
{
unsigned
Size
=
getFixupKindSize
(
Fixup
.
getKind
(
)
)
;
assert
(
Fixup
.
getOffset
(
)
+
Size
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
int64_t
SignedValue
=
static_cast
<
int64_t
>
(
Value
)
;
if
(
(
Target
.
isAbsolute
(
)
||
IsResolved
)
&&
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
.
Flags
&
MCFixupKindInfo
::
FKF_IsPCRel
)
{
if
(
Size
>
0
&&
!
isIntN
(
Size
*
8
,
SignedValue
)
)
Asm
.
getContext
(
)
.
reportError
(
Fixup
.
getLoc
(
)
,
"value of "
+
Twine
(
SignedValue
)
+
" is too large for field of "
+
Twine
(
Size
)
+
(
(
Size
==
1
)
" byte."
:
" bytes."
)
)
;
}
else
{
assert
(
(
Size
==
0
||
isIntN
(
Size
*
8
+
1
,
SignedValue
)
)
&&
"Value does not fit in the Fixup field"
)
;
}
for
(
unsigned
i
=
0
;
i
!=
Size
;
++
i
)
Data
[
Fixup
.
getOffset
(
)
+
i
]
=
uint8_t
(
Value
>>
(
i
*
8
)
)
;
}
</s>


<s>
static
void
ix86_avoid_jump_mispredicts
(
void
)
{
rtx_insn
*
insn
,
*
start
=
get_insns
(
)
;
int
nbytes
=
0
,
njumps
=
0
;
bool
isjump
=
false
;
for
(
insn
=
start
;
insn
;
insn
=
NEXT_INSN
(
insn
)
)
{
int
min_size
;
if
(
LABEL_P
(
insn
)
)
{
int
align
=
label_to_alignment
(
insn
)
;
int
max_skip
=
label_to_max_skip
(
insn
)
;
if
(
max_skip
>
15
)
max_skip
=
15
;
if
(
align
<=
0
||
(
align
<=
3
&&
max_skip
!=
(
1
<<
align
)
1
)
)
max_skip
=
0
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Label %i with max_skip %i\n"
,
INSN_UID
(
insn
)
,
max_skip
)
;
if
(
max_skip
)
{
while
(
nbytes
+
max_skip
>=
16
)
{
start
=
NEXT_INSN
(
start
)
;
if
(
(
JUMP_P
(
start
)
&&
asm_noperands
(
PATTERN
(
start
)
)
<
0
)
||
CALL_P
(
start
)
)
njumps
,
isjump
=
true
;
else
isjump
=
false
;
nbytes
-=
min_insn_size
(
start
)
;
}
}
continue
;
}
min_size
=
min_insn_size
(
insn
)
;
nbytes
+=
min_size
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Insn %i estimated to %i bytes\n"
,
INSN_UID
(
insn
)
,
min_size
)
;
if
(
(
JUMP_P
(
insn
)
&&
asm_noperands
(
PATTERN
(
insn
)
)
<
0
)
||
CALL_P
(
insn
)
)
njumps
++
;
else
continue
;
while
(
njumps
>
3
)
{
start
=
NEXT_INSN
(
start
)
;
if
(
(
JUMP_P
(
start
)
&&
asm_noperands
(
PATTERN
(
start
)
)
<
0
)
||
CALL_P
(
start
)
)
njumps
,
isjump
=
true
;
else
isjump
=
false
;
nbytes
-=
min_insn_size
(
start
)
;
}
gcc_assert
(
njumps
>=
0
)
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Interval %i to %i has %i bytes\n"
,
INSN_UID
(
start
)
,
INSN_UID
(
insn
)
,
nbytes
)
;
if
(
njumps
==
3
&&
isjump
&&
nbytes
<
16
)
{
int
padsize
=
15
nbytes
+
min_insn_size
(
insn
)
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Padding insn %i by %i bytes!\n"
,
INSN_UID
(
insn
)
,
padsize
)
;
emit_insn_before
(
gen_pad
(
GEN_INT
(
padsize
)
)
,
insn
)
;
}
}
}
</s>

AMD K8 core mispredicts jumps when there are more than 3 jumps in 16 byte window .


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

Does the system support unaligned memory access .


<s> bool runOnFunction ( Function & F ) override { if ( ! X86ScalarizeAMX ) return false ; TargetMachine * TM = & getAnalysis < TargetPassConfig > ( ) . getTM < TargetMachine > ( ) ; if ( ! F . hasFnAttribute ( Attribute :: OptimizeNone ) && TM -> getOptLevel ( ) != CodeGenOpt :: None ) return false ; auto * DTWP = getAnalysisIfAvailable < DominatorTreeWrapperPass > ( ) ; auto * DT = DTWP ? & DTWP -> getDomTree ( ) : nullptr ; auto * LIWP = getAnalysisIfAvailable < LoopInfoWrapperPass > ( ) ; auto * LI = LIWP ? & LIWP -> getLoopInfo ( ) : nullptr ; DomTreeUpdater DTU ( DT , DomTreeUpdater :: UpdateStrategy :: Lazy ) ; X86LowerAMXIntrinsics LAT ( F , DTU , LI ) ; return LAT . visit ( ) ; } </s>

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


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

Return true if complex patterns for this target can mutate the DAG .


"Constant Island pass failed to converge!"

"Branch Fix Up pass failed to converge!"

runOnMachineFunction - Emit the function body .


<s> void PPCAIXAsmPrinter :: SetupMachineFunction ( MachineFunction & MF ) { MCSectionXCOFF * FnDescSec = cast < MCSectionXCOFF > ( getObjFileLowering ( ) . getSectionForFunctionDescriptor ( & MF . getFunction ( ) , TM ) ) ; FnDescSec -> setAlignment ( Align ( Subtarget -> isPPC64 ( ) ? 8 : 4 ) ) ; CurrentFnDescSym = FnDescSec -> getQualNameSymbol ( ) ; return AsmPrinter :: SetupMachineFunction ( MF ) ; } </s>

This should be called when a new MachineFunction is being processed from runOnMachineFunction .


<s>
bool
X86InstrInfo
::
isReallyTriviallyReMaterializable
(
const
MachineInstr
*
MI
,
AliasAnalysis
*
AA
)
const
{
switch
(
MI
->
getOpcode
(
)
)
{
default
:
break
;
case
X86
::
MOV8rm
:
case
X86
::
MOV16rm
:
case
X86
::
MOV32rm
:
case
X86
::
MOV64rm
:
case
X86
::
LD_Fp64m
:
case
X86
::
MOVSSrm
:
case
X86
::
MOVSDrm
:
case
X86
::
MOVAPSrm
:
case
X86
::
MOVUPSrm
:
case
X86
::
MOVUPSrm_Int
:
case
X86
::
MOVAPDrm
:
case
X86
::
MOVDQArm
:
case
X86
::
MMX_MOVD64rm
:
case
X86
::
MMX_MOVQ64rm
:
case
X86
::
FsMOVAPSrm
:
case
X86
::
FsMOVAPDrm
:
{
if
(
MI
->
getOperand
(
1
)
.
isReg
(
)
&&
MI
->
getOperand
(
2
)
.
isImm
(
)
&&
MI
->
getOperand
(
3
)
.
isReg
(
)
&&
MI
->
getOperand
(
3
)
.
getReg
(
)
==
0
&&
MI
->
isInvariantLoad
(
AA
)
)
{
unsigned
BaseReg
=
MI
->
getOperand
(
1
)
.
getReg
(
)
;
if
(
BaseReg
==
0
||
BaseReg
==
X86
::
RIP
)
return
true
;
if
(
!
ReMatPICStubLoad
&&
MI
->
getOperand
(
4
)
.
isGlobal
(
)
)
return
false
;
const
MachineFunction
&
MF
=
*
MI
->
getParent
(
)
->
getParent
(
)
;
const
MachineRegisterInfo
&
MRI
=
MF
.
getRegInfo
(
)
;
bool
isPICBase
=
false
;
for
(
MachineRegisterInfo
::
def_iterator
I
=
MRI
.
def_begin
(
BaseReg
)
,
E
=
MRI
.
def_end
(
)
;
I
!=
E
;
++
I
)
{
MachineInstr
*
DefMI
=
I
.
getOperand
(
)
.
getParent
(
)
;
if
(
DefMI
->
getOpcode
(
)
!=
X86
::
MOVPC32r
)
return
false
;
assert
(
!
isPICBase
&&
"More than one PIC base?"
)
;
isPICBase
=
true
;
}
return
isPICBase
;
}
return
false
;
}
case
X86
::
LEA32r
:
case
X86
::
LEA64r
:
{
if
(
MI
->
getOperand
(
2
)
.
isImm
(
)
&&
MI
->
getOperand
(
3
)
.
isReg
(
)
&&
MI
->
getOperand
(
3
)
.
getReg
(
)
==
0
&&
!
MI
->
getOperand
(
4
)
.
isReg
(
)
)
{
if
(
!
MI
->
getOperand
(
1
)
.
isReg
(
)
)
return
true
;
unsigned
BaseReg
=
MI
->
getOperand
(
1
)
.
getReg
(
)
;
if
(
BaseReg
==
0
)
return
true
;
const
MachineFunction
&
MF
=
*
MI
->
getParent
(
)
->
getParent
(
)
;
const
MachineRegisterInfo
&
MRI
=
MF
.
getRegInfo
(
)
;
return
regIsPICBase
(
BaseReg
,
MRI
)
;
}
return
false
;
}
}
return
true
;
}
</s>

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


<s> bool X86RegisterInfo :: hasFP ( const MachineFunction & MF ) const { const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; const MachineModuleInfo & MMI = MF . getMMI ( ) ; return ( NoFramePointerElim || needsStackRealignment ( MF ) || MFI -> hasVarSizedObjects ( ) || MFI -> isFrameAddressTaken ( ) || MF . getInfo < X86MachineFunctionInfo > ( ) -> getForceFramePointer ( ) || MMI . callsUnwindInit ( ) ) ; } </s>

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


<s> bool enableIndirectBrExpand ( ) const override { return useIndirectThunkBranches ( ) ; } </s>

If we are using indirect thunks , we need to expand indirectbr to avoid it lowering to an actual indirect jump .


<s> static void aarch64_save_callee_saves ( machine_mode mode , HOST_WIDE_INT start_offset , unsigned start , unsigned limit , bool skip_wb ) { rtx_insn * insn ; rtx ( * gen_mem_ref ) ( machine_mode , rtx ) = ( frame_pointer_needed ? gen_frame_mem : gen_rtx_MEM ) ; unsigned regno ; unsigned regno2 ; for ( regno = aarch64_next_callee_save ( start , limit ) ; regno <= limit ; regno = aarch64_next_callee_save ( regno + 1 , limit ) ) { rtx reg , mem ; HOST_WIDE_INT offset ; if ( skip_wb && ( regno == cfun -> machine -> frame . wb_candidate1 || regno == cfun -> machine -> frame . wb_candidate2 ) ) continue ; if ( cfun -> machine -> reg_is_wrapped_separately [ regno ] ) continue ; reg = gen_rtx_REG ( mode , regno ) ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno ] ; mem = gen_mem_ref ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; regno2 = aarch64_next_callee_save ( regno + 1 , limit ) ; if ( regno2 <= limit && ! cfun -> machine -> reg_is_wrapped_separately [ regno2 ] && ( ( cfun -> machine -> frame . reg_offset [ regno ] + UNITS_PER_WORD ) == cfun -> machine -> frame . reg_offset [ regno2 ] ) ) { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; rtx mem2 ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno2 ] ; mem2 = gen_mem_ref ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; insn = emit_insn ( aarch64_gen_store_pair ( mode , mem , reg , mem2 , reg2 ) ) ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 1 ) ) = 1 ; regno = regno2 ; } else insn = emit_move_insn ( mem , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Emit code to save the callee-saved registers from register number START to LIMIT to the stack at the location starting at offset START_OFFSET , skipping any write-back candidates if SKIP_WB is true .


<s> TOYSubtarget & TOYSubtarget :: initializeSubtargetDependencies ( StringRef CPU , StringRef FS , bool Is64Bit = false ) { std :: string CPUName = CPU ; if ( CPUName . empty ( ) ) CPUName = Is64Bit ? "generic-rv64" : "generic-rv32" ; ParseSubtargetFeatures ( CPUName , FS ) ; return * this ; } </s>

initializeSubtargetDependencies - Initializes using a CPU , a TuneCPU , and feature string so that we can use initializer lists for subtarget initialization .


<s> static int ix86_mode_after ( int entity , int mode , rtx_insn * insn ) { switch ( entity ) { case X86_DIRFLAG : return mode ; case AVX_U128 : return ix86_avx_u128_mode_after ( mode , insn ) ; case I387_TRUNC : case I387_FLOOR : case I387_CEIL : case I387_MASK_PM : return mode ; default : gcc_unreachable ( ) ; } } </s>

Return the mode that an insn results in .


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

getPassName - Return a nice clean name for a pass .


Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS . The register allocator chooses GEN_OR_VSX_REGS for the allocno class if GENERAL_REGS and VSX_REGS cost is lower than the memory cost . This happens a lot when TARGET_DIRECT_MOVE makes the register move cost between GENERAL_REGS and VSX_REGS low . It might seem reasonable to use a union class . After all , if usage of vsr is low and gpr high , it might make sense to spill gpr to vsr rather than memory . However , in cases where register pressure of both is high , like the cactus_adm spec test , allowing GEN_OR_VSX_REGS as the allocno class results in bad decisions in the first scheduling pass . This is partly due to an allocno of GEN_OR_VSX_REGS wrongly contributing to the GENERAL_REGS pressure class , which gives too high a pressure for GENERAL_REGS and too low for VSX_REGS . So , force a choice of the subclass here . The best class is also the union if GENERAL_REGS and VSX_REGS have the same cost . In that case we do use GEN_OR_VSX_REGS as the allocno class , since trying to narrow down the class by regno mode is prone to error . For example , SImode is allowed in VSX regs and in some cases ( eg . gcc.target/powerpc/p9-xxbr-3.c do_bswap32_vect ) it would be wrong to choose an allocno of GENERAL_REGS based on SImode .


<s> void DLXInstrInfo :: loadRegFromStackSlot ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator Position , unsigned DestinationRegister , int FrameIndex , const TargetRegisterClass * RegisterClass , const TargetRegisterInfo * RegisterInfo ) const { } </s>

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


<s> std :: unique_ptr < CSEConfigBase > X86PassConfig :: getCSEConfig ( ) const { return getStandardCSEConfigForOpt ( TM -> getOptLevel ( ) ) ; } </s>

Returns the CSEConfig object to use for the current optimization level .


Expand a builtin . These builtins are `` special '' because they do n't have symbolic constants defined per-instruction or per instruction-variant . Instead , the required info is looked up in the ARM_BUILTIN_DATA record that is passed into the function .