Fix fast-isel address mode folding to avoid folding instructions
[oota-llvm.git] / lib / Target / X86 / X86FastISel.cpp
index 6fa928462b28ad0a49ce47d33eff352925fb91fe..88744861e86ec42d7108b60ac196b80460f8a27e 100644 (file)
@@ -399,33 +399,39 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) {
         Disp += SL->getElementOffset(Idx);
       } else {
         uint64_t S = TD.getTypeAllocSize(GTI.getIndexedType());
-        SmallVector<const Value *, 4> Worklist;
-        Worklist.push_back(Op);
-        do {
-          Op = Worklist.pop_back_val();
+        for (;;) {
           if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
             // Constant-offset addressing.
             Disp += CI->getSExtValue() * S;
-          } else if (isa<AddOperator>(Op) &&
-                     isa<ConstantInt>(cast<AddOperator>(Op)->getOperand(1))) {
-            // An add with a constant operand. Fold the constant.
+            break;
+          }
+          if (isa<AddOperator>(Op) &&
+              (!isa<Instruction>(Op) ||
+               FuncInfo.MBBMap[cast<Instruction>(Op)->getParent()]
+                 == FuncInfo.MBB) &&
+              isa<ConstantInt>(cast<AddOperator>(Op)->getOperand(1))) {
+            // An add (in the same block) with a constant operand. Fold the
+            // constant.
             ConstantInt *CI =
               cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
             Disp += CI->getSExtValue() * S;
-            // Add the other operand back to the work list.
-            Worklist.push_back(cast<AddOperator>(Op)->getOperand(0));
-          } else if (IndexReg == 0 &&
-                     (!AM.GV || !Subtarget->isPICStyleRIPRel()) &&
-                     (S == 1 || S == 2 || S == 4 || S == 8)) {
+            // Iterate on the other operand.
+            Op = cast<AddOperator>(Op)->getOperand(0);
+            continue;
+          }
+          if (IndexReg == 0 &&
+              (!AM.GV || !Subtarget->isPICStyleRIPRel()) &&
+              (S == 1 || S == 2 || S == 4 || S == 8)) {
             // Scaled-index addressing.
             Scale = S;
             IndexReg = getRegForGEPIndex(Op).first;
             if (IndexReg == 0)
               return false;
-          } else
-            // Unsupported.
-            goto unsupported_gep;
-        } while (!Worklist.empty());
+            break;
+          }
+          // Unsupported.
+          goto unsupported_gep;
+        }
       }
     }
     // Check for displacement overflow.