From 37496d05582c786c22c4fa2447fddb0308b7213e Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 15 Feb 2018 19:57:35 +0000 Subject: [PATCH] [X86] Use btc/btr/bts to implement xor/and/or that affects a single bit in the upper 32-bits of a 64-bit operation. We can't fold a large immediate into a 64-bit operation. But if we know we're only operating on a single bit we can use the bit instructions. For now only do this for optsize. Differential Revision: https://reviews.llvm.org/D37418 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325287 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 5 +++++ lib/Target/X86/X86InstrCompiler.td | 31 +++++++++++++++++++++++++++++++ lib/Target/X86/X86InstrInfo.td | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 1e9ad7a1b3c..396133d4272 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -368,6 +368,11 @@ namespace { return CurDAG->getTargetConstant(Imm, DL, MVT::i32); } + /// Return a target constant with the specified value, of type i64. + inline SDValue getI64Imm(uint64_t Imm, const SDLoc &DL) { + return CurDAG->getTargetConstant(Imm, DL, MVT::i64); + } + SDValue getExtractVEXTRACTImmediate(SDNode *N, unsigned VecWidth, const SDLoc &DL) { assert((VecWidth == 128 || VecWidth == 256) && "Unexpected vector width"); diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td index 959fca3a03d..bf70832515c 100644 --- a/lib/Target/X86/X86InstrCompiler.td +++ b/lib/Target/X86/X86InstrCompiler.td @@ -1471,6 +1471,37 @@ def : Pat<(and GR64:$src, 0xff), } // AddedComplexity = 1 +// Try to use BTS/BTR/BTC for single bit operations on the upper 32-bits. + +def BTRXForm : SDNodeXFormgetAPIntValue().countTrailingOnes(), SDLoc(N)); +}]>; + +def BTCBTSXForm : SDNodeXFormgetAPIntValue().countTrailingZeros(), SDLoc(N)); +}]>; + +def BTRMask64 : ImmLeaf(Imm) && !isInt<32>(Imm) && isPowerOf2_64(~Imm); +}]>; + +def BTCBTSMask64 : ImmLeaf(Imm) && isPowerOf2_64(Imm); +}]>; + +// For now only do this for optsize. +let AddedComplexity = 1, Predicates=[OptForSize] in { + def : Pat<(and GR64:$src1, BTRMask64:$mask), + (BTR64ri8 GR64:$src1, (BTRXForm imm:$mask))>; + def : Pat<(or GR64:$src1, BTCBTSMask64:$mask), + (BTS64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>; + def : Pat<(xor GR64:$src1, BTCBTSMask64:$mask), + (BTC64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>; +} + + // sext_inreg patterns def : Pat<(sext_inreg GR32:$src, i16), (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, sub_16bit))>; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 0193d3ea071..82062dd0b4f 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -2407,7 +2407,7 @@ def BEXTRMaskXForm : SDNodeXForm; def AndMask64 : ImmLeaf UINT32_MAX; + return isMask_64(Imm) && !isUInt<32>(Imm); }]>; // Use BEXTR for 64-bit 'and' with large immediate 'mask'. -- 2.11.0