Skip to content

Commit 74c047e

Browse files
author
Nikolai Bozhenov
committedOct 18, 2017
Improve lookThroughCast function.
Summary: When we have the following case: %cond = cmp iN %x, CmpConst %tr = trunc iN %x to iK %narrowsel = select i1 %cond, iK %t, iK C We could possibly match only min/max pattern after looking through cast. So it is more profitable if widened C constant will be equal CmpConst. That is why just set widened C constant equal to CmpConst, because there is a further check in this function that trunc CmpConst == C. Also description for lookTroughCast function was added. Reviewers: spatel Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D38536 Patch by: Artur Gainullin <artur.gainullin@intel.com> llvm-svn: 316070
1 parent 480892b commit 74c047e

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed
 

‎llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4320,6 +4320,20 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
43204320
return matchFastFloatClamp(Pred, CmpLHS, CmpRHS, TrueVal, FalseVal, LHS, RHS);
43214321
}
43224322

4323+
/// Helps to match a select pattern in case of a type mismatch.
4324+
///
4325+
/// The function processes the case when type of true and false values of a
4326+
/// select instruction differs from type of the cmp instruction operands because
4327+
/// of a cast instructon. The function checks if it is legal to move the cast
4328+
/// operation after "select". If yes, it returns the new second value of
4329+
/// "select" (with the assumption that cast is moved):
4330+
/// 1. As operand of cast instruction when both values of "select" are same cast
4331+
/// instructions.
4332+
/// 2. As restored constant (by applying reverse cast operation) when the first
4333+
/// value of the "select" is a cast operation and the second value is a
4334+
/// constant.
4335+
/// NOTE: We return only the new second value because the first value could be
4336+
/// accessed as operand of cast instruction.
43234337
static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2,
43244338
Instruction::CastOps *CastOp) {
43254339
auto *Cast1 = dyn_cast<CastInst>(V1);
@@ -4350,7 +4364,33 @@ static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2,
43504364
CastedTo = ConstantExpr::getTrunc(C, SrcTy, true);
43514365
break;
43524366
case Instruction::Trunc:
4353-
CastedTo = ConstantExpr::getIntegerCast(C, SrcTy, CmpI->isSigned());
4367+
Constant *CmpConst;
4368+
if (match(CmpI->getOperand(1), m_Constant(CmpConst))) {
4369+
// Here we have the following case:
4370+
//
4371+
// %cond = cmp iN %x, CmpConst
4372+
// %tr = trunc iN %x to iK
4373+
// %narrowsel = select i1 %cond, iK %t, iK C
4374+
//
4375+
// We can always move trunc after select operation:
4376+
//
4377+
// %cond = cmp iN %x, CmpConst
4378+
// %widesel = select i1 %cond, iN %x, iN CmpConst
4379+
// %tr = trunc iN %widesel to iK
4380+
//
4381+
// Note that C could be extended in any way because we don't care about
4382+
// upper bits after truncation. It can't be abs pattern, because it would
4383+
// look like:
4384+
//
4385+
// select i1 %cond, x, -x.
4386+
//
4387+
// So only min/max pattern could be matched. Such match requires widened C
4388+
// == CmpConst. That is why set widened C = CmpConst, condition trunc
4389+
// CmpConst == C is checked below.
4390+
CastedTo = CmpConst;
4391+
} else {
4392+
CastedTo = ConstantExpr::getIntegerCast(C, SrcTy, CmpI->isSigned());
4393+
}
43544394
break;
43554395
case Instruction::FPTrunc:
43564396
CastedTo = ConstantExpr::getFPExtend(C, SrcTy, true);

‎llvm/test/Transforms/InstCombine/minmax-fold.ll

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,3 +688,57 @@ define <8 x float> @bitcast_vector_umin(<8 x float> %x, <8 x float> %y) {
688688
%sel = select <8 x i1> %cmp, <8 x float> %x, <8 x float> %y
689689
ret <8 x float> %sel
690690
}
691+
692+
; Check that we look through cast and recognize min idiom.
693+
define zeroext i8 @look_through_cast1(i32 %x) {
694+
; CHECK-LABEL: @look_through_cast1(
695+
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 511
696+
; CHECK-NEXT: [[RES1:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 511
697+
; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[RES1]] to i8
698+
; CHECK-NEXT: ret i8 [[TMP2]]
699+
;
700+
%cmp1 = icmp slt i32 %x, 511
701+
%x_trunc = trunc i32 %x to i8
702+
%res = select i1 %cmp1, i8 %x_trunc, i8 255
703+
ret i8 %res
704+
}
705+
706+
; Check that we look through cast but min is not recognized.
707+
define zeroext i8 @look_through_cast2(i32 %x) {
708+
; CHECK-LABEL: @look_through_cast2(
709+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X:%.*]], 510
710+
; CHECK-NEXT: [[X_TRUNC:%.*]] = trunc i32 [[X]] to i8
711+
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP1]], i8 [[X_TRUNC]], i8 -1
712+
; CHECK-NEXT: ret i8 [[RES]]
713+
;
714+
%cmp1 = icmp slt i32 %x, 510
715+
%x_trunc = trunc i32 %x to i8
716+
%res = select i1 %cmp1, i8 %x_trunc, i8 255
717+
ret i8 %res
718+
}
719+
720+
define <2 x i8> @min_through_cast_vec1(<2 x i32> %x) {
721+
; CHECK-LABEL: @min_through_cast_vec1(
722+
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 510, i32 511>
723+
; CHECK-NEXT: [[RES1:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[X]], <2 x i32> <i32 510, i32 511>
724+
; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i32> [[RES1]] to <2 x i8>
725+
; CHECK-NEXT: ret <2 x i8> [[TMP2]]
726+
;
727+
%cmp = icmp slt <2 x i32> %x, <i32 510, i32 511>
728+
%x_trunc = trunc <2 x i32> %x to <2 x i8>
729+
%res = select <2 x i1> %cmp, <2 x i8> %x_trunc, <2 x i8> <i8 254, i8 255>
730+
ret <2 x i8> %res
731+
}
732+
733+
define <2 x i8> @min_through_cast_vec2(<2 x i32> %x) {
734+
; CHECK-LABEL: @min_through_cast_vec2(
735+
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 511, i32 511>
736+
; CHECK-NEXT: [[RES1:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[X]], <2 x i32> <i32 511, i32 511>
737+
; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i32> [[RES1]] to <2 x i8>
738+
; CHECK-NEXT: ret <2 x i8> [[TMP2]]
739+
;
740+
%cmp = icmp slt <2 x i32> %x, <i32 511, i32 511>
741+
%x_trunc = trunc <2 x i32> %x to <2 x i8>
742+
%res = select <2 x i1> %cmp, <2 x i8> %x_trunc, <2 x i8> <i8 255, i8 255>
743+
ret <2 x i8> %res
744+
}

0 commit comments

Comments
 (0)
Please sign in to comment.