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

Evan Cheng evan.cheng at apple.com
Wed Dec 7 18:01:47 PST 2005



Changes in directory llvm/lib/Target/X86:

X86ISelDAGToDAG.cpp updated: 1.6 -> 1.7
X86InstrInfo.td updated: 1.148 -> 1.149
---
Log message:

* Added intelligence to X86 LEA addressing mode matching routine so it returns
false if the match is not profitable. e.g. leal 1(%eax), %eax.
* Added patterns for X86 integer loads and LEA32.


---
Diffs of the changes:  (+103 -84)

 X86ISelDAGToDAG.cpp |  158 +++++++++++++++++++++++++++-------------------------
 X86InstrInfo.td     |   29 +++++----
 2 files changed, 103 insertions(+), 84 deletions(-)


Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.6 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.7
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.6	Wed Nov 30 18:43:55 2005
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp	Wed Dec  7 20:01:35 2005
@@ -36,6 +36,7 @@
     enum {
       RegBase,
       FrameIndexBase,
+      ConstantPoolBase
     } BaseType;
 
     struct {            // This is really a union, discriminated by BaseType!
@@ -94,8 +95,11 @@
   private:
     SDOperand Select(SDOperand N);
 
-    void SelectAddress(SDOperand N, X86ISelAddressMode &AM);
     bool MatchAddress(SDOperand N, X86ISelAddressMode &AM);
+    bool SelectAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
+                    SDOperand &Index, SDOperand &Disp);
+    bool SelectLEAAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
+                       SDOperand &Index, SDOperand &Disp);
 
     /// getI8Imm - Return a target constant with the specified value, of type
     /// i8.
@@ -130,23 +134,6 @@
   ScheduleAndEmitDAG(DAG);
 }
 
-/// SelectAddress - Pattern match the maximal addressing mode for this node.
-void X86DAGToDAGISel::SelectAddress(SDOperand N, X86ISelAddressMode &AM) {
-  MatchAddress(N, AM);
-
-  if (AM.BaseType == X86ISelAddressMode::RegBase) {
-    if (AM.Base.Reg.Val)
-      AM.Base.Reg = Select(AM.Base.Reg);
-    else
-      AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
-  }
-  if (!AM.IndexReg.Val) {
-    AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
-  } else {
-    AM.IndexReg = Select(AM.IndexReg);
-  }
-}
-
 /// FIXME: copied from X86ISelPattern.cpp
 /// MatchAddress - Add the specified node to the specified addressing mode,
 /// returning true if it cannot be done.  This just pattern matches for the
@@ -161,6 +148,17 @@
       return false;
     }
     break;
+
+  case ISD::ConstantPool:
+    if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
+      if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N)) {
+        AM.BaseType = X86ISelAddressMode::ConstantPoolBase;
+        AM.Base.Reg = CurDAG->getTargetConstantPool(CP->get(), MVT::i32);
+        return false;
+      }
+    }
+    break;
+
   case ISD::GlobalAddress:
     if (AM.GV == 0) {
       GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
@@ -177,9 +175,11 @@
       }
     }
     break;
+
   case ISD::Constant:
     AM.Disp += cast<ConstantSDNode>(N)->getValue();
     return false;
+
   case ISD::SHL:
     if (AM.IndexReg.Val == 0 && AM.Scale == 1)
       if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1))) {
@@ -204,6 +204,7 @@
         }
       }
     break;
+
   case ISD::MUL:
     // X*[3,5,9] -> X+X*[2,4,8]
     if (AM.IndexReg.Val == 0 && AM.BaseType == X86ISelAddressMode::RegBase &&
@@ -266,6 +267,67 @@
   return false;
 }
 
