diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -7635,6 +7635,7 @@ break; case PPC::ADDItoc: case PPC::ADDItoc8: + ReplaceFlags = false; if (RequiresMod4Offset) { if (GlobalAddressSDNode *GA = dyn_cast(Base.getOperand(0))) { @@ -7649,24 +7650,27 @@ break; } - SDValue ImmOpnd = Base.getOperand(1); - - // On PPC64, the TOC base pointer is guaranteed by the ABI only to have - // 8-byte alignment, and so we can only use offsets less than 8 (otherwise, - // we might have needed different @ha relocation values for the offset - // pointers). - int MaxDisplacement = 7; - if (GlobalAddressSDNode *GA = dyn_cast(ImmOpnd)) { - const GlobalValue *GV = GA->getGlobal(); - Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout()); - MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement); - } + // The AIX small code model nodes have the operands reversed. + SDValue ImmOpnd = + Subtarget->isAIXABI() ? Base.getOperand(0) : Base.getOperand(1); bool UpdateHBase = false; SDValue HBase = Base.getOperand(0); int Offset = N->getConstantOperandVal(FirstOp); + if (ReplaceFlags) { + // On PPC64, the TOC base pointer is guaranteed by the ABI only to have + // 8-byte alignment, and so we can only use offsets less than 8 + // (otherwise, we might have needed different @ha relocation values for + // the offset pointers). + int MaxDisplacement = 7; + if (GlobalAddressSDNode *GA = dyn_cast(ImmOpnd)) { + const GlobalValue *GV = GA->getGlobal(); + Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout()); + MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement); + } + 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 @@ -7746,22 +7750,15 @@ // model when a global is defined in the TOC. const bool OpcodeIsAIXTocData = BaseOpcode == PPC::ADDItoc || BaseOpcode == PPC::ADDItoc8; + SDValue RegOperand = + OpcodeIsAIXTocData ? Base->getOperand(1) : Base.getOperand(0); if (FirstOp == 1) // Store - if (OpcodeIsAIXTocData) - (void)CurDAG->UpdateNodeOperands(N, N->getOperand(0), - Base.getOperand(0), Base.getOperand(1), - N->getOperand(3)); - else - (void)CurDAG->UpdateNodeOperands(N, N->getOperand(0), ImmOpnd, - Base.getOperand(0), N->getOperand(3)); + (void)CurDAG->UpdateNodeOperands(N, N->getOperand(0), ImmOpnd, RegOperand, + N->getOperand(3)); else // Load - if (OpcodeIsAIXTocData) - (void)CurDAG->UpdateNodeOperands(N, Base.getOperand(0), - Base.getOperand(1), N->getOperand(2)); - else - (void)CurDAG->UpdateNodeOperands(N, ImmOpnd, Base.getOperand(0), - N->getOperand(2)); + (void)CurDAG->UpdateNodeOperands(N, ImmOpnd, RegOperand, + N->getOperand(2)); if (UpdateHBase) (void)CurDAG->UpdateNodeOperands(HBase.getNode(), HBase.getOperand(0), diff --git a/llvm/test/CodeGen/PowerPC/aix-toc-data-offset.ll b/llvm/test/CodeGen/PowerPC/aix-toc-data-offset.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-toc-data-offset.ll @@ -0,0 +1,20 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | \ +; RUN: FileCheck %s + +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \ +; RUN: FileCheck %s + +@x = local_unnamed_addr global i32 218114560, align 4 #0 + +define i32 @main() local_unnamed_addr { +entry: + %0 = load i32, ptr @x, align 4 + %shr = lshr i32 %0, 8 + %and = and i32 %shr, 255 + ret i32 %and +} + +attributes #0 = { "toc-data" } + +; CHECK: la [[ADDR:[0-9]+]], x[TD](2) +; CHECK: lbz {{.*}}, 2([[ADDR]])