Reduce the number of arguments in the instruction builder and make some
authorReid Spencer <rspencer@reidspencer.com>
Mon, 30 Aug 2004 00:13:26 +0000 (00:13 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Mon, 30 Aug 2004 00:13:26 +0000 (00:13 +0000)
improvements on instruction selection that account for register and frame
index bases.

Patch contributed by Jeff Cohen. Thanks Jeff!

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

lib/Target/X86/X86ISelSimple.cpp
lib/Target/X86/X86InstrBuilder.h

index 3f71a9720f3e42f64745b7b6795e74e55360e180..19c61080db62d96017401f90a7d27c12d5ec3554 100644 (file)
@@ -237,23 +237,21 @@ namespace {
 
     /// getAddressingMode - Get the addressing mode to use to address the
     /// specified value.  The returned value should be used with addFullAddress.
 
     /// getAddressingMode - Get the addressing mode to use to address the
     /// specified value.  The returned value should be used with addFullAddress.
-    void getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale,
-                           unsigned &IndexReg, unsigned &Disp);
+    void getAddressingMode(Value *Addr, X86AddressMode &AM);
 
 
     /// getGEPIndex - This is used to fold GEP instructions into X86 addressing
     /// expressions.
     void getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
                      std::vector<Value*> &GEPOps,
 
 
     /// getGEPIndex - This is used to fold GEP instructions into X86 addressing
     /// expressions.
     void getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
                      std::vector<Value*> &GEPOps,
-                     std::vector<const Type*> &GEPTypes, unsigned &BaseReg,
-                     unsigned &Scale, unsigned &IndexReg, unsigned &Disp);
+                     std::vector<const Type*> &GEPTypes,
+                     X86AddressMode &AM);
 
     /// isGEPFoldable - Return true if the specified GEP can be completely
     /// folded into the addressing mode of a load/store or lea instruction.
     bool isGEPFoldable(MachineBasicBlock *MBB,
                        Value *Src, User::op_iterator IdxBegin,
 
     /// isGEPFoldable - Return true if the specified GEP can be completely
     /// folded into the addressing mode of a load/store or lea instruction.
     bool isGEPFoldable(MachineBasicBlock *MBB,
                        Value *Src, User::op_iterator IdxBegin,
-                       User::op_iterator IdxEnd, unsigned &BaseReg,
-                       unsigned &Scale, unsigned &IndexReg, unsigned &Disp);
+                       User::op_iterator IdxEnd, X86AddressMode &AM);
 
     /// emitGEPOperation - Common code shared between visitGetElementPtrInst and
     /// constant expression GEP support.
 
     /// emitGEPOperation - Common code shared between visitGetElementPtrInst and
     /// constant expression GEP support.
@@ -812,23 +810,28 @@ void ISel::InsertFPRegKills() {
 }
 
 
 }
 
 
-void ISel::getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale,
-                             unsigned &IndexReg, unsigned &Disp) {
-  BaseReg = 0; Scale = 1; IndexReg = 0; Disp = 0;
+void ISel::getAddressingMode(Value *Addr, X86AddressMode &AM) {
+  AM.BaseType = X86AddressMode::RegBase;
+  AM.Base.Reg = 0; AM.Scale = 1; AM.IndexReg = 0; AM.Disp = 0;
   if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) {
     if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(),
   if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) {
     if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(),
-                       BaseReg, Scale, IndexReg, Disp))
+                       AM))
       return;
   } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) {
     if (CE->getOpcode() == Instruction::GetElementPtr)
       if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(),
       return;
   } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) {
     if (CE->getOpcode() == Instruction::GetElementPtr)
       if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(),
-                        BaseReg, Scale, IndexReg, Disp))
+                        AM))
         return;
         return;
+  } else if (AllocaInst *AI = dyn_castFixedAlloca(Addr)) {
+    AM.BaseType = X86AddressMode::FrameIndexBase;
+    AM.Base.FrameIndex = getFixedSizedAllocaFI(AI);
+    return;
   }
 
   // If it's not foldable, reset addr mode.
   }
 
   // If it's not foldable, reset addr mode.
