Index: llvm/lib/Target/ARM/ARMScheduleA57.td =================================================================== --- llvm/lib/Target/ARM/ARMScheduleA57.td +++ llvm/lib/Target/ARM/ARMScheduleA57.td @@ -29,22 +29,46 @@ def IsR1P0AndLaterPred : SchedPredicate<[{false}]>; // If Addrmode3 contains register offset (not immediate) -def IsLdrAm3RegOffPred : - SchedPredicate<[{!TII->isAddrMode3OpImm(*MI, 1)}]>; +def IsLdrAm3RegOff : CheckFunctionPredicate< + "!ARM_MC::isAddrMode3OpImm(, 1)", + "!TII->isAddrMode3OpImm(, 1)" +>; + +def IsLdrAm3RegOffX2 : CheckFunctionPredicate< + "!ARM_MC::isAddrMode3OpImm(, 2)", + "!TII->isAddrMode3OpImm(, 2)" +>; + +def IsLdrAm3RegOffX3 : CheckFunctionPredicate< + "!ARM_MC::isAddrMode3OpImm(, 3)", + "!TII->isAddrMode3OpImm(, 3)" +>; + +def IsLdrAm3RegOffPred : MCSchedPredicate; // The same predicate with operand offset 2 and 3: -def IsLdrAm3RegOffPredX2 : - SchedPredicate<[{!TII->isAddrMode3OpImm(*MI, 2)}]>; -def IsLdrAm3RegOffPredX3 : - SchedPredicate<[{!TII->isAddrMode3OpImm(*MI, 3)}]>; +def IsLdrAm3RegOffPredX2 : MCSchedPredicate; +def IsLdrAm3RegOffPredX3 : MCSchedPredicate; // If Addrmode3 contains "minus register" -def IsLdrAm3NegRegOffPred : - SchedPredicate<[{TII->isAddrMode3OpMinusReg(*MI, 1)}]>; +def IsLdrAm3NegRegOff : CheckFunctionPredicate< + "ARM_MC::isAddrMode3OpMinusReg(, 1)", + "TII->isAddrMode3OpMinusReg(, 1)" +>; + +def IsLdrAm3NegRegOffX2 : CheckFunctionPredicate< + "ARM_MC::isAddrMode3OpMinusReg(, 2)", + "TII->isAddrMode3OpMinusReg(, 2)" +>; + +def IsLdrAm3NegRegOffX3 : CheckFunctionPredicate< + "ARM_MC::isAddrMode3OpMinusReg(, 3)", + "TII->isAddrMode3OpMinusReg(, 3)" +>; + +def IsLdrAm3NegRegOffPred : MCSchedPredicate; // The same predicate with operand offset 2 and 3: -def IsLdrAm3NegRegOffPredX2 : - SchedPredicate<[{TII->isAddrMode3OpMinusReg(*MI, 2)}]>; -def IsLdrAm3NegRegOffPredX3 : - SchedPredicate<[{TII->isAddrMode3OpMinusReg(*MI, 3)}]>; +def IsLdrAm3NegRegOffPredX2 : MCSchedPredicate; +def IsLdrAm3NegRegOffPredX3 : MCSchedPredicate; // Load, scaled register offset, not plus LSL2 def IsLdstsoScaledNotOptimalPredX0 : Index: llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h =================================================================== --- llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h +++ llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h @@ -45,6 +45,8 @@ bool isPredicated(const MCInst &MI, const MCInstrInfo *MCII); bool isCPSRDefined(const MCInst &MI, const MCInstrInfo *MCII); +bool isAddrMode3OpImm(const MCInst &MI, unsigned Op); +bool isAddrMode3OpMinusReg(const MCInst &MI, unsigned Op); /// Create a ARM MCSubtargetInfo instance. This is exposed so Asm parser, etc. /// do not need to go through TargetRegistry. Index: llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "ARMMCTargetDesc.h" +#include "ARMAddressingModes.h" #include "ARMBaseInfo.h" #include "ARMInstPrinter.h" #include "ARMMCAsmInfo.h" @@ -198,6 +199,22 @@ return false; } +bool ARM_MC::isAddrMode3OpImm(const MCInst &MI, unsigned Op) { + const MCOperand &Offset = MI.getOperand(Op + 1); + return Offset.getReg() != 0; +} + +bool ARM_MC::isAddrMode3OpMinusReg(const MCInst &MI, unsigned Op) { + const MCOperand &Offset = MI.getOperand(Op + 1); + const MCOperand &Opc = MI.getOperand(Op + 2); + assert(Opc.isImm()); + assert(Offset.isReg()); + int64_t OpcImm = Opc.getImm(); + + bool isSub = ARM_AM::getAM3Op(OpcImm) == ARM_AM::sub; + return (isSub && Offset.getReg() != 0); +} + MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU); Index: llvm/test/tools/llvm-mca/ARM/cortex-a57-memory-instructions.s =================================================================== --- llvm/test/tools/llvm-mca/ARM/cortex-a57-memory-instructions.s +++ llvm/test/tools/llvm-mca/ARM/cortex-a57-memory-instructions.s @@ -180,7 +180,7 @@ # CHECK-NEXT: 2 4 1.00 * ldrbt r1, [r2], -r6, lsl #12 # CHECK-NEXT: 2 4 2.00 * ldrd r0, r1, [r5] # CHECK-NEXT: 2 4 2.00 * ldrd r8, r9, [r2, #15] -# CHECK-NEXT: 4 4 2.00 * ldrd r2, r3, [r9, #32]! +# CHECK-NEXT: 4 5 2.00 * ldrd r2, r3, [r9, #32]! # CHECK-NEXT: 4 4 2.00 * ldrd r6, r7, [r1], #8 # CHECK-NEXT: 4 4 2.00 * ldrd r2, r3, [r8], #0 # CHECK-NEXT: 4 4 2.00 * ldrd r2, r3, [r8], #0 Index: llvm/utils/TableGen/PredicateExpander.cpp =================================================================== --- llvm/utils/TableGen/PredicateExpander.cpp +++ llvm/utils/TableGen/PredicateExpander.cpp @@ -210,11 +210,25 @@ OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)"; } +std::pair parseFunctionNameAndArgs(StringRef Fn) { + size_t Begin = Fn.rfind('('); + StringRef Name = Fn.substr(0, Begin); + if (Begin == StringRef::npos) + return {Name, ""}; + size_t End = Fn.rfind(')'); + if (End == StringRef::npos || End < Begin) + return {Name, ""}; + return {Name, Fn.substr(Begin + 1, End - Begin - 1)}; +} + void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn) { - OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn) - << (isByRef() ? "(MI)" : "(*MI)"); + auto NameAndArgs = shouldExpandForMC() + ? parseFunctionNameAndArgs(MCInstFn) + : parseFunctionNameAndArgs(MachineInstrFn); + OS << NameAndArgs.first << "(" << (isByRef() ? "MI" : "*MI") + << NameAndArgs.second << ")"; } void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,