diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 21 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.h | 12 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/cmp.ll | 21 | 
4 files changed, 58 insertions, 4 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 891d401201f..9902ed76fa7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2322,6 +2322,27 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,            }          }        } + +    if (!isLegalICmpImmediate(C1.getSExtValue())) { +      // (X & -256) == 256 -> (X >> 8) == 1 +      if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && +          N0.getOpcode() == ISD::AND && N0.hasOneUse()) { +        if (ConstantSDNode *AndRHS = +            dyn_cast<ConstantSDNode>(N0.getOperand(1))) { +          const APInt &AndRHSC = AndRHS->getAPIntValue(); +          if ((-AndRHSC).isPowerOf2() && (AndRHSC & C1) == C1) { +            unsigned ShiftBits = AndRHSC.countTrailingZeros(); +            EVT ShiftTy = DCI.isBeforeLegalize() ? +              getPointerTy() : getShiftAmountTy(N0.getValueType()); +            EVT CmpTy = N0.getValueType(); +            SDValue Shift = DAG.getNode(ISD::SRL, dl, CmpTy, N0.getOperand(0), +                                        DAG.getConstant(ShiftBits, ShiftTy)); +            SDValue CmpRHS = DAG.getConstant(C1.lshr(ShiftBits), CmpTy); +            return DAG.getSetCC(dl, VT, Shift, CmpRHS, Cond); +          } +        } +      } +    }    }    if (isa<ConstantFPSDNode>(N0.getNode())) { diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 1d72aad6754..347f1977e71 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -11384,6 +11384,14 @@ bool X86TargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const {    return true;  } +bool X86TargetLowering::isLegalICmpImmediate(int64_t Imm) const { +  return Imm == (int32_t)Imm; +} + +bool X86TargetLowering::isLegalAddImmediate(int64_t Imm) const { +  return Imm == (int32_t)Imm; +} +  bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {    if (!VT1.isInteger() || !VT2.isInteger())      return false; diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index 41bdd06f37e..1afe68ad67f 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -568,6 +568,18 @@ namespace llvm {      /// by AM is legal for this target, for a load/store of the specified type.      virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty)const; +    /// isLegalICmpImmediate - Return true if the specified immediate is legal +    /// icmp immediate, that is the target has icmp instructions which can +    /// compare a register against the immediate without having to materialize +    /// the immediate into a register. +    virtual bool isLegalICmpImmediate(int64_t Imm) const; + +    /// isLegalAddImmediate - Return true if the specified immediate is legal +    /// add immediate, that is the target has add instructions which can +    /// add a register and the immediate without having to materialize +    /// the immediate into a register. +    virtual bool isLegalAddImmediate(int64_t Imm) const; +      /// isTruncateFree - Return true if it's free to truncate a value of      /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in      /// register EAX to i16 by referencing its sub-register AX. diff --git a/llvm/test/CodeGen/X86/cmp.ll b/llvm/test/CodeGen/X86/cmp.ll index c9c85abad85..8343cece459 100644 --- a/llvm/test/CodeGen/X86/cmp.ll +++ b/llvm/test/CodeGen/X86/cmp.ll @@ -91,7 +91,7 @@ F:  }  ; rdar://11866926 -define i32 @test7(i64 %res) nounwind uwtable readnone ssp { +define i32 @test7(i64 %res) nounwind {  entry:  ; CHECK: test7:  ; CHECK-NOT: movabsq @@ -103,7 +103,7 @@ entry:    ret i32 %lnot.ext  } -define i32 @test8(i64 %res) nounwind uwtable readnone ssp { +define i32 @test8(i64 %res) nounwind {  entry:  ; CHECK: test8:  ; CHECK-NOT: movabsq @@ -114,7 +114,7 @@ entry:    ret i32 %lnot.ext  } -define i32 @test9(i64 %res) nounwind uwtable readnone ssp { +define i32 @test9(i64 %res) nounwind {  entry:  ; CHECK: test9:  ; CHECK-NOT: movabsq @@ -126,7 +126,7 @@ entry:    ret i32 %lnot.ext  } -define i32 @test10(i64 %res) nounwind uwtable readnone ssp { +define i32 @test10(i64 %res) nounwind {  entry:  ; CHECK: test10:  ; CHECK-NOT: movabsq @@ -138,3 +138,16 @@ entry:    ret i32 %lnot.ext  } +; rdar://9758774 +define i32 @test11(i64 %l) nounwind { +entry: +; CHECK: test11: +; CHECK-NOT: movabsq +; CHECK-NOT: andq +; CHECK: shrq $47, %rdi +; CHECK: cmpq $1, %rdi +  %shr.mask = and i64 %l, -140737488355328 +  %cmp = icmp eq i64 %shr.mask, 140737488355328 +  %conv = zext i1 %cmp to i32 +  ret i32 %conv +}  | 

