diff options
| author | Chris Lattner <sabre@nondot.org> | 2005-01-19 06:18:43 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2005-01-19 06:18:43 +0000 | 
| commit | 41fe201b61956decdf54f7ba4245e1b31c72fdbd (patch) | |
| tree | 1769ea6d3016d76017c437234e7a351621707520 /llvm/lib/Target/X86 | |
| parent | 7230239553052ecd02894d6ce9f21000fccbafdd (diff) | |
| download | bcm5719-llvm-41fe201b61956decdf54f7ba4245e1b31c72fdbd.tar.gz bcm5719-llvm-41fe201b61956decdf54f7ba4245e1b31c72fdbd.zip | |
Codegen long >> 2 to this:
foo:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %EDX, DWORD PTR [%ESP + 8]
        shrd %EAX, %EDX, 2
        sar %EDX, 2
        ret
instead of this:
test1:
        mov %ECX, DWORD PTR [%ESP + 4]
        shr %ECX, 2
        mov %EDX, DWORD PTR [%ESP + 8]
        mov %EAX, %EDX
        shl %EAX, 30
        or %EAX, %ECX
        sar %EDX, 2
        ret
and long << 2 to this:
foo:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %ECX, DWORD PTR [%ESP + 8]
***     mov %EDX, %EAX
        shrd %EDX, %ECX, 30
        shl %EAX, 2
        ret
instead of this:
foo:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %ECX, %EAX
        shr %ECX, 30
        mov %EDX, DWORD PTR [%ESP + 8]
        shl %EDX, 2
        or %EDX, %ECX
        shl %EAX, 2
        ret
The extra copy (marked ***) can be eliminated when I teach the code generator
that shrd32rri8 is really commutative.
llvm-svn: 19681
Diffstat (limited to 'llvm/lib/Target/X86')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelPattern.cpp | 86 | 
1 files changed, 85 insertions, 1 deletions
| diff --git a/llvm/lib/Target/X86/X86ISelPattern.cpp b/llvm/lib/Target/X86/X86ISelPattern.cpp index 1228d70bc04..2701f322d9a 100644 --- a/llvm/lib/Target/X86/X86ISelPattern.cpp +++ b/llvm/lib/Target/X86/X86ISelPattern.cpp @@ -370,6 +370,7 @@ namespace {      void EmitFoldedLoad(SDOperand Op, X86AddressMode &AM);      bool TryToFoldLoadOpStore(SDNode *Node); +    bool EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg);      void EmitCMP(SDOperand LHS, SDOperand RHS, bool isOnlyUse);      bool EmitBranchCC(MachineBasicBlock *Dest, SDOperand Chain, SDOperand Cond);      void EmitSelectCC(SDOperand Cond, MVT::ValueType SVT, @@ -1141,6 +1142,84 @@ void ISel::EmitFoldedLoad(SDOperand Op, X86AddressMode &AM) {      assert(0 && "Load emitted more than once!");  } +// EmitDoubleShift - Pattern match the expression (Op1|Op2), where we know that +// op1 and op2 are i32 values with one use each (the or).  If we can form a SHLD +// or SHRD, emit the instruction (generating the value into DestReg) and return +// true. +bool ISel::EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg) { +  if (Op1.getOpcode() == ISD::SHL && Op2.getOpcode() == ISD::SRL) { +    // good! +  } else if (Op2.getOpcode() == ISD::SHL && Op1.getOpcode() == ISD::SRL) { +    std::swap(Op1, Op2);  // Op1 is the SHL now. +  } else { +    return false;  // No match +  } + +  SDOperand ShlVal = Op1.getOperand(0); +  SDOperand ShlAmt = Op1.getOperand(1); +  SDOperand ShrVal = Op2.getOperand(0); +  SDOperand ShrAmt = Op2.getOperand(1); + +  // Find out if ShrAmt = 32-ShlAmt  or  ShlAmt = 32-ShrAmt. +  if (ShlAmt.getOpcode() == ISD::SUB && ShlAmt.getOperand(1) == ShrAmt) +    if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShlAmt.getOperand(0))) +      if (SubCST->getValue() == 32) { +        // (A >> ShrAmt) | (B << (32-ShrAmt)) ==> SHRD A, B, ShrAmt +        unsigned AReg, BReg; +        if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) { +          AReg = SelectExpr(ShrVal); +          BReg = SelectExpr(ShlVal); +        } else { +          BReg = SelectExpr(ShlVal); +          AReg = SelectExpr(ShrVal); +        } +        unsigned ShAmt = SelectExpr(ShrAmt); +        BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt); +        BuildMI(BB, X86::SHRD32rrCL,2,DestReg).addReg(AReg).addReg(BReg); +        return true; +      } + +  if (ShrAmt.getOpcode() == ISD::SUB && ShrAmt.getOperand(1) == ShlAmt) +    if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShrAmt.getOperand(0))) +      if (SubCST->getValue() == 32) { +        // (A << ShlAmt) | (B >> (32-ShlAmt)) ==> SHLD A, B, ShrAmt +        unsigned AReg, BReg; +        if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) { +          AReg = SelectExpr(ShrVal); +          BReg = SelectExpr(ShlVal); +        } else { +          BReg = SelectExpr(ShlVal); +          AReg = SelectExpr(ShrVal); +        } +        unsigned ShAmt = SelectExpr(ShlAmt); +        BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt); +        BuildMI(BB, X86::SHLD32rrCL,2,DestReg).addReg(AReg).addReg(BReg); +        return true; +      } + +  if (ConstantSDNode *ShrCst = dyn_cast<ConstantSDNode>(ShrAmt)) +    if (ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(ShlAmt)) +      if (ShrCst->getValue() < 32 && ShlCst->getValue() < 32) { +        if (ShrCst->getValue() == 32-ShlCst->getValue()) { +          // (A >> 5) | (B << 27) --> SHRD A, B, 5 +          unsigned AReg, BReg; +          if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) { +            AReg = SelectExpr(ShrVal); +            BReg = SelectExpr(ShlVal); +          } else { +            BReg = SelectExpr(ShlVal); +            AReg = SelectExpr(ShrVal); +          } +          BuildMI(BB, X86::SHRD32rri8, 3, DestReg).addReg(AReg).addReg(BReg) +            .addImm(ShrCst->getValue()); +          return true; +        } +      } + + +  return false; +} +  unsigned ISel::SelectExpr(SDOperand N) {    unsigned Result;    unsigned Tmp1, Tmp2, Tmp3; @@ -1658,7 +1737,12 @@ unsigned ISel::SelectExpr(SDOperand N) {      Op0 = Node->getOperand(0);      Op1 = Node->getOperand(1); -    if (Node->getOpcode() == ISD::SUB && MVT::isInteger(N.getValueType())) +    if (Node->getOpcode() == ISD::OR && N.getValueType() == MVT::i32 && +        Op0.hasOneUse() && Op1.hasOneUse())          // Match SHLD and SHRD. +      if (EmitDoubleShift(Op0, Op1, Result)) +        return Result; + +    if (Node->getOpcode() == ISD::SUB)        if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(0)))          if (CN->isNullValue()) {   // 0 - N -> neg N            switch (N.getValueType()) { | 