-  BaseReg = getReg(Addr);
-  Scale = 1; IndexReg = 0; Disp = 0;
+  AM.BaseType = X86AddressMode::RegBase;
+  AM.Base.Reg = getReg(Addr);
+  AM.Scale = 1; AM.IndexReg = 0; AM.Disp = 0;
 }
 
 // canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold
 }
 
 // canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold
@@ -1995,12 +1998,10 @@ void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) {
       addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), FI);
 
     } else {
       addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), FI);
 
     } else {
-      unsigned BaseReg, Scale, IndexReg, Disp;
-      getAddressingMode(cast<LoadInst>(Op1)->getOperand(0), BaseReg,
-                        Scale, IndexReg, Disp);
+      X86AddressMode AM;
+      getAddressingMode(cast<LoadInst>(Op1)->getOperand(0), AM);
       
       
-      addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r),
-                     BaseReg, Scale, IndexReg, Disp);
+      addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), AM);
     }
     return;
   }
     }
     return;
   }
@@ -2020,12 +2021,10 @@ void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) {
       unsigned FI = getFixedSizedAllocaFI(AI);
       addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), FI);
     } else {
       unsigned FI = getFixedSizedAllocaFI(AI);
       addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), FI);
     } else {
-      unsigned BaseReg, Scale, IndexReg, Disp;
-      getAddressingMode(cast<LoadInst>(Op0)->getOperand(0), BaseReg,
-                        Scale, IndexReg, Disp);
+      X86AddressMode AM;
+      getAddressingMode(cast<LoadInst>(Op0)->getOperand(0), AM);
       
       
-      addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r),
-                     BaseReg, Scale, IndexReg, Disp);
+      addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), AM);
     }
     return;
   }
     }
     return;
   }
@@ -2352,8 +2351,13 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
   case 5:
   case 9:
     if (Class == cInt) {
   case 5:
   case 9:
     if (Class == cInt) {
-      addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, DestReg),
-                     op0Reg, ConstRHS-1, op0Reg, 0);
+      X86AddressMode AM;
+      AM.BaseType = X86AddressMode::RegBase;
+      AM.Base.Reg = op0Reg;
+      AM.Scale = ConstRHS-1;
+      AM.IndexReg = op0Reg;
+      AM.Disp = 0;
+      addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, DestReg), AM);
       return;
     }
   case -3:
       return;
     }
   case -3:
@@ -2361,8 +2365,13 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
   case -9:
     if (Class == cInt) {
       TmpReg = makeAnotherReg(DestTy);
   case -9:
     if (Class == cInt) {
       TmpReg = makeAnotherReg(DestTy);
-      addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TmpReg),
-                     op0Reg, -ConstRHS-1, op0Reg, 0);
+      X86AddressMode AM;
+      AM.BaseType = X86AddressMode::RegBase;
+      AM.Base.Reg = op0Reg;
+      AM.Scale = -ConstRHS-1;
+      AM.IndexReg = op0Reg;
+      AM.Disp = 0;
+      addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TmpReg), AM);
       BuildMI(*MBB, IP, NEGrTab[Class], 1, DestReg).addReg(TmpReg);
       return;
     }
       BuildMI(*MBB, IP, NEGrTab[Class], 1, DestReg).addReg(TmpReg);
       return;
     }
@@ -2444,12 +2453,10 @@ void ISel::visitMul(BinaryOperator &I) {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI);
         } else {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI);
         } else {
-          unsigned BaseReg, Scale, IndexReg, Disp;
-          getAddressingMode(LI->getOperand(0), BaseReg,
-                            Scale, IndexReg, Disp);
+          X86AddressMode AM;
+          getAddressingMode(LI->getOperand(0), AM);
           
           
-          addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r),
-                         BaseReg, Scale, IndexReg, Disp);
+          addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), AM);
         }
         return;
       }
         }
         return;
       }
