enum {
RegBase,
FrameIndexBase,
+ ConstantPoolBase
} BaseType;
struct { // This is really a union, discriminated by BaseType!
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.
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
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();
}
}
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))) {
}
}
break;
+
case ISD::MUL:
// X*[3,5,9] -> X+X*[2,4,8]
if (AM.IndexReg.Val == 0 && AM.BaseType == X86ISelAddressMode::RegBase &&
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);
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)) {
}
}
- 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);
}
}
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";
// 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.
return (unsigned)N->getValue() == (unsigned char)N->getValue();
}]>;
-
//===----------------------------------------------------------------------===//
// Instruction templates...
"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}", []>,
"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}", []>;