summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Lamb <christopher.lamb@gmail.com>2008-03-13 05:47:01 +0000
committerChristopher Lamb <christopher.lamb@gmail.com>2008-03-13 05:47:01 +0000
commit6634e26aa11b0e2eabde8b3b463bb943364f8d9d (patch)
treef6acb329d49272da4adec8fba66734bba41760b5
parent3bdfa04cbe42106d2dc55d0dd980ba9e52a3bd84 (diff)
downloadllvm-6634e26aa11b0e2eabde8b3b463bb943364f8d9d.tar.gz
llvm-6634e26aa11b0e2eabde8b3b463bb943364f8d9d.tar.bz2
llvm-6634e26aa11b0e2eabde8b3b463bb943364f8d9d.tar.xz
Get rid of a pseudo instruction and replace it with subreg based operation on real instructions, ridding the asm printers of the hack used to do this previously. In the process, update LowerSubregs to be careful about eliminating copies that have side affects.
Note: the coalescer will have to be careful about this too, when it starts coalescing insert_subreg nodes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48329 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Target/TargetInstrInfo.h10
-rw-r--r--lib/CodeGen/LowerSubregs.cpp24
-rw-r--r--lib/Target/TargetSelectionDAG.td7
-rw-r--r--lib/Target/X86/X86ATTAsmPrinter.cpp8
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp7
-rw-r--r--lib/Target/X86/X86Instr64bit.td43
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp6
-rw-r--r--lib/Target/X86/X86InstrInfo.h10
-rw-r--r--lib/Target/X86/X86InstrInfo.td4
-rw-r--r--lib/Target/X86/X86IntelAsmPrinter.cpp8
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp17
11 files changed, 65 insertions, 79 deletions
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 75260878dd..d19ca12420 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -51,6 +51,15 @@ public:
EXTRACT_SUBREG = 4,
INSERT_SUBREG = 5
};
+
+ // Target independent implict values for use with subreg insert. All targets
+ // that support insert_subreg support IMPL_VAL_UNDEF. Support for the other
+ // values is target dependent.
+ enum ImplictVal {
+ IMPL_VAL_UNDEF = 0,
+ IMPL_VAL_ZERO = 1,
+ LAST_IMPL_VAL = 3
+ };
unsigned getNumOpcodes() const { return NumOpcodes; }
@@ -120,7 +129,6 @@ public:
return false;
}
-
/// convertToThreeAddress - This method must be implemented by targets that
/// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target
/// may be able to convert a two-address instruction into one or more true
diff --git a/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp
index 531713e47f..8945dd57b1 100644
--- a/lib/CodeGen/LowerSubregs.cpp
+++ b/lib/CodeGen/LowerSubregs.cpp
@@ -96,13 +96,10 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
(MI->getOperand(2).isRegister() && MI->getOperand(2).isUse()) &&
MI->getOperand(3).isImmediate() && "Invalid insert_subreg");
+ // Check if we're inserting into an implicit undef value.
+ bool isImplicit = MI->getOperand(1).isImmediate();
unsigned DstReg = MI->getOperand(0).getReg();
- unsigned SrcReg = 0;
- // Check if we're inserting into an implicit value.
- if (MI->getOperand(1).isImmediate())
- SrcReg = DstReg;
- else
- SrcReg = MI->getOperand(1).getReg();
+ unsigned SrcReg = isImplicit ? DstReg : MI->getOperand(1).getReg();
unsigned InsReg = MI->getOperand(2).getReg();
unsigned SubIdx = MI->getOperand(3).getImm();
@@ -118,13 +115,20 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
DOUT << "subreg: CONVERTING: " << *MI;
+ // Check whether the implict subreg copy has side affects or not. Only copies
+ // into an undef value have no side affects, that is they can be eliminated
+ // without changing the semantics of the program.
+ bool copyHasSideAffects = isImplicit?
+ MI->getOperand(1).getImm() != TargetInstrInfo::IMPL_VAL_UNDEF
+ : false;
+
// If the inserted register is already allocated into a subregister
// of the destination, we copy the subreg into the source
// However, this is only safe if the insert instruction is the kill
// of the source register
bool revCopyOrder = TRI.isSubRegister(DstReg, InsReg);
- if (revCopyOrder && InsReg != DstSubReg) {
- if (MI->getOperand(1).isKill()) {
+ if (revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
+ if (isImplicit || MI->getOperand(1).isKill()) {
DstSubReg = TRI.getSubReg(SrcReg, SubIdx);
// Insert sub-register copy
const TargetRegisterClass *TRC1 = 0;
@@ -144,7 +148,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
}
}
#ifndef NDEBUG
- if (InsReg == DstSubReg) {
+ if (InsReg == DstSubReg && !copyHasSideAffects) {
DOUT << "subreg: Eliminated subreg copy\n";
}
#endif
@@ -174,7 +178,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
}
#endif
- if (!revCopyOrder && InsReg != DstSubReg) {
+ if (!revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
// Insert sub-register copy
const TargetRegisterClass *TRC1 = 0;
if (TargetRegisterInfo::isPhysicalRegister(InsReg)) {
diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td
index dc0fcb5443..73280f3f6f 100644
--- a/lib/Target/TargetSelectionDAG.td
+++ b/lib/Target/TargetSelectionDAG.td
@@ -919,5 +919,10 @@ def SDT_dwarf_loc : SDTypeProfile<0, 3,
[SDTCisInt<0>, SDTCisInt<1>, SDTCisInt<2>]>;
def dwarf_loc : SDNode<"ISD::DEBUG_LOC", SDT_dwarf_loc,[SDNPHasChain]>;
-
+//===----------------------------------------------------------------------===//
+// Implict value insert subreg support.
+//
+// These should match the enum TargetInstrInfo::ImplictVal.
+def tii_impl_val_undef : PatLeaf<(i32 0)>;
+def tii_impl_val_zero : PatLeaf<(i32 1)>;
diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp
index 4fef3827e3..e51e065540 100644
--- a/lib/Target/X86/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/X86ATTAsmPrinter.cpp
@@ -637,14 +637,6 @@ bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
- // See if a truncate instruction can be turned into a nop.
- switch (MI->getOpcode()) {
- default: break;
- case X86::PsMOVZX64rr32:
- O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t";
- break;
- }
-
// Call the autogenerated instruction printer routines.
printInstruction(MI);
}
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index d5601b74ea..bf233bfcbb 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -1533,14 +1533,9 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
AddToISelQueue(N0);
if (NVT == MVT::i64 || NVT == MVT::i32 || NVT == MVT::i16) {
SDOperand SRIdx;
- SDOperand ImplVal = CurDAG->getTargetConstant(X86::IMPL_VAL_UNDEF,
- MVT::i32);
switch(N0.getValueType()) {
case MVT::i32:
SRIdx = CurDAG->getTargetConstant(X86::SUBREG_32BIT, MVT::i32);
- // x86-64 zero extends 32-bit inserts int 64-bit registers
- if (Subtarget->is64Bit())
- ImplVal = CurDAG->getTargetConstant(X86::IMPL_VAL_ZERO, MVT::i32);
break;
case MVT::i16:
SRIdx = CurDAG->getTargetConstant(X86::SUBREG_16BIT, MVT::i32);
@@ -1552,6 +1547,8 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
default: assert(0 && "Unknown any_extend!");
}
if (SRIdx.Val) {
+ SDOperand ImplVal =
+ CurDAG->getTargetConstant(X86InstrInfo::IMPL_VAL_UNDEF, MVT::i32);
SDNode *ResNode = CurDAG->getTargetNode(X86::INSERT_SUBREG,
NVT, ImplVal, N0, SRIdx);
diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td
index 3002b2c210..d5a9f0bc66 100644
--- a/lib/Target/X86/X86Instr64bit.td
+++ b/lib/Target/X86/X86Instr64bit.td
@@ -1089,22 +1089,6 @@ def Int_CVTTSS2SI64rm: RSSI<0x2C, MRMSrcMem, (outs GR64:$dst), (ins f32mem:$src)
// Alias Instructions
//===----------------------------------------------------------------------===//
-// Zero-extension
-// TODO: Remove this after proper i32 -> i64 zext support.
-def PsMOVZX64rr32: I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR32:$src),
- "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}",
- [(set GR64:$dst, (zext GR32:$src))]>;
-def PsMOVZX64rm32: I<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src),
- "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}",
- [(set GR64:$dst, (zextloadi64i32 addr:$src))]>;
-
-/// PsAND64rrFFFFFFFF - r = r & (2^32-1)
-def PsAND64rrFFFFFFFF
- : I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src),
- "mov{l}\t{${src:subreg32}, ${dst:subreg32}|${dst:subreg32}, ${src:subreg32}}",
- [(set GR64:$dst, (and GR64:$src, i64immFFFFFFFF))]>;
-
-
// Alias instructions that map movr0 to xor. Use xorl instead of xorq; it's
// equivalent due to implicit zero-extending, and it sometimes has a smaller
// encoding.
@@ -1220,27 +1204,48 @@ def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off),
def : Pat<(parallel (X86cmp GR64:$src1, 0), (implicit EFLAGS)),
(TEST64rr GR64:$src1, GR64:$src1)>;
+
+
+// Zero-extension
+def : Pat<(i64 (zext GR32:$src)), (INSERT_SUBREG tii_impl_val_zero,
+ GR32:$src, x86_subreg_32bit)>;
+
// zextload bool -> zextload byte
def : Pat<(zextloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>;
+def : Pat<(zextloadi64i32 addr:$src), (INSERT_SUBREG tii_impl_val_zero,
+ (MOV32rm addr:$src), x86_subreg_32bit)>;
+
// extload
def : Pat<(extloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>;
def : Pat<(extloadi64i8 addr:$src), (MOVZX64rm8 addr:$src)>;
def : Pat<(extloadi64i16 addr:$src), (MOVZX64rm16 addr:$src)>;
-def : Pat<(extloadi64i32 addr:$src), (PsMOVZX64rm32 addr:$src)>;
+def : Pat<(extloadi64i32 addr:$src), (INSERT_SUBREG tii_impl_val_undef,
+ (MOV32rm addr:$src), x86_subreg_32bit)>;
// anyext -> zext
def : Pat<(i64 (anyext GR8 :$src)), (MOVZX64rr8 GR8 :$src)>;
def : Pat<(i64 (anyext GR16:$src)), (MOVZX64rr16 GR16:$src)>;
-def : Pat<(i64 (anyext GR32:$src)), (PsMOVZX64rr32 GR32:$src)>;
+def : Pat<(i64 (anyext GR32:$src)), (INSERT_SUBREG tii_impl_val_undef,
+ GR32:$src, x86_subreg_32bit)>;
+
def : Pat<(i64 (anyext (loadi8 addr:$src))), (MOVZX64rm8 addr:$src)>;
def : Pat<(i64 (anyext (loadi16 addr:$src))), (MOVZX64rm16 addr:$src)>;
-def : Pat<(i64 (anyext (loadi32 addr:$src))), (PsMOVZX64rm32 addr:$src)>;
+def : Pat<(i64 (anyext (loadi32 addr:$src))), (INSERT_SUBREG tii_impl_val_undef,
+ (MOV32rm addr:$src),
+ x86_subreg_32bit)>;
//===----------------------------------------------------------------------===//
// Some peepholes
//===----------------------------------------------------------------------===//
+
+// r & (2^32-1) ==> mov32 + implicit zext
+def : Pat<(and GR64:$src, i64immFFFFFFFF),
+ (INSERT_SUBREG tii_impl_val_zero,
+ (MOV32rr (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)),
+ x86_subreg_32bit)>;
+
// (shl x, 1) ==> (add x, x)
def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>;
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 8497fe3039..ff666ff3c2 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -392,7 +392,6 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
{ X86::PSHUFDri, X86::PSHUFDmi },
{ X86::PSHUFHWri, X86::PSHUFHWmi },
{ X86::PSHUFLWri, X86::PSHUFLWmi },
- { X86::PsMOVZX64rr32, X86::PsMOVZX64rm32 },
{ X86::RCPPSr, X86::RCPPSm },
{ X86::RCPPSr_Int, X86::RCPPSm_Int },
{ X86::RSQRTPSr, X86::RSQRTPSm },
@@ -922,8 +921,9 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
// Build and insert into an implicit UNDEF value. This is OK because
// well be shifting and then extracting the lower 16-bits.
MachineInstr *Ins =
- BuildMI(get(X86::INSERT_SUBREG),leaInReg).addImm(X86::IMPL_VAL_UNDEF)
- .addReg(Src).addImm(X86::SUBREG_16BIT);
+ BuildMI(get(X86::INSERT_SUBREG),leaInReg)
+ .addImm(X86InstrInfo::IMPL_VAL_UNDEF)
+ .addReg(Src).addImm(X86::SUBREG_16BIT);
NewMI = BuildMI(get(Opc), leaOutReg)
.addReg(0).addImm(1 << ShAmt).addReg(leaInReg).addImm(0);
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index e0d0342ae6..f4cdb70695 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -45,15 +45,7 @@ namespace X86 {
COND_S = 15,
COND_INVALID
};
-
- // X86 specific implict values used for subregister inserts.
- // This can be used to model the fact that x86-64 by default
- // inserts 32-bit values into 64-bit registers implicitly containing zeros.
- enum ImplicitVal {
- IMPL_VAL_UNDEF = 0,
- IMPL_VAL_ZERO = 1
- };
-
+
// Turn condition code into conditional branch opcode.
unsigned GetCondBranchFromCond(CondCode CC);
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 4d03dba32d..e32fb9c4b5 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -161,10 +161,6 @@ def i32i8imm : Operand<i32>;
// Branch targets have OtherVT type.
def brtarget : Operand<OtherVT>;
-// These should match the enum X86::ImplicitVal
-def x86_impl_val_undef : PatLeaf<(i32 0)>;
-def x86_impl_val_zero : PatLeaf<(i32 1)>;
-
//===----------------------------------------------------------------------===//
// X86 Complex Pattern Definitions.
//
diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp
index 6c46b45456..16d819a3d7 100644
--- a/lib/Target/X86/X86IntelAsmPrinter.cpp
+++ b/lib/Target/X86/X86IntelAsmPrinter.cpp
@@ -314,14 +314,6 @@ bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
- // See if a truncate instruction can be turned into a nop.
- switch (MI->getOpcode()) {
- default: break;
- case X86::PsMOVZX64rr32:
- O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t";
- break;
- }
-
// Call the autogenerated instruction printer routines.
printInstruction(MI);
}
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 291a913c37..0c6afab4c9 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -975,9 +975,9 @@ public:
}
}
- // Generate MemOperandSDNodes nodes for each memory accesses covered by this
- // pattern.
- if (isRoot) {
+ // Generate MemOperandSDNodes nodes for each memory accesses covered by
+ // this pattern.
+ if (II.isSimpleLoad | II.mayLoad | II.mayStore) {
std::vector<std::string>::const_iterator mi, mie;
for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
emitCode("SDOperand LSI_" + *mi + " = "
@@ -1880,14 +1880,9 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
<< " SDOperand Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
<< " AddToISelQueue(N1);\n"
<< " SDOperand Ops[] = { N0, N1, Tmp };\n"
- << " if (N0.getOpcode() == ISD::UNDEF) {\n"
- << " return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n"
- << " N.getValueType(), Ops+1, 2);\n"
- << " } else {\n"
- << " AddToISelQueue(N0);\n"
- << " return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n"
- << " N.getValueType(), Ops, 3);\n"
- << " }\n"
+ << " AddToISelQueue(N0);\n"
+ << " return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n"
+ << " N.getValueType(), Ops, 3);\n"
<< "}\n\n";
OS << "// The main instruction selector code.\n"