Can't fold the bit_convert is the store is a truncating store.
[oota-llvm.git] / lib / CodeGen / SelectionDAG / DAGCombiner.cpp
index 88596d65db345a1f9a9c79cf45bf24976b7654a1..744a474ba4e979e58919f1616dac0a5106371dab 100644 (file)
@@ -34,7 +34,9 @@
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
+#include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/CommandLine.h"
@@ -1263,7 +1265,9 @@ SDOperand DAGCombiner::visitAND(SDNode *N) {
         (!AfterLegalize || TLI.isLoadXLegal(ISD::ZEXTLOAD, EVT))) {
       SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
                                          LN0->getBasePtr(), LN0->getSrcValue(),
-                                         LN0->getSrcValueOffset(), EVT);
+                                         LN0->getSrcValueOffset(), EVT,
+                                         LN0->isVolatile(), 
+                                         LN0->getAlignment());
       AddToWorkList(N);
       CombineTo(N0.Val, ExtLoad, ExtLoad.getValue(1));
       return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
@@ -1280,7 +1284,9 @@ SDOperand DAGCombiner::visitAND(SDNode *N) {
         (!AfterLegalize || TLI.isLoadXLegal(ISD::ZEXTLOAD, EVT))) {
       SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
                                          LN0->getBasePtr(), LN0->getSrcValue(),
-                                         LN0->getSrcValueOffset(), EVT);
+                                         LN0->getSrcValueOffset(), EVT,
+                                         LN0->isVolatile(), 
+                                         LN0->getAlignment());
       AddToWorkList(N);
       CombineTo(N0.Val, ExtLoad, ExtLoad.getValue(1));
       return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
@@ -1320,7 +1326,8 @@ SDOperand DAGCombiner::visitAND(SDNode *N) {
         AddToWorkList(NewPtr.Val);
         SDOperand Load =
           DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(), NewPtr,
-                         LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT);
+                         LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT,
+                         LN0->isVolatile(), LN0->getAlignment());
         AddToWorkList(N);
         CombineTo(N0.Val, Load, Load.getValue(1));
         return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
@@ -2120,7 +2127,8 @@ SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
     SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
                                        LN0->getBasePtr(), LN0->getSrcValue(),
                                        LN0->getSrcValueOffset(),
-                                       N0.getValueType());
+                                       N0.getValueType(), 
+                                       LN0->isVolatile());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -2136,7 +2144,9 @@ SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
     if (!AfterLegalize || TLI.isLoadXLegal(ISD::SEXTLOAD, EVT)) {
       SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
                                          LN0->getBasePtr(), LN0->getSrcValue(),
-                                         LN0->getSrcValueOffset(), EVT);
+                                         LN0->getSrcValueOffset(), EVT,
+                                         LN0->isVolatile(), 
+                                         LN0->getAlignment());
       CombineTo(N, ExtLoad);
       CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
                 ExtLoad.getValue(1));
@@ -2212,7 +2222,9 @@ SDOperand DAGCombiner::visitZERO_EXTEND(SDNode *N) {
     SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
                                        LN0->getBasePtr(), LN0->getSrcValue(),
                                        LN0->getSrcValueOffset(),
-                                       N0.getValueType());
+                                       N0.getValueType(),
+                                       LN0->isVolatile(), 
+                                       LN0->getAlignment());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -2227,7 +2239,9 @@ SDOperand DAGCombiner::visitZERO_EXTEND(SDNode *N) {
     MVT::ValueType EVT = LN0->getLoadedVT();
     SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
                                        LN0->getBasePtr(), LN0->getSrcValue(),
-                                       LN0->getSrcValueOffset(), EVT);
+                                       LN0->getSrcValueOffset(), EVT,
+                                       LN0->isVolatile(), 
+                                       LN0->getAlignment());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -2303,7 +2317,9 @@ SDOperand DAGCombiner::visitANY_EXTEND(SDNode *N) {
     SDOperand ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, VT, LN0->getChain(),
                                        LN0->getBasePtr(), LN0->getSrcValue(),
                                        LN0->getSrcValueOffset(),
-                                       N0.getValueType());
+                                       N0.getValueType(),
+                                       LN0->isVolatile(), 
+                                       LN0->getAlignment());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -2321,7 +2337,9 @@ SDOperand DAGCombiner::visitANY_EXTEND(SDNode *N) {
     SDOperand ExtLoad = DAG.getExtLoad(LN0->getExtensionType(), VT,
                                        LN0->getChain(), LN0->getBasePtr(),
                                        LN0->getSrcValue(),
-                                       LN0->getSrcValueOffset(), EVT);
+                                       LN0->getSrcValueOffset(), EVT,
+                                       LN0->isVolatile(), 
+                                       LN0->getAlignment());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -2398,9 +2416,11 @@ SDOperand DAGCombiner::ReduceLoadWidth(SDNode *N) {
     AddToWorkList(NewPtr.Val);
     SDOperand Load = (ExtType == ISD::NON_EXTLOAD)
       ? DAG.getLoad(VT, LN0->getChain(), NewPtr,
-                    LN0->getSrcValue(), LN0->getSrcValueOffset())
+                    LN0->getSrcValue(), LN0->getSrcValueOffset(),
+                    LN0->isVolatile(), LN0->getAlignment())
       : DAG.getExtLoad(ExtType, VT, LN0->getChain(), NewPtr,
-                       LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT);
+                       LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT,
+                       LN0->isVolatile(), LN0->getAlignment());
     AddToWorkList(N);
     if (CombineSRL) {
       std::vector<SDNode*> NowDead;
@@ -2479,7 +2499,9 @@ SDOperand DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
     LoadSDNode *LN0 = cast<LoadSDNode>(N0);
     SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
                                        LN0->getBasePtr(), LN0->getSrcValue(),
-                                       LN0->getSrcValueOffset(), EVT);
+                                       LN0->getSrcValueOffset(), EVT,
+                                       LN0->isVolatile(), 
+                                       LN0->getAlignment());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, ExtLoad, ExtLoad.getValue(1));
     return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