@@ -2588,12 +2595,10 @@ void ISel::visitDivRem(BinaryOperator &I) {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI);
         } else {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI);
         } else {
-          unsigned BaseReg, Scale, IndexReg, Disp;
-          getAddressingMode(LI->getOperand(0), BaseReg,
-                            Scale, IndexReg, Disp);
+          X86AddressMode AM;
+          getAddressingMode(LI->getOperand(0), AM);
           
           
-          addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r),
-                         BaseReg, Scale, IndexReg, Disp);
+          addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), AM);
         }
         return;
       }
         }
         return;
       }
@@ -2609,10 +2614,9 @@ void ISel::visitDivRem(BinaryOperator &I) {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), FI);
         } else {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), FI);
         } else {
-          unsigned BaseReg, Scale, IndexReg, Disp;
-          getAddressingMode(LI->getOperand(0), BaseReg, Scale, IndexReg, Disp);
-          addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r),
-                         BaseReg, Scale, IndexReg, Disp);
+          X86AddressMode AM;
+          getAddressingMode(LI->getOperand(0), AM);
+          addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), AM);
         }
         return;
       }
         }
         return;
       }
@@ -2938,10 +2942,9 @@ void ISel::visitLoadInst(LoadInst &I) {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode[Class], 4, DestReg), FI);
         } else {
           unsigned FI = getFixedSizedAllocaFI(AI);
           addFrameReference(BuildMI(BB, Opcode[Class], 4, DestReg), FI);
         } else {
-          unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0;
-          getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp);
-          addFullAddress(BuildMI(BB, Opcode[Class], 4, DestReg),
-                         BaseReg, Scale, IndexReg, Disp);
+          X86AddressMode AM;
+          getAddressingMode(I.getOperand(0), AM);
+          addFullAddress(BuildMI(BB, Opcode[Class], 4, DestReg), AM);
         }
         return;
       } else {
         }
         return;
       } else {
@@ -3011,17 +3014,15 @@ void ISel::visitLoadInst(LoadInst &I) {
       addFrameReference(BuildMI(BB, Opcode, 4, DestReg), FI);
     }
   } else {
       addFrameReference(BuildMI(BB, Opcode, 4, DestReg), FI);
     }
   } else {
-    unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0;
-    getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp);
+    X86AddressMode AM;
+    getAddressingMode(I.getOperand(0), AM);
     
     if (Class == cLong) {
     
     if (Class == cLong) {
-      addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg),
-                     BaseReg, Scale, IndexReg, Disp);
-      addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg+1),
-                     BaseReg, Scale, IndexReg, Disp+4);
+      addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg), AM);
+      AM.Disp += 4;
+      addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg+1), AM);
     } else {
     } else {
-      addFullAddress(BuildMI(BB, Opcode, 4, DestReg),
-                     BaseReg, Scale, IndexReg, Disp);
+      addFullAddress(BuildMI(BB, Opcode, 4, DestReg), AM);
     }
   }
 }
     }
   }
 }
