Skip to content

Commit

Permalink
[PowerPC] For larger offsets, when possible, fold offset into addis t…
Browse files Browse the repository at this point in the history
…oc@ha

When we have an offset into a global, etc. that is accessed relative to the TOC
base pointer, and the offset is larger than the minimum alignment of the global
itself and the TOC base pointer (which is 8-byte aligned), we can still fold
the @toc@ha into the memory access, but we must update the addis instruction's
symbol reference with the offset as the symbol addend. When there is only one
use of the addi to be folded and only one use of the addis that would need its
symbol's offset adjusted, then we can make the adjustment and fold the @toc@l
into the memory access.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280545 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Hal Finkel committed Sep 2, 2016
1 parent 5bcf846 commit bcc57c0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
7 changes: 7 additions & 0 deletions lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
29 changes: 27 additions & 2 deletions lib/Target/PowerPC/PPCISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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());
Expand Down
6 changes: 2 additions & 4 deletions test/CodeGen/PowerPC/peephole-align.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit bcc57c0

Please sign in to comment.