From 0bfa1bfbff1ddc5a85494c9e2b1f985f145dc8a6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 20 Aug 2008 21:27:32 +0000 Subject: [PATCH] Move the handling of ANY_EXTEND, SIGN_EXTEND_INREG, and TRUNCATE out of X86ISelDAGToDAG.cpp C++ code and into tablegen code. Among other things, using tablegen for these things makes them friendlier to FastISel. Tablegen can handle the case of i8 subregs on x86-32, but currently the C++ code for that case uses MVT::Flag in a tricky way, and it happens to schedule better in some cases. So for now, leave the C++ code in place to handle the i8 case on x86-32. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55078 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 169 +++++++++++------------------ lib/Target/X86/X86Instr64bit.td | 76 ++++++++++--- lib/Target/X86/X86InstrInfo.td | 52 ++++++--- 3 files changed, 159 insertions(+), 138 deletions(-) diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 2bd875e92e3..13ed07c04c7 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -234,9 +234,11 @@ namespace { /// base register. Return the virtual register that holds this value. SDNode *getGlobalBaseReg(); - /// getTruncate - return an SDNode that implements a subreg based truncate - /// of the specified operand to the the specified value type. - SDNode *getTruncate(SDValue N0, MVT VT); + /// getTruncateTo8Bit - return an SDNode that implements a subreg based + /// truncate of the specified operand to i8. This can be done with tablegen, + /// except that this code uses MVT::Flag in a tricky way that happens to + /// improve scheduling in some cases. + SDNode *getTruncateTo8Bit(SDValue N0); #ifndef NDEBUG unsigned Indent; @@ -1133,38 +1135,33 @@ static SDNode *FindCallStartFromCall(SDNode *Node) { return FindCallStartFromCall(Node->getOperand(0).Val); } -SDNode *X86DAGToDAGISel::getTruncate(SDValue N0, MVT VT) { - SDValue SRIdx; - switch (VT.getSimpleVT()) { - default: assert(0 && "Unknown truncate!"); - case MVT::i8: - SRIdx = CurDAG->getTargetConstant(1, MVT::i32); // SubRegSet 1 - // Ensure that the source register has an 8-bit subreg on 32-bit targets - if (!Subtarget->is64Bit()) { - unsigned Opc; - MVT N0VT = N0.getValueType(); - switch (N0VT.getSimpleVT()) { - default: assert(0 && "Unknown truncate!"); - case MVT::i16: - Opc = X86::MOV16to16_; - break; - case MVT::i32: - Opc = X86::MOV32to32_; - break; - } - N0 = SDValue(CurDAG->getTargetNode(Opc, N0VT, MVT::Flag, N0), 0); - return CurDAG->getTargetNode(X86::EXTRACT_SUBREG, - VT, N0, SRIdx, N0.getValue(1)); - } - break; - case MVT::i16: - SRIdx = CurDAG->getTargetConstant(2, MVT::i32); // SubRegSet 2 - break; - case MVT::i32: - SRIdx = CurDAG->getTargetConstant(3, MVT::i32); // SubRegSet 3 - break; - } - return CurDAG->getTargetNode(X86::EXTRACT_SUBREG, VT, N0, SRIdx); +/// getTruncateTo8Bit - return an SDNode that implements a subreg based +/// truncate of the specified operand to i8. This can be done with tablegen, +/// except that this code uses MVT::Flag in a tricky way that happens to +/// improve scheduling in some cases. +SDNode *X86DAGToDAGISel::getTruncateTo8Bit(SDValue N0) { + assert(!Subtarget->is64Bit() && + "getTruncateTo8Bit is only needed on x86-32!"); + SDValue SRIdx = CurDAG->getTargetConstant(1, MVT::i32); // SubRegSet 1 + + // Ensure that the source register has an 8-bit subreg on 32-bit targets + unsigned Opc; + MVT N0VT = N0.getValueType(); + switch (N0VT.getSimpleVT()) { + default: assert(0 && "Unknown truncate!"); + case MVT::i16: + Opc = X86::MOV16to16_; + break; + case MVT::i32: + Opc = X86::MOV32to32_; + break; + } + + // The use of MVT::Flag here is not strictly accurate, but it helps + // scheduling in some cases. + N0 = SDValue(CurDAG->getTargetNode(Opc, N0VT, MVT::Flag, N0), 0); + return CurDAG->getTargetNode(X86::EXTRACT_SUBREG, + MVT::i8, N0, SRIdx, N0.getValue(1)); } @@ -1507,90 +1504,45 @@ SDNode *X86DAGToDAGISel::Select(SDValue N) { return NULL; } - case ISD::ANY_EXTEND: { - // Check if the type extended to supports subregs. - if (NVT == MVT::i8) - break; - - SDValue N0 = Node->getOperand(0); - // Get the subregsiter index for the type to extend. - MVT N0VT = N0.getValueType(); - // FIXME: In x86-32, 8-bit value may be in AH, etc. which don't have - // super-registers. - unsigned Idx = (N0VT == MVT::i32) ? X86::SUBREG_32BIT : - (N0VT == MVT::i16) ? X86::SUBREG_16BIT : - (Subtarget->is64Bit()) ? X86::SUBREG_8BIT : 0; - - // If we don't have a subreg Idx, let generated ISel have a try. - if (Idx == 0) - break; - - // If we have an index, generate an insert_subreg into undef. - AddToISelQueue(N0); - SDValue Undef = - SDValue(CurDAG->getTargetNode(X86::IMPLICIT_DEF, NVT), 0); - SDValue SRIdx = CurDAG->getTargetConstant(Idx, MVT::i32); - SDNode *ResNode = CurDAG->getTargetNode(X86::INSERT_SUBREG, - NVT, Undef, N0, SRIdx); - -#ifndef NDEBUG - DOUT << std::string(Indent-2, ' ') << "=> "; - DEBUG(ResNode->dump(CurDAG)); - DOUT << "\n"; - Indent -= 2; -#endif - return ResNode; - } - case ISD::SIGN_EXTEND_INREG: { - SDValue N0 = Node->getOperand(0); - AddToISelQueue(N0); - MVT SVT = cast(Node->getOperand(1))->getVT(); - SDValue TruncOp = SDValue(getTruncate(N0, SVT), 0); - unsigned Opc = 0; - switch (NVT.getSimpleVT()) { - default: assert(0 && "Unknown sign_extend_inreg!"); - case MVT::i16: - if (SVT == MVT::i8) Opc = X86::MOVSX16rr8; - else assert(0 && "Unknown sign_extend_inreg!"); - break; - case MVT::i32: - switch (SVT.getSimpleVT()) { - default: assert(0 && "Unknown sign_extend_inreg!"); - case MVT::i8: Opc = X86::MOVSX32rr8; break; - case MVT::i16: Opc = X86::MOVSX32rr16; break; - } - break; - case MVT::i64: - switch (SVT.getSimpleVT()) { + if (SVT == MVT::i8 && !Subtarget->is64Bit()) { + SDValue N0 = Node->getOperand(0); + AddToISelQueue(N0); + + SDValue TruncOp = SDValue(getTruncateTo8Bit(N0), 0); + unsigned Opc = 0; + switch (NVT.getSimpleVT()) { default: assert(0 && "Unknown sign_extend_inreg!"); - case MVT::i8: Opc = X86::MOVSX64rr8; break; - case MVT::i16: Opc = X86::MOVSX64rr16; break; - case MVT::i32: Opc = X86::MOVSX64rr32; break; + case MVT::i16: + Opc = X86::MOVSX16rr8; + break; + case MVT::i32: + Opc = X86::MOVSX32rr8; + break; } - break; - } - SDNode *ResNode = CurDAG->getTargetNode(Opc, NVT, TruncOp); + SDNode *ResNode = CurDAG->getTargetNode(Opc, NVT, TruncOp); #ifndef NDEBUG - DOUT << std::string(Indent-2, ' ') << "=> "; - DEBUG(TruncOp.Val->dump(CurDAG)); - DOUT << "\n"; - DOUT << std::string(Indent-2, ' ') << "=> "; - DEBUG(ResNode->dump(CurDAG)); - DOUT << "\n"; - Indent -= 2; + DOUT << std::string(Indent-2, ' ') << "=> "; + DEBUG(TruncOp.Val->dump(CurDAG)); + DOUT << "\n"; + DOUT << std::string(Indent-2, ' ') << "=> "; + DEBUG(ResNode->dump(CurDAG)); + DOUT << "\n"; + Indent -= 2; #endif - return ResNode; + return ResNode; + } break; } case ISD::TRUNCATE: { - SDValue Input = Node->getOperand(0); - AddToISelQueue(Node->getOperand(0)); - SDNode *ResNode = getTruncate(Input, NVT); + if (NVT == MVT::i8 && !Subtarget->is64Bit()) { + SDValue Input = Node->getOperand(0); + AddToISelQueue(Node->getOperand(0)); + SDNode *ResNode = getTruncateTo8Bit(Input); #ifndef NDEBUG DOUT << std::string(Indent-2, ' ') << "=> "; @@ -1598,7 +1550,8 @@ SDNode *X86DAGToDAGISel::Select(SDValue N) { DOUT << "\n"; Indent -= 2; #endif - return ResNode; + return ResNode; + } break; } diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index da981c361a3..5e7c73c0baa 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -1254,24 +1254,40 @@ def : Pat<(i64 (zext GR32:$src)), def : Pat<(zextloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>; // 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), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (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<(extloadi64i1 addr:$src), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV8rm addr:$src), + x86_subreg_8bit)>; +def : Pat<(extloadi64i8 addr:$src), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV8rm addr:$src), + x86_subreg_8bit)>; +def : Pat<(extloadi64i16 addr:$src), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV16rm addr:$src), + x86_subreg_16bit)>; +def : Pat<(extloadi64i32 addr:$src), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV32rm addr:$src), + x86_subreg_32bit)>; +def : Pat<(extloadi16i1 addr:$src), + (INSERT_SUBREG (i16 (IMPLICIT_DEF)), (MOV8rm addr:$src), + x86_subreg_8bit)>, + Requires<[In64BitMode]>; +def : Pat<(extloadi16i8 addr:$src), + (INSERT_SUBREG (i16 (IMPLICIT_DEF)), (MOV8rm addr:$src), + x86_subreg_8bit)>, + Requires<[In64BitMode]>; + +// anyext +def : Pat<(i64 (anyext GR8:$src)), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src, x86_subreg_8bit)>; +def : Pat<(i64 (anyext GR16:$src)), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR16:$src, x86_subreg_16bit)>; def : Pat<(i64 (anyext GR32:$src)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), 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))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV32rm addr:$src), - x86_subreg_32bit)>; +def : Pat<(i16 (anyext GR8:$src)), + (INSERT_SUBREG (i16 (IMPLICIT_DEF)), GR8:$src, x86_subreg_8bit)>, + Requires<[In64BitMode]>; +def : Pat<(i32 (anyext GR8:$src)), + (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src, x86_subreg_8bit)>, + Requires<[In64BitMode]>; //===----------------------------------------------------------------------===// // Some peepholes @@ -1295,6 +1311,34 @@ def : Pat<(and GR16:$src1, 0xff), (MOVZX16rr8 (i8 (EXTRACT_SUBREG GR16:$src1, x86_subreg_8bit)))>, Requires<[In64BitMode]>; +// sext_inreg patterns +def : Pat<(sext_inreg GR64:$src, i32), + (MOVSX64rr32 (i32 (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)))>; +def : Pat<(sext_inreg GR64:$src, i16), + (MOVSX64rr16 (i16 (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit)))>; +def : Pat<(sext_inreg GR64:$src, i8), + (MOVSX64rr8 (i8 (EXTRACT_SUBREG GR64:$src, x86_subreg_8bit)))>; +def : Pat<(sext_inreg GR32:$src, i8), + (MOVSX32rr8 (i8 (EXTRACT_SUBREG GR32:$src, x86_subreg_8bit)))>, + Requires<[In64BitMode]>; +def : Pat<(sext_inreg GR16:$src, i8), + (MOVSX16rr8 (i8 (EXTRACT_SUBREG GR16:$src, x86_subreg_8bit)))>, + Requires<[In64BitMode]>; + +// trunc patterns +def : Pat<(i32 (trunc GR64:$src)), + (i32 (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit))>; +def : Pat<(i16 (trunc GR64:$src)), + (i16 (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit))>; +def : Pat<(i8 (trunc GR64:$src)), + (i8 (EXTRACT_SUBREG GR64:$src, x86_subreg_8bit))>; +def : Pat<(i8 (trunc GR32:$src)), + (i8 (EXTRACT_SUBREG GR32:$src, x86_subreg_8bit))>, + Requires<[In64BitMode]>; +def : Pat<(i8 (trunc GR16:$src)), + (i8 (EXTRACT_SUBREG GR16:$src, x86_subreg_8bit))>, + Requires<[In64BitMode]>; + // (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.td b/lib/Target/X86/X86InstrInfo.td index abf95ee9452..e55edceff19 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -2784,19 +2784,21 @@ def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; // extload bool -> extload byte def : Pat<(extloadi8i1 addr:$src), (MOV8rm addr:$src)>; -def : Pat<(extloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; +def : Pat<(extloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>, + Requires<[In32BitMode]>; def : Pat<(extloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; -def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>; +def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>, + Requires<[In32BitMode]>; def : Pat<(extloadi32i8 addr:$src), (MOVZX32rm8 addr:$src)>; def : Pat<(extloadi32i16 addr:$src), (MOVZX32rm16 addr:$src)>; -// anyext -> zext -def : Pat<(i16 (anyext GR8 :$src)), (MOVZX16rr8 GR8 :$src)>; -def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8 GR8 :$src)>; -def : Pat<(i32 (anyext GR16:$src)), (MOVZX32rr16 GR16:$src)>; -def : Pat<(i16 (anyext (loadi8 addr:$src))), (MOVZX16rm8 addr:$src)>; -def : Pat<(i32 (anyext (loadi8 addr:$src))), (MOVZX32rm8 addr:$src)>; -def : Pat<(i32 (anyext (loadi16 addr:$src))), (MOVZX32rm16 addr:$src)>; +// anyext +def : Pat<(i16 (anyext GR8 :$src)), (MOVZX16rr8 GR8 :$src)>, + Requires<[In32BitMode]>; +def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8 GR8 :$src)>, + Requires<[In32BitMode]>; +def : Pat<(i32 (anyext GR16:$src)), + (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR16:$src, x86_subreg_16bit)>; // (and (i32 load), 255) -> (zextload i8) def : Pat<(i32 (and (loadi32 addr:$src), (i32 255))), (MOVZX32rm8 addr:$src)>; @@ -2808,16 +2810,38 @@ def : Pat<(i32 (and (loadi32 addr:$src), (i32 65535))),(MOVZX32rm16 addr:$src)>; // r & (2^16-1) ==> movz def : Pat<(and GR32:$src1, 0xffff), - (MOVZX32rr16 (i16 (EXTRACT_SUBREG GR32:$src1, x86_subreg_16bit)))>; + (MOVZX32rr16 (i16 (EXTRACT_SUBREG GR32:$src1, x86_subreg_16bit)))>; // r & (2^8-1) ==> movz def : Pat<(and GR32:$src1, 0xff), - (MOVZX32rr8 (i8 (EXTRACT_SUBREG (MOV32to32_ GR32:$src1), - x86_subreg_8bit)))>, + (MOVZX32rr8 (i8 (EXTRACT_SUBREG (MOV32to32_ GR32:$src1), + x86_subreg_8bit)))>, Requires<[In32BitMode]>; // r & (2^8-1) ==> movz def : Pat<(and GR16:$src1, 0xff), - (MOVZX16rr8 (i8 (EXTRACT_SUBREG (MOV16to16_ GR16:$src1), - x86_subreg_8bit)))>, + (MOVZX16rr8 (i8 (EXTRACT_SUBREG (MOV16to16_ GR16:$src1), + x86_subreg_8bit)))>, + Requires<[In32BitMode]>; + +// sext_inreg patterns +def : Pat<(sext_inreg GR32:$src, i16), + (MOVSX32rr16 (i16 (EXTRACT_SUBREG GR32:$src, x86_subreg_16bit)))>; +def : Pat<(sext_inreg GR32:$src, i8), + (MOVSX32rr8 (i8 (EXTRACT_SUBREG (MOV32to32_ GR32:$src), + x86_subreg_8bit)))>, + Requires<[In32BitMode]>; +def : Pat<(sext_inreg GR16:$src, i8), + (MOVSX16rr8 (i8 (EXTRACT_SUBREG (MOV16to16_ GR16:$src), + x86_subreg_8bit)))>, + Requires<[In32BitMode]>; + +// trunc patterns +def : Pat<(i16 (trunc GR32:$src)), + (i16 (EXTRACT_SUBREG GR32:$src, x86_subreg_16bit))>; +def : Pat<(i8 (trunc GR32:$src)), + (i8 (EXTRACT_SUBREG (MOV32to32_ GR32:$src), x86_subreg_8bit))>, + Requires<[In32BitMode]>; +def : Pat<(i8 (trunc GR16:$src)), + (i8 (EXTRACT_SUBREG (MOV16to16_ GR16:$src), x86_subreg_8bit))>, Requires<[In32BitMode]>; // (shl x, 1) ==> (add x, x) -- 2.34.1