@@ -3030,13 +3031,8 @@ void ISel::visitLoadInst(LoadInst &I) {
 /// instruction.
 ///
 void ISel::visitStoreInst(StoreInst &I) {
 /// instruction.
 ///
 void ISel::visitStoreInst(StoreInst &I) {
-  unsigned BaseReg = ~0U, Scale = ~0U, IndexReg = ~0U, Disp = ~0U;
-  unsigned AllocaFrameIdx = ~0U;
-
-  if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(1)))
-    AllocaFrameIdx = getFixedSizedAllocaFI(AI);
-  else
-    getAddressingMode(I.getOperand(1), BaseReg, Scale, IndexReg, Disp);
+  X86AddressMode AM;
+  getAddressingMode(I.getOperand(1), AM);
 
   const Type *ValTy = I.getOperand(0)->getType();
   unsigned Class = getClassB(ValTy);
 
   const Type *ValTy = I.getOperand(0)->getType();
   unsigned Class = getClassB(ValTy);
@@ -3044,42 +3040,20 @@ void ISel::visitStoreInst(StoreInst &I) {
   if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(0))) {
     uint64_t Val = CI->getRawValue();
     if (Class == cLong) {
   if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(0))) {
     uint64_t Val = CI->getRawValue();
     if (Class == cLong) {
-      if (AllocaFrameIdx != ~0U) {
-        addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
-                          AllocaFrameIdx).addImm(Val & ~0U);
-        addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
-                          AllocaFrameIdx, 4).addImm(Val>>32);
-      } else {
-        addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
-                       BaseReg, Scale, IndexReg, Disp).addImm(Val & ~0U);
-        addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
-                       BaseReg, Scale, IndexReg, Disp+4).addImm(Val>>32);
-      }
+      addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(Val & ~0U);
+      AM.Disp += 4;
+      addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(Val>>32);
     } else {
       static const unsigned Opcodes[] = {
         X86::MOV8mi, X86::MOV16mi, X86::MOV32mi
       };
       unsigned Opcode = Opcodes[Class];
     } else {
       static const unsigned Opcodes[] = {
         X86::MOV8mi, X86::MOV16mi, X86::MOV32mi
       };
       unsigned Opcode = Opcodes[Class];
-      if (AllocaFrameIdx != ~0U)
-        addFrameReference(BuildMI(BB, Opcode, 5), AllocaFrameIdx).addImm(Val);
-      else
-        addFullAddress(BuildMI(BB, Opcode, 5),
-                       BaseReg, Scale, IndexReg, Disp).addImm(Val);
+      addFullAddress(BuildMI(BB, Opcode, 5), AM).addImm(Val);
     }
   } else if (isa<ConstantPointerNull>(I.getOperand(0))) {
     }
   } else if (isa<ConstantPointerNull>(I.getOperand(0))) {
-    if (AllocaFrameIdx != ~0U)
-      addFrameReference(BuildMI(BB, X86::MOV32mi, 5), AllocaFrameIdx).addImm(0);
-    else
-      addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
-                     BaseReg, Scale, IndexReg, Disp).addImm(0);
-    
+     addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(0);
   } else if (ConstantBool *CB = dyn_cast<ConstantBool>(I.getOperand(0))) {
   } else if (ConstantBool *CB = dyn_cast<ConstantBool>(I.getOperand(0))) {
-    if (AllocaFrameIdx != ~0U)
-      addFrameReference(BuildMI(BB, X86::MOV8mi, 5),
-                        AllocaFrameIdx).addImm(CB->getValue());
-    else
-      addFullAddress(BuildMI(BB, X86::MOV8mi, 5),
-                     BaseReg, Scale, IndexReg, Disp).addImm(CB->getValue());
+    addFullAddress(BuildMI(BB, X86::MOV8mi, 5), AM).addImm(CB->getValue());
   } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0))) {
     // Store constant FP values with integer instructions to avoid having to
     // load the constants from the constant pool then do a store.
   } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0))) {
     // Store constant FP values with integer instructions to avoid having to
     // load the constants from the constant pool then do a store.
@@ -3089,45 +3063,24 @@ void ISel::visitStoreInst(StoreInst &I) {
         float    F;
       } V;
       V.F = CFP->getValue();
         float    F;
       } V;
       V.F = CFP->getValue();
