Fix PR11985

- BlockAddress has no support of BA + offset form and there is no way to
  propagate that offset into machine operand;
- Add BA + offset support and a new interface 'getTargetBlockAddress' to
  simplify target block address forming;
- All targets are modified to use new interface and X86 backend is enhanced to
  support BA + offset addressing.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163743 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Liao 2012-09-12 21:43:09 +00:00
parent 0d1bc5f916
commit 6c7ccaa3fd
15 changed files with 86 additions and 35 deletions

View File

@ -628,11 +628,11 @@ public:
Op.setTargetFlags(TargetFlags); Op.setTargetFlags(TargetFlags);
return Op; return Op;
} }
static MachineOperand CreateBA(const BlockAddress *BA, static MachineOperand CreateBA(const BlockAddress *BA, int64_t Offset,
unsigned char TargetFlags = 0) { unsigned char TargetFlags = 0) {
MachineOperand Op(MachineOperand::MO_BlockAddress); MachineOperand Op(MachineOperand::MO_BlockAddress);
Op.Contents.OffsetedInfo.Val.BA = BA; Op.Contents.OffsetedInfo.Val.BA = BA;
Op.setOffset(0); // Offset is always 0. Op.setOffset(Offset);
Op.setTargetFlags(TargetFlags); Op.setTargetFlags(TargetFlags);
return Op; return Op;
} }

View File

@ -437,7 +437,13 @@ public:
SDValue getRegisterMask(const uint32_t *RegMask); SDValue getRegisterMask(const uint32_t *RegMask);
SDValue getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label); SDValue getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label);
SDValue getBlockAddress(const BlockAddress *BA, EVT VT, SDValue getBlockAddress(const BlockAddress *BA, EVT VT,
bool isTarget = false, unsigned char TargetFlags = 0); int64_t Offset = 0, bool isTarget = false,
unsigned char TargetFlags = 0);
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT,
int64_t Offset = 0,
unsigned char TargetFlags = 0) {
return getBlockAddress(BA, VT, Offset, true, TargetFlags);
}
SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) { SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) {
return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, return getNode(ISD::CopyToReg, dl, MVT::Other, Chain,

View File

@ -1483,15 +1483,17 @@ public:
class BlockAddressSDNode : public SDNode { class BlockAddressSDNode : public SDNode {
const BlockAddress *BA; const BlockAddress *BA;
int64_t Offset;
unsigned char TargetFlags; unsigned char TargetFlags;
friend class SelectionDAG; friend class SelectionDAG;
BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba,
unsigned char Flags) int64_t o, unsigned char Flags)
: SDNode(NodeTy, DebugLoc(), getSDVTList(VT)), : SDNode(NodeTy, DebugLoc(), getSDVTList(VT)),
BA(ba), TargetFlags(Flags) { BA(ba), Offset(o), TargetFlags(Flags) {
} }
public: public:
const BlockAddress *getBlockAddress() const { return BA; } const BlockAddress *getBlockAddress() const { return BA; }
int64_t getOffset() const { return Offset; }
unsigned char getTargetFlags() const { return TargetFlags; } unsigned char getTargetFlags() const { return TargetFlags; }
static bool classof(const BlockAddressSDNode *) { return true; } static bool classof(const BlockAddressSDNode *) { return true; }

View File

@ -198,7 +198,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
return !strcmp(getSymbolName(), Other.getSymbolName()) && return !strcmp(getSymbolName(), Other.getSymbolName()) &&
getOffset() == Other.getOffset(); getOffset() == Other.getOffset();
case MachineOperand::MO_BlockAddress: case MachineOperand::MO_BlockAddress:
return getBlockAddress() == Other.getBlockAddress(); return getBlockAddress() == Other.getBlockAddress() &&
getOffset() == Other.getOffset();
case MO_RegisterMask: case MO_RegisterMask:
return getRegMask() == Other.getRegMask(); return getRegMask() == Other.getRegMask();
case MachineOperand::MO_MCSymbol: case MachineOperand::MO_MCSymbol:
@ -239,7 +240,7 @@ hash_code llvm::hash_value(const MachineOperand &MO) {
MO.getOffset()); MO.getOffset());
case MachineOperand::MO_BlockAddress: case MachineOperand::MO_BlockAddress:
return hash_combine(MO.getType(), MO.getTargetFlags(), return hash_combine(MO.getType(), MO.getTargetFlags(),
MO.getBlockAddress()); MO.getBlockAddress(), MO.getOffset());
case MachineOperand::MO_RegisterMask: case MachineOperand::MO_RegisterMask:
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask());
case MachineOperand::MO_Metadata: case MachineOperand::MO_Metadata:
@ -362,6 +363,7 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const {
case MachineOperand::MO_BlockAddress: case MachineOperand::MO_BlockAddress:
OS << '<'; OS << '<';
WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false); WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false);
if (getOffset()) OS << "+" << getOffset();
OS << '>'; OS << '>';
break; break;
case MachineOperand::MO_RegisterMask: case MachineOperand::MO_RegisterMask:

View File

