| //===- 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 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">; | |
| } | |
| // 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>; | |
| } | |
| // Generic predicates. | |
| // Identify whether an instruction is NEON or floating point | |
| def CheckFpOrNEON : CheckFunctionPredicateWithTII< | |
| "AArch64_MC::isFpOrNEON", | |
| "AArch64InstrInfo::isFpOrNEON" | |
| >; | |
| // 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<!listconcat(IsArithImmOp.ValidOpcodes, | |
| IsLogicImmOp.ValidOpcodes)>; | |
| // Identify arithmetic and logic instructions with shift. | |
| def IsArithLogicShiftOp : CheckOpcode<!listconcat(IsArithShiftOp.ValidOpcodes, | |
| IsLogicShiftOp.ValidOpcodes)>; | |
| // Identify arithmetic and logic instructions without shift. | |
| def IsArithLogicUnshiftOp : CheckOpcode<!listconcat(IsArithUnshiftOp.ValidOpcodes, | |
| IsLogicUnshiftOp.ValidOpcodes)>; | |
| // 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<!listconcat(IsLoadASIMDPostOp.ValidOpcodes, | |
| IsStoreASIMDPostOp.ValidOpcodes)>; | |
| // 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<!listconcat(IsLoadRegOffsetOp.ValidOpcodes, | |
| IsStoreRegOffsetOp.ValidOpcodes)>; | |
| // Target predicates. | |
| // 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< | |
| [CheckIsRegOperand<1>, | |
| CheckIsRegOperand<2>, | |
| CheckAny< | |
| [CheckRegOperand<1, WZR>, | |
| CheckRegOperand<1, XZR>]>, | |
| CheckShiftBy0]>>>], | |
| MCReturnStatement<FalsePred>>>; | |
| def IsCopyIdiomPred : MCSchedPredicate<IsCopyIdiomFn>; | |
| // Identify arithmetic instructions with an extended register. | |
| def RegExtendedFn : TIIPredicate<"hasExtendedReg", | |
| MCOpcodeSwitchStatement< | |
| [MCOpcodeSwitchCase< | |
| IsArithExtOp.ValidOpcodes, | |
| MCReturnStatement< | |
| CheckNot<CheckZeroOperand<3>>>>], | |
| MCReturnStatement<FalsePred>>>; | |
| def RegExtendedPred : MCSchedPredicate<RegExtendedFn>; | |
| // Identify arithmetic and logic instructions with a shifted register. | |
| def RegShiftedFn : TIIPredicate<"hasShiftedReg", | |
| MCOpcodeSwitchStatement< | |
| [MCOpcodeSwitchCase< | |
| IsArithLogicShiftOp.ValidOpcodes, | |
| MCReturnStatement< | |
| CheckNot<CheckZeroOperand<3>>>>], | |
| MCReturnStatement<FalsePred>>>; | |
| def RegShiftedPred : MCSchedPredicate<RegShiftedFn>; | |
| // 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<CheckMemExtLSL>, | |
| CheckMemScaled]>>>], | |
| MCReturnStatement<FalsePred>>>; | |
| def ScaledIdxPred : MCSchedPredicate<ScaledIdxFn>; | |
| // 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<CheckZeroOperand<1>>>, | |
| // MOVI Vd, #0, LSL #0 | |
| MCOpcodeSwitchCase< | |
| [MOVIv4i16, MOVIv8i16, | |
| MOVIv2i32, MOVIv4i32], | |
| MCReturnStatement< | |
| CheckAll< | |
| [CheckZeroOperand<1>, | |
| CheckZeroOperand<2>]>>>], | |
| MCReturnStatement<FalsePred>>>; | |
| def IsZeroFPIdiomPred : MCSchedPredicate<IsZeroFPIdiomFn>; | |
| // 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< | |
| [CheckIsRegOperand<1>, | |
| CheckAny< | |
| [CheckRegOperand<1, WZR>, | |
| CheckRegOperand<1, XZR>]>, | |
| CheckZeroOperand<2>]>>>], | |
| MCReturnStatement<FalsePred>>>; | |
| def IsZeroIdiomPred : MCSchedPredicate<IsZeroIdiomFn>; |