diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 5bdec80ac42..5813abe527d 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -673,6 +673,13 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *Exp = MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_HA, OutContext); + + if (!MO.isJTI() && MO.getOffset()) + Exp = MCBinaryExpr::createAdd(Exp, + MCConstantExpr::create(MO.getOffset(), + OutContext), + OutContext); + TmpInst.getOperand(2) = MCOperand::createExpr(Exp); EmitToStreamer(*OutStreamer, TmpInst); return; diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 23ee3e7312f..56e39221edf 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4381,9 +4381,30 @@ void PPCDAGToDAGISel::PeepholePPC64() { MaxDisplacement = std::min((int) GV->getAlignment() - 1, MaxDisplacement); } + bool UpdateHBase = false; + SDValue HBase = Base.getOperand(0); + int Offset = N->getConstantOperandVal(FirstOp); - if (Offset < 0 || Offset > MaxDisplacement) - continue; + if (Offset < 0 || Offset > MaxDisplacement) { + // If we have a addi(toc@l)/addis(toc@ha) pair, and the addis has only + // one use, then we can do this for any offset, we just need to also + // update the offset (i.e. the symbol addend) on the addis also. + if (Base.getMachineOpcode() != PPC::ADDItocL) + continue; + + if (!HBase.isMachineOpcode() || + HBase.getMachineOpcode() != PPC::ADDIStocHA) + continue; + + if (!Base.hasOneUse() || !HBase.hasOneUse()) + continue; + + SDValue HImmOpnd = HBase.getOperand(1); + if (HImmOpnd != ImmOpnd) + continue; + + UpdateHBase = true; + } // We found an opportunity. Reverse the operands from the add // immediate and substitute them into the load or store. If @@ -4426,6 +4447,10 @@ void PPCDAGToDAGISel::PeepholePPC64() { (void)CurDAG->UpdateNodeOperands(N, ImmOpnd, Base.getOperand(0), N->getOperand(2)); + if (UpdateHBase) + (void)CurDAG->UpdateNodeOperands(HBase.getNode(), HBase.getOperand(0), + ImmOpnd); + // The add-immediate may now be dead, in which case remove it. if (Base.getNode()->use_empty()) CurDAG->RemoveDeadNode(Base.getNode()); diff --git a/test/CodeGen/PowerPC/peephole-align.ll b/test/CodeGen/PowerPC/peephole-align.ll index 1be84170734..3b35e6234bd 100644 --- a/test/CodeGen/PowerPC/peephole-align.ll +++ b/test/CodeGen/PowerPC/peephole-align.ll @@ -227,11 +227,9 @@ entry: ret void } -; register 3 is the return value, so it should be chosen ; CHECK-LABEL: test_singleuse: -; CHECK: addis 3, 2, d2v@toc@ha -; CHECK: addi 3, 3, d2v@toc@l -; CHECK: ld 3, 8(3) +; CHECK: addis [[REG:[0-9]+]], 2, d2v@toc@ha+8 +; CHECK: ld 3, d2v@toc@l+8([[REG]]) define i64 @test_singleuse() nounwind { entry: %0 = load i64, i64* getelementptr inbounds (%struct.d2, %struct.d2* @d2v, i32 0, i32 1), align 8