[instcombine] umin(x, 1) == zext(x != 0)

We already implemented this for the select form, but the intrinsic form was missing.  Note that this doesn't change poison behavior as 1 is non-poison, and the optimized form is still poison exactly when x is.
This commit is contained in:
Philip Reames
2021-06-30 10:18:38 -07:00
parent f617ab1044
commit c4fc2cb5b2
2 changed files with 51 additions and 1 deletions

View File

@@ -956,8 +956,17 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
break;
}
case Intrinsic::umax:
case Intrinsic::umin: {
Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1);
// umin(x, 1) == zext(x != 0)
if (match(I1, m_One())) {
Value *Zero = Constant::getNullValue(I0->getType());
Value *Cmp = Builder.CreateICmpNE(I0, Zero);
return CastInst::Create(Instruction::ZExt, Cmp, II->getType());
}
LLVM_FALLTHROUGH;
}
case Intrinsic::umax: {
Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1);
Value *X, *Y;
if (match(I0, m_ZExt(m_Value(X))) && match(I1, m_ZExt(m_Value(Y))) &&

View File

@@ -817,3 +817,44 @@ define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
%r = call i8 @llvm.smax.i8(i8 %m, i8 127)
ret i8 %r
}
define i8 @umin_non_zero_idiom1(i8 %a) {
; CHECK-LABEL: @umin_non_zero_idiom1(
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8
; CHECK-NEXT: ret i8 [[RES]]
;
%res = call i8 @llvm.umin.i8(i8 %a, i8 1)
ret i8 %res
}
define i8 @umin_non_zero_idiom2(i8 %a) {
; CHECK-LABEL: @umin_non_zero_idiom2(
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8
; CHECK-NEXT: ret i8 [[RES]]
;
%res = call i8 @llvm.umin.i8(i8 1, i8 %a)
ret i8 %res
}
define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) {
; CHECK-LABEL: @umin_non_zero_idiom3(
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
; CHECK-NEXT: ret <3 x i8> [[RES]]
;
%res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)
ret <3 x i8> %res
}
define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) {
; CHECK-LABEL: @umin_non_zero_idiom4(
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
; CHECK-NEXT: ret <3 x i8> [[RES]]
;
%res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 undef, i8 undef>)
ret <3 x i8> %res
}