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:
parent
d5928b4916
commit
fa04d281c5
@ -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: {
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user