1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[InstCombine] hoist min/max intrinsics above select with constant op

This is an extension of the handling for unary intrinsics and
follows the logic that we use for binary ops.

We don't canonicalize to min/max intrinsics yet, but this might
help unlock other folds seen in D98152.
This commit is contained in:
Sanjay Patel 2021-06-27 09:58:28 -04:00
parent d5928b4916
commit fa04d281c5
3 changed files with 26 additions and 22 deletions

View File

@ -1041,6 +1041,11 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Instruction *Sel = foldClampRangeOfTwo(II, Builder))
return Sel;
if (match(I1, m_ImmConstant()))
if (auto *Sel = dyn_cast<SelectInst>(I0))
if (Instruction *R = FoldOpIntoSelect(*II, Sel))
return R;
break;
}
case Intrinsic::bswap: {

View File

@ -942,13 +942,16 @@ static Value *foldOperationIntoSelectOperand(Instruction &I, Value *SO,
assert(canConstantFoldCallTo(II, cast<Function>(II->getCalledOperand())) &&
"Expected constant-foldable intrinsic");
Intrinsic::ID IID = II->getIntrinsicID();
SmallVector<Value *, 2> Args = {SO};
if (II->getNumArgOperands() == 1)
return Builder.CreateUnaryIntrinsic(IID, SO);
// Propagate the zero-is-undef argument to the new instruction.
if (IID == Intrinsic::ctlz || IID == Intrinsic::cttz)
Args.push_back(II->getArgOperand(1));
return Builder.CreateIntrinsic(IID, I.getType(), Args);
// This works for real binary ops like min/max (where we always expect the
// constant operand to be canonicalized as op1) and unary ops with a bonus
// constant argument like ctlz/cttz.
// TODO: Handle non-commutative binary intrinsics as below for binops.
assert(II->getNumArgOperands() == 2 && "Expected binary intrinsic");
assert(isa<Constant>(II->getArgOperand(1)) && "Expected constant operand");
return Builder.CreateBinaryIntrinsic(IID, SO, II->getArgOperand(1));
}
assert(I.isBinaryOp() && "Unexpected opcode for select folding");

View File

@ -111,8 +111,7 @@ define i5 @umin_umin_common_op_10_uses(i1 %cond, i5 %x, i5 %y, i5 %z, i5* %p1, i
define i5 @smin_select_const_const(i1 %b) {
; CHECK-LABEL: @smin_select_const_const(
; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i5 -3, i5 8
; CHECK-NEXT: [[C:%.*]] = call i5 @llvm.smin.i5(i5 [[S]], i5 5)
; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 -3, i5 5
; CHECK-NEXT: ret i5 [[C]]
;
%s = select i1 %b, i5 -3, i5 8
@ -122,8 +121,7 @@ define i5 @smin_select_const_const(i1 %b) {
define <2 x i8> @smax_select_const_const(<2 x i1> %b) {
; CHECK-LABEL: @smax_select_const_const(
; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> <i8 1, i8 3>, <2 x i8> <i8 5, i8 43>
; CHECK-NEXT: [[C:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[S]], <2 x i8> <i8 0, i8 42>)
; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> <i8 1, i8 42>, <2 x i8> <i8 5, i8 43>
; CHECK-NEXT: ret <2 x i8> [[C]]
;
%s = select <2 x i1> %b, <2 x i8> <i8 1, i8 3>, <2 x i8> <i8 5, i8 43>
@ -133,8 +131,7 @@ define <2 x i8> @smax_select_const_const(<2 x i1> %b) {
define i5 @umin_select_const_const(i1 %b) {
; CHECK-LABEL: @umin_select_const_const(
; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i5 8, i5 3
; CHECK-NEXT: [[C:%.*]] = call i5 @llvm.umin.i5(i5 [[S]], i5 4)
; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 4, i5 3
; CHECK-NEXT: ret i5 [[C]]
;
%s = select i1 %b, i5 8, i5 3
@ -144,8 +141,7 @@ define i5 @umin_select_const_const(i1 %b) {
define <3 x i5> @umax_select_const_const(<3 x i1> %b) {
; CHECK-LABEL: @umax_select_const_const(
; CHECK-NEXT: [[S:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> <i5 7, i5 8, i5 9>
; CHECK-NEXT: [[C:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[S]], <3 x i5> <i5 5, i5 8, i5 -16>)
; CHECK-NEXT: [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 5, i5 8, i5 -16>, <3 x i5> <i5 7, i5 8, i5 -16>
; CHECK-NEXT: ret <3 x i5> [[C]]
;
%s = select <3 x i1> %b, <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> <i5 7, i5 8, i5 9>
@ -155,8 +151,8 @@ define <3 x i5> @umax_select_const_const(<3 x i1> %b) {
define i5 @smin_select_const(i1 %b, i5 %x) {
; CHECK-LABEL: @smin_select_const(
; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i5 -3, i5 [[X:%.*]]
; CHECK-NEXT: [[C:%.*]] = call i5 @llvm.smin.i5(i5 [[S]], i5 5)
; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 5)
; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 -3, i5 [[TMP1]]
; CHECK-NEXT: ret i5 [[C]]
;
%s = select i1 %b, i5 -3, i5 %x
@ -166,8 +162,8 @@ define i5 @smin_select_const(i1 %b, i5 %x) {
define <2 x i8> @smax_select_const(<2 x i1> %b, <2 x i8> %x) {
; CHECK-LABEL: @smax_select_const(
; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> [[X:%.*]], <2 x i8> <i8 5, i8 43>
; CHECK-NEXT: [[C:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[S]], <2 x i8> <i8 0, i8 42>)
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> <i8 0, i8 42>)
; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> [[TMP1]], <2 x i8> <i8 5, i8 43>
; CHECK-NEXT: ret <2 x i8> [[C]]
;
%s = select <2 x i1> %b, <2 x i8> %x, <2 x i8> <i8 5, i8 43>
@ -177,8 +173,8 @@ define <2 x i8> @smax_select_const(<2 x i1> %b, <2 x i8> %x) {
define i5 @umin_select_const(i1 %b, i5 %x) {
; CHECK-LABEL: @umin_select_const(
; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i5 [[X:%.*]], i5 3
; CHECK-NEXT: [[C:%.*]] = call i5 @llvm.umin.i5(i5 [[S]], i5 4)
; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 4)
; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 [[TMP1]], i5 3
; CHECK-NEXT: ret i5 [[C]]
;
%s = select i1 %b, i5 %x, i5 3
@ -188,8 +184,8 @@ define i5 @umin_select_const(i1 %b, i5 %x) {
define <3 x i5> @umax_select_const(<3 x i1> %b, <3 x i5> %x) {
; CHECK-LABEL: @umax_select_const(
; CHECK-NEXT: [[S:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> [[X:%.*]]
; CHECK-NEXT: [[C:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[S]], <3 x i5> <i5 5, i5 8, i5 1>)
; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 5, i5 8, i5 1>)
; CHECK-NEXT: [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 5, i5 8, i5 4>, <3 x i5> [[TMP1]]
; CHECK-NEXT: ret <3 x i5> [[C]]
;
%s = select <3 x i1> %b, <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> %x