[llvm-commits] [llvm] r161687 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/bool-simplify.ll

David Dean david_dean at apple.com
Fri Aug 10 19:15:18 PDT 2012


This is breaking some of the dejagnu tests:

gcc.c-torture/execute/ieee/copysign1.c compilation,  -O0
gcc.c-torture/execute/ieee/copysign1.c compilation,  -O1
gcc.c-torture/execute/ieee/copysign1.c compilation,  -O2
gcc.c-torture/execute/ieee/copysign1.c compilation,  -O3 -fomit-frame-pointer
gcc.c-torture/execute/ieee/copysign1.c compilation,  -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions
gcc.c-torture/execute/ieee/copysign1.c compilation,  -O3 -fomit-frame-pointer -funroll-loops
gcc.c-torture/execute/ieee/copysign1.c compilation,  -O3 -g
gcc.c-torture/execute/ieee/copysign1.c compilation,  -Os
gcc.c-torture/execute/ieee/copysign2.c compilation,  -O0

You can reproduce it with:

clang gcc.c-torture/execute/ieee/copysign1.c -w -fnested-functions -O0 -ffloat-store -fno-show-column -Wl,-multiply_defined,suppress -lm -o copysign1.x0

The result is:
fatal error: error in backend: Cannot select: 0x10213c310: f80,glue = X86ISD::CMOV 0x10213c510, 0x10213c610, 0x10213c810, 0x102137310 [ID=25]
  0x10213c510: f80 = fabs 0x10213bf10 [ID=22]
    0x10213bf10: f80,ch = load 0x102137010, 0x10213bb10, 0x10213ba10<LD10[%x.addr](align=16)> [ORD=7] [ID=20]
      0x10213bb10: i64 = FrameIndex<0> [ORD=5] [ID=2]
      0x10213ba10: i64 = undef [ORD=5] [ID=3]
  0x10213c610: f80 = fneg 0x10213c510 [ID=24]
    0x10213c510: f80 = fabs 0x10213bf10 [ID=22]
      0x10213bf10: f80,ch = load 0x102137010, 0x10213bb10, 0x10213ba10<LD10[%x.addr](align=16)> [ORD=7] [ID=20]
        0x10213bb10: i64 = FrameIndex<0> [ORD=5] [ID=2]
        0x10213ba10: i64 = undef [ORD=5] [ID=3]
  0x10213c810: i8 = Constant<15> [ID=12]
  0x102137310: i32 = X86ISD::CMP 0x10213c110, 0x10213c210 [ID=23]
    0x10213c110: i64 = shl 0x102137510, 0x10213c010 [ID=21]
      0x102137510: i64,ch = load 0x102136e10, 0x102143310, 0x10213ba10<LD8[FixedStack2+8]> [ID=19]
        0x102143310: i64 = or 0x102137710, 0x10213bc10 [ID=15]
          0x102137710: i64 = FrameIndex<2> [ID=8]
          0x10213bc10: i64 = Constant<8> [ID=9]
        0x10213ba10: i64 = undef [ORD=5] [ID=3]
      0x10213c010: i8 = Constant<48> [ID=10]
    0x10213c210: i64 = Constant<0> [ID=11]
In function: cl
compiler exited with status 1

On 10 Aug 2012, at 12:58 PM, Michael Liao <michael.liao at intel.com> wrote:

