summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86ISelLowering.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2017-06-22 23:47:15 +0000
committerSanjay Patel <spatel@rotateright.com>2017-06-22 23:47:15 +0000
commit359ae44fb45205cea2a9a8f12bae9d3748f4e2ad (patch)
treea63014479ceec85805a42805be2191103aa87f7a /llvm/lib/Target/X86/X86ISelLowering.cpp
parent8456411e3bd4d50c807cc6b785cb49d344081dd3 (diff)
downloadbcm5719-llvm-359ae44fb45205cea2a9a8f12bae9d3748f4e2ad.tar.gz
bcm5719-llvm-359ae44fb45205cea2a9a8f12bae9d3748f4e2ad.zip
[x86] add/sub (X==0) --> sbb(cmp X, 1)
This is very similar to the transform in: https://reviews.llvm.org/rL306040 ...but in this case, we use cmp X, 1 to set the carry bit as needed. Again, we can show that all of these are logically equivalent (although InstCombine currently canonicalizes to a form not seen here), and if we believe IACA, then this is the smallest/fastest code. Eg, with SNB: | Num Of | Ports pressure in cycles | | | Uops | 0 - DV | 1 | 2 - D | 3 - D | 4 | 5 | | --------------------------------------------------------------------- | 1 | 1.0 | | | | | | | cmp edi, 0x1 | 2 | | 1.0 | | | | 1.0 | CP | sbb eax, eax The larger motivation is to clean up all select-of-constants combining/lowering because we're missing some common cases. llvm-svn: 306072
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp22
1 files changed, 17 insertions, 5 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 2b51137901f..b7e008c46a7 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -34900,12 +34900,13 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, SelectionDAG &DAG) {
SDValue Z = Cmp.getOperand(0);
SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i32);
- // If X is -1 or 0, then we have an opportunity to avoid constants required by
- // the cmp transform below. 'neg' sets the carry flag when Z != 0, so create 0
- // or -1 using 'sbb' with fake operands:
- // 0 - (Z != 0) --> sbb %eax, %eax, (neg Z)
- // -1 + (Z == 0) --> sbb %eax, %eax, (neg Z)
+ // If X is -1 or 0, then we have an opportunity to avoid constants required in
+ // the general case below.
if (auto *ConstantX = dyn_cast<ConstantSDNode>(X)) {
+ // 'neg' sets the carry flag when Z != 0, so create 0 or -1 using 'sbb' with
+ // fake operands:
+ // 0 - (Z != 0) --> sbb %eax, %eax, (neg Z)
+ // -1 + (Z == 0) --> sbb %eax, %eax, (neg Z)
if ((IsSub && CC == X86::COND_NE && ConstantX->isNullValue()) ||
(!IsSub && CC == X86::COND_E && ConstantX->isAllOnesValue())) {
SDValue Zero = DAG.getConstant(0, DL, VT);
@@ -34914,6 +34915,17 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, SelectionDAG &DAG) {
DAG.getConstant(X86::COND_B, DL, MVT::i8),
SDValue(Neg.getNode(), 1));
}
+ // cmp with 1 sets the carry flag when Z == 0, so create 0 or -1 using 'sbb'
+ // with fake operands:
+ // 0 - (Z == 0) --> sbb %eax, %eax, (cmp Z, 1)
+ // -1 + (Z != 0) --> sbb %eax, %eax, (cmp Z, 1)
+ if ((IsSub && CC == X86::COND_E && ConstantX->isNullValue()) ||
+ (!IsSub && CC == X86::COND_NE && ConstantX->isAllOnesValue())) {
+ SDValue One = DAG.getConstant(1, DL, Z.getValueType());
+ SDValue Cmp1 = DAG.getNode(X86ISD::CMP, DL, MVT::i32, Z, One);
+ return DAG.getNode(X86ISD::SETCC_CARRY, DL, VT,
+ DAG.getConstant(X86::COND_B, DL, MVT::i8), Cmp1);
+ }
}
// (cmp Z, 1) sets the carry flag if Z is 0.
OpenPOWER on IntegriCloud