mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
AArch64/ARM64: expunge CPSR from the sources
AArch64 does not have a CPSR register in the same way that AArch32 does. Most of its compiler-relevant roles have been taken over by the more specific NZCV register (representing just the flags set by normal instructions). Its system control functions still remain, but are now under the pseudo-register referred to as "PSTATE". They're accessed via various MRS & MSR instructions described in the reference manual. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207645 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d805bf8d61
commit
36c7472106
@ -63,8 +63,8 @@ STATISTIC(NumCmpBranchRejs, "Number of ccmps rejected (CmpBB branch)");
|
||||
STATISTIC(NumCmpTermRejs, "Number of ccmps rejected (CmpBB is cbz...)");
|
||||
STATISTIC(NumImmRangeRejs, "Number of ccmps rejected (Imm out of range)");
|
||||
STATISTIC(NumLiveDstRejs, "Number of ccmps rejected (Cmp dest live)");
|
||||
STATISTIC(NumMultCPSRUses, "Number of ccmps rejected (CPSR used)");
|
||||
STATISTIC(NumUnknCPSRDefs, "Number of ccmps rejected (CPSR def unknown)");
|
||||
STATISTIC(NumMultNZCVUses, "Number of ccmps rejected (NZCV used)");
|
||||
STATISTIC(NumUnknNZCVDefs, "Number of ccmps rejected (NZCV def unknown)");
|
||||
|
||||
STATISTIC(NumSpeculateRejs, "Number of ccmps rejected (Can't speculate)");
|
||||
|
||||
@ -300,7 +300,7 @@ MachineInstr *SSACCmpConv::findConvertibleCompare(MachineBasicBlock *MBB) {
|
||||
if (I == MBB->end())
|
||||
return nullptr;
|
||||
// The terminator must be controlled by the flags.
|
||||
if (!I->readsRegister(ARM64::CPSR)) {
|
||||
if (!I->readsRegister(ARM64::NZCV)) {
|
||||
switch (I->getOpcode()) {
|
||||
case ARM64::CBZW:
|
||||
case ARM64::CBZX:
|
||||
@ -351,20 +351,20 @@ MachineInstr *SSACCmpConv::findConvertibleCompare(MachineBasicBlock *MBB) {
|
||||
|
||||
// Check for flag reads and clobbers.
|
||||
MIOperands::PhysRegInfo PRI =
|
||||
MIOperands(I).analyzePhysReg(ARM64::CPSR, TRI);
|
||||
MIOperands(I).analyzePhysReg(ARM64::NZCV, TRI);
|
||||
|
||||
if (PRI.Reads) {
|
||||
// The ccmp doesn't produce exactly the same flags as the original
|
||||
// compare, so reject the transform if there are uses of the flags
|
||||
// besides the terminators.
|
||||
DEBUG(dbgs() << "Can't create ccmp with multiple uses: " << *I);
|
||||
++NumMultCPSRUses;
|
||||
++NumMultNZCVUses;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (PRI.Clobbers) {
|
||||
DEBUG(dbgs() << "Not convertible compare: " << *I);
|
||||
++NumUnknCPSRDefs;
|
||||
++NumUnknNZCVDefs;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -379,7 +379,7 @@ MachineInstr *SSACCmpConv::findConvertibleCompare(MachineBasicBlock *MBB) {
|
||||
///
|
||||
bool SSACCmpConv::canSpeculateInstrs(MachineBasicBlock *MBB,
|
||||
const MachineInstr *CmpMI) {
|
||||
// Reject any live-in physregs. It's probably CPSR/EFLAGS, and very hard to
|
||||
// Reject any live-in physregs. It's probably NZCV/EFLAGS, and very hard to
|
||||
// get right.
|
||||
if (!MBB->livein_empty()) {
|
||||
DEBUG(dbgs() << "BB#" << MBB->getNumber() << " has live-ins.\n");
|
||||
@ -422,7 +422,7 @@ bool SSACCmpConv::canSpeculateInstrs(MachineBasicBlock *MBB,
|
||||
}
|
||||
|
||||
// Only CmpMI is allowed to clobber the flags.
|
||||
if (&I != CmpMI && I.modifiesRegister(ARM64::CPSR, TRI)) {
|
||||
if (&I != CmpMI && I.modifiesRegister(ARM64::NZCV, TRI)) {
|
||||
DEBUG(dbgs() << "Clobbers flags: " << I);
|
||||
return false;
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ ARM64TargetLowering::ARM64TargetLowering(ARM64TargetMachine &TM)
|
||||
// BlockAddress
|
||||
setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
|
||||
|
||||
// Add/Sub overflow ops with MVT::Glues are lowered to CPSR dependences.
|
||||
// Add/Sub overflow ops with MVT::Glues are lowered to NZCV dependences.
|
||||
setOperationAction(ISD::ADDC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::ADDE, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SUBC, MVT::i32, Custom);
|
||||
@ -738,7 +738,7 @@ ARM64TargetLowering::EmitF128CSEL(MachineInstr *MI,
|
||||
unsigned IfTrueReg = MI->getOperand(1).getReg();
|
||||
unsigned IfFalseReg = MI->getOperand(2).getReg();
|
||||
unsigned CondCode = MI->getOperand(3).getImm();
|
||||
bool CPSRKilled = MI->getOperand(4).isKill();
|
||||
bool NZCVKilled = MI->getOperand(4).isKill();
|
||||
|
||||
MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(LLVM_BB);
|
||||
MachineBasicBlock *EndBB = MF->CreateMachineBasicBlock(LLVM_BB);
|
||||
@ -758,9 +758,9 @@ ARM64TargetLowering::EmitF128CSEL(MachineInstr *MI,
|
||||
// TrueBB falls through to the end.
|
||||
TrueBB->addSuccessor(EndBB);
|
||||
|
||||
if (!CPSRKilled) {
|
||||
TrueBB->addLiveIn(ARM64::CPSR);
|
||||
EndBB->addLiveIn(ARM64::CPSR);
|
||||
if (!NZCVKilled) {
|
||||
TrueBB->addLiveIn(ARM64::NZCV);
|
||||
EndBB->addLiveIn(ARM64::NZCV);
|
||||
}
|
||||
|
||||
BuildMI(*EndBB, EndBB->begin(), DL, TII->get(ARM64::PHI), DestReg)
|
||||
@ -2350,7 +2350,7 @@ ARM64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
|
||||
MFI->setAdjustsStack(true);
|
||||
|
||||
// TLS calls preserve all registers except those that absolutely must be
|
||||
// trashed: X0 (it takes an argument), LR (it's a call) and CPSR (let's not be
|
||||
// trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
|
||||
// silly).
|
||||
const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo();
|
||||
const ARM64RegisterInfo *ARI = static_cast<const ARM64RegisterInfo *>(TRI);
|
||||
@ -2371,7 +2371,7 @@ ARM64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
|
||||
/// have a descriptor, accessible via a PC-relative ADRP, and whose first entry
|
||||
/// is a function pointer to carry out the resolution. This function takes the
|
||||
/// address of the descriptor in X0 and returns the TPIDR_EL0 offset in X0. All
|
||||
/// other registers (except LR, CPSR) are preserved.
|
||||
/// other registers (except LR, NZCV) are preserved.
|
||||
///
|
||||
/// Thus, the ideal call sequence on AArch64 is:
|
||||
///
|
||||
@ -2398,7 +2398,7 @@ SDValue ARM64TargetLowering::LowerELFTLSDescCall(SDValue SymAddr,
|
||||
SDValue Func = DAG.getNode(ARM64ISD::LOADgot, DL, PtrVT, SymAddr);
|
||||
|
||||
// TLS calls preserve all registers except those that absolutely must be
|
||||
// trashed: X0 (it takes an argument), LR (it's a call) and CPSR (let's not be
|
||||
// trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
|
||||
// silly).
|
||||
const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo();
|
||||
const ARM64RegisterInfo *ARI = static_cast<const ARM64RegisterInfo *>(TRI);
|
||||
@ -3602,7 +3602,7 @@ ARM64TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
}
|
||||
}
|
||||
if (StringRef("{cc}").equals_lower(Constraint))
|
||||
return std::make_pair(unsigned(ARM64::CPSR), &ARM64::CCRRegClass);
|
||||
return std::make_pair(unsigned(ARM64::NZCV), &ARM64::CCRRegClass);
|
||||
|
||||
// Use the default implementation in TargetLowering to convert the register
|
||||
// constraint into a member of a register class.
|
||||
|
@ -752,7 +752,7 @@ class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
|
||||
let Inst{19-5} = systemreg;
|
||||
}
|
||||
|
||||
// FIXME: Some of these def CPSR, others don't. Best way to model that?
|
||||
// FIXME: Some of these def NZCV, others don't. Best way to model that?
|
||||
// Explicitly modeling each of the system register as a register class
|
||||
// would do it, but feels like overkill at this point.
|
||||
class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
|
||||
@ -762,28 +762,29 @@ class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
|
||||
let Inst{19-5} = systemreg;
|
||||
}
|
||||
|
||||
def SystemCPSRFieldOperand : AsmOperandClass {
|
||||
let Name = "SystemCPSRField";
|
||||
def SystemPStateFieldOperand : AsmOperandClass {
|
||||
let Name = "SystemPStateField";
|
||||
let ParserMethod = "tryParseSysReg";
|
||||
}
|
||||
def cpsrfield_op : Operand<i32> {
|
||||
let ParserMatchClass = SystemCPSRFieldOperand;
|
||||
let PrintMethod = "printSystemCPSRField";
|
||||
def pstatefield_op : Operand<i32> {
|
||||
let ParserMatchClass = SystemPStateFieldOperand;
|
||||
let PrintMethod = "printSystemPStateField";
|
||||
}
|
||||
|
||||
let Defs = [CPSR] in
|
||||
class MSRcpsrI : SimpleSystemI<0, (ins cpsrfield_op:$cpsr_field, imm0_15:$imm),
|
||||
"msr", "\t$cpsr_field, $imm">,
|
||||
Sched<[WriteSys]> {
|
||||
bits<6> cpsrfield;
|
||||
let Defs = [NZCV] in
|
||||
class MSRpstateI
|
||||
: SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
|
||||
"msr", "\t$pstate_field, $imm">,
|
||||
Sched<[WriteSys]> {
|
||||
bits<6> pstatefield;
|
||||
bits<4> imm;
|
||||
let Inst{20-19} = 0b00;
|
||||
let Inst{18-16} = cpsrfield{5-3};
|
||||
let Inst{18-16} = pstatefield{5-3};
|
||||
let Inst{15-12} = 0b0100;
|
||||
let Inst{11-8} = imm;
|
||||
let Inst{7-5} = cpsrfield{2-0};
|
||||
let Inst{7-5} = pstatefield{2-0};
|
||||
|
||||
let DecoderMethod = "DecodeSystemCPSRInstruction";
|
||||
let DecoderMethod = "DecodeSystemPStateInstruction";
|
||||
}
|
||||
|
||||
// SYS and SYSL generic system instructions.
|
||||
@ -882,11 +883,11 @@ def am_brcond : Operand<OtherVT> {
|
||||
|
||||
class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
|
||||
"b", "$cond\t$target", "",
|
||||
[(ARM64brcond bb:$target, imm:$cond, CPSR)]>,
|
||||
[(ARM64brcond bb:$target, imm:$cond, NZCV)]>,
|
||||
Sched<[WriteBr]> {
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let Uses = [CPSR];
|
||||
let Uses = [NZCV];
|
||||
|
||||
bits<4> cond;
|
||||
bits<19> target;
|
||||
@ -1041,7 +1042,7 @@ class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
|
||||
: I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
|
||||
asm, "\t$Rd, $Rn, $Rm", "", pattern>,
|
||||
Sched<[WriteI]> {
|
||||
let Uses = [CPSR];
|
||||
let Uses = [NZCV];
|
||||
bits<5> Rd;
|
||||
bits<5> Rn;
|
||||
bits<5> Rm;
|
||||
@ -1056,14 +1057,14 @@ class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
|
||||
class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
|
||||
SDNode OpNode>
|
||||
: BaseBaseAddSubCarry<isSub, regtype, asm,
|
||||
[(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR))]>;
|
||||
[(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
|
||||
|
||||
class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
|
||||
SDNode OpNode>
|
||||
: BaseBaseAddSubCarry<isSub, regtype, asm,
|
||||
[(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR)),
|
||||
(implicit CPSR)]> {
|
||||
let Defs = [CPSR];
|
||||
[(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
|
||||
(implicit NZCV)]> {
|
||||
let Defs = [NZCV];
|
||||
}
|
||||
|
||||
multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
|
||||
@ -1522,7 +1523,7 @@ multiclass AddSub<bit isSub, string mnemonic,
|
||||
}
|
||||
|
||||
multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
|
||||
let isCompare = 1, Defs = [CPSR] in {
|
||||
let isCompare = 1, Defs = [NZCV] in {
|
||||
// Add/Subtract immediate
|
||||
def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
|
||||
mnemonic, OpNode> {
|
||||
@ -1565,7 +1566,7 @@ multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
|
||||
let Inst{14-13} = 0b11;
|
||||
let Inst{31} = 1;
|
||||
}
|
||||
} // Defs = [CPSR]
|
||||
} // Defs = [NZCV]
|
||||
|
||||
// Register/register aliases with no shift when SP is not used.
|
||||
def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
|
||||
@ -1770,7 +1771,7 @@ multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
|
||||
}
|
||||
|
||||
multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
|
||||
let isCompare = 1, Defs = [CPSR] in {
|
||||
let isCompare = 1, Defs = [NZCV] in {
|
||||
def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
|
||||
[(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
|
||||
let Inst{31} = 0;
|
||||
@ -1780,7 +1781,7 @@ multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
|
||||
[(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
|
||||
let Inst{31} = 1;
|
||||
}
|
||||
} // end Defs = [CPSR]
|
||||
} // end Defs = [NZCV]
|
||||
}
|
||||
|
||||
class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
|
||||
@ -1811,10 +1812,10 @@ multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
|
||||
!cast<Instruction>(NAME#"Xrs"), GPR64>;
|
||||
}
|
||||
|
||||
// Split from LogicalReg to allow setting CPSR Defs
|
||||
// Split from LogicalReg to allow setting NZCV Defs
|
||||
multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
|
||||
SDPatternOperator OpNode = null_frag> {
|
||||
let Defs = [CPSR], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
|
||||
let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
|
||||
def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
|
||||
def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
|
||||
|
||||
@ -1826,7 +1827,7 @@ multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
|
||||
[(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
|
||||
let Inst{31} = 1;
|
||||
}
|
||||
} // Defs = [CPSR]
|
||||
} // Defs = [NZCV]
|
||||
|
||||
def : LogicalRegAlias<mnemonic,
|
||||
!cast<Instruction>(NAME#"Wrs"), GPR32>;
|
||||
@ -1849,8 +1850,8 @@ class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
|
||||
: I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
|
||||
asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
|
||||
Sched<[WriteI]> {
|
||||
let Uses = [CPSR];
|
||||
let Defs = [CPSR];
|
||||
let Uses = [NZCV];
|
||||
let Defs = [NZCV];
|
||||
|
||||
bits<5> Rn;
|
||||
bits<5> imm;
|
||||
@ -1881,8 +1882,8 @@ class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
|
||||
: I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
|
||||
asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
|
||||
Sched<[WriteI]> {
|
||||
let Uses = [CPSR];
|
||||
let Defs = [CPSR];
|
||||
let Uses = [NZCV];
|
||||
let Defs = [NZCV];
|
||||
|
||||
bits<5> Rn;
|
||||
bits<5> Rm;
|
||||
@ -1916,9 +1917,9 @@ class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
|
||||
: I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
|
||||
asm, "\t$Rd, $Rn, $Rm, $cond", "",
|
||||
[(set regtype:$Rd,
|
||||
(ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), CPSR))]>,
|
||||
(ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
|
||||
Sched<[WriteI]> {
|
||||
let Uses = [CPSR];
|
||||
let Uses = [NZCV];
|
||||
|
||||
bits<5> Rd;
|
||||
bits<5> Rn;
|
||||
@ -1949,9 +1950,9 @@ class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
|
||||
asm, "\t$Rd, $Rn, $Rm, $cond", "",
|
||||
[(set regtype:$Rd,
|
||||
(ARM64csel regtype:$Rn, (frag regtype:$Rm),
|
||||
(i32 imm:$cond), CPSR))]>,
|
||||
(i32 imm:$cond), NZCV))]>,
|
||||
Sched<[WriteI]> {
|
||||
let Uses = [CPSR];
|
||||
let Uses = [NZCV];
|
||||
|
||||
bits<5> Rd;
|
||||
bits<5> Rn;
|
||||
@ -1980,11 +1981,11 @@ multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
|
||||
let Inst{31} = 1;
|
||||
}
|
||||
|
||||
def : Pat<(ARM64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), CPSR),
|
||||
def : Pat<(ARM64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
|
||||
(!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
|
||||
(inv_cond_XFORM imm:$cond))>;
|
||||
|
||||
def : Pat<(ARM64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), CPSR),
|
||||
def : Pat<(ARM64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
|
||||
(!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
|
||||
(inv_cond_XFORM imm:$cond))>;
|
||||
}
|
||||
@ -3610,27 +3611,27 @@ class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
|
||||
|
||||
multiclass FPComparison<bit signalAllNans, string asm,
|
||||
SDPatternOperator OpNode = null_frag> {
|
||||
let Defs = [CPSR] in {
|
||||
let Defs = [NZCV] in {
|
||||
def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
|
||||
[(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
|
||||
[(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
|
||||
let Inst{22} = 0;
|
||||
}
|
||||
|
||||
def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
|
||||
[(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
|
||||
[(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
|
||||
let Inst{22} = 0;
|
||||
}
|
||||
|
||||
def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
|
||||
[(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
|
||||
[(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
|
||||
let Inst{22} = 1;
|
||||
}
|
||||
|
||||
def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
|
||||
[(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
|
||||
[(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
|
||||
let Inst{22} = 1;
|
||||
}
|
||||
} // Defs = [CPSR]
|
||||
} // Defs = [NZCV]
|
||||
}
|
||||
|
||||
//---
|
||||
@ -3659,7 +3660,7 @@ class BaseFPCondComparison<bit signalAllNans,
|
||||
}
|
||||
|
||||
multiclass FPCondComparison<bit signalAllNans, string asm> {
|
||||
let Defs = [CPSR], Uses = [CPSR] in {
|
||||
let Defs = [NZCV], Uses = [NZCV] in {
|
||||
def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
|
||||
let Inst{22} = 0;
|
||||
}
|
||||
@ -3667,7 +3668,7 @@ multiclass FPCondComparison<bit signalAllNans, string asm> {
|
||||
def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
|
||||
let Inst{22} = 1;
|
||||
}
|
||||
} // Defs = [CPSR], Uses = [CPSR]
|
||||
} // Defs = [NZCV], Uses = [NZCV]
|
||||
}
|
||||
|
||||
//---
|
||||
@ -3679,7 +3680,7 @@ class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
|
||||
asm, "\t$Rd, $Rn, $Rm, $cond", "",
|
||||
[(set regtype:$Rd,
|
||||
(ARM64csel (vt regtype:$Rn), regtype:$Rm,
|
||||
(i32 imm:$cond), CPSR))]>,
|
||||
(i32 imm:$cond), NZCV))]>,
|
||||
Sched<[WriteF]> {
|
||||
bits<5> Rd;
|
||||
bits<5> Rn;
|
||||
@ -3696,7 +3697,7 @@ class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
|
||||
}
|
||||
|
||||
multiclass FPCondSelect<string asm> {
|
||||
let Uses = [CPSR] in {
|
||||
let Uses = [NZCV] in {
|
||||
def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
|
||||
let Inst{22} = 0;
|
||||
}
|
||||
@ -3704,7 +3705,7 @@ multiclass FPCondSelect<string asm> {
|
||||
def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
|
||||
let Inst{22} = 1;
|
||||
}
|
||||
} // Uses = [CPSR]
|
||||
} // Uses = [NZCV]
|
||||
}
|
||||
|
||||
//---
|
||||
|
@ -301,8 +301,8 @@ static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
|
||||
switch (DefMI->getOpcode()) {
|
||||
case ARM64::ADDSXri:
|
||||
case ARM64::ADDSWri:
|
||||
// if CPSR is used, do not fold.
|
||||
if (DefMI->findRegisterDefOperandIdx(ARM64::CPSR, true) == -1)
|
||||
// if NZCV is used, do not fold.
|
||||
if (DefMI->findRegisterDefOperandIdx(ARM64::NZCV, true) == -1)
|
||||
return 0;
|
||||
// fall-through to ADDXri and ADDWri.
|
||||
case ARM64::ADDXri:
|
||||
@ -328,8 +328,8 @@ static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
|
||||
|
||||
case ARM64::SUBSXrr:
|
||||
case ARM64::SUBSWrr:
|
||||
// if CPSR is used, do not fold.
|
||||
if (DefMI->findRegisterDefOperandIdx(ARM64::CPSR, true) == -1)
|
||||
// if NZCV is used, do not fold.
|
||||
if (DefMI->findRegisterDefOperandIdx(ARM64::NZCV, true) == -1)
|
||||
return 0;
|
||||
// fall-through to SUBXrr and SUBWrr.
|
||||
case ARM64::SUBXrr:
|
||||
@ -559,7 +559,7 @@ bool ARM64InstrInfo::analyzeCompare(const MachineInstr *MI, unsigned &SrcReg,
|
||||
case ARM64::ADDSXrr:
|
||||
case ARM64::ADDSXrs:
|
||||
case ARM64::ADDSXrx:
|
||||
// Replace SUBSWrr with SUBWrr if CPSR is not used.
|
||||
// Replace SUBSWrr with SUBWrr if NZCV is not used.
|
||||
SrcReg = MI->getOperand(1).getReg();
|
||||
SrcReg2 = MI->getOperand(2).getReg();
|
||||
CmpMask = ~0;
|
||||
@ -635,9 +635,9 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, int CmpMask,
|
||||
int CmpValue, const MachineRegisterInfo *MRI) const {
|
||||
|
||||
// Replace SUBSWrr with SUBWrr if CPSR is not used.
|
||||
int Cmp_CPSR = CmpInstr->findRegisterDefOperandIdx(ARM64::CPSR, true);
|
||||
if (Cmp_CPSR != -1) {
|
||||
// Replace SUBSWrr with SUBWrr if NZCV is not used.
|
||||
int Cmp_NZCV = CmpInstr->findRegisterDefOperandIdx(ARM64::NZCV, true);
|
||||
if (Cmp_NZCV != -1) {
|
||||
unsigned NewOpc;
|
||||
switch (CmpInstr->getOpcode()) {
|
||||
default:
|
||||
@ -662,7 +662,7 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
|
||||
const MCInstrDesc &MCID = get(NewOpc);
|
||||
CmpInstr->setDesc(MCID);
|
||||
CmpInstr->RemoveOperand(Cmp_CPSR);
|
||||
CmpInstr->RemoveOperand(Cmp_NZCV);
|
||||
bool succeeded = UpdateOperandRegClass(CmpInstr);
|
||||
(void)succeeded;
|
||||
assert(succeeded && "Some operands reg class are incompatible!");
|
||||
@ -684,7 +684,7 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
|
||||
// We iterate backward, starting from the instruction before CmpInstr and
|
||||
// stop when reaching the definition of the source register or done with the
|
||||
// basic block, to check whether CPSR is used or modified in between.
|
||||
// basic block, to check whether NZCV is used or modified in between.
|
||||
MachineBasicBlock::iterator I = CmpInstr, E = MI,
|
||||
B = CmpInstr->getParent()->begin();
|
||||
|
||||
@ -697,15 +697,15 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
if (MI->getParent() != CmpInstr->getParent())
|
||||
return false;
|
||||
|
||||
// Check that CPSR isn't set between the comparison instruction and the one we
|
||||
// Check that NZCV isn't set between the comparison instruction and the one we
|
||||
// want to change.
|
||||
const TargetRegisterInfo *TRI = &getRegisterInfo();
|
||||
for (--I; I != E; --I) {
|
||||
const MachineInstr &Instr = *I;
|
||||
|
||||
if (Instr.modifiesRegister(ARM64::CPSR, TRI) ||
|
||||
Instr.readsRegister(ARM64::CPSR, TRI))
|
||||
// This instruction modifies or uses CPSR after the one we want to
|
||||
if (Instr.modifiesRegister(ARM64::NZCV, TRI) ||
|
||||
Instr.readsRegister(ARM64::NZCV, TRI))
|
||||
// This instruction modifies or uses NZCV after the one we want to
|
||||
// change. We can't do this transformation.
|
||||
return false;
|
||||
if (I == B)
|
||||
@ -742,11 +742,11 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
case ARM64::ANDXri: NewOpc = ARM64::ANDSXri; break;
|
||||
}
|
||||
|
||||
// Scan forward for the use of CPSR.
|
||||
// Scan forward for the use of NZCV.
|
||||
// When checking against MI: if it's a conditional code requires
|
||||
// checking of V bit, then this is not safe to do.
|
||||
// It is safe to remove CmpInstr if CPSR is redefined or killed.
|
||||
// If we are done with the basic block, we need to check whether CPSR is
|
||||
// It is safe to remove CmpInstr if NZCV is redefined or killed.
|
||||
// If we are done with the basic block, we need to check whether NZCV is
|
||||
// live-out.
|
||||
bool IsSafe = false;
|
||||
for (MachineBasicBlock::iterator I = CmpInstr,
|
||||
@ -756,11 +756,11 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
for (unsigned IO = 0, EO = Instr.getNumOperands(); !IsSafe && IO != EO;
|
||||
++IO) {
|
||||
const MachineOperand &MO = Instr.getOperand(IO);
|
||||
if (MO.isRegMask() && MO.clobbersPhysReg(ARM64::CPSR)) {
|
||||
if (MO.isRegMask() && MO.clobbersPhysReg(ARM64::NZCV)) {
|
||||
IsSafe = true;
|
||||
break;
|
||||
}
|
||||
if (!MO.isReg() || MO.getReg() != ARM64::CPSR)
|
||||
if (!MO.isReg() || MO.getReg() != ARM64::NZCV)
|
||||
continue;
|
||||
if (MO.isDef()) {
|
||||
IsSafe = true;
|
||||
@ -793,7 +793,7 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
// It is not safe to remove Compare instruction if Overflow(V) is used.
|
||||
switch (CC) {
|
||||
default:
|
||||
// CPSR can be used multiple times, we should continue.
|
||||
// NZCV can be used multiple times, we should continue.
|
||||
break;
|
||||
case ARM64CC::VS:
|
||||
case ARM64CC::VC:
|
||||
@ -806,22 +806,22 @@ bool ARM64InstrInfo::optimizeCompareInstr(
|
||||
}
|
||||
}
|
||||
|
||||
// If CPSR is not killed nor re-defined, we should check whether it is
|
||||
// If NZCV is not killed nor re-defined, we should check whether it is
|
||||
// live-out. If it is live-out, do not optimize.
|
||||
if (!IsSafe) {
|
||||
MachineBasicBlock *ParentBlock = CmpInstr->getParent();
|
||||
for (auto *MBB : ParentBlock->successors())
|
||||
if (MBB->isLiveIn(ARM64::CPSR))
|
||||
if (MBB->isLiveIn(ARM64::NZCV))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the instruction to set CPSR.
|
||||
// Update the instruction to set NZCV.
|
||||
MI->setDesc(get(NewOpc));
|
||||
CmpInstr->eraseFromParent();
|
||||
bool succeeded = UpdateOperandRegClass(MI);
|
||||
(void)succeeded;
|
||||
assert(succeeded && "Some operands reg class are incompatible!");
|
||||
MI->addRegisterDefined(ARM64::CPSR, TRI);
|
||||
MI->addRegisterDefined(ARM64::NZCV, TRI);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1591,7 +1591,7 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI, DebugLoc DL,
|
||||
unsigned DestReg, unsigned SrcReg, int Offset,
|
||||
const ARM64InstrInfo *TII, MachineInstr::MIFlag Flag,
|
||||
bool SetCPSR) {
|
||||
bool SetNZCV) {
|
||||
if (DestReg == SrcReg && Offset == 0)
|
||||
return;
|
||||
|
||||
@ -1611,7 +1611,7 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB,
|
||||
// assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
|
||||
|
||||
unsigned Opc;
|
||||
if (SetCPSR)
|
||||
if (SetNZCV)
|
||||
Opc = isSub ? ARM64::SUBSXri : ARM64::ADDSXri;
|
||||
else
|
||||
Opc = isSub ? ARM64::SUBXri : ARM64::ADDXri;
|
||||
|
@ -162,7 +162,7 @@ void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
DebugLoc DL, unsigned DestReg, unsigned SrcReg, int Offset,
|
||||
const ARM64InstrInfo *TII,
|
||||
MachineInstr::MIFlag = MachineInstr::NoFlags,
|
||||
bool SetCPSR = false);
|
||||
bool SetNZCV = false);
|
||||
|
||||
/// rewriteARM64FrameIndex - Rewrite MI to access 'Offset' bytes from the
|
||||
/// FP. Return false if the offset could not be handled directly in MI, and
|
||||
|
@ -339,7 +339,7 @@ def : InstAlias<"isb", (ISB 0xf)>;
|
||||
|
||||
def MRS : MRSI;
|
||||
def MSR : MSRI;
|
||||
def MSRcpsr: MSRcpsrI;
|
||||
def MSRpstate: MSRpstateI;
|
||||
|
||||
// The thread pointer (on Linux, at least, where this has been implemented) is
|
||||
// TPIDR_EL0.
|
||||
@ -847,26 +847,26 @@ defm CSINC : CondSelectOp<0, 0b01, "csinc", inc>;
|
||||
defm CSINV : CondSelectOp<1, 0b00, "csinv", not>;
|
||||
defm CSNEG : CondSelectOp<1, 0b01, "csneg", ineg>;
|
||||
|
||||
def : Pat<(ARM64csinv GPR32:$tval, GPR32:$fval, (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csinv GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
|
||||
(CSINVWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csinv GPR64:$tval, GPR64:$fval, (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csinv GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
|
||||
(CSINVXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csneg GPR32:$tval, GPR32:$fval, (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csneg GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
|
||||
(CSNEGWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csneg GPR64:$tval, GPR64:$fval, (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csneg GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
|
||||
(CSNEGXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csinc GPR32:$tval, GPR32:$fval, (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csinc GPR32:$tval, GPR32:$fval, (i32 imm:$cc), NZCV),
|
||||
(CSINCWr GPR32:$tval, GPR32:$fval, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csinc GPR64:$tval, GPR64:$fval, (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csinc GPR64:$tval, GPR64:$fval, (i32 imm:$cc), NZCV),
|
||||
(CSINCXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>;
|
||||
|
||||
def : Pat<(ARM64csel (i32 0), (i32 1), (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV),
|
||||
(CSINCWr WZR, WZR, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csel (i64 0), (i64 1), (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csel (i64 0), (i64 1), (i32 imm:$cc), NZCV),
|
||||
(CSINCXr XZR, XZR, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csel (i32 0), (i32 -1), (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csel (i32 0), (i32 -1), (i32 imm:$cc), NZCV),
|
||||
(CSINVWr WZR, WZR, (i32 imm:$cc))>;
|
||||
def : Pat<(ARM64csel (i64 0), (i64 -1), (i32 imm:$cc), CPSR),
|
||||
def : Pat<(ARM64csel (i64 0), (i64 -1), (i32 imm:$cc), NZCV),
|
||||
(CSINVXr XZR, XZR, (i32 imm:$cc))>;
|
||||
|
||||
// The inverse of the condition code from the alias instruction is what is used
|
||||
@ -2115,8 +2115,8 @@ def F128CSEL : Pseudo<(outs FPR128:$Rd),
|
||||
(ins FPR128:$Rn, FPR128:$Rm, ccode:$cond),
|
||||
[(set (f128 FPR128:$Rd),
|
||||
(ARM64csel FPR128:$Rn, FPR128:$Rm,
|
||||
(i32 imm:$cond), CPSR))]> {
|
||||
let Uses = [CPSR];
|
||||
(i32 imm:$cond), NZCV))]> {
|
||||
let Uses = [NZCV];
|
||||
let usesCustomInserter = 1;
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ ARM64RegisterInfo::getPointerRegClass(const MachineFunction &MF,
|
||||
const TargetRegisterClass *
|
||||
ARM64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
|
||||
if (RC == &ARM64::CCRRegClass)
|
||||
return nullptr; // Can't copy CPSR.
|
||||
return nullptr; // Can't copy NZCV.
|
||||
return RC;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ def XZR : ARM64Reg<31, "xzr", [WZR]>, DwarfRegAlias<WSP>;
|
||||
}
|
||||
|
||||
// Condition code register.
|
||||
def CPSR : ARM64Reg<0, "cpsr">;
|
||||
def NZCV : ARM64Reg<0, "nzcv">;
|
||||
|
||||
// GPR register classes with the intersections of GPR32/GPR32sp and
|
||||
// GPR64/GPR64sp for use by the coalescer.
|
||||
@ -181,7 +181,7 @@ def GPR64pi48 : RegisterOperand<GPR64, "printPostIncOperand<48>">;
|
||||
def GPR64pi64 : RegisterOperand<GPR64, "printPostIncOperand<64>">;
|
||||
|
||||
// Condition code regclass.
|
||||
def CCR : RegisterClass<"ARM64", [i32], 32, (add CPSR)> {
|
||||
def CCR : RegisterClass<"ARM64", [i32], 32, (add NZCV)> {
|
||||
let CopyCost = -1; // Don't allow copying of status registers.
|
||||
|
||||
// CCR is not allocatable.
|
||||
|
@ -680,7 +680,7 @@ public:
|
||||
|
||||
return IsKnownRegister;
|
||||
}
|
||||
bool isSystemCPSRField() const {
|
||||
bool isSystemPStateField() const {
|
||||
if (!isSysReg()) return false;
|
||||
|
||||
bool IsKnownRegister;
|
||||
@ -1346,7 +1346,7 @@ public:
|
||||
Inst.addOperand(MCOperand::CreateImm(Bits));
|
||||
}
|
||||
|
||||
void addSystemCPSRFieldOperands(MCInst &Inst, unsigned N) const {
|
||||
void addSystemPStateFieldOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
|
||||
bool Valid;
|
||||
|
@ -137,9 +137,10 @@ static DecodeStatus DecodeBaseAddSubImm(llvm::MCInst &Inst, uint32_t insn,
|
||||
static DecodeStatus DecodeUnconditionalBranch(llvm::MCInst &Inst, uint32_t insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder);
|
||||
static DecodeStatus DecodeSystemCPSRInstruction(llvm::MCInst &Inst,
|
||||
uint32_t insn, uint64_t Address,
|
||||
const void *Decoder);
|
||||
static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst,
|
||||
uint32_t insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder);
|
||||
static DecodeStatus DecodeTestAndBranch(llvm::MCInst &Inst, uint32_t insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeSIMDLdStPost(llvm::MCInst &Inst, uint32_t insn,
|
||||
@ -1408,20 +1409,20 @@ static DecodeStatus DecodeUnconditionalBranch(llvm::MCInst &Inst, uint32_t insn,
|
||||
return Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeSystemCPSRInstruction(llvm::MCInst &Inst,
|
||||
uint32_t insn, uint64_t Addr,
|
||||
const void *Decoder) {
|
||||
static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst,
|
||||
uint32_t insn, uint64_t Addr,
|
||||
const void *Decoder) {
|
||||
uint64_t op1 = fieldFromInstruction(insn, 16, 3);
|
||||
uint64_t op2 = fieldFromInstruction(insn, 5, 3);
|
||||
uint64_t crm = fieldFromInstruction(insn, 8, 4);
|
||||
|
||||
uint64_t cpsr_field = (op1 << 3) | op2;
|
||||
uint64_t pstate_field = (op1 << 3) | op2;
|
||||
|
||||
Inst.addOperand(MCOperand::CreateImm(cpsr_field));
|
||||
Inst.addOperand(MCOperand::CreateImm(pstate_field));
|
||||
Inst.addOperand(MCOperand::CreateImm(crm));
|
||||
|
||||
bool ValidNamed;
|
||||
(void)ARM64PState::PStateMapper().toString(cpsr_field, ValidNamed);
|
||||
(void)ARM64PState::PStateMapper().toString(pstate_field, ValidNamed);
|
||||
|
||||
return ValidNamed ? Success : Fail;
|
||||
}
|
||||
|
@ -1418,8 +1418,8 @@ void ARM64InstPrinter::printMSRSystemRegister(const MCInst *MI, unsigned OpNo,
|
||||
O << StringRef(Name).upper();
|
||||
}
|
||||
|
||||
void ARM64InstPrinter::printSystemCPSRField(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
void ARM64InstPrinter::printSystemPStateField(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
unsigned Val = MI->getOperand(OpNo).getImm();
|
||||
|
||||
bool Valid;
|
||||
|
@ -119,7 +119,7 @@ protected:
|
||||
void printBarrierOption(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printMSRSystemRegister(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printMRSSystemRegister(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printSystemCPSRField(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printSystemPStateField(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printSIMDType10Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user