> Author: hliao
> Date: Fri Aug 10 14:58:13 2012
> New Revision: 161687
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=161687&view=rev
> Log:
> add X86-specific DAG optimization to simplify boolean test
> 
> - if a boolean test (X86ISD::CMP or X86ISD:SUB) checks a boolean value
>  generated from X86ISD::SETCC, try to simplify the boolean value
>  generation and checking by reusing the original EFLAGS with proper
>  condition code
> - add hooks to X86 specific SETCC/BRCOND/CMOV, the major 3 places
>  consuming EFLAGS
> 
> part of patches fixing PR12312
> 
> 
> Added:
>    llvm/trunk/test/CodeGen/X86/bool-simplify.ll
> Modified:
>    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> 
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=161687&r1=161686&r2=161687&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Aug 10 14:58:13 2012
> @@ -13782,6 +13782,72 @@
>   return SDValue();
> }
> 
> +// Check whether a boolean test is testing a boolean value generated by
> +// X86ISD::SETCC. If so, return the operand of that SETCC and proper condition
> +// code.
> +//
> +// Simplify the following patterns:
> +// (Op (CMP (SETCC Cond EFLAGS) 1) EQ) or
> +// (Op (CMP (SETCC Cond EFLAGS) 0) NEQ)
> +// to (Op EFLAGS Cond)
> +//
> +// (Op (CMP (SETCC Cond EFLAGS) 0) EQ) or
> +// (Op (CMP (SETCC Cond EFLAGS) 1) NEQ)
> +// to (Op EFLAGS !Cond)
> +//
> +// where Op could be BRCOND or CMOV.
> +//
> +static SDValue BoolTestSetCCCombine(SDValue Cmp, X86::CondCode &CC) {
> +  // Quit if not CMP and SUB with its value result used.
> +  if (Cmp.getOpcode() != X86ISD::CMP &&
> +      (Cmp.getOpcode() != X86ISD::SUB || Cmp.getNode()->hasAnyUseOfValue(0)))
> +      return SDValue();
> +
> +  // Quit if not used as a boolean value.
> +  if (CC != X86::COND_E && CC != X86::COND_NE)
> +    return SDValue();
> +
> +  // Check CMP operands. One of them should be 0 or 1 and the other should be
> +  // an SetCC or extended from it.
> +  SDValue Op1 = Cmp.getOperand(0);
> +  SDValue Op2 = Cmp.getOperand(1);
> +
> +  SDValue SetCC;
> +  const ConstantSDNode* C = 0;
> +  bool needOppositeCond = (CC == X86::COND_E);
> +
> +  if ((C = dyn_cast<ConstantSDNode>(Op1)))
> +    SetCC = Op2;
> +  else if ((C = dyn_cast<ConstantSDNode>(Op2)))
> +    SetCC = Op1;
> +  else // Quit if all operands are not constants.
> +    return SDValue();
> +
> +  if (C->getZExtValue() == 1)
> +    needOppositeCond = !needOppositeCond;
> +  else if (C->getZExtValue() != 0)
> +    // Quit if the constant is neither 0 or 1.
> +    return SDValue();
> +
> +  // Skip 'zext' node.
> +  if (SetCC.getOpcode() == ISD::ZERO_EXTEND)
> +    SetCC = SetCC.getOperand(0);
> +
> +  // Quit if not SETCC.
> +  // FIXME: So far we only handle the boolean value generated from SETCC. If
> +  // there is other ways to generate boolean values, we need handle them here
> +  // as well.
> +  if (SetCC.getOpcode() != X86ISD::SETCC)
> +    return SDValue();
> +
> +  // Set the condition code or opposite one if necessary.
> +  CC = X86::CondCode(SetCC.getConstantOperandVal(0));
> +  if (needOppositeCond)
> +    CC = X86::GetOppositeBranchCondition(CC);
> +
> +  return SetCC.getOperand(1);
> +}
> +
> /// Optimize X86ISD::CMOV [LHS, RHS, CONDCODE (e.g. X86::COND_NE), CONDVAL]
> static SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG,
>                                   TargetLowering::DAGCombinerInfo &DCI) {
> @@ -13795,6 +13861,7 @@
>   SDValue TrueOp = N->getOperand(1);
>   X86::CondCode CC = (X86::CondCode)N->getConstantOperandVal(2);
>   SDValue Cond = N->getOperand(3);
> +
>   if (CC == X86::COND_E || CC == X86::COND_NE) {
>     switch (Cond.getOpcode()) {
>     default: break;
> @@ -13806,6 +13873,16 @@
>     }
>   }
> 
> +  SDValue Flags;
> +
> +  Flags = BoolTestSetCCCombine(Cond, CC);
> +  if (Flags.getNode()) {
> +    SDValue Ops[] = { FalseOp, TrueOp,
> +                      DAG.getConstant(CC, MVT::i8), Flags };
> +    return DAG.getNode(X86ISD::CMOV, DL, N->getVTList(),
> +                       Ops, array_lengthof(Ops));
> +  }
> +
>   // If this is a select between two integer constants, try to do some
>   // optimizations.  Note that the operands are ordered the opposite of SELECT
>   // operands.
> @@ -15285,19 +15362,50 @@
> 
> // Optimize  RES = X86ISD::SETCC CONDCODE, EFLAG_INPUT
> static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG &DAG) {
> -  unsigned X86CC = N->getConstantOperandVal(0);
> -  SDValue EFLAG = N->getOperand(1);
>   DebugLoc DL = N->getDebugLoc();
> +  X86::CondCode CC = X86::CondCode(N->getConstantOperandVal(0));
> +  SDValue EFLAGS = N->getOperand(1);
> 
>   // Materialize "setb reg" as "sbb reg,reg", since it can be extended without
>   // a zext and produces an all-ones bit which is more useful than 0/1 in some
>   // cases.
> -  if (X86CC == X86::COND_B)
> +  if (CC == X86::COND_B)
>     return DAG.getNode(ISD::AND, DL, MVT::i8,
>                        DAG.getNode(X86ISD::SETCC_CARRY, DL, MVT::i8,
> -                                   DAG.getConstant(X86CC, MVT::i8), EFLAG),
> +                                   DAG.getConstant(CC, MVT::i8), EFLAGS),
>                        DAG.getConstant(1, MVT::i8));
> 
> +  SDValue Flags;
> +
> +  Flags = BoolTestSetCCCombine(EFLAGS, CC);
> +  if (Flags.getNode()) {
> +    SDValue Cond = DAG.getConstant(CC, MVT::i8);
> +    return DAG.getNode(X86ISD::SETCC, DL, N->getVTList(), Cond, Flags);
> +  }
> +
> +  return SDValue();
> +}
> +
> +// Optimize branch condition evaluation.
> +//
> +static SDValue PerformBrCondCombine(SDNode *N, SelectionDAG &DAG,
> +                                    TargetLowering::DAGCombinerInfo &DCI,
> +                                    const X86Subtarget *Subtarget) {
> +  DebugLoc DL = N->getDebugLoc();
> +  SDValue Chain = N->getOperand(0);
> +  SDValue Dest = N->getOperand(1);
> +  SDValue EFLAGS = N->getOperand(3);
> +  X86::CondCode CC = X86::CondCode(N->getConstantOperandVal(2));
> +
> +  SDValue Flags;
> +
> +  Flags = BoolTestSetCCCombine(EFLAGS, CC);
> +  if (Flags.getNode()) {
> +    SDValue Cond = DAG.getConstant(CC, MVT::i8);
> +    return DAG.getNode(X86ISD::BRCOND, DL, N->getVTList(), Chain, Dest, Cond,
> +                       Flags);
> +  }
> +
>   return SDValue();
> }
> 
> @@ -15515,6 +15623,7 @@
>   case ISD::TRUNCATE:       return PerformTruncateCombine(N, DAG, DCI);
>   case ISD::SETCC:          return PerformISDSETCCCombine(N, DAG);
>   case X86ISD::SETCC:       return PerformSETCCCombine(N, DAG);
> +  case X86ISD::BRCOND:      return PerformBrCondCombine(N, DAG, DCI, Subtarget);
>   case X86ISD::SHUFP:       // Handle all target specific shuffles
>   case X86ISD::PALIGN:
>   case X86ISD::UNPCKH:
> 
> Added: llvm/trunk/test/CodeGen/X86/bool-simplify.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/bool-simplify.ll?rev=161687&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/bool-simplify.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/bool-simplify.ll Fri Aug 10 14:58:13 2012
> @@ -0,0 +1,42 @@
> +; RUN: llc < %s -march=x86-64 -mattr=+sse41,-avx | FileCheck %s
> +
> +define i32 @foo(<2 x i64> %c, i32 %a, i32 %b) {
> +  %t1 = call i32 @llvm.x86.sse41.ptestz(<2 x i64> %c, <2 x i64> %c)
> +  %t2 = icmp ne i32 %t1, 0
> +  %t3 = select i1 %t2, i32 %a, i32 %b
> +  ret i32 %t3
> +; CHECK: foo
> +; CHECK: ptest
> +; CHECK-NOT: testl
> +; CHECK: cmov
> +; CHECK: ret
> +}
> +
> +define i32 @bar(<2 x i64> %c) {
> +entry:
> +  %0 = call i32 @llvm.x86.sse41.ptestz(<2 x i64> %c, <2 x i64> %c)
> +  %1 = icmp ne i32 %0, 0
> +  br i1 %1, label %if-true-block, label %endif-block
> +if-true-block:                                    ; preds = %entry
> +  ret i32 0
> +endif-block:                                      ; preds = %entry,
> +  ret i32 1
> +; CHECK: bar
> +; CHECK: ptest
> +; CHECK-NOT: testl
> +; CHECK: jne
> +; CHECK: ret
> +}
> +
> +define i32 @bax(<2 x i64> %c) {
> +  %t1 = call i32 @llvm.x86.sse41.ptestz(<2 x i64> %c, <2 x i64> %c)
> +  %t2 = icmp eq i32 %t1, 1
> +  %t3 = zext i1 %t2 to i32
> +  ret i32 %t3
> +; CHECK: bax
> +; CHECK: ptest
> +; CHECK-NOT: cmpl
> +; CHECK: ret
> +}
> +
> +declare i32 @llvm.x86.sse41.ptestz(<2 x i64>, <2 x i64>) nounwind readnone
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-David





More information about the llvm-commits mailing list