[llvm] r265875 - [x86] use BMI 'andn' for logic + compare ops
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 9 09:02:56 PDT 2016
Author: spatel
Date: Sat Apr 9 11:02:52 2016
New Revision: 265875
URL: http://llvm.org/viewvc/llvm-project?rev=265875&view=rev
Log:
[x86] use BMI 'andn' for logic + compare ops
With BMI, we can use 'andn' to save an instruction when the result is only used in a compare.
This is related to one of the potential sequences to check 'isfinite' in:
https://llvm.org/bugs/show_bug.cgi?id=27164
Differential Revision: http://reviews.llvm.org/D18910
Modified:
llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
llvm/trunk/test/CodeGen/X86/bmi.ll
Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=265875&r1=265874&r2=265875&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Sat Apr 9 11:02:52 2016
@@ -1358,6 +1358,9 @@ bool isNullFPConstant(SDValue V);
bool isAllOnesConstant(SDValue V);
/// Returns true if \p V is a constant integer one.
bool isOneConstant(SDValue V);
+/// Returns true if \p V is a bitwise not operation. Assumes that an all ones
+/// constant is canonicalized to be operand 1.
+bool isBitwiseNot(SDValue V);
class GlobalAddressSDNode : public SDNode {
const GlobalValue *TheGlobal;
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=265875&r1=265874&r2=265875&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Sat Apr 9 11:02:52 2016
@@ -6708,6 +6708,10 @@ bool llvm::isOneConstant(SDValue V) {
return Const != nullptr && Const->isOne();
}
+bool llvm::isBitwiseNot(SDValue V) {
+ return V.getOpcode() == ISD::XOR && isAllOnesConstant(V.getOperand(1));
+}
+
HandleSDNode::~HandleSDNode() {
DropOperands();
}
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=265875&r1=265874&r2=265875&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Sat Apr 9 11:02:52 2016
@@ -14677,10 +14677,20 @@ SDValue X86TargetLowering::EmitTest(SDVa
break;
case ISD::AND:
- // If the primary and result isn't used, don't bother using X86ISD::AND,
+ // If the primary 'and' result isn't used, don't bother using X86ISD::AND,
// because a TEST instruction will be better.
- if (!hasNonFlagsUse(Op))
- break;
+ if (!hasNonFlagsUse(Op)) {
+ SDValue Op0 = ArithOp->getOperand(0);
+ SDValue Op1 = ArithOp->getOperand(1);
+ EVT VT = ArithOp.getValueType();
+ bool isAndn = isBitwiseNot(Op0) || isBitwiseNot(Op1);
+ bool isLegalAndnType = VT == MVT::i32 || VT == MVT::i64;
+
+ // But if we can combine this into an ANDN operation, then create an AND
+ // now and allow it to be pattern matched into an ANDN.
+ if (!Subtarget.hasBMI() || !isAndn || !isLegalAndnType)
+ break;
+ }
// FALL THROUGH
case ISD::SUB:
case ISD::OR:
Modified: llvm/trunk/test/CodeGen/X86/bmi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/bmi.ll?rev=265875&r1=265874&r2=265875&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/bmi.ll (original)
+++ llvm/trunk/test/CodeGen/X86/bmi.ll Sat Apr 9 11:02:52 2016
@@ -136,12 +136,11 @@ define i64 @andn64(i64 %x, i64 %y) {
ret i64 %tmp2
}
-; FIXME: Don't choose a 'test' if an 'andn' can be used.
+; Don't choose a 'test' if an 'andn' can be used.
define i1 @andn_cmp(i32 %x, i32 %y) {
; CHECK-LABEL: andn_cmp:
; CHECK: # BB#0:
-; CHECK-NEXT: notl %edi
-; CHECK-NEXT: testl %esi, %edi
+; CHECK-NEXT: andnl %esi, %edi, %eax
; CHECK-NEXT: sete %al
; CHECK-NEXT: retq
;
@@ -151,12 +150,11 @@ define i1 @andn_cmp(i32 %x, i32 %y) {
ret i1 %cmp
}
-; FIXME: Don't choose a 'test' if an 'andn' can be used.
+; Don't choose a 'test' if an 'andn' can be used.
define i1 @andn_cmp_swap_ops(i64 %x, i64 %y) {
; CHECK-LABEL: andn_cmp_swap_ops:
; CHECK: # BB#0:
-; CHECK-NEXT: notq %rdi
-; CHECK-NEXT: testq %rdi, %rsi
+; CHECK-NEXT: andnq %rsi, %rdi, %rax
; CHECK-NEXT: sete %al
; CHECK-NEXT: retq
;
More information about the llvm-commits
mailing list