-      if (AllocaFrameIdx != ~0U)
-        addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
-                          AllocaFrameIdx).addImm(V.I);
-      else
-        addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
-                       BaseReg, Scale, IndexReg, Disp).addImm(V.I);
+      addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(V.I);
     } else {
       union {
         uint64_t I;
         double   F;
       } V;
       V.F = CFP->getValue();
     } else {
       union {
         uint64_t I;
         double   F;
       } V;
       V.F = CFP->getValue();
-      if (AllocaFrameIdx != ~0U) {
-        addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
-                          AllocaFrameIdx).addImm((unsigned)V.I);
-        addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
-                          AllocaFrameIdx, 4).addImm(unsigned(V.I >> 32));
-      } else {
-        addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
-                       BaseReg, Scale, IndexReg, Disp).addImm((unsigned)V.I);
-        addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
-                       BaseReg, Scale, IndexReg, Disp+4).addImm(
+      addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm((unsigned)V.I);
+      AM.Disp += 4;
+      addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(
                                                           unsigned(V.I >> 32));
                                                           unsigned(V.I >> 32));
-      }
     }
     
   } else if (Class == cLong) {
     unsigned ValReg = getReg(I.getOperand(0));
     }
     
   } else if (Class == cLong) {
     unsigned ValReg = getReg(I.getOperand(0));
-    if (AllocaFrameIdx != ~0U) {
-      addFrameReference(BuildMI(BB, X86::MOV32mr, 5),
-                        AllocaFrameIdx).addReg(ValReg);
-      addFrameReference(BuildMI(BB, X86::MOV32mr, 5),
-                        AllocaFrameIdx, 4).addReg(ValReg+1);
-    } else {
-      addFullAddress(BuildMI(BB, X86::MOV32mr, 5),
-                     BaseReg, Scale, IndexReg, Disp).addReg(ValReg);
-      addFullAddress(BuildMI(BB, X86::MOV32mr, 5),
-                     BaseReg, Scale, IndexReg, Disp+4).addReg(ValReg+1);
-    }
+    addFullAddress(BuildMI(BB, X86::MOV32mr, 5), AM).addReg(ValReg);
+    AM.Disp += 4;
+    addFullAddress(BuildMI(BB, X86::MOV32mr, 5), AM).addReg(ValReg+1);
   } else {
     unsigned ValReg = getReg(I.getOperand(0));
     static const unsigned Opcodes[] = {
   } else {
     unsigned ValReg = getReg(I.getOperand(0));
     static const unsigned Opcodes[] = {
@@ -3136,11 +3089,7 @@ void ISel::visitStoreInst(StoreInst &I) {
     unsigned Opcode = Opcodes[Class];
     if (ValTy == Type::DoubleTy) Opcode = X86::FST64m;
 
     unsigned Opcode = Opcodes[Class];
     if (ValTy == Type::DoubleTy) Opcode = X86::FST64m;
 
-    if (AllocaFrameIdx != ~0U)
-      addFrameReference(BuildMI(BB, Opcode, 5), AllocaFrameIdx).addReg(ValReg);
-    else
-      addFullAddress(BuildMI(BB, Opcode, 1+4),
-                     BaseReg, Scale, IndexReg, Disp).addReg(ValReg);
+    addFullAddress(BuildMI(BB, Opcode, 1+4), AM).addReg(ValReg);
   }
 }
 
   }
 }
 
