diff options
author | Craig Topper <craig.topper@intel.com> | 2018-12-21 21:42:43 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2018-12-21 21:42:43 +0000 |
commit | e58cd9cbc6f5039a45da77713eb68977f01c9f31 (patch) | |
tree | 347412a7bcb652a3696553c12a7c8285bb579da0 /llvm/lib | |
parent | c6027e20d4b6756833e1692baeec78c9a5ff4e5e (diff) | |
download | bcm5719-llvm-e58cd9cbc6f5039a45da77713eb68977f01c9f31.tar.gz bcm5719-llvm-e58cd9cbc6f5039a45da77713eb68977f01c9f31.zip |
[X86] Add isel patterns to match BMI/TBMI instructions when lowering has turned the root nodes into one of the flag producing binops.
This fixes the patterns that have or/and as a root. 'and' is handled differently since thy usually have a CMP wrapped around them.
I had to look for uses of the CF flag because all these nodes have non-standard CF flag behavior. A real or/xor would always clear CF. In practice we shouldn't be using the CF flag from these nodes as far as I know.
Differential Revision: https://reviews.llvm.org/D55813
llvm-svn: 349962
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.td | 57 |
2 files changed, 62 insertions, 2 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 8115753904f..0274867459d 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -472,6 +472,9 @@ namespace { SDValue &InFlag); bool tryOptimizeRem8Extend(SDNode *N); + + bool hasNoSignFlagUses(SDValue Flags) const; + bool hasNoCarryFlagUses(SDValue Flags) const; }; } @@ -2225,7 +2228,7 @@ static X86::CondCode getCondFromOpc(unsigned Opc) { /// Test whether the given X86ISD::CMP node has any uses which require the SF /// flag to be accurate. -static bool hasNoSignFlagUses(SDValue Flags) { +bool X86DAGToDAGISel::hasNoSignFlagUses(SDValue Flags) const { // Examine each user of the node. for (SDNode::use_iterator UI = Flags->use_begin(), UE = Flags->use_end(); UI != UE; ++UI) { @@ -2265,7 +2268,7 @@ static bool hasNoSignFlagUses(SDValue Flags) { /// Test whether the given node which sets flags has any uses which require the /// CF flag to be accurate. -static bool hasNoCarryFlagUses(SDValue Flags) { + bool X86DAGToDAGISel::hasNoCarryFlagUses(SDValue Flags) const { // Examine each user of the node. for (SDNode::use_iterator UI = Flags->use_begin(), UE = Flags->use_end(); UI != UE; ++UI) { diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index fe9b530e8ea..7a401d4fc35 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -2387,6 +2387,16 @@ let Predicates = [HasBMI], Defs = [EFLAGS] in { // Pattern fragments to auto generate BMI instructions. //===----------------------------------------------------------------------===// +def or_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86or_flag node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 1)); +}]>; + +def xor_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86xor_flag node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 1)); +}]>; + let Predicates = [HasBMI] in { // FIXME: patterns for the load versions are not implemented def : Pat<(and GR32:$src, (add GR32:$src, -1)), @@ -2403,6 +2413,14 @@ let Predicates = [HasBMI] in { (BLSI32rr GR32:$src)>; def : Pat<(and GR64:$src, (ineg GR64:$src)), (BLSI64rr GR64:$src)>; + + // Versions to match flag producing ops. + // X86and_flag nodes are rarely created. Those should use CMP+AND. We do + // TESTrr matching in PostProcessISelDAG to allow BLSR/BLSI to be formed. + def : Pat<(xor_flag_nocf GR32:$src, (add GR32:$src, -1)), + (BLSMSK32rr GR32:$src)>; + def : Pat<(xor_flag_nocf GR64:$src, (add GR64:$src, -1)), + (BLSMSK64rr GR64:$src)>; } multiclass bmi_bextr<bits<8> opc, string mnemonic, RegisterClass RC, @@ -2801,6 +2819,45 @@ let Predicates = [HasTBM] in { (TZMSK32rr GR32:$src)>; def : Pat<(and (not GR64:$src), (add GR64:$src, -1)), (TZMSK64rr GR64:$src)>; + + // Patterns to match flag producing ops. + // X86and_flag nodes are rarely created. Those should use CMP+AND. We do + // TESTrr matching in PostProcessISelDAG to allow BLSR/BLSI to be formed. + def : Pat<(or_flag_nocf GR32:$src, (not (add GR32:$src, 1))), + (BLCI32rr GR32:$src)>; + def : Pat<(or_flag_nocf GR64:$src, (not (add GR64:$src, 1))), + (BLCI64rr GR64:$src)>; + + // Extra patterns because opt can optimize the above patterns to this. + def : Pat<(or_flag_nocf GR32:$src, (sub -2, GR32:$src)), + (BLCI32rr GR32:$src)>; + def : Pat<(or_flag_nocf GR64:$src, (sub -2, GR64:$src)), + (BLCI64rr GR64:$src)>; + + def : Pat<(xor_flag_nocf GR32:$src, (add GR32:$src, 1)), + (BLCMSK32rr GR32:$src)>; + def : Pat<(xor_flag_nocf GR64:$src, (add GR64:$src, 1)), + (BLCMSK64rr GR64:$src)>; + + def : Pat<(or_flag_nocf GR32:$src, (add GR32:$src, 1)), + (BLCS32rr GR32:$src)>; + def : Pat<(or_flag_nocf GR64:$src, (add GR64:$src, 1)), + (BLCS64rr GR64:$src)>; + + def : Pat<(or_flag_nocf GR32:$src, (add GR32:$src, -1)), + (BLSFILL32rr GR32:$src)>; + def : Pat<(or_flag_nocf GR64:$src, (add GR64:$src, -1)), + (BLSFILL64rr GR64:$src)>; + + def : Pat<(or_flag_nocf (not GR32:$src), (add GR32:$src, -1)), + (BLSIC32rr GR32:$src)>; + def : Pat<(or_flag_nocf (not GR64:$src), (add GR64:$src, -1)), + (BLSIC64rr GR64:$src)>; + + def : Pat<(or_flag_nocf (not GR32:$src), (add GR32:$src, 1)), + (T1MSKC32rr GR32:$src)>; + def : Pat<(or_flag_nocf (not GR64:$src), (add GR64:$src, 1)), + (T1MSKC64rr GR64:$src)>; } // HasTBM //===----------------------------------------------------------------------===// |