[llvm-branch-commits] [llvm] caa1a8b - [PPC][AIX] Fix toc-data peephole bug and some related cleanup.

Tobias Hieta via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Aug 11 00:08:08 PDT 2023


Author: Sean Fertile
Date: 2023-08-11T09:00:08+02:00
New Revision: caa1a8b0d6b51d0cf44ca9d0cd1cdd9af370583e

URL: https://github.com/llvm/llvm-project/commit/caa1a8b0d6b51d0cf44ca9d0cd1cdd9af370583e
DIFF: https://github.com/llvm/llvm-project/commit/caa1a8b0d6b51d0cf44ca9d0cd1cdd9af370583e.diff

LOG: [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 https://github.com/llvm/llvm-project/issues/63927

Differential Revision: https://reviews.llvm.org/D155957

(cherry picked from commit b37c7ed0c95c7f24758b1532f04275b4bb65d3c1)

Added: 
    llvm/test/CodeGen/PowerPC/aix-toc-data-offset.ll

Modified: 
    llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 0ebfc007b3d7d7..9f52da5ae0e2d9 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -7635,6 +7635,7 @@ void PPCDAGToDAGISel::PeepholePPC64() {
       break;
     case PPC::ADDItoc:
     case PPC::ADDItoc8:
+      ReplaceFlags = false;
       if (RequiresMod4Offset) {
         if (GlobalAddressSDNode *GA =
                 dyn_cast<GlobalAddressSDNode>(Base.getOperand(0))) {
@@ -7649,42 +7650,58 @@ void PPCDAGToDAGISel::PeepholePPC64() {
       break;
     }
 
-    SDValue ImmOpnd = Base.getOperand(1);
+    const unsigned BaseOpcode = Base.getMachineOpcode();
+    // ADDItoc and ADDItoc8 are pseudos used exclusively by AIX small code
+    // model when a global is defined in the TOC.
+    const bool OpcodeIsAIXSmallTocData =
+        BaseOpcode == PPC::ADDItoc || BaseOpcode == PPC::ADDItoc8;
 
-    // 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 
diff erent @ha relocation values for the offset
-    // pointers).
-    int MaxDisplacement = 7;
-    if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
-      const GlobalValue *GV = GA->getGlobal();
-      Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
-      MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement);
+    SDValue RegOperand;
+    SDValue ImmOpnd;
+    // The AIX small code model nodes have the operands reversed.
+    if (OpcodeIsAIXSmallTocData) {
+      RegOperand = Base.getOperand(1);
+      ImmOpnd = Base.getOperand(0);
+    } else {
+      RegOperand = Base.getOperand(0);
+      ImmOpnd = Base.getOperand(1);
     }
 
-    bool UpdateHBase = false;
-    SDValue HBase = Base.getOperand(0);
-
     int Offset = N->getConstantOperandVal(FirstOp);
+
+    SDValue HBase;
+    bool UpdateHBase = false;
     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 
diff erent @ha relocation values for
+      // the offset pointers).
+      int MaxDisplacement = 7;
+      if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(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 at l)/addis(toc at 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)
+        if (BaseOpcode != PPC::ADDItocL)
           continue;
 
-        if (!HBase.isMachineOpcode() ||
-            HBase.getMachineOpcode() != PPC::ADDIStocHA8)
+        if (!RegOperand.isMachineOpcode() ||
+            RegOperand.getMachineOpcode() != PPC::ADDIStocHA8)
           continue;
 
-        if (!Base.hasOneUse() || !HBase.hasOneUse())
+        if (!Base.hasOneUse() || !RegOperand.hasOneUse())
           continue;
 
-        SDValue HImmOpnd = HBase.getOperand(1);
+        SDValue HImmOpnd = RegOperand.getOperand(1);
         if (HImmOpnd != ImmOpnd)
           continue;
 
+        HBase = RegOperand;
         UpdateHBase = true;
       }
     } else {
@@ -7709,10 +7726,10 @@ void PPCDAGToDAGISel::PeepholePPC64() {
       }
     }
 
-    // We found an opportunity.  Reverse the operands from the add
-    // immediate and substitute them into the load or store.  If
-    // needed, update the target flags for the immediate operand to
-    // reflect the necessary relocation information.
+    // We found an opportunity.  Forward the operands from the add
+    // immediate to the load or store.  If needed, update the target
+    // flags for the immediate operand to reflect the necessary
+    // relocation information.
     LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase:    ");
     LLVM_DEBUG(Base->dump(CurDAG));
     LLVM_DEBUG(dbgs() << "\nN: ");
@@ -7728,6 +7745,10 @@ void PPCDAGToDAGISel::PeepholePPC64() {
         Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
         // We can't perform this optimization for data whose alignment
         // is insufficient for the instruction encoding.
+        // TODO FIXME Verify and document why the offset must be a multiple of
+        // 4 when the aligment is less than 4. It is not about the encoding of
+        // the instruction: the value of Offset comes directly from the original
+        // load/store instruction on the path that reaches this check.
         if (Alignment < 4 && (RequiresMod4Offset || (Offset % 4) != 0)) {
           LLVM_DEBUG(dbgs() << "Rejected this candidate for alignment.\n\n");
           continue;
@@ -7741,27 +7762,12 @@ void PPCDAGToDAGISel::PeepholePPC64() {
       }
     }
 
-    const unsigned BaseOpcode = Base.getMachineOpcode();
-    // ADDItoc and ADDItoc8 are pseudos used exclusively by AIX small code
-    // model when a global is defined in the TOC.
-    const bool OpcodeIsAIXTocData =
-        BaseOpcode == PPC::ADDItoc || BaseOpcode == PPC::ADDItoc8;
-
     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
index 00000000000000..b3ece6b6192bb9
--- /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
+
+ at 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]])


        


More information about the llvm-branch-commits mailing list