[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Chris Lattner
sabre at nondot.org
Tue Sep 19 20:39:02 PDT 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
LegalizeDAG.cpp updated: 1.398 -> 1.399
---
Log message:
Expand 64-bit shifts more optimally if we know that the high bit of the
shift amount is one or zero. For example, for:
long long foo1(long long X, int C) {
return X << (C|32);
}
long long foo2(long long X, int C) {
return X << (C&~32);
}
we get:
_foo1:
movb $31, %cl
movl 4(%esp), %edx
andb 12(%esp), %cl
shll %cl, %edx
xorl %eax, %eax
ret
_foo2:
movb $223, %cl
movl 4(%esp), %eax
movl 8(%esp), %edx
andb 12(%esp), %cl
shldl %cl, %eax, %edx
shll %cl, %eax
ret
instead of:
_foo1:
subl $4, %esp
movl %ebx, (%esp)
movb $32, %bl
movl 8(%esp), %eax
movl 12(%esp), %edx
movb %bl, %cl
orb 16(%esp), %cl
shldl %cl, %eax, %edx
shll %cl, %eax
xorl %ecx, %ecx
testb %bl, %bl
cmovne %eax, %edx
cmovne %ecx, %eax
movl (%esp), %ebx
addl $4, %esp
ret
_foo2:
subl $4, %esp
movl %ebx, (%esp)
movb $223, %cl
movl 8(%esp), %eax
movl 12(%esp), %edx
andb 16(%esp), %cl
shldl %cl, %eax, %edx
shll %cl, %eax
xorl %ecx, %ecx
xorb %bl, %bl
testb %bl, %bl
cmovne %eax, %edx
cmovne %ecx, %eax
movl (%esp), %ebx
addl $4, %esp
ret
---
Diffs of the changes: (+66 -0)
LegalizeDAG.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+)
Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.398 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.399
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.398 Mon Sep 18 18:28:33 2006
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Tue Sep 19 22:38:48 2006
@@ -3781,6 +3781,72 @@
return true;
}
}
+
+ // Okay, the shift amount isn't constant. However, if we can tell that it is
+ // >= 32 or < 32, we can still simplify it, without knowing the actual value.
+ uint64_t Mask = NVTBits, KnownZero, KnownOne;
+ TLI.ComputeMaskedBits(Amt, Mask, KnownZero, KnownOne);
+
+ // If we know that the high bit of the shift amount is one, then we can do
+ // this as a couple of simple shifts.
+ if (KnownOne & Mask) {
+ // Mask out the high bit, which we know is set.
+ Amt = DAG.getNode(ISD::AND, Amt.getValueType(), Amt,
+ DAG.getConstant(NVTBits-1, Amt.getValueType()));
+
+ // Expand the incoming operand to be shifted, so that we have its parts
+ SDOperand InL, InH;
+ ExpandOp(Op, InL, InH);
+ switch(Opc) {
+ case ISD::SHL:
+ Lo = DAG.getConstant(0, NVT); // Low part is zero.
+ Hi = DAG.getNode(ISD::SHL, NVT, InL, Amt); // High part from Lo part.
+ return true;
+ case ISD::SRL:
+ Hi = DAG.getConstant(0, NVT); // Hi part is zero.
+ Lo = DAG.getNode(ISD::SRL, NVT, InH, Amt); // Lo part from Hi part.
+ return true;
+ case ISD::SRA:
+ Hi = DAG.getNode(ISD::SRA, NVT, InH, // Sign extend high part.
+ DAG.getConstant(NVTBits-1, Amt.getValueType()));
+ Lo = DAG.getNode(ISD::SRA, NVT, InH, Amt); // Lo part from Hi part.
+ return true;
+ }
+ }
+
+ // If we know that the high bit of the shift amount is zero, then we can do
+ // this as a couple of simple shifts.
+ if (KnownZero & Mask) {
+ // Compute 32-amt.
+ SDOperand Amt2 = DAG.getNode(ISD::SUB, Amt.getValueType(),
+ DAG.getConstant(NVTBits, Amt.getValueType()),
+ Amt);
+
+ // Expand the incoming operand to be shifted, so that we have its parts
+ SDOperand InL, InH;
+ ExpandOp(Op, InL, InH);
+ switch(Opc) {
+ case ISD::SHL:
+ Lo = DAG.getNode(ISD::SHL, NVT, InL, Amt);
+ Hi = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SHL, NVT, InH, Amt),
+ DAG.getNode(ISD::SRL, NVT, InL, Amt2));
+ return true;
+ case ISD::SRL:
+ Hi = DAG.getNode(ISD::SRL, NVT, InH, Amt);
+ Lo = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SRL, NVT, InL, Amt),
+ DAG.getNode(ISD::SHL, NVT, InH, Amt2));
+ return true;
+ case ISD::SRA:
+ Hi = DAG.getNode(ISD::SRA, NVT, InH, Amt);
+ Lo = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SRL, NVT, InL, Amt),
+ DAG.getNode(ISD::SHL, NVT, InH, Amt2));
+ return true;
+ }
+ }
+
return false;
}
More information about the llvm-commits
mailing list