@@ -3539,8 +3488,8 @@ void ISel::visitVAArgInst(VAArgInst &I) {
 void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
   // If this GEP instruction will be folded into all of its users, we don't need
   // to explicitly calculate it!
 void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
   // If this GEP instruction will be folded into all of its users, we don't need
   // to explicitly calculate it!
-  unsigned A, B, C, D;
-  if (isGEPFoldable(0, I.getOperand(0), I.op_begin()+1, I.op_end(), A,B,C,D)) {
+  X86AddressMode AM;
+  if (isGEPFoldable(0, I.getOperand(0), I.op_begin()+1, I.op_end(), AM)) {
     // Check all of the users of the instruction to see if they are loads and
     // stores.
     bool AllWillFold = true;
     // Check all of the users of the instruction to see if they are loads and
     // stores.
     bool AllWillFold = true;
@@ -3575,15 +3524,16 @@ void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
 ///
 void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
                        std::vector<Value*> &GEPOps,
 ///
 void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
                        std::vector<Value*> &GEPOps,
-                       std::vector<const Type*> &GEPTypes, unsigned &BaseReg,
-                       unsigned &Scale, unsigned &IndexReg, unsigned &Disp) {
+                       std::vector<const Type*> &GEPTypes,
+                       X86AddressMode &AM) {
   const TargetData &TD = TM.getTargetData();
 
   // Clear out the state we are working with...
   const TargetData &TD = TM.getTargetData();
 
   // Clear out the state we are working with...
-  BaseReg = 0;    // No base register
-  Scale = 1;      // Unit scale
-  IndexReg = 0;   // No index register
-  Disp = 0;       // No displacement
+  AM.BaseType = X86AddressMode::RegBase;
+  AM.Base.Reg = 0;   // No base register
+  AM.Scale = 1;      // Unit scale
+  AM.IndexReg = 0;   // No index register
+  AM.Disp = 0;       // No displacement
 
   // While there are GEP indexes that can be folded into the current address,
   // keep processing them.
 
   // While there are GEP indexes that can be folded into the current address,
   // keep processing them.
@@ -3597,7 +3547,7 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
       // structure is in memory.  Since the structure index must be constant, we
       // can get its value and use it to find the right byte offset from the
       // StructLayout class's list of structure member offsets.
       // structure is in memory.  Since the structure index must be constant, we
       // can get its value and use it to find the right byte offset from the
       // StructLayout class's list of structure member offsets.
-      Disp += TD.getStructLayout(StTy)->MemberOffsets[CUI->getValue()];
+      AM.Disp += TD.getStructLayout(StTy)->MemberOffsets[CUI->getValue()];
       GEPOps.pop_back();        // Consume a GEP operand
       GEPTypes.pop_back();
     } else {
       GEPOps.pop_back();        // Consume a GEP operand
       GEPTypes.pop_back();
     } else {
@@ -3612,18 +3562,18 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
       // If idx is a constant, fold it into the offset.
       unsigned TypeSize = TD.getTypeSize(SqTy->getElementType());
       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
       // If idx is a constant, fold it into the offset.
       unsigned TypeSize = TD.getTypeSize(SqTy->getElementType());
       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
-        Disp += TypeSize*CSI->getValue();
+        AM.Disp += TypeSize*CSI->getValue();
       } else if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(idx)) {
       } else if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(idx)) {
-        Disp += TypeSize*CUI->getValue();
+        AM.Disp += TypeSize*CUI->getValue();
       } else {
         // If the index reg is already taken, we can't handle this index.
       } else {
         // If the index reg is already taken, we can't handle this index.
-        if (IndexReg) return;
+        if (AM.IndexReg) return;
 
         // If this is a size that we can handle, then add the index as 
         switch (TypeSize) {
         case 1: case 2: case 4: case 8:
           // These are all acceptable scales on X86.
 
         // If this is a size that we can handle, then add the index as 
         switch (TypeSize) {
         case 1: case 2: case 4: case 8:
           // These are all acceptable scales on X86.
-          Scale = TypeSize;
+          AM.Scale = TypeSize;
           break;
         default:
           // Otherwise, we can't handle this scale
           break;
         default:
           // Otherwise, we can't handle this scale
@@ -3635,7 +3585,7 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
               CI->getOperand(0)->getType() == Type::UIntTy)
             idx = CI->getOperand(0);
 
               CI->getOperand(0)->getType() == Type::UIntTy)
             idx = CI->getOperand(0);
 
-        IndexReg = MBB ? getReg(idx, MBB, IP) : 1;
+        AM.IndexReg = MBB ? getReg(idx, MBB, IP) : 1;
       }
 
       GEPOps.pop_back();        // Consume a GEP operand
       }
 
       GEPOps.pop_back();        // Consume a GEP operand
@@ -3646,22 +3596,23 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
   // GEPTypes is empty, which means we have a single operand left.  Set it as
   // the base register.
   //
   // GEPTypes is empty, which means we have a single operand left.  Set it as
   // the base register.
   //
