mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-22 12:33:33 +02:00
Match 16-bit shld/shrd instructions as well, implementing shift-double.llx:test5
llvm-svn: 19689
This commit is contained in:
parent
33f679dba9
commit
e539ce8223
@ -370,7 +370,7 @@ namespace {
|
|||||||
void EmitFoldedLoad(SDOperand Op, X86AddressMode &AM);
|
void EmitFoldedLoad(SDOperand Op, X86AddressMode &AM);
|
||||||
bool TryToFoldLoadOpStore(SDNode *Node);
|
bool TryToFoldLoadOpStore(SDNode *Node);
|
||||||
|
|
||||||
bool EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg);
|
bool EmitOrOpOp(SDOperand Op1, SDOperand Op2, unsigned DestReg);
|
||||||
void EmitCMP(SDOperand LHS, SDOperand RHS, bool isOnlyUse);
|
void EmitCMP(SDOperand LHS, SDOperand RHS, bool isOnlyUse);
|
||||||
bool EmitBranchCC(MachineBasicBlock *Dest, SDOperand Chain, SDOperand Cond);
|
bool EmitBranchCC(MachineBasicBlock *Dest, SDOperand Chain, SDOperand Cond);
|
||||||
void EmitSelectCC(SDOperand Cond, MVT::ValueType SVT,
|
void EmitSelectCC(SDOperand Cond, MVT::ValueType SVT,
|
||||||
@ -1142,11 +1142,11 @@ void ISel::EmitFoldedLoad(SDOperand Op, X86AddressMode &AM) {
|
|||||||
assert(0 && "Load emitted more than once!");
|
assert(0 && "Load emitted more than once!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmitDoubleShift - Pattern match the expression (Op1|Op2), where we know that
|
// EmitOrOpOp - Pattern match the expression (Op1|Op2), where we know that op1
|
||||||
// op1 and op2 are i32 values with one use each (the or). If we can form a SHLD
|
// and op2 are i8/i16/i32 values with one use each (the or). If we can form a
|
||||||
// or SHRD, emit the instruction (generating the value into DestReg) and return
|
// SHLD or SHRD, emit the instruction (generating the value into DestReg) and
|
||||||
// true.
|
// return true.
|
||||||
bool ISel::EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg) {
|
bool ISel::EmitOrOpOp(SDOperand Op1, SDOperand Op2, unsigned DestReg) {
|
||||||
if (Op1.getOpcode() == ISD::SHL && Op2.getOpcode() == ISD::SRL) {
|
if (Op1.getOpcode() == ISD::SHL && Op2.getOpcode() == ISD::SRL) {
|
||||||
// good!
|
// good!
|
||||||
} else if (Op2.getOpcode() == ISD::SHL && Op1.getOpcode() == ISD::SRL) {
|
} else if (Op2.getOpcode() == ISD::SHL && Op1.getOpcode() == ISD::SRL) {
|
||||||
@ -1160,10 +1160,12 @@ bool ISel::EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg) {
|
|||||||
SDOperand ShrVal = Op2.getOperand(0);
|
SDOperand ShrVal = Op2.getOperand(0);
|
||||||
SDOperand ShrAmt = Op2.getOperand(1);
|
SDOperand ShrAmt = Op2.getOperand(1);
|
||||||
|
|
||||||
|
unsigned RegSize = MVT::getSizeInBits(Op1.getValueType());
|
||||||
|
|
||||||
// Find out if ShrAmt = 32-ShlAmt or ShlAmt = 32-ShrAmt.
|
// Find out if ShrAmt = 32-ShlAmt or ShlAmt = 32-ShrAmt.
|
||||||
if (ShlAmt.getOpcode() == ISD::SUB && ShlAmt.getOperand(1) == ShrAmt)
|
if (ShlAmt.getOpcode() == ISD::SUB && ShlAmt.getOperand(1) == ShrAmt)
|
||||||
if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShlAmt.getOperand(0)))
|
if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShlAmt.getOperand(0)))
|
||||||
if (SubCST->getValue() == 32) {
|
if (SubCST->getValue() == RegSize && RegSize != 8) {
|
||||||
// (A >> ShrAmt) | (B << (32-ShrAmt)) ==> SHRD A, B, ShrAmt
|
// (A >> ShrAmt) | (B << (32-ShrAmt)) ==> SHRD A, B, ShrAmt
|
||||||
unsigned AReg, BReg;
|
unsigned AReg, BReg;
|
||||||
if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
|
if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
|
||||||
@ -1175,13 +1177,14 @@ bool ISel::EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg) {
|
|||||||
}
|
}
|
||||||
unsigned ShAmt = SelectExpr(ShrAmt);
|
unsigned ShAmt = SelectExpr(ShrAmt);
|
||||||
BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt);
|
BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt);
|
||||||
BuildMI(BB, X86::SHRD32rrCL,2,DestReg).addReg(AReg).addReg(BReg);
|
unsigned Opc = RegSize == 16 ? X86::SHRD16rrCL : X86::SHRD32rrCL;
|
||||||
|
BuildMI(BB, Opc, 2, DestReg).addReg(AReg).addReg(BReg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShrAmt.getOpcode() == ISD::SUB && ShrAmt.getOperand(1) == ShlAmt)
|
if (ShrAmt.getOpcode() == ISD::SUB && ShrAmt.getOperand(1) == ShlAmt)
|
||||||
if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShrAmt.getOperand(0)))
|
if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShrAmt.getOperand(0)))
|
||||||
if (SubCST->getValue() == 32) {
|
if (SubCST->getValue() == RegSize && RegSize != 8) {
|
||||||
// (A << ShlAmt) | (B >> (32-ShlAmt)) ==> SHLD A, B, ShrAmt
|
// (A << ShlAmt) | (B >> (32-ShlAmt)) ==> SHLD A, B, ShrAmt
|
||||||
unsigned AReg, BReg;
|
unsigned AReg, BReg;
|
||||||
if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
|
if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
|
||||||
@ -1193,14 +1196,15 @@ bool ISel::EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg) {
|
|||||||
}
|
}
|
||||||
unsigned ShAmt = SelectExpr(ShlAmt);
|
unsigned ShAmt = SelectExpr(ShlAmt);
|
||||||
BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt);
|
BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt);
|
||||||
BuildMI(BB, X86::SHLD32rrCL,2,DestReg).addReg(AReg).addReg(BReg);
|
unsigned Opc = RegSize == 16 ? X86::SHLD16rrCL : X86::SHLD32rrCL;
|
||||||
|
BuildMI(BB, Opc, 2, DestReg).addReg(AReg).addReg(BReg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConstantSDNode *ShrCst = dyn_cast<ConstantSDNode>(ShrAmt))
|
if (ConstantSDNode *ShrCst = dyn_cast<ConstantSDNode>(ShrAmt))
|
||||||
if (ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(ShlAmt))
|
if (ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(ShlAmt))
|
||||||
if (ShrCst->getValue() < 32 && ShlCst->getValue() < 32) {
|
if (ShrCst->getValue() < RegSize && ShlCst->getValue() < RegSize) {
|
||||||
if (ShrCst->getValue() == 32-ShlCst->getValue()) {
|
if (ShrCst->getValue() == RegSize-ShlCst->getValue() && RegSize != 8) {
|
||||||
// (A >> 5) | (B << 27) --> SHRD A, B, 5
|
// (A >> 5) | (B << 27) --> SHRD A, B, 5
|
||||||
unsigned AReg, BReg;
|
unsigned AReg, BReg;
|
||||||
if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
|
if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
|
||||||
@ -1210,7 +1214,8 @@ bool ISel::EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg) {
|
|||||||
BReg = SelectExpr(ShlVal);
|
BReg = SelectExpr(ShlVal);
|
||||||
AReg = SelectExpr(ShrVal);
|
AReg = SelectExpr(ShrVal);
|
||||||
}
|
}
|
||||||
BuildMI(BB, X86::SHRD32rri8, 3, DestReg).addReg(AReg).addReg(BReg)
|
unsigned Opc = RegSize == 16 ? X86::SHRD16rri8 : X86::SHRD32rri8;
|
||||||
|
BuildMI(BB, Opc, 3, DestReg).addReg(AReg).addReg(BReg)
|
||||||
.addImm(ShrCst->getValue());
|
.addImm(ShrCst->getValue());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1737,9 +1742,8 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
|||||||
Op0 = Node->getOperand(0);
|
Op0 = Node->getOperand(0);
|
||||||
Op1 = Node->getOperand(1);
|
Op1 = Node->getOperand(1);
|
||||||
|
|
||||||
if (Node->getOpcode() == ISD::OR && N.getValueType() == MVT::i32 &&
|
if (Node->getOpcode() == ISD::OR && Op0.hasOneUse() && Op1.hasOneUse())
|
||||||
Op0.hasOneUse() && Op1.hasOneUse()) // Match SHLD and SHRD.
|
if (EmitOrOpOp(Op0, Op1, Result)) // Match SHLD, SHRD, and rotates.
|
||||||
if (EmitDoubleShift(Op0, Op1, Result))
|
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
if (Node->getOpcode() == ISD::SUB)
|
if (Node->getOpcode() == ISD::SUB)
|
||||||
|
Loading…
Reference in New Issue
Block a user