From ec693f77c03f5511001bfcac8180de6b551f7b1d Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 8 Dec 2005 02:01:35 +0000 Subject: [PATCH] * 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24635 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 158 ++++++++++++++++------------- lib/Target/X86/X86InstrInfo.td | 29 ++++-- 2 files changed, 103 insertions(+), 84 deletions(-) diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 59f659acb84..57baee2c386 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -36,6 +36,7 @@ namespace { enum { RegBase, FrameIndexBase, + ConstantPoolBase } BaseType; struct { // This is really a union, discriminated by BaseType! @@ -94,8 +95,11 @@ namespace { 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 @@ void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 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 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) { return false; } break; + + case ISD::ConstantPool: + if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) { + if (ConstantPoolSDNode *CP = dyn_cast(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(N)->getGlobal(); @@ -177,9 +175,11 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) { } } break; + case ISD::Constant: AM.Disp += cast(N)->getValue(); return false; + case ISD::SHL: if (AM.IndexReg.Val == 0 && AM.Scale == 1) if (ConstantSDNode *CN = dyn_cast(N.Val->getOperand(1))) { @@ -204,6 +204,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) { } } 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 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) { 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(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(Scale)->getValue() > 1) + Complexity++; + if (!isRegister0(Index)) + Complexity++; + if (ConstantSDNode *CN = dyn_cast(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 @@ SDOperand X86DAGToDAGISel::Select(SDOperand Op) { 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(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(N->getOperand(1))) { switch (CN->getValueType(0)) { @@ -394,19 +414,11 @@ SDOperand X86DAGToDAGISel::Select(SDOperand Op) { } } - 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); } } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 5482838e7e5..9399018fb93 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -21,13 +21,13 @@ class X86MemOperand : Operand { let MIOperandInfo = (ops R32, i8imm, R32, i32imm); } -def i8mem : X86MemOperand; -def i16mem : X86MemOperand; +def i8mem : X86MemOperand; +def i16mem : X86MemOperand; def i32mem : X86MemOperand; -def i64mem : X86MemOperand; -def f32mem : X86MemOperand; -def f64mem : X86MemOperand; -def f80mem : X86MemOperand; +def i64mem : X86MemOperand; +def f32mem : X86MemOperand; +def f64mem : X86MemOperand; +def f80mem : X86MemOperand; def SSECC : Operand { let PrintMethod = "printSSECC"; @@ -46,6 +46,10 @@ let PrintMethod = "printCallOperand" in // Branch targets have OtherVT type. def brtarget : Operand; +// 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 @@ def immZExt8 : PatLeaf<(imm), [{ return (unsigned)N->getValue() == (unsigned char)N->getValue(); }]>; - //===----------------------------------------------------------------------===// // Instruction templates... @@ -297,7 +300,8 @@ def LEA16r : I<0x8D, MRMSrcMem, "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 @@ def MOV32mi : Ii32<0xC7, MRM0m, (ops i32mem:$dst, i32imm:$src), "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}", []>; -- 2.34.1