Skip to content

Commit c4fc2cb

Browse files
committed
[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.
1 parent f617ab1 commit c4fc2cb

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,8 +956,17 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
956956

957957
break;
958958
}
959-
case Intrinsic::umax:
960959
case Intrinsic::umin: {
960+
Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1);
961+
// umin(x, 1) == zext(x != 0)
962+
if (match(I1, m_One())) {
963+
Value *Zero = Constant::getNullValue(I0->getType());
964+
Value *Cmp = Builder.CreateICmpNE(I0, Zero);
965+
return CastInst::Create(Instruction::ZExt, Cmp, II->getType());
966+
}
967+
LLVM_FALLTHROUGH;
968+
}
969+
case Intrinsic::umax: {
961970
Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1);
962971
Value *X, *Y;
963972
if (match(I0, m_ZExt(m_Value(X))) && match(I1, m_ZExt(m_Value(Y))) &&

llvm/test/Transforms/InstCombine/minmax-intrinsics.ll

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,3 +817,44 @@ define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
817817
%r = call i8 @llvm.smax.i8(i8 %m, i8 127)
818818
ret i8 %r
819819
}
820+
821+
822+
define i8 @umin_non_zero_idiom1(i8 %a) {
823+
; CHECK-LABEL: @umin_non_zero_idiom1(
824+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
825+
; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8
826+
; CHECK-NEXT: ret i8 [[RES]]
827+
;
828+
%res = call i8 @llvm.umin.i8(i8 %a, i8 1)
829+
ret i8 %res
830+
}
831+
832+
define i8 @umin_non_zero_idiom2(i8 %a) {
833+
; CHECK-LABEL: @umin_non_zero_idiom2(
834+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
835+
; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8
836+
; CHECK-NEXT: ret i8 [[RES]]
837+
;
838+
%res = call i8 @llvm.umin.i8(i8 1, i8 %a)
839+
ret i8 %res
840+
}
841+
842+
define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) {
843+
; CHECK-LABEL: @umin_non_zero_idiom3(
844+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
845+
; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
846+
; CHECK-NEXT: ret <3 x i8> [[RES]]
847+
;
848+
%res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)
849+
ret <3 x i8> %res
850+
}
851+
852+
define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) {
853+
; CHECK-LABEL: @umin_non_zero_idiom4(
854+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
855+
; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
856+
; CHECK-NEXT: ret <3 x i8> [[RES]]
857+
;
858+
%res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 undef, i8 undef>)
859+
ret <3 x i8> %res
860+
}

0 commit comments

Comments
 (0)