-  assert(BaseReg == 0);
+  assert(AM.Base.Reg == 0);
 
 
-#if 0   // FIXME: TODO!
-  if (AllocaInst *AI = dyn_castFixedAlloca(V)) {
-    // FIXME: When we can add FrameIndex values as the first operand, we can
-    // make GEP's of allocas MUCH more efficient!
-    unsigned FI = getFixedSizedAllocaFI(AI);
+  if (AllocaInst *AI = dyn_castFixedAlloca(GEPOps.back())) {
+    AM.BaseType = X86AddressMode::FrameIndexBase;
+    AM.Base.FrameIndex = getFixedSizedAllocaFI(AI);
     GEPOps.pop_back();
     return;
     GEPOps.pop_back();
     return;
-  } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
+  }
+
+#if 0   // FIXME: TODO!
+  if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
     // FIXME: When addressing modes are more powerful/correct, we could load
     // global addresses directly as 32-bit immediates.
   }
 #endif
 
     // FIXME: When addressing modes are more powerful/correct, we could load
     // global addresses directly as 32-bit immediates.
   }
 #endif
 
-  BaseReg = MBB ? getReg(GEPOps[0], MBB, IP) : 1;
+  AM.Base.Reg = MBB ? getReg(GEPOps[0], MBB, IP) : 1;
   GEPOps.pop_back();        // Consume the last GEP operand
 }
 
   GEPOps.pop_back();        // Consume the last GEP operand
 }
 
