Skip to content

Commit b37c7ed

Browse files
committed
[PPC][AIX] Fix toc-data peephole bug and some related cleanup.
Set the ReplaceFlags variable to false, since there is code meant only for the ADDItocHi/ADDItocL nodes. This has the side effect of disabling the peephole when the load/store instruction has a non-zero offset. This patch also fixes retrieving the `ImmOpnd` node from the AIX small code model pseduos and does the same for the register operand node. This allows cleaning up the later calls to replaceOperands. Finally move calculating the MaxOffset into the code guarded by ReplaceFlags as it is only used there and the comment is specific to the ELF ABI. Fixes llvm#63927 Differential Revision: https://reviews.llvm.org/D155957
1 parent 6a0a19a commit b37c7ed

File tree

2 files changed

+67
-41
lines changed

2 files changed

+67
-41
lines changed

llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7635,6 +7635,7 @@ void PPCDAGToDAGISel::PeepholePPC64() {
76357635
break;
76367636
case PPC::ADDItoc:
76377637
case PPC::ADDItoc8:
7638+
ReplaceFlags = false;
76387639
if (RequiresMod4Offset) {
76397640
if (GlobalAddressSDNode *GA =
76407641
dyn_cast<GlobalAddressSDNode>(Base.getOperand(0))) {
@@ -7649,42 +7650,58 @@ void PPCDAGToDAGISel::PeepholePPC64() {
76497650
break;
76507651
}
76517652

7652-
SDValue ImmOpnd = Base.getOperand(1);
7653+
const unsigned BaseOpcode = Base.getMachineOpcode();
7654+
// ADDItoc and ADDItoc8 are pseudos used exclusively by AIX small code
7655+
// model when a global is defined in the TOC.
7656+
const bool OpcodeIsAIXSmallTocData =
7657+
BaseOpcode == PPC::ADDItoc || BaseOpcode == PPC::ADDItoc8;
76537658

7654-
// On PPC64, the TOC base pointer is guaranteed by the ABI only to have
7655-
// 8-byte alignment, and so we can only use offsets less than 8 (otherwise,
7656-
// we might have needed different @ha relocation values for the offset
7657-
// pointers).
7658-
int MaxDisplacement = 7;
7659-
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
7660-
const GlobalValue *GV = GA->getGlobal();
7661-
Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
7662-
MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement);
7659+
SDValue RegOperand;
7660+
SDValue ImmOpnd;
7661+
// The AIX small code model nodes have the operands reversed.
7662+
if (OpcodeIsAIXSmallTocData) {
7663+
RegOperand = Base.getOperand(1);
7664+
ImmOpnd = Base.getOperand(0);
7665+
} else {
7666+
RegOperand = Base.getOperand(0);
7667+
ImmOpnd = Base.getOperand(1);
76637668
}
76647669

7665-
bool UpdateHBase = false;
7666-
SDValue HBase = Base.getOperand(0);
7667-
76687670
int Offset = N->getConstantOperandVal(FirstOp);
7671+
7672+
SDValue HBase;
7673+
bool UpdateHBase = false;
76697674
if (ReplaceFlags) {
7675+
// On PPC64, the TOC base pointer is guaranteed by the ABI only to have
7676+
// 8-byte alignment, and so we can only use offsets less than 8
7677+
// (otherwise, we might have needed different @ha relocation values for
7678+
// the offset pointers).
7679+
int MaxDisplacement = 7;
7680+
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
7681+
const GlobalValue *GV = GA->getGlobal();
7682+
Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
7683+
MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement);
7684+
}
7685+
76707686
if (Offset < 0 || Offset > MaxDisplacement) {
76717687
// If we have a addi(toc@l)/addis(toc@ha) pair, and the addis has only
76727688
// one use, then we can do this for any offset, we just need to also
76737689
// update the offset (i.e. the symbol addend) on the addis also.
7674-
if (Base.getMachineOpcode() != PPC::ADDItocL)
7690+
if (BaseOpcode != PPC::ADDItocL)
76757691
continue;
76767692

7677-
if (!HBase.isMachineOpcode() ||
7678-
HBase.getMachineOpcode() != PPC::ADDIStocHA8)
7693+
if (!RegOperand.isMachineOpcode() ||
7694+
RegOperand.getMachineOpcode() != PPC::ADDIStocHA8)
76797695
continue;
76807696

7681-
if (!Base.hasOneUse() || !HBase.hasOneUse())
7697+
if (!Base.hasOneUse() || !RegOperand.hasOneUse())
76827698
continue;
76837699

7684-
SDValue HImmOpnd = HBase.getOperand(1);
7700+
SDValue HImmOpnd = RegOperand.getOperand(1);
76857701
if (HImmOpnd != ImmOpnd)
76867702
continue;
76877703

7704+
HBase = RegOperand;
76887705
UpdateHBase = true;
76897706
}
76907707
} else {
@@ -7709,10 +7726,10 @@ void PPCDAGToDAGISel::PeepholePPC64() {
77097726
}
77107727
}
77117728

