include "AArch64Schedule.td"
include "AArch64InstrInfo.td"
+include "AArch64SchedPredicates.td"
def AArch64InstrInfo : InstrInfo;
return 0;
}
-/// Return true if this is load/store scales or extends its register offset.
-/// This refers to scaling a dynamic index as opposed to scaled immediates.
-/// MI should be a memory op that allows scaled addressing.
-bool AArch64InstrInfo::isScaledAddr(const MachineInstr &MI) {
- switch (MI.getOpcode()) {
- default:
- break;
- case AArch64::LDRBBroW:
- case AArch64::LDRBroW:
- case AArch64::LDRDroW:
- case AArch64::LDRHHroW:
- case AArch64::LDRHroW:
- case AArch64::LDRQroW:
- case AArch64::LDRSBWroW:
- case AArch64::LDRSBXroW:
- case AArch64::LDRSHWroW:
- case AArch64::LDRSHXroW:
- case AArch64::LDRSWroW:
- case AArch64::LDRSroW:
- case AArch64::LDRWroW:
- case AArch64::LDRXroW:
- case AArch64::STRBBroW:
- case AArch64::STRBroW:
- case AArch64::STRDroW:
- case AArch64::STRHHroW:
- case AArch64::STRHroW:
- case AArch64::STRQroW:
- case AArch64::STRSroW:
- case AArch64::STRWroW:
- case AArch64::STRXroW:
- case AArch64::LDRBBroX:
- case AArch64::LDRBroX:
- case AArch64::LDRDroX:
- case AArch64::LDRHHroX:
- case AArch64::LDRHroX:
- case AArch64::LDRQroX:
- case AArch64::LDRSBWroX:
- case AArch64::LDRSBXroX:
- case AArch64::LDRSHWroX:
- case AArch64::LDRSHXroX:
- case AArch64::LDRSWroX:
- case AArch64::LDRSroX:
- case AArch64::LDRWroX:
- case AArch64::LDRXroX:
- case AArch64::STRBBroX:
- case AArch64::STRBroX:
- case AArch64::STRDroX:
- case AArch64::STRHHroX:
- case AArch64::STRHroX:
- case AArch64::STRQroX:
- case AArch64::STRSroX:
- case AArch64::STRWroX:
- case AArch64::STRXroX:
-
- unsigned Val = MI.getOperand(3).getImm();
- AArch64_AM::ShiftExtendType ExtType = AArch64_AM::getMemExtendType(Val);
- return (ExtType != AArch64_AM::UXTX) || AArch64_AM::getMemDoShift(Val);
- }
- return false;
-}
-
/// Check all MachineMemOperands for a hint to suppress pairing.
bool AArch64InstrInfo::isLdStPairSuppressed(const MachineInstr &MI) {
return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
MachineFunction &MF) const {
return MF.getFunction().optForMinSize();
}
+
+#define GET_TII_HELPERS
+#include "AArch64GenInstrInfo.inc"
/// Does this instruction rename an FPR without modifying bits?
static bool isFPRCopy(const MachineInstr &MI);
- /// Return true if this is load/store scales or extends its register offset.
- /// This refers to scaling a dynamic index as opposed to scaled immediates.
- /// MI should be a memory op that allows scaled addressing.
- static bool isScaledAddr(const MachineInstr &MI);
-
/// Return true if pairing the given load or store is hinted to be
/// unprofitable.
static bool isLdStPairSuppressed(const MachineInstr &MI);
/// on Windows.
static bool isSEHInstruction(const MachineInstr &MI);
+#define GET_TII_HELPER_DECLS
+#include "AArch64GenInstrInfo.inc"
+
private:
/// Sets the offsets on outlined instructions in \p MBB which use SP
/// so that they will be valid post-outlining.
--- /dev/null
+//===- AArch64SchedPredicates.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 subtargets.
+//
+//===----------------------------------------------------------------------===//
+
+// Function mappers.
+
+// 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<3>;
+
+// Generic predicates.
+
+// Identify whether an instruction is a load
+// using the register offset addressing mode.
+def IsLoadRegOffsetPred : 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]>;
+
+// Identify whether an instruction is a load
+// using the register offset addressing mode.
+def IsStoreRegOffsetPred : CheckOpcode<[STRBBroW, STRBBroX,
+ STRHHroW, STRHHroX,
+ STRWroW, STRWroX,
+ STRXroW, STRXroX,
+ STRBroW, STRBroX,
+ STRHroW, STRHroX,
+ STRSroW, STRSroX,
+ STRDroW, STRDroX]>;
+
+// Target predicates.
+
+// Identify a load or store using the register offset addressing mode
+// with an extended or scaled register.
+def ScaledIdxFn : TIIPredicate<"isScaledAddr",
+ MCOpcodeSwitchStatement<
+ [MCOpcodeSwitchCase<
+ !listconcat(IsLoadRegOffsetPred.ValidOpcodes,
+ IsStoreRegOffsetPred.ValidOpcodes),
+ MCReturnStatement<
+ CheckAny<[CheckNot<CheckMemExtLSL>,
+ CheckMemScaled]>>>],
+ MCReturnStatement<FalsePred>>>;
+def ScaledIdxPred : MCSchedPredicate<ScaledIdxFn>;
// Predicate for determining when a extendedable register is extended.
def RegExtendedPred : SchedPredicate<[{TII->hasExtendedReg(*MI)}]>;
-// ScaledIdxPred is true if a WriteLDIdx operand will be
-// scaled. Subtargets can use this to dynamically select resources and
-// latency for WriteLDIdx and ReadAdrBase.
-def ScaledIdxPred : SchedPredicate<[{TII->isScaledAddr(*MI)}]>;
-
// Serialized two-level address load.
// EXAMPLE: LOADGot
def WriteLDAdr : WriteSequence<[WriteAdr, WriteLD]>;
#include "AArch64Subtarget.h"
#include "AArch64.h"
-#include "AArch64InstrInfo.h"
-#include "AArch64PBQPRegAlloc.h"
-#include "AArch64TargetMachine.h"
-
#include "AArch64CallLowering.h"
+#include "AArch64InstrInfo.h"
#include "AArch64LegalizerInfo.h"
+#include "AArch64PBQPRegAlloc.h"
#include "AArch64RegisterBankInfo.h"
+#include "AArch64TargetMachine.h"
+#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include "llvm/IR/GlobalValue.h"
#include "AArch64MCAsmInfo.h"
#include "AArch64WinCOFFStreamer.h"
#include "InstPrinter/AArch64InstPrinter.h"
+#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCInstrAnalysis.h"
using namespace llvm;
#define GET_INSTRINFO_MC_DESC
+#define GET_GENINSTRINFO_MC_HELPERS
#include "AArch64GenInstrInfo.inc"
#define GET_SUBTARGETINFO_MC_DESC
// Defines symbolic names for the AArch64 instructions.
//
#define GET_INSTRINFO_ENUM
+#define GET_GENINSTRINFO_MC_DECL
#include "AArch64GenInstrInfo.inc"
#define GET_SUBTARGETINFO_ENUM
# CHECK: Iterations: 100
# CHECK-NEXT: Instructions: 300
-# CHECK-NEXT: Total Cycles: 156
-# CHECK-NEXT: Total uOps: 300
+# CHECK-NEXT: Total Cycles: 157
+# CHECK-NEXT: Total uOps: 500
# CHECK: Dispatch Width: 6
-# CHECK-NEXT: uOps Per Cycle: 1.92
-# CHECK-NEXT: IPC: 1.92
+# CHECK-NEXT: uOps Per Cycle: 3.18
+# CHECK-NEXT: IPC: 1.91
# CHECK-NEXT: Block RThroughput: 1.5
# CHECK: Instruction Info:
# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
# CHECK-NEXT: 1 4 0.50 * ldr x7, [x1, #8]
-# CHECK-NEXT: 1 4 0.50 * ldr x6, [x1, x2]
-# CHECK-NEXT: 1 4 0.50 * ldr x4, [x1, x2, sxtx]
+# CHECK-NEXT: 2 5 0.50 * ldr x6, [x1, x2]
+# CHECK-NEXT: 2 5 0.50 * ldr x4, [x1, x2, sxtx]