@@ -3670,8 +3621,7 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
 /// folded into the addressing mode of a load/store or lea instruction.
 bool ISel::isGEPFoldable(MachineBasicBlock *MBB,
                          Value *Src, User::op_iterator IdxBegin,
 /// folded into the addressing mode of a load/store or lea instruction.
 bool ISel::isGEPFoldable(MachineBasicBlock *MBB,
                          Value *Src, User::op_iterator IdxBegin,
-                         User::op_iterator IdxEnd, unsigned &BaseReg,
-                         unsigned &Scale, unsigned &IndexReg, unsigned &Disp) {
+                         User::op_iterator IdxEnd, X86AddressMode &AM) {
 
   std::vector<Value*> GEPOps;
   GEPOps.resize(IdxEnd-IdxBegin+1);
 
   std::vector<Value*> GEPOps;
   GEPOps.resize(IdxEnd-IdxBegin+1);
@@ -3684,7 +3634,7 @@ bool ISel::isGEPFoldable(MachineBasicBlock *MBB,
 
   MachineBasicBlock::iterator IP;
   if (MBB) IP = MBB->end();
 
   MachineBasicBlock::iterator IP;
   if (MBB) IP = MBB->end();
-  getGEPIndex(MBB, IP, GEPOps, GEPTypes, BaseReg, Scale, IndexReg, Disp);
+  getGEPIndex(MBB, IP, GEPOps, GEPTypes, AM);
 
   // We can fold it away iff the getGEPIndex call eliminated all operands.
   return GEPOps.empty();
 
   // We can fold it away iff the getGEPIndex call eliminated all operands.
   return GEPOps.empty();
@@ -3723,23 +3673,23 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
   // Keep emitting instructions until we consume the entire GEP instruction.
   while (!GEPOps.empty()) {
     unsigned OldSize = GEPOps.size();
   // Keep emitting instructions until we consume the entire GEP instruction.
   while (!GEPOps.empty()) {
     unsigned OldSize = GEPOps.size();
-    unsigned BaseReg, Scale, IndexReg, Disp;
-    getGEPIndex(MBB, IP, GEPOps, GEPTypes, BaseReg, Scale, IndexReg, Disp);
+    X86AddressMode AM;
+    getGEPIndex(MBB, IP, GEPOps, GEPTypes, AM);
     
     if (GEPOps.size() != OldSize) {
       // getGEPIndex consumed some of the input.  Build an LEA instruction here.
       unsigned NextTarget = 0;
       if (!GEPOps.empty()) {
     
     if (GEPOps.size() != OldSize) {
       // getGEPIndex consumed some of the input.  Build an LEA instruction here.
       unsigned NextTarget = 0;
       if (!GEPOps.empty()) {
-        assert(BaseReg == 0 &&
+        assert(AM.Base.Reg == 0 &&
            "getGEPIndex should have left the base register open for chaining!");
            "getGEPIndex should have left the base register open for chaining!");
-        NextTarget = BaseReg = makeAnotherReg(Type::UIntTy);
+        NextTarget = AM.Base.Reg = makeAnotherReg(Type::UIntTy);
       }
 
       }
 
-      if (IndexReg == 0 && Disp == 0)
-        BuildMI(*MBB, IP, X86::MOV32rr, 1, TargetReg).addReg(BaseReg);
+      if (AM.BaseType == X86AddressMode::RegBase &&
+              AM.IndexReg == 0 && AM.Disp == 0)
+        BuildMI(*MBB, IP, X86::MOV32rr, 1, TargetReg).addReg(AM.Base.Reg);
       else
       else
-        addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TargetReg),
-                       BaseReg, Scale, IndexReg, Disp);
+        addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TargetReg), AM);
       --IP;
       TargetReg = NextTarget;
     } else if (GEPTypes.empty()) {
       --IP;
       TargetReg = NextTarget;
     } else if (GEPTypes.empty()) {
index 6612cd3e674c228ab2cbc6a42e83ceb393ed0f6f..3c8cfd73a16ee848d9189c9949248c4eb2d71d0d 100644 (file)
 
 namespace llvm {
 
 
 namespace llvm {
 
+/// X86AddressMode - This struct holds a generalized full x86 address mode.
+/// The base register can be a frame index, which will eventually be replaced
+/// with BP or SP and Disp being offsetted accordingly.
+/// FIXME: add support for globals as a new base type.
+struct X86AddressMode {
+    enum {
+      UnknownBase,
+      RegBase,
+      FrameIndexBase
+    } BaseType;
+
+    union {
+      unsigned Reg;
+      int FrameIndex;
+    } Base;
+
+    unsigned Scale;
+    unsigned IndexReg;
+    unsigned Disp;
+
+    X86AddressMode() : BaseType(UnknownBase) {}
+};
+
 /// addDirectMem - This function is used to add a direct memory reference to the
 /// current instruction -- that is, a dereference of an address in a register,
 /// with no scale, index or displacement. An example is: DWORD PTR [EAX].
 /// addDirectMem - This function is used to add a direct memory reference to the
 /// current instruction -- that is, a dereference of an address in a register,
 /// with no scale, index or displacement. An example is: DWORD PTR [EAX].
@@ -50,12 +73,16 @@ inline const MachineInstrBuilder &addRegOffset(const MachineInstrBuilder &MIB,
 }
 
 inline const MachineInstrBuilder &addFullAddress(const MachineInstrBuilder &MIB,
 }
 
 inline const MachineInstrBuilder &addFullAddress(const MachineInstrBuilder &MIB,
-                                                 unsigned BaseReg,
-                                                 unsigned Scale,
-                                                 unsigned IndexReg,
-                                                 unsigned Disp) {
-  assert (Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8);
-  return MIB.addReg(BaseReg).addZImm(Scale).addReg(IndexReg).addSImm(Disp);
+                                                 const X86AddressMode &AM) {
+  assert (AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8);
+
+  if (AM.BaseType == X86AddressMode::RegBase)
+    MIB.addReg(AM.Base.Reg);
+  else if (AM.BaseType == X86AddressMode::FrameIndexBase)
+    MIB.addFrameIndex(AM.Base.FrameIndex);
+  else
+    assert (0);
+  return MIB.addZImm(AM.Scale).addReg(AM.IndexReg).addSImm(AM.Disp);
 }
 
 /// addFrameReference - This function is used to add a reference to the base of
 }
 
 /// addFrameReference - This function is used to add a reference to the base of