@@ -2492,7 +2514,9 @@ SDOperand DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
     LoadSDNode *LN0 = cast<LoadSDNode>(N0);
     SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
                                        LN0->getBasePtr(), LN0->getSrcValue(),
-                                       LN0->getSrcValueOffset(), EVT);
+                                       LN0->getSrcValueOffset(), EVT,
+                                       LN0->isVolatile(), 
+                                       LN0->getAlignment());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, ExtLoad, ExtLoad.getValue(1));
     return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
@@ -2547,16 +2571,22 @@ SDOperand DAGCombiner::visitBIT_CONVERT(SDNode *N) {
     return DAG.getNode(ISD::BIT_CONVERT, VT, N0.getOperand(0));
 
   // fold (conv (load x)) -> (load (conv*)x)
-  // FIXME: These xforms need to know that the resultant load doesn't need a 
-  // higher alignment than the original!
-  if (0 && ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse()) {
+  // If the resultant load doesn't need a  higher alignment than the original!
+  if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() &&
+      TLI.isOperationLegal(ISD::LOAD, VT)) {
     LoadSDNode *LN0 = cast<LoadSDNode>(N0);
-    SDOperand Load = DAG.getLoad(VT, LN0->getChain(), LN0->getBasePtr(),
-                                 LN0->getSrcValue(), LN0->getSrcValueOffset());
-    AddToWorkList(N);
-    CombineTo(N0.Val, DAG.getNode(ISD::BIT_CONVERT, N0.getValueType(), Load),
-              Load.getValue(1));
-    return Load;
+    unsigned Align = TLI.getTargetMachine().getTargetData()->
+      getPrefTypeAlignment(getTypeForValueType(VT));
+    unsigned OrigAlign = LN0->getAlignment();
+    if (Align <= OrigAlign) {
+      SDOperand Load = DAG.getLoad(VT, LN0->getChain(), LN0->getBasePtr(),
+                                   LN0->getSrcValue(), LN0->getSrcValueOffset(),
+                                   LN0->isVolatile(), LN0->getAlignment());
+      AddToWorkList(N);
+      CombineTo(N0.Val, DAG.getNode(ISD::BIT_CONVERT, N0.getValueType(), Load),
+                Load.getValue(1));
+      return Load;
+    }
   }
   
   return SDOperand();
@@ -2942,7 +2972,9 @@ SDOperand DAGCombiner::visitFP_EXTEND(SDNode *N) {
     SDOperand ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, VT, LN0->getChain(),
                                        LN0->getBasePtr(), LN0->getSrcValue(),
                                        LN0->getSrcValueOffset(),
-                                       N0.getValueType());
+                                       N0.getValueType(),
+                                       LN0->isVolatile(), 
+                                       LN0->getAlignment());
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::FP_ROUND, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -3085,6 +3117,10 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
   ISD::MemIndexedMode AM = ISD::UNINDEXED;
   if (!TLI.getPreIndexedAddressParts(N, BasePtr, Offset, AM, DAG))
     return false;
+  // Don't create a indexed load / store with zero offset.
+  if (isa<ConstantSDNode>(Offset) &&
+      cast<ConstantSDNode>(Offset)->getValue() == 0)
+    return false;
   
   // Try turning it into a pre-indexed load / store except when:
   // 1) The base is a frame index.
@@ -3214,6 +3250,10 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
         std::swap(BasePtr, Offset);
       if (Ptr != BasePtr)
         continue;
