The guaranteed alignment of ptr+offset is only the minimum of
authorDuncan Sands <baldrick@free.fr>
Sun, 28 Oct 2007 12:59:45 +0000 (12:59 +0000)
committerDuncan Sands <baldrick@free.fr>
Sun, 28 Oct 2007 12:59:45 +0000 (12:59 +0000)
of offset and the alignment of ptr if these are both powers of
2.  While the ptr alignment is guaranteed to be a power of 2,
there is no reason to think that offset is.  For example, if
offset is 12 (the size of a long double on x86-32 linux) and
the alignment of ptr is 8, then the alignment of ptr+offset
will in general be 4, not 8.  Introduce a function MinAlign,
lifted from gcc, for computing the minimum guaranteed alignment.
I've tried to fix up everywhere under lib/CodeGen/SelectionDAG/.
I also changed some places that weren't wrong (because both values
were a power of 2), as a defensive change against people copying
and pasting the code.
Hopefully someone who cares about alignment will review the rest
of LLVM and fix up the remaining places.  Since I'm on x86 I'm
not very motivated to do this myself...

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43421 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/Alignment.h [new file with mode: 0644]
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp

diff --git a/include/llvm/Support/Alignment.h b/include/llvm/Support/Alignment.h
new file mode 100644 (file)
index 0000000..41259b6
--- /dev/null
@@ -0,0 +1,28 @@
+//===----------- Alignment.h - Alignment computation ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Duncan Sands and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utilities for computing alignments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALIGNMENT_H
+#define LLVM_SUPPORT_ALIGNMENT_H
+
+namespace llvm {
+
+/// MinAlign - A and B are either alignments or offsets.  Return the minimum
+/// alignment that may be assumed after adding the two together.
+
+static inline unsigned MinAlign(unsigned A, unsigned B) {
+  // The largest power of 2 that divides both A and B.
+  return (A | B) & -(A | B);
+}
+
+} // end namespace llvm
+#endif
index 5b5a70edb6e62a067d288b07758f172c2099dd63..d3b8b000a1a1c44075a964df016b51731b9a8c09 100644 (file)
@@ -37,6 +37,7 @@
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Alignment.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -1713,15 +1714,18 @@ SDOperand DAGCombiner::visitAND(SDNode *N) {
         // read fewer bytes from the same pointer.
         unsigned PtrOff =
           (MVT::getSizeInBits(LoadedVT) - MVT::getSizeInBits(EVT)) / 8;
+        unsigned Alignment = LN0->getAlignment();
         SDOperand NewPtr = LN0->getBasePtr();
-        if (!TLI.isLittleEndian())
+        if (!TLI.isLittleEndian()) {
           NewPtr = DAG.getNode(ISD::ADD, PtrType, NewPtr,
                                DAG.getConstant(PtrOff, PtrType));
+          Alignment = MinAlign(Alignment, PtrOff);
+        }
         AddToWorkList(NewPtr.Val);
         SDOperand Load =
           DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(), NewPtr,
                          LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT,
-                         LN0->isVolatile(), LN0->getAlignment());
+                         LN0->isVolatile(), Alignment);
         AddToWorkList(N);
         CombineTo(N0.Val, Load, Load.getValue(1));
         return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
@@ -2879,16 +2883,17 @@ SDOperand DAGCombiner::ReduceLoadWidth(SDNode *N) {
     if (!TLI.isLittleEndian())
       ShAmt = MVT::getSizeInBits(N0.getValueType()) - ShAmt - EVTBits;
     uint64_t PtrOff =  ShAmt / 8;
+    unsigned NewAlign = MinAlign(LN0->getAlignment(), PtrOff);
     SDOperand NewPtr = DAG.getNode(ISD::ADD, PtrType, LN0->getBasePtr(),
                                    DAG.getConstant(PtrOff, PtrType));
     AddToWorkList(NewPtr.Val);
     SDOperand Load = (ExtType == ISD::NON_EXTLOAD)
       ? DAG.getLoad(VT, LN0->getChain(), NewPtr,
                     LN0->getSrcValue(), LN0->getSrcValueOffset(),
-                    LN0->isVolatile(), LN0->getAlignment())
+                    LN0->isVolatile(), NewAlign)
       : DAG.getExtLoad(ExtType, VT, LN0->getChain(), NewPtr,
                        LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT,
-                       LN0->isVolatile(), LN0->getAlignment());
+                       LN0->isVolatile(), NewAlign);
     AddToWorkList(N);
     if (CombineSRL) {
       DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1));
@@ -3905,8 +3910,8 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
       // Replace the chain to void dependency.
       if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
         ReplLoad = DAG.getLoad(N->getValueType(0), BetterChain, Ptr,
-                              LD->getSrcValue(), LD->getSrcValueOffset(),
-                              LD->isVolatile(), LD->getAlignment());
+                               LD->getSrcValue(), LD->getSrcValueOffset(),
+                               LD->isVolatile(), LD->getAlignment());
       } else {
         ReplLoad = DAG.getExtLoad(LD->getExtensionType(),
                                   LD->getValueType(0),
@@ -3980,7 +3985,7 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
                               ST->getSrcValueOffset(), ST->isVolatile(),
                               ST->getAlignment());
         } else if (TLI.isTypeLegal(MVT::i32)) {
-          // Many FP stores are not make apparent until after legalize, e.g. for
+          // Many FP stores are not made apparent until after legalize, e.g. for
           // argument passing.  Since this is so common, custom legalize the
           // 64-bit integer store into two 32-bit stores.
           uint64_t Val = CFP->getValueAPF().convertToAPInt().getZExtValue();
@@ -3998,8 +4003,7 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
           Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
                             DAG.getConstant(4, Ptr.getValueType()));
           SVOffset += 4;
