diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3695,7 +3695,8 @@ (Locality << 1) | // Cache level bits (unsigned)IsStream; // Stream bit return DAG.getNode(AArch64ISD::PREFETCH, DL, MVT::Other, Op.getOperand(0), - DAG.getConstant(PrfOp, DL, MVT::i32), Op.getOperand(1)); + DAG.getTargetConstant(PrfOp, DL, MVT::i32), + Op.getOperand(1)); } SDValue AArch64TargetLowering::LowerFP_EXTEND(SDValue Op, diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -3890,7 +3890,7 @@ multiclass PrefetchRO sz, bit V, bits<2> opc, string asm> { def roW : BasePrefetchRO { let Inst{13} = 0b0; @@ -3898,7 +3898,7 @@ def roX : BasePrefetchRO { let Inst{13} = 0b1; diff --git a/llvm/lib/Target/AArch64/AArch64InstrGISel.td b/llvm/lib/Target/AArch64/AArch64InstrGISel.td --- a/llvm/lib/Target/AArch64/AArch64InstrGISel.td +++ b/llvm/lib/Target/AArch64/AArch64InstrGISel.td @@ -209,6 +209,12 @@ let hasSideEffects = 0; } +def G_PREFETCH : AArch64GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$imm, ptype0:$src1); + let hasSideEffects = 1; +} + def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; @@ -241,6 +247,8 @@ def : GINodeEquiv; +def : GINodeEquiv; + // These are patterns that we only use for GlobalISel via the importer. def : Pat<(f32 (fadd (vector_extract (v2f32 FPR64:$Rn), (i64 0)), (vector_extract (v2f32 FPR64:$Rn), (i64 1)))), diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2938,7 +2938,7 @@ // Pre-fetch. def PRFMui : PrefetchUI<0b11, 0, 0b10, "prfm", - [(AArch64Prefetch imm:$Rt, + [(AArch64Prefetch timm:$Rt, (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))]>; @@ -3183,7 +3183,7 @@ // Pre-fetch. defm PRFUM : PrefetchUnscaled<0b11, 0, 0b10, "prfum", - [(AArch64Prefetch imm:$Rt, + [(AArch64Prefetch timm:$Rt, (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>; //--- diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -1025,6 +1025,30 @@ Value.setReg(ZExtValueReg); return true; } + case Intrinsic::prefetch: { + MachineIRBuilder MIB(MI); + auto &AddrVal = MI.getOperand(1); + + int64_t IsWrite = MI.getOperand(2).getImm(); + int64_t Locality = MI.getOperand(3).getImm(); + int64_t IsData = MI.getOperand(4).getImm(); + + bool IsStream = Locality == 0; + if (Locality != 0) { + assert(Locality <= 3 && "Prefetch locality out-of-range"); + // The locality degree is the opposite of the cache speed. + // Put the number the other way around. + // The encoding starts at 0 for level 1 + Locality = 3 - Locality; + } + + unsigned PrfOp = + (IsWrite << 4) | (!IsData << 3) | (Locality << 1) | IsStream; + + MIB.buildInstr(AArch64::G_PREFETCH).addImm(PrfOp).add(AddrVal); + MI.eraseFromParent(); + return true; + } } return true; diff --git a/llvm/test/CodeGen/AArch64/arm64-prefetch.ll b/llvm/test/CodeGen/AArch64/arm64-prefetch.ll --- a/llvm/test/CodeGen/AArch64/arm64-prefetch.ll +++ b/llvm/test/CodeGen/AArch64/arm64-prefetch.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s +; RUN: llc -O0 --global-isel-abort=1 < %s -mtriple=arm64-eabi | FileCheck %s @a = common global i32* null, align 8