7712-
// We found an opportunity. Reverse the operands from the add
7713-
// immediate and substitute them into the load or store. If
7714-
// needed, update the target flags for the immediate operand to
7715-
// reflect the necessary relocation information.
7729+
// We found an opportunity. Forward the operands from the add
7730+
// immediate to the load or store. If needed, update the target
7731+
// flags for the immediate operand to reflect the necessary
7732+
// relocation information.
77167733
LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: ");
77177734
LLVM_DEBUG(Base->dump(CurDAG));
77187735
LLVM_DEBUG(dbgs() << "\nN: ");
@@ -7728,6 +7745,10 @@ void PPCDAGToDAGISel::PeepholePPC64() {
77287745
Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
77297746
// We can't perform this optimization for data whose alignment
77307747
// is insufficient for the instruction encoding.
7748+
// TODO FIXME Verify and document why the offset must be a multiple of
7749+
// 4 when the aligment is less than 4. It is not about the encoding of
7750+
// the instruction: the value of Offset comes directly from the original
7751+
// load/store instruction on the path that reaches this check.
77317752
if (Alignment < 4 && (RequiresMod4Offset || (Offset % 4) != 0)) {
77327753
LLVM_DEBUG(dbgs() << "Rejected this candidate for alignment.\n\n");
77337754
continue;
@@ -7741,27 +7762,12 @@ void PPCDAGToDAGISel::PeepholePPC64() {
77417762
}
77427763
}
77437764

7744-
const unsigned BaseOpcode = Base.getMachineOpcode();
7745-
// ADDItoc and ADDItoc8 are pseudos used exclusively by AIX small code
7746-
// model when a global is defined in the TOC.
7747-
const bool OpcodeIsAIXTocData =
7748-
BaseOpcode == PPC::ADDItoc || BaseOpcode == PPC::ADDItoc8;
7749-
77507765
if (FirstOp == 1) // Store
7751-
if (OpcodeIsAIXTocData)
7752-
(void)CurDAG->UpdateNodeOperands(N, N->getOperand(0),
7753-
Base.getOperand(0), Base.getOperand(1),
7754-
N->getOperand(3));
7755-
else
7756-
(void)CurDAG->UpdateNodeOperands(N, N->getOperand(0), ImmOpnd,
7757-
Base.getOperand(0), N->getOperand(3));
7766+
(void)CurDAG->UpdateNodeOperands(N, N->getOperand(0), ImmOpnd, RegOperand,
7767+
N->getOperand(3));
77587768
else // Load
7759-
if (OpcodeIsAIXTocData)
7760-
(void)CurDAG->UpdateNodeOperands(N, Base.getOperand(0),
7761-
Base.getOperand(1), N->getOperand(2));
7762-
else
7763-
(void)CurDAG->UpdateNodeOperands(N, ImmOpnd, Base.getOperand(0),
7764-
N->getOperand(2));
7769+
(void)CurDAG->UpdateNodeOperands(N, ImmOpnd, RegOperand,
7770+
N->getOperand(2));
77657771

77667772
if (UpdateHBase)
77677773
(void)CurDAG->UpdateNodeOperands(HBase.getNode(), HBase.getOperand(0),
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | \
2+
; RUN: FileCheck %s
3+
4+
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \
5+
; RUN: FileCheck %s
6+
7+
@x = local_unnamed_addr global i32 218114560, align 4 #0
8+
9+
define i32 @main() local_unnamed_addr {
10+
entry:
11+
%0 = load i32, ptr @x, align 4
12+
%shr = lshr i32 %0, 8
13+
%and = and i32 %shr, 255
14+
ret i32 %and
15+
}
16+
17+
attributes #0 = { "toc-data" }
18+
19+
; CHECK: la [[ADDR:[0-9]+]], x[TD](2)
20+
; CHECK: lbz {{.*}}, 2([[ADDR]])

0 commit comments

Comments
 (0)