[llvm] r211077 - [FastISel][X86] Refactor the code to get the X86 condition from a helper function. NFC.

Eric Christopher echristo at gmail.com
Mon Jun 16 17:10:43 PDT 2014


Excellent. Thanks!

-eric

On Mon, Jun 16, 2014 at 4:58 PM, Juergen Ributzka <juergen at apple.com> wrote:
> Author: ributzka
> Date: Mon Jun 16 18:58:24 2014
> New Revision: 211077
>
> URL: http://llvm.org/viewvc/llvm-project?rev=211077&view=rev
> Log:
> [FastISel][X86] Refactor the code to get the X86 condition from a helper function. NFC.
>
> Make use of helper functions to simplify the branch and compare instruction
> selection in FastISel. Also add test cases for compare and conditonal branch.
>
> Added:
>     llvm/trunk/test/CodeGen/X86/fast-isel-cmp-branch2.ll
>     llvm/trunk/test/CodeGen/X86/fast-isel-cmp.ll
> Modified:
>     llvm/trunk/lib/Target/X86/X86FastISel.cpp
>     llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>     llvm/trunk/lib/Target/X86/X86InstrInfo.h
>
> Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=211077&r1=211076&r2=211077&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Mon Jun 16 18:58:24 2014
> @@ -16,6 +16,7 @@
>  #include "X86.h"
>  #include "X86CallingConv.h"
>  #include "X86InstrBuilder.h"
> +#include "X86InstrInfo.h"
>  #include "X86MachineFunctionInfo.h"
>  #include "X86RegisterInfo.h"
>  #include "X86Subtarget.h"
> @@ -154,6 +155,44 @@ private:
>
>  } // end anonymous namespace.
>
> +static std::pair<X86::CondCode, bool>
> +getX86ConditonCode(CmpInst::Predicate Predicate) {
> +  X86::CondCode CC = X86::COND_INVALID;
> +  bool NeedSwap = false;
> +  switch (Predicate) {
> +  default: break;
> +  // Floating-point Predicates
> +  case CmpInst::FCMP_UEQ: CC = X86::COND_E;       break;
> +  case CmpInst::FCMP_OLT: NeedSwap = true; // fall-through
> +  case CmpInst::FCMP_OGT: CC = X86::COND_A;       break;
> +  case CmpInst::FCMP_OLE: NeedSwap = true; // fall-through
> +  case CmpInst::FCMP_OGE: CC = X86::COND_AE;      break;
> +  case CmpInst::FCMP_UGT: NeedSwap = true; // fall-through
> +  case CmpInst::FCMP_ULT: CC = X86::COND_B;       break;
> +  case CmpInst::FCMP_UGE: NeedSwap = true; // fall-through
> +  case CmpInst::FCMP_ULE: CC = X86::COND_BE;      break;
> +  case CmpInst::FCMP_ONE: CC = X86::COND_NE;      break;
> +  case CmpInst::FCMP_UNO: CC = X86::COND_P;       break;
> +  case CmpInst::FCMP_ORD: CC = X86::COND_NP;      break;
> +  case CmpInst::FCMP_OEQ: // fall-through
> +  case CmpInst::FCMP_UNE: CC = X86::COND_INVALID; break;
> +
> +  // Integer Predicates
> +  case CmpInst::ICMP_EQ:  CC = X86::COND_E;       break;
> +  case CmpInst::ICMP_NE:  CC = X86::COND_NE;      break;
> +  case CmpInst::ICMP_UGT: CC = X86::COND_A;       break;
> +  case CmpInst::ICMP_UGE: CC = X86::COND_AE;      break;
> +  case CmpInst::ICMP_ULT: CC = X86::COND_B;       break;
> +  case CmpInst::ICMP_ULE: CC = X86::COND_BE;      break;
> +  case CmpInst::ICMP_SGT: CC = X86::COND_G;       break;
> +  case CmpInst::ICMP_SGE: CC = X86::COND_GE;      break;
> +  case CmpInst::ICMP_SLT: CC = X86::COND_L;       break;
> +  case CmpInst::ICMP_SLE: CC = X86::COND_LE;      break;
> +  }
> +
> +  return std::make_pair(CC, NeedSwap);
> +}
> +
>  bool X86FastISel::isTypeLegal(Type *Ty, MVT &VT, bool AllowI1) {
>    EVT evt = TLI.getValueType(Ty, /*HandleUnknown=*/true);
>    if (evt == MVT::Other || !evt.isSimple())
> @@ -1009,73 +1048,51 @@ bool X86FastISel::X86SelectCmp(const Ins
>    if (!isTypeLegal(I->getOperand(0)->getType(), VT))
>      return false;
>
> -  unsigned ResultReg = createResultReg(&X86::GR8RegClass);
> -  unsigned SetCCOpc;
> -  bool SwapArgs;  // false -> compare Op0, Op1.  true -> compare Op1, Op0.
> +  // FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
> +  static unsigned SETFOpcTable[2][2] = {
> +    { X86::SETEr,  X86::SETNPr },
> +    { X86::SETNEr, X86::SETPr  }
> +  };
> +  unsigned *SETFOpc = nullptr;
>    switch (CI->getPredicate()) {
> -  case CmpInst::FCMP_OEQ: {
> -    if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
> -      return false;
> -
> -    unsigned EReg = createResultReg(&X86::GR8RegClass);
> -    unsigned NPReg = createResultReg(&X86::GR8RegClass);
> -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETEr), EReg);
> -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
> -            TII.get(X86::SETNPr), NPReg);
> -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
> -            TII.get(X86::AND8rr), ResultReg).addReg(NPReg).addReg(EReg);
> -    UpdateValueMap(I, ResultReg);
> -    return true;
> +  default: break;
> +  case CmpInst::FCMP_OEQ: SETFOpc = &SETFOpcTable[0][0]; break;
> +  case CmpInst::FCMP_UNE: SETFOpc = &SETFOpcTable[1][0]; break;
>    }
> -  case CmpInst::FCMP_UNE: {
> +
> +  unsigned ResultReg = createResultReg(&X86::GR8RegClass);
> +  if (SETFOpc) {
>      if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
>        return false;
>
> -    unsigned NEReg = createResultReg(&X86::GR8RegClass);
> -    unsigned PReg = createResultReg(&X86::GR8RegClass);
> -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETNEr), NEReg);
> -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETPr), PReg);
> -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::OR8rr),ResultReg)
> -      .addReg(PReg).addReg(NEReg);
> +    unsigned FlagReg1 = createResultReg(&X86::GR8RegClass);
> +    unsigned FlagReg2 = createResultReg(&X86::GR8RegClass);
> +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[0]),
> +            FlagReg1);
> +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[1]),
> +            FlagReg2);
> +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::AND8rr),
> +            ResultReg).addReg(FlagReg1).addReg(FlagReg2);
>      UpdateValueMap(I, ResultReg);
>      return true;
>    }
> -  case CmpInst::FCMP_OGT: SwapArgs = false; SetCCOpc = X86::SETAr;  break;
> -  case CmpInst::FCMP_OGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break;
> -  case CmpInst::FCMP_OLT: SwapArgs = true;  SetCCOpc = X86::SETAr;  break;
> -  case CmpInst::FCMP_OLE: SwapArgs = true;  SetCCOpc = X86::SETAEr; break;
> -  case CmpInst::FCMP_ONE: SwapArgs = false; SetCCOpc = X86::SETNEr; break;
> -  case CmpInst::FCMP_ORD: SwapArgs = false; SetCCOpc = X86::SETNPr; break;
> -  case CmpInst::FCMP_UNO: SwapArgs = false; SetCCOpc = X86::SETPr;  break;
> -  case CmpInst::FCMP_UEQ: SwapArgs = false; SetCCOpc = X86::SETEr;  break;
> -  case CmpInst::FCMP_UGT: SwapArgs = true;  SetCCOpc = X86::SETBr;  break;
> -  case CmpInst::FCMP_UGE: SwapArgs = true;  SetCCOpc = X86::SETBEr; break;
> -  case CmpInst::FCMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr;  break;
> -  case CmpInst::FCMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break;
> -
> -  case CmpInst::ICMP_EQ:  SwapArgs = false; SetCCOpc = X86::SETEr;  break;
> -  case CmpInst::ICMP_NE:  SwapArgs = false; SetCCOpc = X86::SETNEr; break;
> -  case CmpInst::ICMP_UGT: SwapArgs = false; SetCCOpc = X86::SETAr;  break;
> -  case CmpInst::ICMP_UGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break;
> -  case CmpInst::ICMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr;  break;
> -  case CmpInst::ICMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break;
> -  case CmpInst::ICMP_SGT: SwapArgs = false; SetCCOpc = X86::SETGr;  break;
> -  case CmpInst::ICMP_SGE: SwapArgs = false; SetCCOpc = X86::SETGEr; break;
> -  case CmpInst::ICMP_SLT: SwapArgs = false; SetCCOpc = X86::SETLr;  break;
> -  case CmpInst::ICMP_SLE: SwapArgs = false; SetCCOpc = X86::SETLEr; break;
> -  default:
> -    return false;
> -  }
>
> -  const Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
> +  X86::CondCode CC;
> +  bool SwapArgs;  // false -> compare Op0, Op1.  true -> compare Op1, Op0.
> +  std::tie(CC, SwapArgs) = getX86ConditonCode(CI->getPredicate());
> +  assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
> +  unsigned Opc = X86::getSETFromCond(CC);
> +
> +  const Value *LHS = CI->getOperand(0);
> +  const Value *RHS = CI->getOperand(1);
>    if (SwapArgs)
> -    std::swap(Op0, Op1);
> +    std::swap(LHS, RHS);
>
>    // Emit a compare of Op0/Op1.
> -  if (!X86FastEmitCompare(Op0, Op1, VT))
> +  if (!X86FastEmitCompare(LHS, RHS, VT))
>      return false;
>
> -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SetCCOpc), ResultReg);
> +  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg);
>    UpdateValueMap(I, ResultReg);
>    return true;
>  }
> @@ -1152,66 +1169,59 @@ bool X86FastISel::X86SelectBranch(const
>          Predicate = CmpInst::getInversePredicate(Predicate);
>        }
>
> -      bool SwapArgs;  // false -> compare Op0, Op1.  true -> compare Op1, Op0.
> -      unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA"
> -
> +      // FCMP_OEQ and FCMP_UNE cannot be expressed with a single flag/conditon
> +      // code check. Instead two branch instructions are required to check all
> +      // the flags. First we change the predicate to a supported conditon code,
> +      // which will be the first branch. Later one we will emit the second
> +      // branch.
> +      bool NeedExtraBranch = false;
>        switch (Predicate) {
> +      default: break;
>        case CmpInst::FCMP_OEQ:
> -        std::swap(TrueMBB, FalseMBB);
> -        Predicate = CmpInst::FCMP_UNE;
> -        // FALL THROUGH
> -      case CmpInst::FCMP_UNE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
> -      case CmpInst::FCMP_OGT: SwapArgs = false; BranchOpc = X86::JA_4;  break;
> -      case CmpInst::FCMP_OGE: SwapArgs = false; BranchOpc = X86::JAE_4; break;
> -      case CmpInst::FCMP_OLT: SwapArgs = true;  BranchOpc = X86::JA_4;  break;
> -      case CmpInst::FCMP_OLE: SwapArgs = true;  BranchOpc = X86::JAE_4; break;
> -      case CmpInst::FCMP_ONE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
> -      case CmpInst::FCMP_ORD: SwapArgs = false; BranchOpc = X86::JNP_4; break;
> -      case CmpInst::FCMP_UNO: SwapArgs = false; BranchOpc = X86::JP_4;  break;
> -      case CmpInst::FCMP_UEQ: SwapArgs = false; BranchOpc = X86::JE_4;  break;
> -      case CmpInst::FCMP_UGT: SwapArgs = true;  BranchOpc = X86::JB_4;  break;
> -      case CmpInst::FCMP_UGE: SwapArgs = true;  BranchOpc = X86::JBE_4; break;
> -      case CmpInst::FCMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4;  break;
> -      case CmpInst::FCMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break;
> -
> -      case CmpInst::ICMP_EQ:  SwapArgs = false; BranchOpc = X86::JE_4;  break;
> -      case CmpInst::ICMP_NE:  SwapArgs = false; BranchOpc = X86::JNE_4; break;
> -      case CmpInst::ICMP_UGT: SwapArgs = false; BranchOpc = X86::JA_4;  break;
> -      case CmpInst::ICMP_UGE: SwapArgs = false; BranchOpc = X86::JAE_4; break;
> -      case CmpInst::ICMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4;  break;
> -      case CmpInst::ICMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break;
> -      case CmpInst::ICMP_SGT: SwapArgs = false; BranchOpc = X86::JG_4;  break;
> -      case CmpInst::ICMP_SGE: SwapArgs = false; BranchOpc = X86::JGE_4; break;
> -      case CmpInst::ICMP_SLT: SwapArgs = false; BranchOpc = X86::JL_4;  break;
> -      case CmpInst::ICMP_SLE: SwapArgs = false; BranchOpc = X86::JLE_4; break;
> -      default:
> -        return false;
> +        std::swap(TrueMBB, FalseMBB); // fall-through
> +      case CmpInst::FCMP_UNE:
> +        NeedExtraBranch = true;
> +        Predicate = CmpInst::FCMP_ONE;
> +        break;
>        }
>
> -      const Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
> +      X86::CondCode CC;
> +      bool SwapArgs;  // false -> compare Op0, Op1.  true -> compare Op1, Op0.
> +      unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA"
> +      std::tie(CC, SwapArgs) = getX86ConditonCode(Predicate);
> +      assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
> +
> +      BranchOpc = X86::GetCondBranchFromCond(CC);
> +      const Value *CmpLHS = CI->getOperand(0);
> +      const Value *CmpRHS = CI->getOperand(1);
>        if (SwapArgs)
> -        std::swap(Op0, Op1);
> +        std::swap(CmpLHS, CmpRHS);
>
>        // Emit a compare of the LHS and RHS, setting the flags.
> -      if (!X86FastEmitCompare(Op0, Op1, VT))
> +      if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT))
>          return false;
>
>        BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BranchOpc))
>          .addMBB(TrueMBB);
>
> -      if (Predicate == CmpInst::FCMP_UNE) {
> -        // X86 requires a second branch to handle UNE (and OEQ,
> -        // which is mapped to UNE above).
> +      // X86 requires a second branch to handle UNE (and OEQ, which is mapped
> +      // to UNE above).
> +      if (NeedExtraBranch) {
>          BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::JP_4))
>            .addMBB(TrueMBB);
>        }
>
> -      FastEmitBranch(FalseMBB, DbgLoc);
> +      // Obtain the branch weight and add the TrueBB to the successor list.
>        uint32_t BranchWeight = 0;
>        if (FuncInfo.BPI)
>          BranchWeight = FuncInfo.BPI->getEdgeWeight(BI->getParent(),
>                                                     TrueMBB->getBasicBlock());
>        FuncInfo.MBB->addSuccessor(TrueMBB, BranchWeight);
> +
> +      // Emits an unconditional branch to the FalseBB, obtains the branch
> +      // weight, andd adds it to the successor list.
> +      FastEmitBranch(FalseMBB, DbgLoc);
> +
>        return true;
>      }
>    } else if (TruncInst *TI = dyn_cast<TruncInst>(BI->getCondition())) {
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=211077&r1=211076&r2=211077&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Mon Jun 16 18:58:24 2014
> @@ -2670,8 +2670,7 @@ static X86::CondCode getSwappedCondition
>
>  /// getSETFromCond - Return a set opcode for the given condition and
>  /// whether it has memory operand.
> -static unsigned getSETFromCond(X86::CondCode CC,
> -                               bool HasMemoryOperand) {
> +unsigned X86::getSETFromCond(CondCode CC, bool HasMemoryOperand) {
>    static const uint16_t Opc[16][2] = {
>      { X86::SETAr,  X86::SETAm  },
>      { X86::SETAEr, X86::SETAEm },
> @@ -2691,7 +2690,7 @@ static unsigned getSETFromCond(X86::Cond
>      { X86::SETSr,  X86::SETSm  }
>    };
>
> -  assert(CC < 16 && "Can only handle standard cond codes");
> +  assert(CC <= LAST_VALID_COND && "Can only handle standard cond codes");
>    return Opc[CC][HasMemoryOperand ? 1 : 0];
>  }
>
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=211077&r1=211076&r2=211077&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Mon Jun 16 18:58:24 2014
> @@ -46,6 +46,7 @@ namespace X86 {
>      COND_O  = 13,
>      COND_P  = 14,
>      COND_S  = 15,
> +    LAST_VALID_COND = COND_S,
>
>      // Artificial condition codes. These are used by AnalyzeBranch
>      // to indicate a block terminated with two conditional branches to
> @@ -61,12 +62,16 @@ namespace X86 {
>    // Turn condition code into conditional branch opcode.
>    unsigned GetCondBranchFromCond(CondCode CC);
>
> +  /// \brief Return a set opcode for the given condition and whether it has
> +  /// a memory operand.
> +  unsigned getSETFromCond(CondCode CC, bool HasMemoryOperand = false);
> +
>    // Turn CMov opcode into condition code.
>    CondCode getCondFromCMovOpc(unsigned Opc);
>
>    /// GetOppositeBranchCondition - Return the inverse of the specified cond,
>    /// e.g. turning COND_E to COND_NE.
> -  CondCode GetOppositeBranchCondition(X86::CondCode CC);
> +  CondCode GetOppositeBranchCondition(CondCode CC);
>  }  // end namespace X86;
>
>
>
> Added: llvm/trunk/test/CodeGen/X86/fast-isel-cmp-branch2.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fast-isel-cmp-branch2.ll?rev=211077&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/fast-isel-cmp-branch2.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/fast-isel-cmp-branch2.ll Mon Jun 16 18:58:24 2014
> @@ -0,0 +1,294 @@
> +; RUN: llc < %s                             -mtriple=x86_64-apple-darwin10 | FileCheck %s
> +; RUN: llc < %s -fast-isel -fast-isel-abort -mtriple=x86_64-apple-darwin10 | FileCheck %s
> +
> +define i32 @fcmp_oeq(float %x, float %y) {
> +; CHECK-LABEL: fcmp_oeq
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  jne {{LBB.+_1}}
> +; CHECK-NEXT:  jnp {{LBB.+_2}}
> +  %1 = fcmp oeq float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_ogt(float %x, float %y) {
> +; CHECK-LABEL: fcmp_ogt
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  jbe {{LBB.+_1}}
> +  %1 = fcmp ogt float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_oge(float %x, float %y) {
> +; CHECK-LABEL: fcmp_oge
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  jb {{LBB.+_1}}
> +  %1 = fcmp oge float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_olt(float %x, float %y) {
> +; CHECK-LABEL: fcmp_olt
> +; CHECK:       ucomiss  %xmm0, %xmm1
> +; CHECK-NEXT:  jbe {{LBB.+_1}}
> +  %1 = fcmp olt float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_ole(float %x, float %y) {
> +; CHECK-LABEL: fcmp_ole
> +; CHECK:       ucomiss  %xmm0, %xmm1
> +; CHECK-NEXT:  jb {{LBB.+_1}}
> +  %1 = fcmp ole float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_one(float %x, float %y) {
> +; CHECK-LABEL: fcmp_one
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  je {{LBB.+_1}}
> +  %1 = fcmp one float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_ord(float %x, float %y) {
> +; CHECK-LABEL: fcmp_ord
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  jp {{LBB.+_1}}
> +  %1 = fcmp ord float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_uno(float %x, float %y) {
> +; CHECK-LABEL: fcmp_uno
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  jp {{LBB.+_2}}
> +  %1 = fcmp uno float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_ueq(float %x, float %y) {
> +; CHECK-LABEL: fcmp_ueq
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  je {{LBB.+_2}}
> +  %1 = fcmp ueq float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_ugt(float %x, float %y) {
> +; CHECK-LABEL: fcmp_ugt
> +; CHECK:       ucomiss  %xmm0, %xmm1
> +; CHECK-NEXT:  jae {{LBB.+_1}}
> +  %1 = fcmp ugt float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_uge(float %x, float %y) {
> +; CHECK-LABEL: fcmp_uge
> +; CHECK:       ucomiss  %xmm0, %xmm1
> +; CHECK-NEXT:  ja {{LBB.+_1}}
> +  %1 = fcmp uge float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_ult(float %x, float %y) {
> +; CHECK-LABEL: fcmp_ult
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  jae {{LBB.+_1}}
> +  %1 = fcmp ult float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_ule(float %x, float %y) {
> +; CHECK-LABEL: fcmp_ule
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  ja {{LBB.+_1}}
> +  %1 = fcmp ule float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @fcmp_une(float %x, float %y) {
> +; CHECK-LABEL: fcmp_une
> +; CHECK:       ucomiss  %xmm1, %xmm0
> +; CHECK-NEXT:  jne {{LBB.+_2}}
> +; CHECK-NEXT:  jp  {{LBB.+_2}}
> +; CHECK-NEXT:  jmp {{LBB.+_1}}
> +  %1 = fcmp une float %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_eq(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_eq
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jne {{LBB.+_1}}
> +  %1 = icmp eq i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_ne(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_ne
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  je {{LBB.+_1}}
> +  %1 = icmp ne i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_ugt(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_ugt
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jbe {{LBB.+_1}}
> +  %1 = icmp ugt i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_uge(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_uge
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jb {{LBB.+_1}}
> +  %1 = icmp uge i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_ult(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_ult
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jae {{LBB.+_1}}
> +  %1 = icmp ult i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_ule(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_ule
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  ja {{LBB.+_1}}
> +  %1 = icmp ule i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_sgt(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_sgt
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jle {{LBB.+_1}}
> +  %1 = icmp sgt i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_sge(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_sge
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jl {{LBB.+_1}}
> +  %1 = icmp sge i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_slt(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_slt
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jge {{LBB.+_1}}
> +  %1 = icmp slt i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
> +define i32 @icmp_sle(i32 %x, i32 %y) {
> +; CHECK-LABEL: icmp_sle
> +; CHECK:       cmpl %esi, %edi
> +; CHECK-NEXT:  jg {{LBB.+_1}}
> +  %1 = icmp sle i32 %x, %y
> +  br i1 %1, label %bb1, label %bb2
> +bb2:
> +  ret i32 1
> +bb1:
> +  ret i32 0
> +}
> +
>
> Added: llvm/trunk/test/CodeGen/X86/fast-isel-cmp.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fast-isel-cmp.ll?rev=211077&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/fast-isel-cmp.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/fast-isel-cmp.ll Mon Jun 16 18:58:24 2014
> @@ -0,0 +1,272 @@
> +; RUN: llc < %s                             -mtriple=x86_64-apple-darwin10 | FileCheck %s --check-prefix=SDAG
> +; RUN: llc < %s -fast-isel -fast-isel-abort -mtriple=x86_64-apple-darwin10 | FileCheck %s --check-prefix=FAST
> +
> +define zeroext i1 @fcmp_oeq(float %x, float %y) {
> +; SDAG-LABEL: fcmp_oeq
> +; SDAG:       cmpeqss  %xmm1, %xmm0
> +; SDAG-NEXT:  movd     %xmm0, %eax
> +; SDAG-NEXT:  andl     $1, %eax
> +; FAST-LABEL: fcmp_oeq
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  sete     %al
> +; FAST-NEXT:  setnp    %cl
> +; FAST-NEXT:  andb     %al, %cl
> +  %1 = fcmp oeq float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_ogt(float %x, float %y) {
> +; SDAG-LABEL: fcmp_ogt
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  seta     %al
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  seta     %al
> +  %1 = fcmp ogt float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_oge(float %x, float %y) {
> +; SDAG-LABEL: fcmp_oge
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  setae    %al
> +; FAST-LABEL: fcmp_oge
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  setae    %al
> +  %1 = fcmp oge float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_olt(float %x, float %y) {
> +; SDAG-LABEL: fcmp_olt
> +; SDAG:       ucomiss  %xmm0, %xmm1
> +; SDAG-NEXT:  seta     %al
> +; FAST-LABEL: fcmp_olt
> +; FAST:       ucomiss  %xmm0, %xmm1
> +; FAST-NEXT:  seta     %al
> +  %1 = fcmp olt float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_ole(float %x, float %y) {
> +; SDAG-LABEL: fcmp_ole
> +; SDAG:       ucomiss  %xmm0, %xmm1
> +; SDAG-NEXT:  setae    %al
> +; FAST-LABEL: fcmp_ole
> +; FAST:       ucomiss  %xmm0, %xmm1
> +; FAST-NEXT:  setae    %al
> +  %1 = fcmp ole float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_one(float %x, float %y) {
> +; SDAG-LABEL: fcmp_one
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  setne    %al
> +; FAST-LABEL: fcmp_one
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  setne    %al
> +  %1 = fcmp one float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_ord(float %x, float %y) {
> +; SDAG-LABEL: fcmp_ord
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  setnp    %al
> +; FAST-LABEL: fcmp_ord
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  setnp    %al
> +  %1 = fcmp ord float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_uno(float %x, float %y) {
> +; SDAG-LABEL: fcmp_uno
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  setp     %al
> +; FAST-LABEL: fcmp_uno
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  setp     %al
> +  %1 = fcmp uno float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_ueq(float %x, float %y) {
> +; SDAG-LABEL: fcmp_ueq
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  sete     %al
> +; FAST-LABEL: fcmp_ueq
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  sete     %al
> +  %1 = fcmp ueq float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_ugt(float %x, float %y) {
> +; SDAG-LABEL: fcmp_ugt
> +; SDAG:       ucomiss  %xmm0, %xmm1
> +; SDAG-NEXT:  setb     %al
> +; FAST-LABEL: fcmp_ugt
> +; FAST:       ucomiss  %xmm0, %xmm1
> +; FAST-NEXT:  setb     %al
> +  %1 = fcmp ugt float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_uge(float %x, float %y) {
> +; SDAG-LABEL: fcmp_uge
> +; SDAG:       ucomiss  %xmm0, %xmm1
> +; SDAG-NEXT:  setbe    %al
> +; FAST-LABEL: fcmp_uge
> +; FAST:       ucomiss  %xmm0, %xmm1
> +; FAST-NEXT:  setbe    %al
> +  %1 = fcmp uge float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_ult(float %x, float %y) {
> +; SDAG-LABEL: fcmp_ult
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  setb     %al
> +; FAST-LABEL: fcmp_ult
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  setb     %al
> +  %1 = fcmp ult float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_ule(float %x, float %y) {
> +; SDAG-LABEL: fcmp_ule
> +; SDAG:       ucomiss  %xmm1, %xmm0
> +; SDAG-NEXT:  setbe    %al
> +; FAST-LABEL: fcmp_ule
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  setbe    %al
> +  %1 = fcmp ule float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @fcmp_une(float %x, float %y) {
> +; SDAG-LABEL: fcmp_une
> +; SDAG:       cmpneqss %xmm1, %xmm0
> +; SDAG-NEXT:  movd     %xmm0, %eax
> +; SDAG-NEXT:  andl     $1, %eax
> +; FAST-LABEL: fcmp_une
> +; FAST:       ucomiss  %xmm1, %xmm0
> +; FAST-NEXT:  setne    %al
> +; FAST-NEXT:  setp     %cl
> +; FAST-NEXT:  andb     %al, %cl
> +  %1 = fcmp une float %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_eq(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_eq
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  sete     %al
> +; FAST-LABEL: icmp_eq
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  sete     %al
> +  %1 = icmp eq i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_ne(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_ne
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setne    %al
> +; FAST-LABEL: icmp_ne
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setne    %al
> +  %1 = icmp ne i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_ugt(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_ugt
> +; SDAG:       cmpl     %edi, %esi
> +; SDAG-NEXT:  setb     %al
> +; FAST-LABEL: icmp_ugt
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  seta     %al
> +  %1 = icmp ugt i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_uge(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_uge
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setae    %al
> +; FAST-LABEL: icmp_uge
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setae    %al
> +  %1 = icmp uge i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_ult(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_ult
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setb     %al
> +; FAST-LABEL: icmp_ult
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setb     %al
> +  %1 = icmp ult i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_ule(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_ule
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setbe    %al
> +; FAST-LABEL: icmp_ule
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setbe    %al
> +  %1 = icmp ule i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_sgt(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_sgt
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setg     %al
> +; FAST-LABEL: icmp_sgt
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setg     %al
> +  %1 = icmp sgt i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_sge(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_sge
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setge    %al
> +; FAST-LABEL: icmp_sge
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setge    %al
> +  %1 = icmp sge i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_slt(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_slt
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setl     %al
> +; FAST-LABEL: icmp_slt
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setl     %al
> +  %1 = icmp slt i32 %x, %y
> +  ret i1 %1
> +}
> +
> +define zeroext i1 @icmp_sle(i32 %x, i32 %y) {
> +; SDAG-LABEL: icmp_sle
> +; SDAG:       cmpl     %esi, %edi
> +; SDAG-NEXT:  setle    %al
> +; FAST-LABEL: icmp_sle
> +; FAST:       cmpl     %esi, %edi
> +; FAST-NEXT:  setle    %al
> +  %1 = icmp sle i32 %x, %y
> +  ret i1 %1
> +}
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list