Index: llvm/include/llvm/Target/TargetInstrPredicate.td =================================================================== --- llvm/include/llvm/Target/TargetInstrPredicate.td +++ llvm/include/llvm/Target/TargetInstrPredicate.td @@ -39,7 +39,7 @@ // processor scheduling model. // // The `MCInstPredicateExample` definition above is equivalent (and therefore -// could replace) the following definition from the ExynosM3 model (see +// could replace) the following definition from a previous ExynosM3 model (see // AArch64SchedExynosM3.td): // // def M3BranchLinkFastPred : SchedPredicate<[{ Index: llvm/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/lib/Target/AArch64/AArch64.td +++ llvm/lib/Target/AArch64/AArch64.td @@ -129,7 +129,7 @@ def FeatureExynosCheapAsMoveHandling : SubtargetFeature<"exynos-cheap-as-move", "ExynosAsCheapAsMove", "true", - "Use Exynos specific code in TargetInstrInfo::isAsCheapAsAMove()", + "Use Exynos specific handling of cheap instructions", [FeatureCustomCheapAsMoveHandling]>; def FeaturePostRAScheduler : SubtargetFeature<"use-postra-scheduler", @@ -305,6 +305,7 @@ include "AArch64Schedule.td" include "AArch64InstrInfo.td" include "AArch64SchedPredicates.td" +include "AArch64SchedPredExynos.td" def AArch64InstrInfo : InstrInfo; Index: llvm/lib/Target/AArch64/AArch64InstrInfo.h =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -241,18 +241,6 @@ MachineBasicBlock::iterator &It, MachineFunction &MF, const outliner::Candidate &C) const override; bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override; - /// Returns true if the instruction sets a constant value that can be - /// executed more efficiently. - static bool isExynosResetFast(const MachineInstr &MI); - /// Returns true if the load or store has an extension that can be executed - /// more efficiently. - static bool isExynosLdStExtFast(const MachineInstr &MI); - /// Returns true if the instruction has a constant shift left or extension - /// that can be executed more efficiently. - static bool isExynosShiftExtFast(const MachineInstr &MI, unsigned Extra = 0); - /// Returns true if the instruction is a constant shift left that can be - /// executed more quickly. - static bool isExynosShiftFast(const MachineInstr &MI, unsigned Extra = 0); /// Returns true if the instruction has a shift by immediate that can be /// executed in one cycle less. static bool isFalkorShiftExtFast(const MachineInstr &MI); Index: llvm/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -705,8 +705,7 @@ // Secondly, check cases specific to sub-targets. if (Subtarget.hasExynosCheapAsMoveHandling()) { - if (isExynosResetFast(MI) || - isExynosShiftFast(MI) || isExynosShiftExtFast(MI)) + if (isExynosCheapAsMove(MI)) return true; return MI.isAsCheapAsAMove(); @@ -760,225 +759,6 @@ llvm_unreachable("Unknown opcode to check as cheap as a move!"); } -bool AArch64InstrInfo::isExynosResetFast(const MachineInstr &MI) { - unsigned Reg, Imm, Shift; - - switch (MI.getOpcode()) { - default: - return false; - - // MOV Rd, SP - case AArch64::ADDWri: - case AArch64::ADDXri: - if (!MI.getOperand(1).isReg() || !MI.getOperand(2).isImm()) - return false; - - Reg = MI.getOperand(1).getReg(); - Imm = MI.getOperand(2).getImm(); - return ((Reg == AArch64::WSP || Reg == AArch64::SP) && Imm == 0); - - // Literal - case AArch64::ADR: - case AArch64::ADRP: - return true; - - // MOVI Vd, #0 - case AArch64::MOVID: - case AArch64::MOVIv8b_ns: - case AArch64::MOVIv2d_ns: - case AArch64::MOVIv16b_ns: - Imm = MI.getOperand(1).getImm(); - return (Imm == 0); - - // MOVI Vd, #0 - case AArch64::MOVIv2i32: - case AArch64::MOVIv4i16: - case AArch64::MOVIv4i32: - case AArch64::MOVIv8i16: - Imm = MI.getOperand(1).getImm(); - Shift = MI.getOperand(2).getImm(); - return (Imm == 0 && Shift == 0); - - // MOV Rd, Imm - case AArch64::MOVNWi: - case AArch64::MOVNXi: - - // MOV Rd, Imm - case AArch64::MOVZWi: - case AArch64::MOVZXi: - return true; - - // MOV Rd, Imm - case AArch64::ORRWri: - case AArch64::ORRXri: - if (!MI.getOperand(1).isReg()) - return false; - - Reg = MI.getOperand(1).getReg(); - Imm = MI.getOperand(2).getImm(); - return ((Reg == AArch64::WZR || Reg == AArch64::XZR) && Imm == 0); - - // MOV Rd, Rm - case AArch64::ORRWrs: - case AArch64::ORRXrs: - if (!MI.getOperand(1).isReg()) - return false; - - Reg = MI.getOperand(1).getReg(); - Imm = MI.getOperand(3).getImm(); - Shift = AArch64_AM::getShiftValue(Imm); - return ((Reg == AArch64::WZR || Reg == AArch64::XZR) && Shift == 0); - } -} - -bool AArch64InstrInfo::isExynosLdStExtFast(const MachineInstr &MI) { - unsigned Imm; - AArch64_AM::ShiftExtendType Ext; - - switch (MI.getOpcode()) { - default: - return false; - - // WriteLD - case AArch64::PRFMroW: - case AArch64::PRFMroX: - - // WriteLDIdx - case AArch64::LDRBBroW: - case AArch64::LDRBBroX: - case AArch64::LDRHHroW: - case AArch64::LDRHHroX: - case AArch64::LDRSBWroW: - case AArch64::LDRSBWroX: - case AArch64::LDRSBXroW: - case AArch64::LDRSBXroX: - case AArch64::LDRSHWroW: - case AArch64::LDRSHWroX: - case AArch64::LDRSHXroW: - case AArch64::LDRSHXroX: - case AArch64::LDRSWroW: - case AArch64::LDRSWroX: - case AArch64::LDRWroW: - case AArch64::LDRWroX: - case AArch64::LDRXroW: - case AArch64::LDRXroX: - - case AArch64::LDRBroW: - case AArch64::LDRBroX: - case AArch64::LDRDroW: - case AArch64::LDRDroX: - case AArch64::LDRHroW: - case AArch64::LDRHroX: - case AArch64::LDRSroW: - case AArch64::LDRSroX: - - // WriteSTIdx - case AArch64::STRBBroW: - case AArch64::STRBBroX: - case AArch64::STRHHroW: - case AArch64::STRHHroX: - case AArch64::STRWroW: - case AArch64::STRWroX: - case AArch64::STRXroW: - case AArch64::STRXroX: - - case AArch64::STRBroW: - case AArch64::STRBroX: - case AArch64::STRDroW: - case AArch64::STRDroX: - case AArch64::STRHroW: - case AArch64::STRHroX: - case AArch64::STRSroW: - case AArch64::STRSroX: - Imm = MI.getOperand(3).getImm(); - Ext = AArch64_AM::getMemExtendType(Imm); - return (Ext == AArch64_AM::SXTX || Ext == AArch64_AM::UXTX); - } -} - -bool AArch64InstrInfo::isExynosShiftExtFast(const MachineInstr &MI, - unsigned Extra) { - unsigned Imm, Shift; - AArch64_AM::ShiftExtendType Ext; - - switch (MI.getOpcode()) { - default: - return false; - - // WriteI - case AArch64::ADDSWri: - case AArch64::ADDSXri: - case AArch64::ADDWri: - case AArch64::ADDXri: - case AArch64::SUBSWri: - case AArch64::SUBSXri: - case AArch64::SUBWri: - case AArch64::SUBXri: - return true; - - // WriteIEReg - case AArch64::ADDSWrx: - case AArch64::ADDSXrx: - case AArch64::ADDSXrx64: - case AArch64::ADDWrx: - case AArch64::ADDXrx: - case AArch64::ADDXrx64: - case AArch64::SUBSWrx: - case AArch64::SUBSXrx: - case AArch64::SUBSXrx64: - case AArch64::SUBWrx: - case AArch64::SUBXrx: - case AArch64::SUBXrx64: - Imm = MI.getOperand(3).getImm(); - Shift = AArch64_AM::getArithShiftValue(Imm); - Ext = AArch64_AM::getArithExtendType(Imm); - return (Shift == 0 || - (Ext == AArch64_AM::UXTX && (Shift <= 3 || Shift == Extra))); - } -} - -bool AArch64InstrInfo::isExynosShiftFast(const MachineInstr &MI, - unsigned Extra) { - unsigned Imm, Shift; - AArch64_AM::ShiftExtendType Ext; - - switch (MI.getOpcode()) { - default: - return false; - - // WriteISReg - case AArch64::ADDSWrs: - case AArch64::ADDSXrs: - case AArch64::ADDWrs: - case AArch64::ADDXrs: - case AArch64::ANDSWrs: - case AArch64::ANDSXrs: - case AArch64::ANDWrs: - case AArch64::ANDXrs: - case AArch64::BICSWrs: - case AArch64::BICSXrs: - case AArch64::BICWrs: - case AArch64::BICXrs: - case AArch64::EONWrs: - case AArch64::EONXrs: - case AArch64::EORWrs: - case AArch64::EORXrs: - case AArch64::ORNWrs: - case AArch64::ORNXrs: - case AArch64::ORRWrs: - case AArch64::ORRXrs: - case AArch64::SUBSWrs: - case AArch64::SUBSXrs: - case AArch64::SUBWrs: - case AArch64::SUBXrs: - Imm = MI.getOperand(3).getImm(); - Shift = AArch64_AM::getShiftValue(Imm); - Ext = AArch64_AM::getShiftType(Imm); - return (Shift == 0 || - (Ext == AArch64_AM::LSL && (Shift <= 3 || Shift == Extra))); - } -} - bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) { switch (MI.getOpcode()) { default: Index: llvm/lib/Target/AArch64/AArch64SchedExynosM1.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SchedExynosM1.td +++ llvm/lib/Target/AArch64/AArch64SchedExynosM1.td @@ -61,14 +61,6 @@ def M1UnitNALU : ProcResGroup<[M1UnitNAL0, M1UnitNAL1]>; // All simple vector -//===----------------------------------------------------------------------===// -// Predicates. - -def M1BranchLinkPred : SchedPredicate<[{MI->getOpcode() == AArch64::BLR && - MI->getOperand(0).getReg() != AArch64::LR}]>; -def M1LdStExtPred : SchedPredicate<[{TII->isExynosLdStExtFast(*MI)}]>; -def M1ShiftExtPred : SchedPredicate<[{TII->isExynosShiftExtFast(*MI)}]>; - //===----------------------------------------------------------------------===// // Coarse scheduling model. @@ -86,14 +78,14 @@ def M1WriteAD : SchedWriteRes<[M1UnitALU, M1UnitC]> { let Latency = 2; let NumMicroOps = 2; } -def M1WriteAX : SchedWriteVariant<[SchedVar, - SchedVar]>; +def M1WriteAX : SchedWriteVariant<[SchedVar, + SchedVar]>; def M1WriteC1 : SchedWriteRes<[M1UnitC]> { let Latency = 1; } def M1WriteC2 : SchedWriteRes<[M1UnitC]> { let Latency = 2; } def M1WriteB1 : SchedWriteRes<[M1UnitB]> { let Latency = 1; } -def M1WriteBX : SchedWriteVariant<[SchedVar, - SchedVar]>; +def M1WriteBX : SchedWriteVariant<[SchedVar, + SchedVar]>; def M1WriteL5 : SchedWriteRes<[M1UnitL]> { let Latency = 5; } def M1WriteL6 : SchedWriteRes<[M1UnitL]> { let Latency = 6; } @@ -111,9 +103,9 @@ let ResourceCycles = [2, 1]; } def M1WriteLH : SchedWriteRes<[]> { let Latency = 5; let NumMicroOps = 0; } -def M1WriteLX : SchedWriteVariant<[SchedVar, +def M1WriteLX : SchedWriteVariant<[SchedVar, SchedVar]>; -def M1WriteLY : SchedWriteVariant<[SchedVar, +def M1WriteLY : SchedWriteVariant<[SchedVar, SchedVar]>; def M1WriteS1 : SchedWriteRes<[M1UnitS]> { let Latency = 1; } @@ -141,10 +133,10 @@ def M1WriteSE : SchedWriteRes<[M1UnitS, M1UnitA]> { let Latency = 2; let NumMicroOps = 2; } -def M1WriteSX : SchedWriteVariant<[SchedVar, - SchedVar]>; -def M1WriteSY : SchedWriteVariant<[SchedVar, - SchedVar]>; +def M1WriteSX : SchedWriteVariant<[SchedVar, + SchedVar]>; +def M1WriteSY : SchedWriteVariant<[SchedVar, + SchedVar]>; def M1ReadAdrBase : SchedReadVariant<[SchedVar, SchedVar]>; @@ -415,9 +407,9 @@ M1UnitS, M1UnitFST, M1UnitFST, - M1UnitFST]> { let Latency = 14; - let NumMicroOps = 4; - let ResourceCycles = [1, 7, 1, 7, 1]; } + M1UnitFST]> { let Latency = 14; + let NumMicroOps = 4; + let ResourceCycles = [1, 7, 1, 7, 1]; } def M1WriteVSTI : SchedWriteRes<[M1UnitNALU, M1UnitS, M1UnitFST, @@ -428,9 +420,17 @@ M1UnitS, M1UnitFST, M1UnitFST, - M1UnitFST]> { let Latency = 17; - let NumMicroOps = 7; - let ResourceCycles = [1, 7, 1, 7, 1, 1, 1, 1, 1, 1, 1]; } + M1UnitFST]> { let Latency = 17; + let NumMicroOps = 7; + let ResourceCycles = [1, 7, 1, 7, 1, 1, 1, 1, 1, 1, 1]; } + +// Special cases. +def M1WriteAES : SchedWriteRes<[M1UnitNCRYPT]> { let Latency = 1; } +def M1WriteCOPY : SchedWriteVariant<[SchedVar, + SchedVar]>; + +// Fast forwarding. +def M1ReadAES : SchedReadAdvance<1, [M1WriteAES]>; // Branch instructions def : InstRW<[M1WriteB1], (instrs Bcc)>; @@ -440,9 +440,11 @@ def : InstRW<[M1WriteAD], (instregex "^TBN?Z[WX]")>; // Arithmetic and logical integer instructions. -def : InstRW<[M1WriteA1], (instrs COPY)>; def : InstRW<[M1WriteAX], (instregex ".+r[sx](64)?$")>; +// Move instructions. +def : InstRW<[M1WriteCOPY], (instrs COPY)>; + // Divide and multiply instructions. // Miscellaneous instructions. @@ -831,8 +833,6 @@ WriteAdr], (instregex "ST4Fourv(2d)_POST$")>; // Cryptography instructions. -def M1WriteAES : SchedWriteRes<[M1UnitNCRYPT]> { let Latency = 1; } -def M1ReadAES : SchedReadAdvance<1, [M1WriteAES]>; def : InstRW<[M1WriteAES], (instregex "^AES[DE]")>; def : InstRW<[M1WriteAES, M1ReadAES], (instregex "^AESI?MC")>; Index: llvm/lib/Target/AArch64/AArch64SchedExynosM3.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SchedExynosM3.td +++ llvm/lib/Target/AArch64/AArch64SchedExynosM3.td @@ -103,20 +103,6 @@ M3UnitNSHF1, M3UnitNSHF2]>; -//===----------------------------------------------------------------------===// -// Predicates. - -def M3BranchLinkPred : SchedPredicate<[{MI->getOpcode() == AArch64::BLR && - MI->getOperand(0).isReg() && - MI->getOperand(0).getReg() != AArch64::LR}]>; -def M3ResetPred : SchedPredicate<[{TII->isExynosResetFast(*MI)}]>; -def M3RotatePred : SchedPredicate<[{(MI->getOpcode() == AArch64::EXTRWrri || - MI->getOpcode() == AArch64::EXTRXrri) && - MI->getOperand(1).isReg() && MI->getOperand(2).isReg() && - MI->getOperand(1).getReg() == MI->getOperand(2).getReg()}]>; -def M3LdStExtPred : SchedPredicate<[{TII->isExynosLdStExtFast(*MI)}]>; -def M3ShiftExtPred : SchedPredicate<[{TII->isExynosShiftExtFast(*MI)}]>; - //===----------------------------------------------------------------------===// // Coarse scheduling model. @@ -138,15 +124,23 @@ let NumMicroOps = 2; } def M3WriteC1 : SchedWriteRes<[M3UnitC]> { let Latency = 1; } def M3WriteC2 : SchedWriteRes<[M3UnitC]> { let Latency = 2; } -def M3WriteAX : SchedWriteVariant<[SchedVar, - SchedVar, - SchedVar]>; -def M3WriteAY : SchedWriteVariant<[SchedVar, - SchedVar]>; +def M3WriteAU : SchedWriteVariant<[SchedVar, + SchedVar, + SchedVar]>; +def M3WriteAV : SchedWriteVariant<[SchedVar, + SchedVar]>; +def M3WriteAW : SchedWriteVariant<[SchedVar, + SchedVar]>; +def M3WriteAX : SchedWriteVariant<[SchedVar, + SchedVar]>; +def M3WriteAY : SchedWriteVariant<[SchedVar, + SchedVar]>; +def M3WriteAZ : SchedWriteVariant<[SchedVar, + SchedVar]>; def M3WriteB1 : SchedWriteRes<[M3UnitB]> { let Latency = 1; } -def M3WriteBX : SchedWriteVariant<[SchedVar, - SchedVar]>; +def M3WriteBX : SchedWriteVariant<[SchedVar, + SchedVar]>; def M3WriteL4 : SchedWriteRes<[M3UnitL]> { let Latency = 4; } def M3WriteL5 : SchedWriteRes<[M3UnitL]> { let Latency = 5; } @@ -166,8 +160,8 @@ def M3WriteLH : SchedWriteRes<[]> { let Latency = 5; let NumMicroOps = 0; } -def M3WriteLX : SchedWriteVariant<[SchedVar, - SchedVar]>; +def M3WriteLX : SchedWriteVariant<[SchedVar, + SchedVar]>; def M3WriteS1 : SchedWriteRes<[M3UnitS]> { let Latency = 1; } def M3WriteSA : SchedWriteRes<[M3UnitA, @@ -181,10 +175,10 @@ M3UnitS]> { let Latency = 2; let NumMicroOps = 2; } -def M3WriteSX : SchedWriteVariant<[SchedVar, - SchedVar]>; -def M3WriteSY : SchedWriteVariant<[SchedVar, - SchedVar]>; +def M3WriteSX : SchedWriteVariant<[SchedVar, + SchedVar]>; +def M3WriteSY : SchedWriteVariant<[SchedVar, + SchedVar]>; def M3ReadAdrBase : SchedReadVariant<[SchedVar, SchedVar]>; @@ -214,9 +208,7 @@ let ResourceCycles = [2]; } // Miscellaneous instructions. -def : WriteRes { let Latency = 1; - let NumMicroOps = 2; } +def : SchedAlias; // Addressing modes. def : WriteRes { let Latency = 1; @@ -479,11 +471,15 @@ // Special cases. def M3WriteAES : SchedWriteRes<[M3UnitNCRY]> { let Latency = 1; } +def M3WriteCOPY : SchedWriteVariant<[SchedVar, + SchedVar]>; +def M3WriteMOVI : SchedWriteVariant<[SchedVar, + SchedVar]>; + +// Fast forwarding. def M3ReadAES : SchedReadAdvance<1, [M3WriteAES]>; def M3ReadFMAC : SchedReadAdvance<1, [M3WriteFMAC4, M3WriteFMAC5]>; -def M3WriteMOVI : SchedWriteVariant<[SchedVar, - SchedVar]>; def M3ReadNMUL : SchedReadAdvance<1, [M3WriteNMUL3]>; // Branch instructions @@ -494,20 +490,21 @@ def : InstRW<[M3WriteAD], (instregex "^TBN?Z[WX]")>; // Arithmetic and logical integer instructions. -def : InstRW<[M3WriteA1], (instrs COPY)>; -def : InstRW<[M3WriteAX], (instregex "^(ADD|SUB)S?Xrx64")>; -def : InstRW<[M3WriteAX], (instregex "^(ADD|AND|BIC|EON|EOR|ORN|ORR|SUB)[WX]r[sx]$")>; -def : InstRW<[M3WriteAX], (instregex "^(ADD|BIC|SUB)S[WX]r[sx]$")>; -def : InstRW<[M3WriteAX], (instregex "^(ADD|AND|EOR|ORR|SUB)[WX]ri")>; +def : InstRW<[M3WriteAZ], (instregex "^(ADD|AND|BIC|EON|EOR|ORN|SUB)[WX]rs$")>; +def : InstRW<[M3WriteAU], (instrs ORRWrs, ORRXrs)>; +def : InstRW<[M3WriteAX], (instregex "^(ADD|SUB)S?[WX]rx")>; +def : InstRW<[M3WriteAZ], (instregex "^(ADD|AND|BIC|SUB)S[WX]rs$")>; +def : InstRW<[M3WriteAV], (instrs ADDWri, ADDXri)>; +def : InstRW<[M3WriteAW], (instrs ORRWri, ORRXri)>; // Move instructions. -def : InstRW<[M3WriteZ0], (instrs ADR, ADRP)>; -def : InstRW<[M3WriteZ0], (instregex "^MOV[NZ][WX]i")>; +def : InstRW<[M3WriteCOPY], (instrs COPY)>; +def : InstRW<[M3WriteZ0], (instrs ADR, ADRP)>; +def : InstRW<[M3WriteZ0], (instregex "^MOV[NZ][WX]i")>; // Divide and multiply instructions. // Miscellaneous instructions. -def : InstRW<[M3WriteAY], (instrs EXTRWrri, EXTRXrri)>; // Load instructions. def : InstRW<[M3WriteLD, Index: llvm/lib/Target/AArch64/AArch64SchedPredExynos.td =================================================================== --- /dev/null +++ llvm/lib/Target/AArch64/AArch64SchedPredExynos.td @@ -0,0 +1,138 @@ +//===- AArch64SchedPredExynos.td - AArch64 Sched Preds -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines scheduling predicate definitions that are used by the +// AArch64 Exynos processors. +// +//===----------------------------------------------------------------------===// + +// Identify BLR specifying the LR register as the indirect target register. +def ExynosBranchLinkLRPred : MCSchedPredicate< + CheckAll<[CheckOpcode<[BLR]>, + CheckRegOperand<0, LR>]>>; + +// Identify arithmetic and logic instructions without or with limited extension. +def ExynosExtFn : TIIPredicate< + "isExynosExtFast", + MCOpcodeSwitchStatement< + [MCOpcodeSwitchCase< + IsArithExt32Op.ValidOpcodes, + MCReturnStatement< + CheckAny<[CheckExtBy0, + CheckAll< + [CheckExtUXTW, + CheckAny< + [CheckExtBy1, + CheckExtBy2, + CheckExtBy3]>]>]>>>, + MCOpcodeSwitchCase< + IsArithExt64Op.ValidOpcodes, + MCReturnStatement< + CheckAny<[CheckExtBy0, + CheckAll< + [CheckExtUXTX, + CheckAny< + [CheckExtBy1, + CheckExtBy2, + CheckExtBy3]>]>]>>>], + MCReturnStatement>>; +def ExynosExtPred : MCSchedPredicate; + +// Identify FP instructions. +def ExynosFPPred : MCSchedPredicate>; + +// Identify load and store instructions using the register offset +// addressing mode efficiently. +def ExynosLdStExtFn : TIIPredicate< + "isExynosLdStExtFast", + MCOpcodeSwitchStatement< + [MCOpcodeSwitchCase< + IsLoadStoreRegOffsetOp.ValidOpcodes, + MCReturnStatement< + CheckAny< + [CheckMemExtLSL, + CheckMemExtSXTX]>>>], + MCReturnStatement>>; +def ExynosLdStExtPred : MCSchedPredicate; + +// Identify whether an instruction whose result is a long vector +// operates on the upper half of the input registers. +def ExynosLongVectorUpperFn : TIIPredicate< + "isExynosLongVectorUpper", + MCOpcodeSwitchStatement< + [MCOpcodeSwitchCase< + IsLongVectorUpperOp.ValidOpcodes, + MCReturnStatement>], + MCReturnStatement>>; +def ExynosLongVectorUpperPred : MCSchedPredicate; + +// Identify 128-bit NEON instructions. +def ExynosQFormPred : MCSchedPredicate; + +// Identify instructions that reset a register efficiently. +def ExynosResetFn : TIIPredicate< + "isExynosResetFast", + MCOpcodeSwitchStatement< + [MCOpcodeSwitchCase< + [ADR, ADRP, + MOVNWi, MOVNXi, + MOVZWi, MOVZXi], + MCReturnStatement>], + MCReturnStatement< + CheckAny< + [IsCopyIdiomFn, + IsZeroFPIdiomFn, + IsZeroIdiomFn]>>>>; +def ExynosResetPred : MCSchedPredicate; + +// Identify EXTR as the alias for ROR (immediate). +def ExynosRotateRightImmPred : MCSchedPredicate< + CheckAll<[CheckOpcode<[EXTRWrri, EXTRXrri]>, + CheckSameRegOperand<1, 2>]>>; + +// Identify arithmetic and logic instructions without or with limited shift. +def ExynosShiftFn : TIIPredicate< + "isExynosShiftFast", + MCOpcodeSwitchStatement< + [MCOpcodeSwitchCase< + IsArithLogicShiftOp.ValidOpcodes, + MCReturnStatement< + CheckAny<[CheckShiftBy0, + CheckAll< + [CheckShiftLSL, + CheckAny< + [CheckShiftBy1, + CheckShiftBy2, + CheckShiftBy3]>]>]>>>], + MCReturnStatement>>; +def ExynosShiftPred : MCSchedPredicate; + +// Identify more arithmetic and logic instructions without or limited shift. +def ExynosShiftExFn : TIIPredicate< + "isExynosShiftExFast", + MCOpcodeSwitchStatement< + [MCOpcodeSwitchCase< + IsArithLogicShiftOp.ValidOpcodes, + MCReturnStatement< + CheckAll< + [CheckShiftLSL, + CheckShiftBy8]>>>], + MCReturnStatement>>; +def ExynosShiftExPred : MCSchedPredicate; + +// Identify arithmetic and logic immediate instructions. +def ExynosCheapFn : TIIPredicate< + "isExynosCheapAsMove", + MCOpcodeSwitchStatement< + [MCOpcodeSwitchCase< + IsArithLogicImmOp.ValidOpcodes, + MCReturnStatement>], + MCReturnStatement< + CheckAny< + [ExynosExtFn, ExynosResetFn, ExynosShiftFn]>>>>;