mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-30 20:34:21 +00:00
* 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:
parent
0fc7198890
commit
ec693f77c0
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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}", []>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user