-          if (Alignment > 4)
-            Alignment = 4;
+          Alignment = MinAlign(Alignment, 4U);
           SDOperand St1 = DAG.getStore(Chain, Hi, Ptr, ST->getSrcValue(),
                                        SVOffset, isVolatile, Alignment);
           return DAG.getNode(ISD::TokenFactor, MVT::Other, St0, St1);
index 23d132bb09e8a190e0dfaf36a521ddc7638eafd8..5ec74cdc311fd31e581136287ccdf32173e61f75 100644 (file)
 #include "llvm/CallingConv.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
-#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Alignment.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -602,6 +603,7 @@ SDOperand ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
                              ST->isVolatile(), Alignment);
   Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
                     DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+  Alignment = MinAlign(Alignment, IncrementSize);
   Store2 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Hi:Lo, Ptr,
                              ST->getSrcValue(), SVOffset + IncrementSize,
                              NewStoredVT, ST->isVolatile(), Alignment);
@@ -660,7 +662,7 @@ SDOperand ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
                       DAG.getConstant(IncrementSize, TLI.getPointerTy()));
     Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(),
                         SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
-                        Alignment);
+                        MinAlign(Alignment, IncrementSize));
   } else {
     Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(), SVOffset,
                         NewLoadedVT,LD->isVolatile(), Alignment);
@@ -668,7 +670,7 @@ SDOperand ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
                       DAG.getConstant(IncrementSize, TLI.getPointerTy()));
     Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
                         SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
-                        Alignment);
+                        MinAlign(Alignment, IncrementSize));
   }
 
   // aggregate the two parts
@@ -2055,7 +2057,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
             Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
                                getIntPtrConstant(4));
             Hi = DAG.getStore(Tmp1, Hi, Tmp2, ST->getSrcValue(), SVOffset+4,
-                              isVolatile, std::max(Alignment, 4U));
+                              isVolatile, MinAlign(Alignment, 4U));
 
             Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
             break;
@@ -2164,8 +2166,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         assert(isTypeLegal(Tmp2.getValueType()) &&
                "Pointers must be legal!");
         SVOffset += IncrementSize;
-        if (Alignment > IncrementSize)
-          Alignment = IncrementSize;
+        Alignment = MinAlign(Alignment, IncrementSize);
         Hi = DAG.getStore(Tmp1, Hi, Tmp2, ST->getSrcValue(),
                           SVOffset, isVolatile, Alignment);
         Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
@@ -5429,8 +5430,7 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
       Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
                         getIntPtrConstant(IncrementSize));
       SVOffset += IncrementSize;
-      if (Alignment > IncrementSize)
-        Alignment = IncrementSize;
+      Alignment = MinAlign(Alignment, IncrementSize);
       Hi = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset,
                        isVolatile, Alignment);
 
@@ -6336,8 +6336,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
                       getIntPtrConstant(IncrementSize));
     SVOffset += IncrementSize;
-    if (Alignment > IncrementSize)
-      Alignment = IncrementSize;
+    Alignment = MinAlign(Alignment, IncrementSize);
     Hi = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
     
     // Build a factor node to remember that this load is independent of the
index 8699dbc78a2ae4ae59c4a0a6cbf5c60f34119fc1..e8bf080c1f6cc8ee43ef54711b7544649e8c9cf8 100644 (file)
@@ -18,6 +18,7 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Alignment.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 using namespace llvm;
@@ -946,7 +947,7 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
     Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
                       getIntPtrConstant(IncrementSize));
     Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
-                     isVolatile, std::max(Alignment, IncrementSize));
+                     isVolatile, MinAlign(Alignment, IncrementSize));
 
     // Build a factor node to remember that this load is independent of the
     // other one.
@@ -994,7 +995,7 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
                       getIntPtrConstant(IncrementSize));
     Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
                         SVOffset+IncrementSize, NEVT,
-                        isVolatile, std::max(Alignment, IncrementSize));
+                        isVolatile, MinAlign(Alignment, IncrementSize));
 
     // Build a factor node to remember that this load is independent of the
     // other one.
@@ -1019,7 +1020,7 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
     // Load the rest of the low bits.
     Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(),
                         SVOffset+IncrementSize, MVT::getIntegerType(ExcessBits),
-                        isVolatile, std::max(Alignment, IncrementSize));
+                        isVolatile, MinAlign(Alignment, IncrementSize));
 
     // Build a factor node to remember that this load is independent of the
     // other one.
@@ -2002,7 +2003,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) {
                     getIntPtrConstant(IncrementSize));
   assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
   Hi = DAG.getStore(Chain, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
-                    isVolatile, std::max(Alignment, IncrementSize));
+                    isVolatile, MinAlign(Alignment, IncrementSize));
   return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
 }