+/// SelectAddr - returns true if it is able pattern match an addressing mode.
+/// It returns the operands which make up the maximal addressing mode it can
+/// match by reference.
+bool X86DAGToDAGISel::SelectAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
+                                 SDOperand &Index, SDOperand &Disp) {
+  X86ISelAddressMode AM;
+  if (!MatchAddress(N, AM)) {
+    if (AM.BaseType == X86ISelAddressMode::RegBase) {
+      if (AM.Base.Reg.Val)
+        AM.Base.Reg = Select(AM.Base.Reg);
+      else
+        AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
+    }
+    if (AM.IndexReg.Val)
+      AM.IndexReg = Select(AM.IndexReg);
+    else
+      AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
+
+    Base  = (AM.BaseType == X86ISelAddressMode::FrameIndexBase) ?
+      CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, MVT::i32) : AM.Base.Reg;
+    Scale = getI8Imm (AM.Scale);
+    Index = AM.IndexReg;
+    Disp  = AM.GV ? CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp)
+                  : getI32Imm(AM.Disp);
+    return true;
+  }
+  return false;
+}
+
+static bool isRegister0(SDOperand Op)
+{
+  if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op))
+    return (R->getReg() == 0);
+  return false;
+}
+
+/// SelectLEAAddr - it calls SelectAddr and determines if the maximal addressing
+/// mode it matches can be cost effectively emitted as an LEA instruction.
+/// For X86, it always is unless it's just a (Reg + const).
+bool X86DAGToDAGISel::SelectLEAAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
+                                    SDOperand &Index, SDOperand &Disp) {
+  if (SelectAddr(N, Base, Scale, Index, Disp)) {
+    if (!isRegister0(Base)) {
+      unsigned Complexity = 0;
+      if ((unsigned)cast<ConstantSDNode>(Scale)->getValue() > 1)
+        Complexity++;
+      if (!isRegister0(Index))
+        Complexity++;
+      if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Disp)) {
+        if (!CN->isNullValue()) Complexity++;
+      } else {
+        Complexity++;
+      }
+      return (Complexity > 1);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
 SDOperand X86DAGToDAGISel::Select(SDOperand Op) {
   SDNode *N = Op.Val;
   MVT::ValueType OpVT = N->getValueType(0);
@@ -326,51 +388,9 @@
                                     Chain);
     }
 
-    case ISD::LOAD: {
-      switch (OpVT) {
-        default: assert(0 && "Cannot load this type!");
-        case MVT::i1:
-        case MVT::i8:  Opc = X86::MOV8rm; break;
-        case MVT::i16: Opc = X86::MOV16rm; break;
-        case MVT::i32: Opc = X86::MOV32rm; break;
-        case MVT::f32: Opc = X86::MOVSSrm; break;
-        case MVT::f64: Opc = X86::FLD64m; ContainsFPCode = true; break;
-      }
-
-      if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N->getOperand(1))){
-        unsigned CPIdx = BB->getParent()->getConstantPool()->
-          getConstantPoolIndex(CP->get());
-        // ???
-        assert(0 && "Can't handle load from constant pool!");
-      } else {
-        X86ISelAddressMode AM;
-        SDOperand Chain = Select(N->getOperand(0));     // Token chain.
-
-        SelectAddress(N->getOperand(1), AM);
-        SDOperand Scale = getI8Imm (AM.Scale);
-        SDOperand Disp  = AM.GV
-          ? CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp)
-          : getI32Imm(AM.Disp);
-        if (AM.BaseType == X86ISelAddressMode::RegBase) {
-          return CurDAG->SelectNodeTo(N, Opc, OpVT, MVT::Other,
-                                      AM.Base.Reg, Scale, AM.IndexReg, Disp, 
-                                      Chain)
-            .getValue(Op.ResNo);
-        } else {
-          SDOperand Base = CurDAG->getFrameIndex(AM.Base.FrameIndex, MVT::i32);
-          return CurDAG->SelectNodeTo(N, Opc, OpVT, MVT::Other,
-                                      Base, Scale, AM.IndexReg, Disp, Chain)
-            .getValue(Op.ResNo);
-        }
-      }
-    }
-
     case ISD::STORE: {
       SDOperand Chain = Select(N->getOperand(0));     // Token chain.
       SDOperand Tmp1 = Select(N->getOperand(1));
-      X86ISelAddressMode AM;
-      SelectAddress(N->getOperand(2), AM);
-
       Opc = 0;
       if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
         switch (CN->getValueType(0)) {
@@ -394,19 +414,11 @@
         }
       }
 
-      SDOperand Scale = getI8Imm (AM.Scale);
-      SDOperand Disp  = AM.GV
-        ? CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp)
-        : getI32Imm(AM.Disp);
-      if (AM.BaseType == X86ISelAddressMode::RegBase) {
-        return CurDAG->SelectNodeTo(N, Opc, MVT::Other,
-                                    AM.Base.Reg, Scale, AM.IndexReg, Disp, Tmp1,
-                                    Chain);
-      } else {
-        SDOperand Base = CurDAG->getFrameIndex(AM.Base.FrameIndex, MVT::i32);
-        return CurDAG->SelectNodeTo(N, Opc, MVT::Other,
-                                  Base, Scale, AM.IndexReg, Disp, Tmp1, Chain);
-      }
+      SDOperand Base, Scale, Index, Disp;
+      SelectAddr(N->getOperand(2), Base, Scale, Index, Disp);
+      return CurDAG->SelectNodeTo(N, Opc, MVT::Other,
+                                  Base, Scale, Index, Disp, Tmp1, Chain)
+        .getValue(Op.ResNo);
     }
   }
 


