[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Chris Lattner sabre at nondot.org
Sun Feb 4 12:18:33 PST 2007



Changes in directory llvm/lib/Target/X86:

X86ISelDAGToDAG.cpp updated: 1.144 -> 1.145
---
Log message:

Fix a miscompilation in the addr mode code trying to implement X | C and 
X + C to promote LEA formation.  We would incorrectly apply it in some cases
(test) and miss it in others.

This fixes CodeGen/X86/2007-02-04-OrAddrMode.ll



---
Diffs of the changes:  (+17 -20)

 X86ISelDAGToDAG.cpp |   37 +++++++++++++++++--------------------
 1 files changed, 17 insertions(+), 20 deletions(-)


Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.144 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.145
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.144	Mon Jan 22 15:34:25 2007
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp	Sun Feb  4 14:18:17 2007
@@ -677,7 +677,7 @@
     if (!Available &&
         AM.BaseType == X86ISelAddressMode::RegBase &&
         AM.Base.Reg.Val == 0 &&
-        AM.IndexReg.Val == 0)
+        AM.IndexReg.Val == 0) {
       if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1)))
         if (CN->getValue() == 3 || CN->getValue() == 5 || CN->getValue() == 9) {
           AM.Scale = unsigned(CN->getValue())-1;
@@ -705,9 +705,10 @@
           AM.IndexReg = AM.Base.Reg = Reg;
           return false;
         }
+    }
     break;
 
-  case ISD::ADD: {
+  case ISD::ADD:
     if (!Available) {
       X86ISelAddressMode Backup = AM;
       if (!MatchAddress(N.Val->getOperand(0), AM, false) &&
@@ -720,32 +721,28 @@
       AM = Backup;
     }
     break;
-  }
 
-  case ISD::OR: {
+  case ISD::OR:
+    // Handle "X | C" as "X + C" iff X is known to have C bits clear.
     if (!Available) {
-      X86ISelAddressMode Backup = AM;
-      // Look for (x << c1) | c2 where (c2 < c1)
-      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(0));
-      if (CN && !MatchAddress(N.Val->getOperand(1), AM, false)) {
-        if (AM.GV == NULL && AM.Disp == 0 && CN->getValue() < AM.Scale) {
-          AM.Disp = CN->getValue();
+      if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+        X86ISelAddressMode Backup = AM;
+        // Start with the LHS as an addr mode.
+        if (!MatchAddress(N.getOperand(0), AM, false) &&
+            // Address could not have picked a GV address for the displacement.
+            AM.GV == NULL &&
+            // On x86-64, the resultant disp must fit in 32-bits.
+            isInt32(AM.Disp + CN->getSignExtended()) &&
+            // Check to see if the LHS & C is zero.
+            TLI.MaskedValueIsZero(N.getOperand(0), CN->getValue())) {
+          AM.Disp += CN->getValue();
           return false;
         }
+        AM = Backup;
       }
-      AM = Backup;
-      CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1));
-      if (CN && !MatchAddress(N.Val->getOperand(0), AM, false)) {
-        if (AM.GV == NULL && AM.Disp == 0 && CN->getValue() < AM.Scale) {
-          AM.Disp = CN->getValue();
-          return false;
-        }
-      }
-      AM = Backup;
     }
     break;
   }
-  }
 
   // Is the base register already occupied?
   if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.Val) {






More information about the llvm-commits mailing list