[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp
Chris Lattner
lattner at cs.uiuc.edu
Tue Jan 18 22:18:58 PST 2005
Changes in directory llvm/lib/Target/X86:
X86ISelPattern.cpp updated: 1.77 -> 1.78
---
Log message:
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.
---
Diffs of the changes: (+85 -1)
Index: llvm/lib/Target/X86/X86ISelPattern.cpp
diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.77 llvm/lib/Target/X86/X86ISelPattern.cpp:1.78
--- llvm/lib/Target/X86/X86ISelPattern.cpp:1.77 Tue Jan 18 21:36:30 2005
+++ llvm/lib/Target/X86/X86ISelPattern.cpp Wed Jan 19 00:18:43 2005
@@ -370,6 +370,7 @@
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 @@
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 @@
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()) {
More information about the llvm-commits
mailing list