@ -410,6 +410,7 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op,
ES->getTargetFlags())); ES->getTargetFlags()));
} else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) { } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress(), MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress(),
BA->getOffset(),
BA->getTargetFlags())); BA->getTargetFlags()));
} else if (TargetIndexSDNode *TI = dyn_cast<TargetIndexSDNode>(Op)) { } else if (TargetIndexSDNode *TI = dyn_cast<TargetIndexSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateTargetIndex(TI->getIndex(), MI->addOperand(MachineOperand::CreateTargetIndex(TI->getIndex(),

View File

@ -494,8 +494,10 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
} }
case ISD::TargetBlockAddress: case ISD::TargetBlockAddress:
case ISD::BlockAddress: { case ISD::BlockAddress: {
ID.AddPointer(cast<BlockAddressSDNode>(N)->getBlockAddress()); const BlockAddressSDNode *BA = cast<BlockAddressSDNode>(N);
ID.AddInteger(cast<BlockAddressSDNode>(N)->getTargetFlags()); ID.AddPointer(BA->getBlockAddress());
ID.AddInteger(BA->getOffset());
ID.AddInteger(BA->getTargetFlags());
break; break;
} }
} // end switch (N->getOpcode()) } // end switch (N->getOpcode())
@ -1470,6 +1472,7 @@ SDValue SelectionDAG::getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label) {
SDValue SelectionDAG::getBlockAddress(const BlockAddress *BA, EVT VT, SDValue SelectionDAG::getBlockAddress(const BlockAddress *BA, EVT VT,
int64_t Offset,
bool isTarget, bool isTarget,
unsigned char TargetFlags) { unsigned char TargetFlags) {
unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress; unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress;
@ -1477,12 +1480,14 @@ SDValue SelectionDAG::getBlockAddress(const BlockAddress *BA, EVT VT,
FoldingSetNodeID ID; FoldingSetNodeID ID;
AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0);
ID.AddPointer(BA); ID.AddPointer(BA);
ID.AddInteger(Offset);
ID.AddInteger(TargetFlags); ID.AddInteger(TargetFlags);
void *IP = 0; void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
return SDValue(E, 0); return SDValue(E, 0);
SDNode *N = new (NodeAllocator) BlockAddressSDNode(Opc, VT, BA, TargetFlags); SDNode *N = new (NodeAllocator) BlockAddressSDNode(Opc, VT, BA, Offset,
TargetFlags);
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);

View File

@ -475,11 +475,16 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
OS << "<" << *M->getMemOperand() << ">"; OS << "<" << *M->getMemOperand() << ">";
} else if (const BlockAddressSDNode *BA = } else if (const BlockAddressSDNode *BA =
dyn_cast<BlockAddressSDNode>(this)) { dyn_cast<BlockAddressSDNode>(this)) {
int64_t offset = BA->getOffset();
OS << "<"; OS << "<";
WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false); WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false);
OS << ", "; OS << ", ";
WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false); WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false);
OS << ">"; OS << ">";
if (offset > 0)
OS << " + " << offset;
else
OS << " " << offset;
if (unsigned int TF = BA->getTargetFlags()) if (unsigned int TF = BA->getTargetFlags())
OS << " [TF=" << TF << ']'; OS << " [TF=" << TF << ']';
} }

View File

@ -274,8 +274,8 @@ bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
else if (AM.JT != -1) else if (AM.JT != -1)
Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/); Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
else if (AM.BlockAddr) else if (AM.BlockAddr)
Disp = CurDAG->getBlockAddress(AM.BlockAddr, MVT::i32, Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
true, 0/*AM.SymbolFlags*/); 0/*AM.SymbolFlags*/);
else else
Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16); Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16);

View File

@ -655,7 +655,7 @@ SDValue MSP430TargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const { SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc(); DebugLoc dl = Op.getDebugLoc();
const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true); SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy());
return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result); return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result);
} }

View File

@ -1620,8 +1620,8 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op,
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) { if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) {
// %hi/%lo relocation // %hi/%lo relocation
SDValue BAHi = DAG.getBlockAddress(BA, MVT::i32, true, MipsII::MO_ABS_HI); SDValue BAHi = DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_HI);
SDValue BALo = DAG.getBlockAddress(BA, MVT::i32, true, MipsII::MO_ABS_LO); SDValue BALo = DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_LO);
SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi); SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo);
return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo);
@ -1630,10 +1630,10 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op,
EVT ValTy = Op.getValueType(); EVT ValTy = Op.getValueType();
unsigned GOTFlag = HasMips64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; unsigned GOTFlag = HasMips64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
unsigned OFSTFlag = HasMips64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; unsigned OFSTFlag = HasMips64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
SDValue BAGOTOffset = DAG.getBlockAddress(BA, ValTy, true, GOTFlag); SDValue BAGOTOffset = DAG.getTargetBlockAddress(BA, ValTy, 0, GOTFlag);
BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy, BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy,
GetGlobalReg(DAG, ValTy), BAGOTOffset); GetGlobalReg(DAG, ValTy), BAGOTOffset);
SDValue BALOOffset = DAG.getBlockAddress(BA, ValTy, true, OFSTFlag); SDValue BALOOffset = DAG.getTargetBlockAddress(BA, ValTy, 0, OFSTFlag);
SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), BAGOTOffset, SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), BAGOTOffset,
MachinePointerInfo(), false, false, false, 0); MachinePointerInfo(), false, false, false, 0);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, BALOOffset); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, BALOOffset);

