forked from OSchip/llvm-project
[InstCombine] allow icmp (bit-manipulation-intrinsic(), C) folds for vectors
llvm-svn: 276523
This commit is contained in:
parent
488cb137a9
commit
1271bf9178
|
@ -2355,37 +2355,35 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction *InstCombiner::foldICmpIntrinsicWithConstant(ICmpInst &ICI,
|
Instruction *InstCombiner::foldICmpIntrinsicWithConstant(ICmpInst &ICI) {
|
||||||
Instruction *LHSI,
|
IntrinsicInst *II = dyn_cast<IntrinsicInst>(ICI.getOperand(0));
|
||||||
ConstantInt *RHS) {
|
const APInt *Op1C;
|
||||||
IntrinsicInst *II = dyn_cast<IntrinsicInst>(LHSI);
|
if (!II || !ICI.isEquality() || !match(ICI.getOperand(1), m_APInt(Op1C)))
|
||||||
if (!II || !ICI.isEquality())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Handle icmp {eq|ne} <intrinsic>, intcst.
|
// Handle icmp {eq|ne} <intrinsic>, intcst.
|
||||||
const APInt &RHSV = RHS->getValue();
|
|
||||||
switch (II->getIntrinsicID()) {
|
switch (II->getIntrinsicID()) {
|
||||||
case Intrinsic::bswap:
|
case Intrinsic::bswap:
|
||||||
Worklist.Add(II);
|
Worklist.Add(II);
|
||||||
ICI.setOperand(0, II->getArgOperand(0));
|
ICI.setOperand(0, II->getArgOperand(0));
|
||||||
ICI.setOperand(1, Builder->getInt(RHSV.byteSwap()));
|
ICI.setOperand(1, Builder->getInt(Op1C->byteSwap()));
|
||||||
return &ICI;
|
return &ICI;
|
||||||
case Intrinsic::ctlz:
|
case Intrinsic::ctlz:
|
||||||
case Intrinsic::cttz:
|
case Intrinsic::cttz:
|
||||||
// ctz(A) == bitwidth(a) -> A == 0 and likewise for !=
|
// ctz(A) == bitwidth(a) -> A == 0 and likewise for !=
|
||||||
if (RHSV == RHS->getType()->getBitWidth()) {
|
if (*Op1C == Op1C->getBitWidth()) {
|
||||||
Worklist.Add(II);
|
Worklist.Add(II);
|
||||||
ICI.setOperand(0, II->getArgOperand(0));
|
ICI.setOperand(0, II->getArgOperand(0));
|
||||||
ICI.setOperand(1, ConstantInt::get(RHS->getType(), 0));
|
ICI.setOperand(1, ConstantInt::getNullValue(II->getType()));
|
||||||
return &ICI;
|
return &ICI;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Intrinsic::ctpop:
|
case Intrinsic::ctpop:
|
||||||
// popcount(A) == 0 -> A == 0 and likewise for !=
|
// popcount(A) == 0 -> A == 0 and likewise for !=
|
||||||
if (RHS->isZero()) {
|
if (*Op1C == 0) {
|
||||||
Worklist.Add(II);
|
Worklist.Add(II);
|
||||||
ICI.setOperand(0, II->getArgOperand(0));
|
ICI.setOperand(0, II->getArgOperand(0));
|
||||||
ICI.setOperand(1, RHS);
|
ICI.setOperand(1, ConstantInt::getNullValue(II->getType()));
|
||||||
return &ICI;
|
return &ICI;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3641,6 +3639,10 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
||||||
|
|
||||||
// See if we are doing a comparison between a constant and an instruction that
|
// See if we are doing a comparison between a constant and an instruction that
|
||||||
// can be folded into the comparison.
|
// can be folded into the comparison.
|
||||||
|
|
||||||
|
// FIXME: Use m_APInt instead of dyn_cast<ConstantInt> to allow these
|
||||||
|
// transforms for vectors.
|
||||||
|
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
||||||
// Since the RHS is a ConstantInt (CI), if the left hand side is an
|
// Since the RHS is a ConstantInt (CI), if the left hand side is an
|
||||||
// instruction, see if that instruction also has constants so that the
|
// instruction, see if that instruction also has constants so that the
|
||||||
|
@ -3650,11 +3652,12 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
||||||
return Res;
|
return Res;
|
||||||
if (Instruction *Res = foldICmpEqualityWithConstant(I, LHSI, CI))
|
if (Instruction *Res = foldICmpEqualityWithConstant(I, LHSI, CI))
|
||||||
return Res;
|
return Res;
|
||||||
if (Instruction *Res = foldICmpIntrinsicWithConstant(I, LHSI, CI))
|
|
||||||
return Res;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Instruction *Res = foldICmpIntrinsicWithConstant(I))
|
||||||
|
return Res;
|
||||||
|
|
||||||
// Handle icmp with constant (but not simple integer constant) RHS
|
// Handle icmp with constant (but not simple integer constant) RHS
|
||||||
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
|
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
|
||||||
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
|
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
|
||||||
|
|
|
@ -585,8 +585,7 @@ private:
|
||||||
ConstantInt *RHS);
|
ConstantInt *RHS);
|
||||||
Instruction *foldICmpEqualityWithConstant(ICmpInst &ICI, Instruction *LHS,
|
Instruction *foldICmpEqualityWithConstant(ICmpInst &ICI, Instruction *LHS,
|
||||||
ConstantInt *RHS);
|
ConstantInt *RHS);
|
||||||
Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI, Instruction *LHS,
|
Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI);
|
||||||
ConstantInt *RHS);
|
|
||||||
|
|
||||||
Instruction *OptAndOp(Instruction *Op, ConstantInt *OpRHS,
|
Instruction *OptAndOp(Instruction *Op, ConstantInt *OpRHS,
|
||||||
ConstantInt *AndRHS, BinaryOperator &TheAnd);
|
ConstantInt *AndRHS, BinaryOperator &TheAnd);
|
||||||
|
|
|
@ -316,12 +316,9 @@ entry:
|
||||||
; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c
|
; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c
|
||||||
}
|
}
|
||||||
|
|
||||||
; FIXME: Vectors should get the same folds as scalars.
|
|
||||||
|
|
||||||
define <2 x i1> @ctlz_cmp_vec(<2 x i32> %a) {
|
define <2 x i1> @ctlz_cmp_vec(<2 x i32> %a) {
|
||||||
; CHECK-LABEL: @ctlz_cmp_vec(
|
; CHECK-LABEL: @ctlz_cmp_vec(
|
||||||
; CHECK-NEXT: [[X:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #0
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> %a, zeroinitializer
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[X]], <i32 32, i32 32>
|
|
||||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||||
;
|
;
|
||||||
%x = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) nounwind readnone
|
%x = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) nounwind readnone
|
||||||
|
@ -331,8 +328,7 @@ define <2 x i1> @ctlz_cmp_vec(<2 x i32> %a) {
|
||||||
|
|
||||||
define <2 x i1> @cttz_cmp_vec(<2 x i32> %a) {
|
define <2 x i1> @cttz_cmp_vec(<2 x i32> %a) {
|
||||||
; CHECK-LABEL: @cttz_cmp_vec(
|
; CHECK-LABEL: @cttz_cmp_vec(
|
||||||
; CHECK-NEXT: [[X:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #0
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> %a, zeroinitializer
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[X]], <i32 32, i32 32>
|
|
||||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||||
;
|
;
|
||||||
%x = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) nounwind readnone
|
%x = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) nounwind readnone
|
||||||
|
@ -342,8 +338,7 @@ define <2 x i1> @cttz_cmp_vec(<2 x i32> %a) {
|
||||||
|
|
||||||
define <2 x i1> @ctpop_cmp_vec(<2 x i32> %a) {
|
define <2 x i1> @ctpop_cmp_vec(<2 x i32> %a) {
|
||||||
; CHECK-LABEL: @ctpop_cmp_vec(
|
; CHECK-LABEL: @ctpop_cmp_vec(
|
||||||
; CHECK-NEXT: [[X:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a) #0
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> %a, zeroinitializer
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[X]], zeroinitializer
|
|
||||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||||
;
|
;
|
||||||
%x = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a) nounwind readnone
|
%x = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a) nounwind readnone
|
||||||
|
|
Loading…
Reference in New Issue