From a31d4c7548e0f43e07ea59b6cd90e28809496664 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 2 Apr 2005 04:01:14 +0000 Subject: [PATCH] Add support for 64-bit shifts. llvm-svn: 21005 --- llvm/lib/Target/X86/X86ISelPattern.cpp | 100 +++++++++++++++++++++---- 1 file changed, 84 insertions(+), 16 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelPattern.cpp b/llvm/lib/Target/X86/X86ISelPattern.cpp index 0e77a7f8b8ee..ff23e66c04fe 100644 --- a/llvm/lib/Target/X86/X86ISelPattern.cpp +++ b/llvm/lib/Target/X86/X86ISelPattern.cpp @@ -1319,29 +1319,34 @@ unsigned ISel::SelectExpr(SDOperand N) { unsigned &Reg = ExprMap[N]; if (Reg) return Reg; - if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::ADD_PARTS && - N.getOpcode() != ISD::SUB_PARTS) + switch (N.getOpcode()) { + default: Reg = Result = (N.getValueType() != MVT::Other) ? - MakeReg(N.getValueType()) : 1; - else { + MakeReg(N.getValueType()) : 1; + break; + case ISD::CALL: // If this is a call instruction, make sure to prepare ALL of the result // values as well as the chain. - if (N.getOpcode() == ISD::CALL) { - if (Node->getNumValues() == 1) - Reg = Result = 1; // Void call, just a chain. - else { - Result = MakeReg(Node->getValueType(0)); - ExprMap[N.getValue(0)] = Result; - for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) - ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); - ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1; - } - } else { + if (Node->getNumValues() == 1) + Reg = Result = 1; // Void call, just a chain. + else { Result = MakeReg(Node->getValueType(0)); ExprMap[N.getValue(0)] = Result; - for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i) + for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); + ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1; } + break; + case ISD::ADD_PARTS: + case ISD::SUB_PARTS: + case ISD::SHL_PARTS: + case ISD::SRL_PARTS: + case ISD::SRA_PARTS: + Result = MakeReg(Node->getValueType(0)); + ExprMap[N.getValue(0)] = Result; + for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i) + ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); + break; } switch (N.getOpcode()) { @@ -2024,6 +2029,69 @@ unsigned ISel::SelectExpr(SDOperand N) { return Result+N.ResNo; } + case ISD::SHL_PARTS: + case ISD::SRA_PARTS: + case ISD::SRL_PARTS: { + assert(N.getNumOperands() == 3 && N.getValueType() == MVT::i32 && + "Not an i64 shift!"); + unsigned ShiftOpLo = SelectExpr(N.getOperand(0)); + unsigned ShiftOpHi = SelectExpr(N.getOperand(1)); + unsigned TmpReg = MakeReg(MVT::i32); + if (N.getOpcode() == ISD::SRA_PARTS) { + // If this is a SHR of a Long, then we need to do funny sign extension + // stuff. TmpReg gets the value to use as the high-part if we are + // shifting more than 32 bits. + BuildMI(BB, X86::SAR32ri, 2, TmpReg).addReg(ShiftOpHi).addImm(31); + } else { + // Other shifts use a fixed zero value if the shift is more than 32 bits. + BuildMI(BB, X86::MOV32ri, 1, TmpReg).addImm(0); + } + + // Initialize CL with the shift amount. + unsigned ShiftAmountReg = SelectExpr(N.getOperand(2)); + BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShiftAmountReg); + + unsigned TmpReg2 = MakeReg(MVT::i32); + unsigned TmpReg3 = MakeReg(MVT::i32); + if (N.getOpcode() == ISD::SHL_PARTS) { + // TmpReg2 = shld inHi, inLo + BuildMI(BB, X86::SHLD32rrCL, 2,TmpReg2).addReg(ShiftOpHi) + .addReg(ShiftOpLo); + // TmpReg3 = shl inLo, CL + BuildMI(BB, X86::SHL32rCL, 1, TmpReg3).addReg(ShiftOpLo); + + // Set the flags to indicate whether the shift was by more than 32 bits. + BuildMI(BB, X86::TEST8ri, 2).addReg(X86::CL).addImm(32); + + // DestHi = (>32) ? TmpReg3 : TmpReg2; + BuildMI(BB, X86::CMOVNE32rr, 2, + Result+1).addReg(TmpReg2).addReg(TmpReg3); + // DestLo = (>32) ? TmpReg : TmpReg3; + BuildMI(BB, X86::CMOVNE32rr, 2, + Result).addReg(TmpReg3).addReg(TmpReg); + } else { + // TmpReg2 = shrd inLo, inHi + BuildMI(BB, X86::SHRD32rrCL,2,TmpReg2).addReg(ShiftOpLo) + .addReg(ShiftOpHi); + // TmpReg3 = s[ah]r inHi, CL + BuildMI(BB, N.getOpcode() == ISD::SRA_PARTS ? X86::SAR32rCL + : X86::SHR32rCL, 1, TmpReg3) + .addReg(ShiftOpHi); + + // Set the flags to indicate whether the shift was by more than 32 bits. + BuildMI(BB, X86::TEST8ri, 2).addReg(X86::CL).addImm(32); + + // DestLo = (>32) ? TmpReg3 : TmpReg2; + BuildMI(BB, X86::CMOVNE32rr, 2, + Result).addReg(TmpReg2).addReg(TmpReg3); + + // DestHi = (>32) ? TmpReg : TmpReg3; + BuildMI(BB, X86::CMOVNE32rr, 2, + Result+1).addReg(TmpReg3).addReg(TmpReg); + } + return Result+N.ResNo; + } + case ISD::SELECT: if (getRegPressure(N.getOperand(1)) > getRegPressure(N.getOperand(2))) { Tmp2 = SelectExpr(N.getOperand(1));