View File

@ -1264,8 +1264,8 @@ SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op,
unsigned MOHiFlag, MOLoFlag; unsigned MOHiFlag, MOLoFlag;
bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag); bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag);
SDValue TgtBAHi = DAG.getBlockAddress(BA, PtrVT, /*isTarget=*/true, MOHiFlag); SDValue TgtBAHi = DAG.getTargetBlockAddress(BA, PtrVT, 0, MOHiFlag);
SDValue TgtBALo = DAG.getBlockAddress(BA, PtrVT, /*isTarget=*/true, MOLoFlag); SDValue TgtBALo = DAG.getTargetBlockAddress(BA, PtrVT, 0, MOLoFlag);
return LowerLabelRef(TgtBAHi, TgtBALo, isPIC, DAG); return LowerLabelRef(TgtBAHi, TgtBALo, isPIC, DAG);
} }

View File

@ -246,13 +246,15 @@ namespace {
else if (AM.CP) else if (AM.CP)
Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32,
AM.Align, AM.Disp, AM.SymbolFlags); AM.Align, AM.Disp, AM.SymbolFlags);
else if (AM.ES) else if (AM.ES) {
assert(!AM.Disp && "Non-zero displacement is ignored with ES.");
Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags); Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
else if (AM.JT != -1) } else if (AM.JT != -1) {
assert(!AM.Disp && "Non-zero displacement is ignored with JT.");
Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags); Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
else if (AM.BlockAddr) } else if (AM.BlockAddr)
Disp = CurDAG->getBlockAddress(AM.BlockAddr, MVT::i32, Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
true, AM.SymbolFlags); AM.SymbolFlags);
else else
Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32); Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32);
@ -654,10 +656,16 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) {
} else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) { } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
AM.JT = J->getIndex(); AM.JT = J->getIndex();
AM.SymbolFlags = J->getTargetFlags(); AM.SymbolFlags = J->getTargetFlags();
} else { } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(N0)) {
AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress(); X86ISelAddressMode Backup = AM;
AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags(); AM.BlockAddr = BA->getBlockAddress();
AM.SymbolFlags = BA->getTargetFlags();
if (FoldOffsetIntoAddress(BA->getOffset(), AM)) {
AM = Backup;
return true;
} }
} else
llvm_unreachable("Unhandled symbol reference node.");
if (N.getOpcode() == X86ISD::WrapperRIP) if (N.getOpcode() == X86ISD::WrapperRIP)
AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64)); AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
@ -686,10 +694,12 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) {
} else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) { } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
AM.JT = J->getIndex(); AM.JT = J->getIndex();
AM.SymbolFlags = J->getTargetFlags(); AM.SymbolFlags = J->getTargetFlags();
} else { } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(N0)) {
AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress(); AM.BlockAddr = BA->getBlockAddress();
AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags(); AM.Disp += BA->getOffset();
} AM.SymbolFlags = BA->getTargetFlags();
} else
llvm_unreachable("Unhandled symbol reference node.");
return false; return false;
} }

View File

@ -7368,9 +7368,10 @@ X86TargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
Subtarget->ClassifyBlockAddressReference(); Subtarget->ClassifyBlockAddressReference();
CodeModel::Model M = getTargetMachine().getCodeModel(); CodeModel::Model M = getTargetMachine().getCodeModel();
const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
int64_t Offset = cast<BlockAddressSDNode>(Op)->getOffset();
DebugLoc dl = Op.getDebugLoc(); DebugLoc dl = Op.getDebugLoc();
SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy(), Offset,
/*isTarget=*/true, OpFlags); OpFlags);
if (Subtarget->isPICStyleRIPRel() && if (Subtarget->isPICStyleRIPRel() &&
(M == CodeModel::Small || M == CodeModel::Kernel)) (M == CodeModel::Small || M == CodeModel::Kernel))

View File

@ -298,7 +298,7 @@ LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
DebugLoc DL = Op.getDebugLoc(); DebugLoc DL = Op.getDebugLoc();
const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true); SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy());
return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, getPointerTy(), Result); return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, getPointerTy(), Result);
} }

View File

@ -0,0 +1,19 @@
; RUN: llc < %s -mtriple=x86_64-pc-linux -mcpu=prescott | FileCheck %s
define float @foo(i8* nocapture %buf, float %a, float %b) nounwind uwtable {
entry:
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* blockaddress(@foo, %out), i64 22, i32 1, i1 false)
br label %out
out: ; preds = %entry
%add = fadd float %a, %b
ret float %add
; CHECK: foo
; CHECK: movw .L{{.*}}+20(%rip), %{{.*}}
; CHECK: movl .L{{.*}}+16(%rip), %{{.*}}
; CHECK: movq .L{{.*}}+8(%rip), %{{.*}}
; CHECK: movq .L{{.*}}(%rip), %{{.*}}
; CHECK: ret
}
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind