[PATCH] Re-implement BMI instruction selection using TableGen patterns

Craig Topper craig.topper at gmail.com
Thu Oct 3 11:53:25 PDT 2013


I considered moving them, but then load folding can't be done through
patterns. With this change the only load folding that happens is because of
the peephole optimizer, but that doesn't handle a lot of cases. So I guess
it depends on how much we care about good load folding.


On Thu, Oct 3, 2013 at 11:45 AM, Yunzhong Gao <
Yunzhong_Gao at playstation.sony.com> wrote:

> Hi Craig,
> Do you remember why the BMI instruction selection was done by custom
> lowering instead of TableGen patterns? I tried to replace them with the
> following patterns, and there seems to be no visible changes. The tests in
> test/CodeGen/X86/bmi.ll are still passing just fine. Do you think this
> change is helpful?
> - Gao.
>
> http://llvm-reviews.chandlerc.com/D1822
>
> Files:
>   lib/Target/X86/X86InstrInfo.td
>   lib/Target/X86/X86ISelLowering.cpp
>   lib/Target/X86/X86ISelLowering.h
>
> Index: lib/Target/X86/X86InstrInfo.td
> ===================================================================
> --- lib/Target/X86/X86InstrInfo.td
> +++ lib/Target/X86/X86InstrInfo.td
> @@ -249,9 +249,6 @@
>  def X86and_flag  : SDNode<"X86ISD::AND",  SDTBinaryArithWithFlags,
>                            [SDNPCommutative]>;
>
> -def X86blsi   : SDNode<"X86ISD::BLSI",   SDTIntUnaryOp>;
> -def X86blsmsk : SDNode<"X86ISD::BLSMSK", SDTIntUnaryOp>;
> -def X86blsr   : SDNode<"X86ISD::BLSR",   SDTIntUnaryOp>;
>  def X86bzhi   : SDNode<"X86ISD::BZHI",   SDTIntShiftOp>;
>  def X86bextr  : SDNode<"X86ISD::BEXTR",  SDTIntBinOp>;
>
> @@ -1809,30 +1806,22 @@
>  }
>
>  multiclass bmi_bls<string mnemonic, Format RegMRM, Format MemMRM,
> -                  RegisterClass RC, X86MemOperand x86memop, SDNode OpNode,
> -                  PatFrag ld_frag> {
> +                  RegisterClass RC, X86MemOperand x86memop> {
>    def rr : I<0xF3, RegMRM, (outs RC:$dst), (ins RC:$src),
>               !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"),
> -             [(set RC:$dst, (OpNode RC:$src)), (implicit EFLAGS)]>, T8,
> VEX_4V;
> +             []>, T8, VEX_4V;
>    def rm : I<0xF3, MemMRM, (outs RC:$dst), (ins x86memop:$src),
>               !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"),
> -             [(set RC:$dst, (OpNode (ld_frag addr:$src))), (implicit
> EFLAGS)]>,
> -             T8, VEX_4V;
> +             []>, T8, VEX_4V;
>  }
>
>  let Predicates = [HasBMI], Defs = [EFLAGS] in {
> -  defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem,
> -                        X86blsr, loadi32>;
> -  defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem,
> -                        X86blsr, loadi64>, VEX_W;
> -  defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem,
> -                          X86blsmsk, loadi32>;
> -  defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem,
> -                          X86blsmsk, loadi64>, VEX_W;
> -  defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem,
> -                        X86blsi, loadi32>;
> -  defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem,
> -                        X86blsi, loadi64>, VEX_W;
> +  defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem>;
> +  defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem>, VEX_W;
> +  defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem>;
> +  defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem>, VEX_W;
> +  defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem>;
> +  defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem>, VEX_W;
>  }
>
>  multiclass bmi_bextr_bzhi<bits<8> opc, string mnemonic, RegisterClass RC,
> @@ -1875,17 +1864,6 @@
>            (BZHI64rm addr:$src1,
>                      (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2,
> sub_8bit))>;
>
> -let Predicates = [HasBMI] in {
> -  def : Pat<(X86bextr GR32:$src1, GR32:$src2),
> -            (BEXTR32rr GR32:$src1, GR32:$src2)>;
> -  def : Pat<(X86bextr (loadi32 addr:$src1), GR32:$src2),
> -            (BEXTR32rm addr:$src1, GR32:$src2)>;
> -  def : Pat<(X86bextr GR64:$src1, GR64:$src2),
> -            (BEXTR64rr GR64:$src1, GR64:$src2)>;
> -  def : Pat<(X86bextr (loadi64 addr:$src1), GR64:$src2),
> -            (BEXTR64rm addr:$src1, GR64:$src2)>;
> -} // HasBMI
> -
>  multiclass bmi_pdep_pext<string mnemonic, RegisterClass RC,
>                           X86MemOperand x86memop, Intrinsic Int,
>                           PatFrag ld_frag> {
> @@ -1910,6 +1888,36 @@
>  }
>
>
>  //===----------------------------------------------------------------------===//
> +// Pattern fragments to auto generate BMI instructions.
>
> +//===----------------------------------------------------------------------===//
> +
> +let Predicates = [HasBMI] in {
> +  def : Pat<(X86bextr GR32:$src1, GR32:$src2),
> +            (BEXTR32rr GR32:$src1, GR32:$src2)>;
> +  def : Pat<(X86bextr (loadi32 addr:$src1), GR32:$src2),
> +            (BEXTR32rm addr:$src1, GR32:$src2)>;
> +  def : Pat<(X86bextr GR64:$src1, GR64:$src2),
> +            (BEXTR64rr GR64:$src1, GR64:$src2)>;
> +  def : Pat<(X86bextr (loadi64 addr:$src1), GR64:$src2),
> +            (BEXTR64rm addr:$src1, GR64:$src2)>;
> +
> +  def : Pat<(and GR32:$src, (sub 0, GR32:$src)),
> +            (BLSI32rr GR32:$src)>;
> +  def : Pat<(and GR64:$src, (sub 0, GR64:$src)),
> +            (BLSI64rr GR64:$src)>;
> +
> +  def : Pat<(xor GR32:$src, (add GR32:$src, -1)),
> +            (BLSMSK32rr GR32:$src)>;
> +  def : Pat<(xor GR64:$src, (add GR64:$src, -1)),
> +            (BLSMSK64rr GR64:$src)>;
> +
> +  def : Pat<(and GR32:$src, (add GR32:$src, -1)),
> +            (BLSR32rr GR32:$src)>;
> +  def : Pat<(and GR64:$src, (add GR64:$src, -1)),
> +            (BLSR64rr GR64:$src)>;
> +} // HasBMI
> +
>
> +//===----------------------------------------------------------------------===//
>  // TBM Instructions
>  //
>  let Predicates = [HasTBM], Defs = [EFLAGS] in {
> Index: lib/Target/X86/X86ISelLowering.cpp
> ===================================================================
> --- lib/Target/X86/X86ISelLowering.cpp
> +++ lib/Target/X86/X86ISelLowering.cpp
> @@ -13710,9 +13710,6 @@
>    case X86ISD::OR:                 return "X86ISD::OR";
>    case X86ISD::XOR:                return "X86ISD::XOR";
>    case X86ISD::AND:                return "X86ISD::AND";
> -  case X86ISD::BLSI:               return "X86ISD::BLSI";
> -  case X86ISD::BLSMSK:             return "X86ISD::BLSMSK";
> -  case X86ISD::BLSR:               return "X86ISD::BLSR";
>    case X86ISD::BZHI:               return "X86ISD::BZHI";
>    case X86ISD::BEXTR:              return "X86ISD::BEXTR";
>    case X86ISD::MUL_IMM:            return "X86ISD::MUL_IMM";
> @@ -17558,28 +17555,6 @@
>      SDValue N1 = N->getOperand(1);
>      SDLoc DL(N);
>
> -    if (Subtarget->hasBMI()) {
> -      // Check LHS for neg
> -      if (N0.getOpcode() == ISD::SUB && N0.getOperand(1) == N1 &&
> -          isZero(N0.getOperand(0)))
> -        return DAG.getNode(X86ISD::BLSI, DL, VT, N1);
> -
> -      // Check RHS for neg
> -      if (N1.getOpcode() == ISD::SUB && N1.getOperand(1) == N0 &&
> -          isZero(N1.getOperand(0)))
> -        return DAG.getNode(X86ISD::BLSI, DL, VT, N0);
> -
> -      // Check LHS for X-1
> -      if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1 &&
> -          isAllOnes(N0.getOperand(1)))
> -        return DAG.getNode(X86ISD::BLSR, DL, VT, N1);
> -
> -      // Check RHS for X-1
> -      if (N1.getOpcode() == ISD::ADD && N1.getOperand(0) == N0 &&
> -          isAllOnes(N1.getOperand(1)))
> -        return DAG.getNode(X86ISD::BLSR, DL, VT, N0);
> -    }
> -
>      if (Subtarget->hasBMI2()) {
>        // Check for (and (add (shl 1, Y), -1), X)
>        if (N0.getOpcode() == ISD::ADD && isAllOnes(N0.getOperand(1))) {
> @@ -17853,28 +17828,6 @@
>        return RV;
>    }
>
> -  // Try forming BMI if it is available.
> -  if (!Subtarget->hasBMI())
> -    return SDValue();
> -
> -  if (VT != MVT::i32 && VT != MVT::i64)
> -    return SDValue();
> -
> -  assert(Subtarget->hasBMI() && "Creating BLSMSK requires BMI
> instructions");
> -
> -  // Create BLSMSK instructions by finding X ^ (X-1)
> -  SDValue N0 = N->getOperand(0);
> -  SDValue N1 = N->getOperand(1);
> -  SDLoc DL(N);
> -
> -  if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1 &&
> -      isAllOnes(N0.getOperand(1)))
> -    return DAG.getNode(X86ISD::BLSMSK, DL, VT, N1);
> -
> -  if (N1.getOpcode() == ISD::ADD && N1.getOperand(0) == N0 &&
> -      isAllOnes(N1.getOperand(1)))
> -    return DAG.getNode(X86ISD::BLSMSK, DL, VT, N0);
> -
>    return SDValue();
>  }
>
> Index: lib/Target/X86/X86ISelLowering.h
> ===================================================================
> --- lib/Target/X86/X86ISelLowering.h
> +++ lib/Target/X86/X86ISelLowering.h
> @@ -292,9 +292,6 @@
>        ADD, SUB, ADC, SBB, SMUL,
>        INC, DEC, OR, XOR, AND,
>
> -      BLSI,   // BLSI - Extract lowest set isolated bit
> -      BLSMSK, // BLSMSK - Get mask up to lowest set bit
> -      BLSR,   // BLSR - Reset lowest set bit
>        BZHI,   // BZHI - Zero high bits
>        BEXTR,  // BEXTR - Bit field extract
>



-- 
~Craig
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131003/d0041c55/attachment.html>


More information about the llvm-commits mailing list