//===- AArch64SchedPredicates.td - AArch64 Sched Preds -----*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines scheduling predicate definitions that are used by the // AArch64 subtargets. // //===----------------------------------------------------------------------===// // Function mappers. // Check the extension type in arithmetic instructions. let FunctionMapper = "AArch64_AM::getArithExtendType" in { def CheckExtUXTB : CheckImmOperand_s<3, "AArch64_AM::UXTB">; def CheckExtUXTH : CheckImmOperand_s<3, "AArch64_AM::UXTH">; def CheckExtUXTW : CheckImmOperand_s<3, "AArch64_AM::UXTW">; def CheckExtUXTX : CheckImmOperand_s<3, "AArch64_AM::UXTX">; def CheckExtSXTB : CheckImmOperand_s<3, "AArch64_AM::SXTB">; def CheckExtSXTH : CheckImmOperand_s<3, "AArch64_AM::SXTH">; def CheckExtSXTW : CheckImmOperand_s<3, "AArch64_AM::SXTW">; def CheckExtSXTX : CheckImmOperand_s<3, "AArch64_AM::SXTX">; } // Check for shifting in extended arithmetic instructions. foreach I = {0-3} in { let FunctionMapper = "AArch64_AM::getArithShiftValue" in def CheckExtBy#I : CheckImmOperand<3, I>; } // Check for shifting in arithmetic and logic instructions. foreach I = {0-4, 8} in { let FunctionMapper = "AArch64_AM::getShiftValue" in def CheckShiftBy#I : CheckImmOperand<3, I>; } // Check the extension type in the register offset addressing mode. let FunctionMapper = "AArch64_AM::getMemExtendType" in { def CheckMemExtUXTW : CheckImmOperand_s<3, "AArch64_AM::UXTW">; def CheckMemExtLSL : CheckImmOperand_s<3, "AArch64_AM::UXTX">; def CheckMemExtSXTW : CheckImmOperand_s<3, "AArch64_AM::SXTW">; def CheckMemExtSXTX : CheckImmOperand_s<3, "AArch64_AM::SXTX">; } // Check for scaling in the register offset addressing mode. let FunctionMapper = "AArch64_AM::getMemDoShift" in def CheckMemScaled : CheckImmOperandSimple<4>; // Check the shifting type in arithmetic and logic instructions. let FunctionMapper = "AArch64_AM::getShiftType" in { def CheckShiftLSL : CheckImmOperand_s<3, "AArch64_AM::LSL">; def CheckShiftLSR : CheckImmOperand_s<3, "AArch64_AM::LSR">; def CheckShiftASR : CheckImmOperand_s<3, "AArch64_AM::ASR">; def CheckShiftROR : CheckImmOperand_s<3, "AArch64_AM::ROR">; def CheckShiftMSL : CheckImmOperand_s<3, "AArch64_AM::MSL">; } // Generic predicates. // Check for ZR in a register operand. foreach I = {1-3} in { def CheckIsReg#I#Zero : CheckAll< [CheckIsRegOperand, CheckAny< [CheckRegOperand, CheckRegOperand]>]>; } def IsReg1ZeroPred : MCSchedPredicate; def IsReg2ZeroPred : MCSchedPredicate; def IsReg3ZeroPred : MCSchedPredicate; // Identify whether an instruction is NEON or floating point def CheckFpOrNEON : CheckFunctionPredicateWithTII< "AArch64_MC::isFpOrNEON", "AArch64InstrInfo::isFpOrNEON" >; // Identify whether an instruction is the 16-bit NEON form based on its result. def CheckHForm : CheckFunctionPredicateWithTII< "AArch64_MC::isHForm", "AArch64InstrInfo::isHForm" >; // Identify whether an instruction is the 128-bit NEON form based on its result. def CheckQForm : CheckFunctionPredicateWithTII< "AArch64_MC::isQForm", "AArch64InstrInfo::isQForm" >; // Identify arithmetic instructions with extend. def IsArithExtOp : CheckOpcode<[ADDWrx, ADDXrx, ADDSWrx, ADDSXrx, SUBWrx, SUBXrx, SUBSWrx, SUBSXrx, ADDXrx64, ADDSXrx64, SUBXrx64, SUBSXrx64]>; // Identify arithmetic immediate instructions. def IsArithImmOp : CheckOpcode<[ADDWri, ADDXri, ADDSWri, ADDSXri, SUBWri, SUBXri, SUBSWri, SUBSXri]>; // Identify arithmetic instructions with shift. def IsArithShiftOp : CheckOpcode<[ADDWrs, ADDXrs, ADDSWrs, ADDSXrs, SUBWrs, SUBXrs, SUBSWrs, SUBSXrs]>; // Identify arithmetic instructions without shift. def IsArithUnshiftOp : CheckOpcode<[ADDWrr, ADDXrr, ADDSWrr, ADDSXrr, SUBWrr, SUBXrr, SUBSWrr, SUBSXrr]>; // Identify logic immediate instructions. def IsLogicImmOp : CheckOpcode<[ANDWri, ANDXri, EORWri, EORXri, ORRWri, ORRXri]>; // Identify logic instructions with shift. def IsLogicShiftOp : CheckOpcode<[ANDWrs, ANDXrs, ANDSWrs, ANDSXrs, BICWrs, BICXrs, BICSWrs, BICSXrs, EONWrs, EONXrs, EORWrs, EORXrs, ORNWrs, ORNXrs, ORRWrs, ORRXrs]>; // Identify logic instructions without shift. def IsLogicUnshiftOp : CheckOpcode<[ANDWrr, ANDXrr, ANDSWrr, ANDSXrr, BICWrr, BICXrr, BICSWrr, BICSXrr, EONWrr, EONXrr, EORWrr, EORXrr, ORNWrr, ORNXrr, ORRWrr, ORRXrr]>; // Identify arithmetic and logic immediate instructions. def IsArithLogicImmOp : CheckOpcode; // Identify arithmetic and logic instructions with shift. def IsArithLogicShiftOp : CheckOpcode; // Identify arithmetic and logic instructions without shift. def IsArithLogicUnshiftOp : CheckOpcode; // Identify whether an instruction is an ASIMD // load using the post index addressing mode. def IsLoadASIMDPostOp : CheckOpcode<[LD1Onev8b_POST, LD1Onev4h_POST, LD1Onev2s_POST, LD1Onev1d_POST, LD1Onev16b_POST, LD1Onev8h_POST, LD1Onev4s_POST, LD1Onev2d_POST, LD1Twov8b_POST, LD1Twov4h_POST, LD1Twov2s_POST, LD1Twov1d_POST, LD1Twov16b_POST, LD1Twov8h_POST, LD1Twov4s_POST, LD1Twov2d_POST, LD1Threev8b_POST, LD1Threev4h_POST, LD1Threev2s_POST, LD1Threev1d_POST, LD1Threev16b_POST, LD1Threev8h_POST, LD1Threev4s_POST, LD1Threev2d_POST, LD1Fourv8b_POST, LD1Fourv4h_POST, LD1Fourv2s_POST, LD1Fourv1d_POST, LD1Fourv16b_POST, LD1Fourv8h_POST, LD1Fourv4s_POST, LD1Fourv2d_POST, LD1i8_POST, LD1i16_POST, LD1i32_POST, LD1i64_POST, LD1Rv8b_POST, LD1Rv4h_POST, LD1Rv2s_POST, LD1Rv1d_POST, LD1Rv16b_POST, LD1Rv8h_POST, LD1Rv4s_POST, LD1Rv2d_POST, LD2Twov8b_POST, LD2Twov4h_POST, LD2Twov2s_POST, LD2Twov16b_POST, LD2Twov8h_POST, LD2Twov4s_POST, LD2Twov2d_POST, LD2i8_POST, LD2i16_POST, LD2i32_POST, LD2i64_POST, LD2Rv8b_POST, LD2Rv4h_POST, LD2Rv2s_POST, LD2Rv1d_POST, LD2Rv16b_POST, LD2Rv8h_POST, LD2Rv4s_POST, LD2Rv2d_POST, LD3Threev8b_POST, LD3Threev4h_POST, LD3Threev2s_POST, LD3Threev16b_POST, LD3Threev8h_POST, LD3Threev4s_POST, LD3Threev2d_POST, LD3i8_POST, LD3i16_POST, LD3i32_POST, LD3i64_POST, LD3Rv8b_POST, LD3Rv4h_POST, LD3Rv2s_POST, LD3Rv1d_POST, LD3Rv16b_POST, LD3Rv8h_POST, LD3Rv4s_POST, LD3Rv2d_POST, LD4Fourv8b_POST, LD4Fourv4h_POST, LD4Fourv2s_POST, LD4Fourv16b_POST, LD4Fourv8h_POST, LD4Fourv4s_POST, LD4Fourv2d_POST, LD4i8_POST, LD4i16_POST, LD4i32_POST, LD4i64_POST, LD4Rv8b_POST, LD4Rv4h_POST, LD4Rv2s_POST, LD4Rv1d_POST, LD4Rv16b_POST, LD4Rv8h_POST, LD4Rv4s_POST, LD4Rv2d_POST]>; // Identify whether an instruction is an ASIMD // store using the post index addressing mode. def IsStoreASIMDPostOp : CheckOpcode<[ST1Onev8b_POST, ST1Onev4h_POST, ST1Onev2s_POST, ST1Onev1d_POST, ST1Onev16b_POST, ST1Onev8h_POST, ST1Onev4s_POST, ST1Onev2d_POST, ST1Twov8b_POST, ST1Twov4h_POST, ST1Twov2s_POST, ST1Twov1d_POST, ST1Twov16b_POST, ST1Twov8h_POST, ST1Twov4s_POST, ST1Twov2d_POST, ST1Threev8b_POST, ST1Threev4h_POST, ST1Threev2s_POST, ST1Threev1d_POST, ST1Threev16b_POST, ST1Threev8h_POST, ST1Threev4s_POST, ST1Threev2d_POST, ST1Fourv8b_POST, ST1Fourv4h_POST, ST1Fourv2s_POST, ST1Fourv1d_POST, ST1Fourv16b_POST, ST1Fourv8h_POST, ST1Fourv4s_POST, ST1Fourv2d_POST, ST1i8_POST, ST1i16_POST, ST1i32_POST, ST1i64_POST, ST2Twov8b_POST, ST2Twov4h_POST, ST2Twov2s_POST, ST2Twov16b_POST, ST2Twov8h_POST, ST2Twov4s_POST, ST2Twov2d_POST, ST2i8_POST, ST2i16_POST, ST2i32_POST, ST2i64_POST, ST3Threev8b_POST, ST3Threev4h_POST, ST3Threev2s_POST, ST3Threev16b_POST, ST3Threev8h_POST, ST3Threev4s_POST, ST3Threev2d_POST, ST3i8_POST, ST3i16_POST, ST3i32_POST, ST3i64_POST, ST4Fourv8b_POST, ST4Fourv4h_POST, ST4Fourv2s_POST, ST4Fourv16b_POST, ST4Fourv8h_POST, ST4Fourv4s_POST, ST4Fourv2d_POST, ST4i8_POST, ST4i16_POST, ST4i32_POST, ST4i64_POST]>; // Identify whether an instruction is an ASIMD load // or store using the post index addressing mode. def IsLoadStoreASIMDPostOp : CheckOpcode; // Identify whether an instruction is a load // using the register offset addressing mode. def IsLoadRegOffsetOp : CheckOpcode<[PRFMroW, PRFMroX, LDRBBroW, LDRBBroX, LDRSBWroW, LDRSBWroX, LDRSBXroW, LDRSBXroX, LDRHHroW, LDRHHroX, LDRSHWroW, LDRSHWroX, LDRSHXroW, LDRSHXroX, LDRWroW, LDRWroX, LDRSWroW, LDRSWroX, LDRXroW, LDRXroX, LDRBroW, LDRBroX, LDRHroW, LDRHroX, LDRSroW, LDRSroX, LDRDroW, LDRDroX, LDRQroW, LDRQroX]>; // Identify whether an instruction is a store // using the register offset addressing mode. def IsStoreRegOffsetOp : CheckOpcode<[STRBBroW, STRBBroX, STRHHroW, STRHHroX, STRWroW, STRWroX, STRXroW, STRXroX, STRBroW, STRBroX, STRHroW, STRHroX, STRSroW, STRSroX, STRDroW, STRDroX, STRQroW, STRQroX]>; // Identify whether an instruction is a load or // store using the register offset addressing mode. def IsLoadStoreRegOffsetOp : CheckOpcode; // Target predicates. // Identify arithmetic instructions with an extended register. def RegExtendedFn : TIIPredicate<"hasExtendedReg", MCOpcodeSwitchStatement< [MCOpcodeSwitchCase< IsArithExtOp.ValidOpcodes, MCReturnStatement< CheckNot>>>], MCReturnStatement>>; def RegExtendedPred : MCSchedPredicate; // Identify arithmetic and logic instructions with a shifted register. def RegShiftedFn : TIIPredicate<"hasShiftedReg", MCOpcodeSwitchStatement< [MCOpcodeSwitchCase< IsArithLogicShiftOp.ValidOpcodes, MCReturnStatement< CheckNot>>>], MCReturnStatement>>; def RegShiftedPred : MCSchedPredicate; // Identify a load or store using the register offset addressing mode // with an extended or scaled register. def ScaledIdxFn : TIIPredicate<"isScaledAddr", MCOpcodeSwitchStatement< [MCOpcodeSwitchCase< IsLoadStoreRegOffsetOp.ValidOpcodes, MCReturnStatement< CheckAny<[CheckNot, CheckMemScaled]>>>], MCReturnStatement>>; def ScaledIdxPred : MCSchedPredicate; // Special cases. // Check for LSL shift <= 4 def IsCheapLSL : MCSchedPredicate< CheckAll< [CheckShiftLSL, CheckAny< [CheckShiftBy0, CheckShiftBy1, CheckShiftBy2, CheckShiftBy3, CheckShiftBy4]>]>>; // Idioms. // Identify an instruction that effectively transfers a register to another. def IsCopyIdiomFn : TIIPredicate<"isCopyIdiom", MCOpcodeSwitchStatement< [// MOV {Rd, SP}, {SP, Rn} => // ADD {Rd, SP}, {SP, Rn}, #0 MCOpcodeSwitchCase< [ADDWri, ADDXri], MCReturnStatement< CheckAll< [CheckIsRegOperand<0>, CheckIsRegOperand<1>, CheckAny< [CheckRegOperand<0, WSP>, CheckRegOperand<0, SP>, CheckRegOperand<1, WSP>, CheckRegOperand<1, SP>]>, CheckZeroOperand<2>]>>>, // MOV Rd, Rm => // ORR Rd, ZR, Rm, LSL #0 MCOpcodeSwitchCase< [ORRWrs, ORRXrs], MCReturnStatement< CheckAll< [CheckIsReg1Zero, CheckIsRegOperand<2>, CheckShiftBy0]>>>], MCReturnStatement>>; def IsCopyIdiomPred : MCSchedPredicate; // Identify an instruction that effectively resets a GP register to zero. def IsZeroIdiomFn : TIIPredicate<"isZeroIdiom", MCOpcodeSwitchStatement< [// ORR Rd, ZR, #0 MCOpcodeSwitchCase< [ORRWri, ORRXri], MCReturnStatement< CheckAll< [CheckIsReg1Zero, CheckZeroOperand<2>]>>>], MCReturnStatement>>; def IsZeroIdiomPred : MCSchedPredicate; // Identify an instruction that effectively resets a FP register to zero. def IsZeroFPIdiomFn : TIIPredicate<"isZeroFPIdiom", MCOpcodeSwitchStatement< [// MOVI Vd, #0 MCOpcodeSwitchCase< [MOVIv8b_ns, MOVIv16b_ns, MOVID, MOVIv2d_ns], MCReturnStatement>>, // MOVI Vd, #0, LSL #0 MCOpcodeSwitchCase< [MOVIv4i16, MOVIv8i16, MOVIv2i32, MOVIv4i32], MCReturnStatement< CheckAll< [CheckZeroOperand<1>, CheckZeroOperand<2>]>>>], MCReturnStatement>>; def IsZeroFPIdiomPred : MCSchedPredicate; // Identify EXTR as the alias for ROR (immediate). def IsRORImmIdiomPred : MCSchedPredicate< // EXTR Rd, Rs, Rs, #Imm CheckAll<[CheckOpcode<[EXTRWrri, EXTRXrri]>, CheckSameRegOperand<1, 2>]>>;