+      // Don't create a indexed load / store with zero offset.
+      if (isa<ConstantSDNode>(Offset) &&
+          cast<ConstantSDNode>(Offset)->getValue() == 0)
+        continue;
 
       // Try turning it into a post-indexed load / store except when
       // 1) All uses are load / store ops that use it as base ptr.
@@ -3301,11 +3341,26 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
   LoadSDNode *LD  = cast<LoadSDNode>(N);
   SDOperand Chain = LD->getChain();
   SDOperand Ptr   = LD->getBasePtr();
-  
-  // If there are no uses of the loaded value, change uses of the chain value
-  // into uses of the chain input (i.e. delete the dead load).
-  if (N->hasNUsesOfValue(0, 0))
-    return CombineTo(N, DAG.getNode(ISD::UNDEF, N->getValueType(0)), Chain);
+
+  // If load is not volatile and there are no uses of the loaded value (and
+  // the updated indexed value in case of indexed loads), change uses of the
+  // chain value into uses of the chain input (i.e. delete the dead load).
+  if (!LD->isVolatile()) {
+    if (N->getValueType(1) == MVT::Other) {
+      // Unindexed loads.
+      if (N->hasNUsesOfValue(0, 0))
+        return CombineTo(N, DAG.getNode(ISD::UNDEF, N->getValueType(0)), Chain);
+    } else {
+      // Indexed loads.
+      assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?");
+      if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) {
+        SDOperand Undef0 = DAG.getNode(ISD::UNDEF, N->getValueType(0));
+        SDOperand Undef1 = DAG.getNode(ISD::UNDEF, N->getValueType(1));
+        SDOperand To[] = { Undef0, Undef1, Chain };
+        return CombineTo(N, To, 3);
+      }
+    }
+  }
   
   // If this load is directly stored, replace the load value with the stored
   // value.
@@ -3331,13 +3386,16 @@ 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->getSrcValue(), LD->getSrcValueOffset(),
+                              LD->isVolatile(), LD->getAlignment());
       } else {
         ReplLoad = DAG.getExtLoad(LD->getExtensionType(),
                                   LD->getValueType(0),
                                   BetterChain, Ptr, LD->getSrcValue(),
                                   LD->getSrcValueOffset(),
-                                  LD->getLoadedVT());
+                                  LD->getLoadedVT(),
+                                  LD->isVolatile(), 
+                                  LD->getAlignment());
       }
 
       // Create token factor to keep old chain connected.
@@ -3363,12 +3421,16 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
   SDOperand Value = ST->getValue();
   SDOperand Ptr   = ST->getBasePtr();
   
-  // If this is a store of a bit convert, store the input value.
-  // FIXME: This needs to know that the resultant store does not need a 
-  // higher alignment than the original.
-  if (0 && Value.getOpcode() == ISD::BIT_CONVERT) {
-    return DAG.getStore(Chain, Value.getOperand(0), Ptr, ST->getSrcValue(),
-                        ST->getSrcValueOffset());
+  // If this is a store of a bit convert, store the input value if the
+  // resultant store does not need a higher alignment than the original.
+  if (Value.getOpcode() == ISD::BIT_CONVERT && !ST->isTruncatingStore()) {
+    unsigned Align = ST->getAlignment();
+    MVT::ValueType SVT = Value.getOperand(0).getValueType();
+    unsigned OrigAlign = TLI.getTargetMachine().getTargetData()->
+      getPrefTypeAlignment(getTypeForValueType(SVT));
+    if (Align <= OrigAlign && TLI.isOperationLegal(ISD::STORE, SVT))
+      return DAG.getStore(Chain, Value.getOperand(0), Ptr, ST->getSrcValue(),
+                          ST->getSrcValueOffset());
   }
   
   // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr'
@@ -4040,13 +4102,17 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDOperand LHS,
           if (LLD->getExtensionType() == ISD::NON_EXTLOAD)
             Load = DAG.getLoad(TheSelect->getValueType(0), LLD->getChain(),
                                Addr,LLD->getSrcValue(), 
-                               LLD->getSrcValueOffset());
+                               LLD->getSrcValueOffset(),
+                               LLD->isVolatile(), 
+                               LLD->getAlignment());
           else {
             Load = DAG.getExtLoad(LLD->getExtensionType(),
                                   TheSelect->getValueType(0),
                                   LLD->getChain(), Addr, LLD->getSrcValue(),
                                   LLD->getSrcValueOffset(),
-                                  LLD->getLoadedVT());
+                                  LLD->getLoadedVT(),
+                                  LLD->isVolatile(), 
+                                  LLD->getAlignment());
           }
           // Users of the select now use the result of the load.
           CombineTo(TheSelect, Load);