* 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
This commit is contained in:
Evan Cheng 2005-12-08 02:01:35 +00:00
parent 0fc7198890
commit ec693f77c0
2 changed files with 103 additions and 84 deletions

View File

@ -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<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 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) {
}
}
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 @@ 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<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 @@ 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<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 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);
}
}

View File

@ -21,13 +21,13 @@ class X86MemOperand<ValueType Ty, string printMethod> : Operand<Ty> {
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 @@ let PrintMethod = "printCallOperand" in
// 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 @@ 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}", []>;