diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2553,7 +2553,9 @@ bool Global = GSDN && GSDN->getTargetFlags() == PPCII::MO_PCREL_FLAG; JumpTableSDNode *JT = dyn_cast(N.getNode()); bool JumpTable = JT && JT->getTargetFlags() == PPCII::MO_PCREL_FLAG; - if (ConstPool || Global || JumpTable) { + BlockAddressSDNode *BASDN = dyn_cast(N.getNode()); + bool BlockAddress = BASDN && BASDN->getTargetFlags() == PPCII::MO_PCREL_FLAG; + if (ConstPool || Global || JumpTable || BlockAddress) { Base = N; return true; } @@ -2890,6 +2892,13 @@ // 64-bit SVR4 ABI and AIX ABI code are always position-independent. // The actual BlockAddress is stored in the TOC. if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) { + if (Subtarget.hasPCRelativeMemops()) { + SDLoc DL(BASDN); + EVT Ty = getPointerTy(DAG.getDataLayout()); + SDValue GA = DAG.getTargetBlockAddress(BA, Ty, BASDN->getOffset(), + PPCII::MO_PCREL_FLAG); + return DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, GA); + } setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset()); return getTOCEntry(DAG, SDLoc(BASDN), GA); diff --git a/llvm/test/CodeGen/PowerPC/block-address.ll b/llvm/test/CodeGen/PowerPC/block-address.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/block-address.ll @@ -0,0 +1,17 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=future -ppc-asm-full-reg-names < %s | FileCheck %s \ +; RUN: --check-prefix=CHECK +define dso_local void @blockaddress() { +; CHECK-LABEL: blockaddress: +; CHECK: # %bb.0: # %entry +; CHECK: paddi r3, 0, .Ltmp0@PCREL, 1 +; CHECK: bl helper@notoc +entry: + tail call void @helper(i8* blockaddress(@blockaddress, %label)) + br label %label + +label: ; preds = %entry + ret void +} + +declare void @helper(i8*)