Index: llvm/lib/Target/X86/X86InstrInfo.td
diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.148 llvm/lib/Target/X86/X86InstrInfo.td:1.149
--- llvm/lib/Target/X86/X86InstrInfo.td:1.148	Mon Dec  5 17:09:43 2005
+++ llvm/lib/Target/X86/X86InstrInfo.td	Wed Dec  7 20:01:35 2005
@@ -21,13 +21,13 @@
   let MIOperandInfo = (ops R32, i8imm, R32, i32imm);
 }
 
-def i8mem   : X86MemOperand<i8,  "printi8mem">;
-def i16mem  : X86MemOperand<i16, "printi16mem">;
+def i8mem   : X86MemOperand<i32, "printi8mem">;
+def i16mem  : X86MemOperand<i32, "printi16mem">;
 def i32mem  : X86MemOperand<i32, "printi32mem">;
-def i64mem  : X86MemOperand<i64, "printi64mem">;
-def f32mem  : X86MemOperand<f32, "printf32mem">;
-def f64mem  : X86MemOperand<f64, "printf64mem">;
-def f80mem  : X86MemOperand<f80, "printf80mem">;
+def i64mem  : X86MemOperand<i32, "printi64mem">;
+def f32mem  : X86MemOperand<i32, "printf32mem">;
+def f64mem  : X86MemOperand<i32, "printf64mem">;
+def f80mem  : X86MemOperand<i32, "printf80mem">;
 
 def SSECC : Operand<i8> {
   let PrintMethod = "printSSECC";
@@ -46,6 +46,10 @@
 // Branch targets have OtherVT type.
 def brtarget : Operand<OtherVT>;
 
+// Define X86 specific addressing mode.
+def addr    : ComplexPattern<4, "SelectAddr", []>;
+def leaaddr : ComplexPattern<4, "SelectLEAAddr", [add]>;
+
 // Format specifies the encoding used by the instruction.  This is part of the
 // ad-hoc solution used to emit machine instruction encodings by our machine
 // code emitter.
@@ -151,7 +155,6 @@
   return (unsigned)N->getValue() == (unsigned char)N->getValue();
 }]>;
 
-
 //===----------------------------------------------------------------------===//
 // Instruction templates...
 
@@ -297,7 +300,8 @@
                  "lea{w} {$src|$dst}, {$dst|$src}", []>, OpSize;
 def LEA32r   : I<0x8D, MRMSrcMem,
                  (ops R32:$dst, i32mem:$src),
-                 "lea{l} {$src|$dst}, {$dst|$src}", []>;
+                 "lea{l} {$src|$dst}, {$dst|$src}",
+                 [(set R32:$dst, leaaddr:$src)]>;
 
 
 def REP_MOVSB : I<0xA4, RawFrm, (ops), "{rep;movsb|rep movsb}", []>,
@@ -381,11 +385,14 @@
                    "mov{l} {$src, $dst|$dst, $src}", []>;
 
 def MOV8rm  : I<0x8A, MRMSrcMem, (ops R8 :$dst, i8mem :$src),
-                "mov{b} {$src, $dst|$dst, $src}", []>;
+                "mov{b} {$src, $dst|$dst, $src}",
+                [(set R8:$dst, (load addr:$src))]>;
 def MOV16rm : I<0x8B, MRMSrcMem, (ops R16:$dst, i16mem:$src),
-                "mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
+                "mov{w} {$src, $dst|$dst, $src}",
+                [(set R16:$dst, (load addr:$src))]>, OpSize;
 def MOV32rm : I<0x8B, MRMSrcMem, (ops R32:$dst, i32mem:$src),
-                "mov{l} {$src, $dst|$dst, $src}", []>;
+                "mov{l} {$src, $dst|$dst, $src}",
+                [(set R32:$dst, (load addr:$src))]>;
 
 def MOV8mr  : I<0x88, MRMDestMem, (ops i8mem :$dst, R8 :$src),
                 "mov{b} {$src, $dst|$dst, $src}", []>;






More information about the llvm-commits mailing list