[llvm] 463ea28 - [InstCombine] Fold comparison of integers by parts
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon May 10 13:23:04 PDT 2021
Author: Nikita Popov
Date: 2021-05-10T22:22:39+02:00
New Revision: 463ea28e96c78f484d9ea44912d9bc70ff084c86
URL: https://github.com/llvm/llvm-project/commit/463ea28e96c78f484d9ea44912d9bc70ff084c86
DIFF: https://github.com/llvm/llvm-project/commit/463ea28e96c78f484d9ea44912d9bc70ff084c86.diff
LOG: [InstCombine] Fold comparison of integers by parts
Let's say you represent (i32, i32) as an i64 from which the parts
are extracted with lshr/trunc. Then, if you compare two tuples by
parts you get something like A[0] == B[0] && A[1] == B[1], just
that the part extraction happens by lshr/trunc and not a narrow
load or similar.
The fold implemented here reduces such equality comparisons by
converting them into a comparison on a larger part of the integer
(which might be the whole integer). It handles both the "and of eq"
and the conjugated "or of ne" case.
I'm being conservative with one-use for now, though this could be
relaxed if profitable (the base pattern converts 11 instructions
into 5 instructions, but there's quite a few variations on how it
can play out).
Differential Revision: https://reviews.llvm.org/D101232
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/eq-of-parts.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index e2671734d0935..51bdbb6206a8d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1076,6 +1076,87 @@ static Value *foldUnsignedUnderflowCheck(ICmpInst *ZeroICmp,
return nullptr;
}
+struct IntPart {
+ Value *From;
+ unsigned StartBit;
+ unsigned NumBits;
+};
+
+/// Match an extraction of bits from an integer.
+static Optional<IntPart> matchIntPart(Value *V) {
+ Value *X;
+ if (!match(V, m_OneUse(m_Trunc(m_Value(X)))))
+ return None;
+
+ unsigned NumOriginalBits = X->getType()->getScalarSizeInBits();
+ unsigned NumExtractedBits = V->getType()->getScalarSizeInBits();
+ Value *Y;
+ const APInt *Shift;
+ // For a trunc(lshr Y, Shift) pattern, make sure we're only extracting bits
+ // from Y, not any shifted-in zeroes.
+ if (match(X, m_OneUse(m_LShr(m_Value(Y), m_APInt(Shift)))) &&
+ Shift->ule(NumOriginalBits - NumExtractedBits))
+ return {{Y, (unsigned)Shift->getZExtValue(), NumExtractedBits}};
+ return {{X, 0, NumExtractedBits}};
+}
+
+/// Materialize an extraction of bits from an integer in IR.
+static Value *extractIntPart(const IntPart &P, IRBuilderBase &Builder) {
+ Value *V = P.From;
+ if (P.StartBit)
+ V = Builder.CreateLShr(V, P.StartBit);
+ Type *TruncTy = V->getType()->getWithNewBitWidth(P.NumBits);
+ if (TruncTy != V->getType())
+ V = Builder.CreateTrunc(V, TruncTy);
+ return V;
+}
+
+/// (icmp eq X0, Y0) & (icmp eq X1, Y1) -> icmp eq X01, Y01
+/// (icmp ne X0, Y0) | (icmp ne X1, Y1) -> icmp ne X01, Y01
+/// where X0, X1 and Y0, Y1 are adjacent parts extracted from an integer.
+static Value *foldEqOfParts(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
+ InstCombiner::BuilderTy &Builder) {
+ if (!Cmp0->hasOneUse() || !Cmp1->hasOneUse())
+ return nullptr;
+
+ CmpInst::Predicate Pred = IsAnd ? CmpInst::ICMP_EQ : CmpInst::ICMP_NE;
+ if (Cmp0->getPredicate() != Pred || Cmp1->getPredicate() != Pred)
+ return nullptr;
+
+ Optional<IntPart> L0 = matchIntPart(Cmp0->getOperand(0));
+ Optional<IntPart> R0 = matchIntPart(Cmp0->getOperand(1));
+ Optional<IntPart> L1 = matchIntPart(Cmp1->getOperand(0));
+ Optional<IntPart> R1 = matchIntPart(Cmp1->getOperand(1));
+ if (!L0 || !R0 || !L1 || !R1)
+ return nullptr;
+
+ // Make sure the LHS/RHS compare a part of the same value, possibly after
+ // an operand swap.
+ if (L0->From != L1->From || R0->From != R1->From) {
+ if (L0->From != R1->From || R0->From != L1->From)
+ return nullptr;
+ std::swap(L1, R1);
+ }
+
+ // Make sure the extracted parts are adjacent, canonicalizing to L0/R0 being
+ // the low part and L1/R1 being the high part.
+ if (L0->StartBit + L0->NumBits != L1->StartBit ||
+ R0->StartBit + R0->NumBits != R1->StartBit) {
+ if (L1->StartBit + L1->NumBits != L0->StartBit ||
+ R1->StartBit + R1->NumBits != R0->StartBit)
+ return nullptr;
+ std::swap(L0, L1);
+ std::swap(R0, R1);
+ }
+
+ // We can simplify to a comparison of these larger parts of the integers.
+ IntPart L = {L0->From, L0->StartBit, L0->NumBits + L1->NumBits};
+ IntPart R = {R0->From, R0->StartBit, R0->NumBits + R1->NumBits};
+ Value *LValue = extractIntPart(L, Builder);
+ Value *RValue = extractIntPart(R, Builder);
+ return Builder.CreateICmp(Pred, LValue, RValue);
+}
+
/// Reduce logic-of-compares with equality to a constant by substituting a
/// common operand with the constant. Callers are expected to call this with
/// Cmp0/Cmp1 switched to handle logic op commutativity.
@@ -1181,6 +1262,9 @@ Value *InstCombinerImpl::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS,
foldUnsignedUnderflowCheck(RHS, LHS, /*IsAnd=*/true, Q, Builder))
return X;
+ if (Value *X = foldEqOfParts(LHS, RHS, /*IsAnd=*/true, Builder))
+ return X;
+
// This only handles icmp of constants: (icmp1 A, C1) & (icmp2 B, C2).
Value *LHS0 = LHS->getOperand(0), *RHS0 = RHS->getOperand(0);
@@ -2411,6 +2495,9 @@ Value *InstCombinerImpl::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
foldUnsignedUnderflowCheck(RHS, LHS, /*IsAnd=*/false, Q, Builder))
return X;
+ if (Value *X = foldEqOfParts(LHS, RHS, /*IsAnd=*/false, Builder))
+ return X;
+
// (icmp ne A, 0) | (icmp ne B, 0) --> (icmp ne (A|B), 0)
// TODO: Remove this when foldLogOpOfMaskedICmps can handle vectors.
if (PredL == ICmpInst::ICMP_NE && match(LHS1, m_Zero()) &&
diff --git a/llvm/test/Transforms/InstCombine/eq-of-parts.ll b/llvm/test/Transforms/InstCombine/eq-of-parts.ll
index 5e8d70914dc87..3e7ac275e3847 100644
--- a/llvm/test/Transforms/InstCombine/eq-of-parts.ll
+++ b/llvm/test/Transforms/InstCombine/eq-of-parts.ll
@@ -10,16 +10,10 @@ declare void @use.i1(i1)
define i1 @eq_10(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_10(
-; CHECK-NEXT: [[X_0:%.*]] = trunc i32 [[X:%.*]] to i8
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[Y_0:%.*]] = trunc i32 [[Y:%.*]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[C_0:%.*]] = icmp eq i8 [[X_0]], [[Y_0]]
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_10:%.*]] = and i1 [[C_0]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_10]]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i16 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: ret i1 [[TMP3]]
;
%x.0 = trunc i32 %x to i8
%x.321 = lshr i32 %x, 8
@@ -35,22 +29,10 @@ define i1 @eq_10(i32 %x, i32 %y) {
define i1 @eq_210(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_210(
-; CHECK-NEXT: [[X_0:%.*]] = trunc i32 [[X:%.*]] to i8
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_0:%.*]] = trunc i32 [[Y:%.*]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_0:%.*]] = icmp eq i8 [[X_0]], [[Y_0]]
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_10:%.*]] = and i1 [[C_0]], [[C_1]]
-; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_10]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i24
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i24
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i24 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: ret i1 [[TMP3]]
;
%x.0 = trunc i32 %x to i8
%x.321 = lshr i32 %x, 8
@@ -72,28 +54,8 @@ define i1 @eq_210(i32 %x, i32 %y) {
define i1 @eq_3210(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_3210(
-; CHECK-NEXT: [[X_0:%.*]] = trunc i32 [[X:%.*]] to i8
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[X_3_EXT:%.*]] = lshr i32 [[X]], 24
-; CHECK-NEXT: [[X_3:%.*]] = trunc i32 [[X_3_EXT]] to i8
-; CHECK-NEXT: [[Y_0:%.*]] = trunc i32 [[Y:%.*]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[Y_3_EXT:%.*]] = lshr i32 [[Y]], 24
-; CHECK-NEXT: [[Y_3:%.*]] = trunc i32 [[Y_3_EXT]] to i8
-; CHECK-NEXT: [[C_0:%.*]] = icmp eq i8 [[X_0]], [[Y_0]]
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_3:%.*]] = icmp eq i8 [[X_3]], [[Y_3]]
-; CHECK-NEXT: [[C_10:%.*]] = and i1 [[C_0]], [[C_1]]
-; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_10]]
-; CHECK-NEXT: [[C_3210:%.*]] = and i1 [[C_3]], [[C_210]]
-; CHECK-NEXT: ret i1 [[C_3210]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: ret i1 [[TMP1]]
;
%x.0 = trunc i32 %x to i8
%x.321 = lshr i32 %x, 8
@@ -121,18 +83,12 @@ define i1 @eq_3210(i32 %x, i32 %y) {
define i1 @eq_21(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_21(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -152,18 +108,12 @@ define i1 @eq_21(i32 %x, i32 %y) {
define i1 @eq_21_comm_and(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_21_comm_and(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_1]], [[C_2]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -181,18 +131,12 @@ define i1 @eq_21_comm_and(i32 %x, i32 %y) {
define i1 @eq_21_comm_eq(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_21_comm_eq(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[Y_2]], [[X_2]]
-; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -210,18 +154,12 @@ define i1 @eq_21_comm_eq(i32 %x, i32 %y) {
define i1 @eq_21_comm_eq2(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_21_comm_eq2(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[Y_1]], [[X_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -241,18 +179,12 @@ define i1 @eq_21_comm_eq2(i32 %x, i32 %y) {
define <2x i1> @eq_21_vector(<2x i32> %x, <2x i32> %y) {
; CHECK-LABEL: @eq_21_vector(
-; CHECK-NEXT: [[X_321:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 8, i32 8>
-; CHECK-NEXT: [[X_1:%.*]] = trunc <2 x i32> [[X_321]] to <2 x i8>
-; CHECK-NEXT: [[X_32:%.*]] = lshr <2 x i32> [[X]], <i32 16, i32 16>
-; CHECK-NEXT: [[X_2:%.*]] = trunc <2 x i32> [[X_32]] to <2 x i8>
-; CHECK-NEXT: [[Y_321:%.*]] = lshr <2 x i32> [[Y:%.*]], <i32 8, i32 8>
-; CHECK-NEXT: [[Y_1:%.*]] = trunc <2 x i32> [[Y_321]] to <2 x i8>
-; CHECK-NEXT: [[Y_32:%.*]] = lshr <2 x i32> [[Y]], <i32 16, i32 16>
-; CHECK-NEXT: [[Y_2:%.*]] = trunc <2 x i32> [[Y_32]] to <2 x i8>
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq <2 x i8> [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq <2 x i8> [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = and <2 x i1> [[C_2]], [[C_1]]
-; CHECK-NEXT: ret <2 x i1> [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 8, i32 8>
+; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i32> [[TMP1]] to <2 x i16>
+; CHECK-NEXT: [[TMP3:%.*]] = lshr <2 x i32> [[Y:%.*]], <i32 8, i32 8>
+; CHECK-NEXT: [[TMP4:%.*]] = trunc <2 x i32> [[TMP3]] to <2 x i16>
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <2 x i16> [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret <2 x i1> [[TMP5]]
;
%x.321 = lshr <2x i32> %x, <i32 8, i32 8>
%x.1 = trunc <2x i32> %x.321 to <2x i8>
@@ -273,18 +205,12 @@ define <2x i1> @eq_21_vector(<2x i32> %x, <2x i32> %y) {
define i1 @eq_irregular_bit_widths(i31 %x, i31 %y) {
; CHECK-LABEL: @eq_irregular_bit_widths(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i31 [[X:%.*]], 7
-; CHECK-NEXT: [[X_1:%.*]] = trunc i31 [[X_321]] to i6
-; CHECK-NEXT: [[X_32:%.*]] = lshr i31 [[X]], 13
-; CHECK-NEXT: [[X_2:%.*]] = trunc i31 [[X_32]] to i5
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i31 [[Y:%.*]], 7
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i31 [[Y_321]] to i6
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i31 [[Y]], 13
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i31 [[Y_32]] to i5
-; CHECK-NEXT: [[C_1:%.*]] = icmp eq i6 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp eq i5 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i31 [[X:%.*]], 7
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i31 [[TMP1]] to i11
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i31 [[Y:%.*]], 7
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i31 [[TMP3]] to i11
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i11 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i31 %x, 7
%x.1 = trunc i31 %x.321 to i6
@@ -724,16 +650,10 @@ define i1 @eq_21_wrong_pred2(i32 %x, i32 %y) {
define i1 @ne_10(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_10(
-; CHECK-NEXT: [[X_0:%.*]] = trunc i32 [[X:%.*]] to i8
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[Y_0:%.*]] = trunc i32 [[Y:%.*]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[C_0:%.*]] = icmp ne i8 [[X_0]], [[Y_0]]
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_10:%.*]] = or i1 [[C_0]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_10]]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i16 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: ret i1 [[TMP3]]
;
%x.0 = trunc i32 %x to i8
%x.321 = lshr i32 %x, 8
@@ -749,22 +669,10 @@ define i1 @ne_10(i32 %x, i32 %y) {
define i1 @ne_210(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_210(
-; CHECK-NEXT: [[X_0:%.*]] = trunc i32 [[X:%.*]] to i8
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_0:%.*]] = trunc i32 [[Y:%.*]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_0:%.*]] = icmp ne i8 [[X_0]], [[Y_0]]
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_10:%.*]] = or i1 [[C_0]], [[C_1]]
-; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_10]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i24
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i24
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i24 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: ret i1 [[TMP3]]
;
%x.0 = trunc i32 %x to i8
%x.321 = lshr i32 %x, 8
@@ -786,28 +694,8 @@ define i1 @ne_210(i32 %x, i32 %y) {
define i1 @ne_3210(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_3210(
-; CHECK-NEXT: [[X_0:%.*]] = trunc i32 [[X:%.*]] to i8
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[X_3_EXT:%.*]] = lshr i32 [[X]], 24
-; CHECK-NEXT: [[X_3:%.*]] = trunc i32 [[X_3_EXT]] to i8
-; CHECK-NEXT: [[Y_0:%.*]] = trunc i32 [[Y:%.*]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[Y_3_EXT:%.*]] = lshr i32 [[Y]], 24
-; CHECK-NEXT: [[Y_3:%.*]] = trunc i32 [[Y_3_EXT]] to i8
-; CHECK-NEXT: [[C_0:%.*]] = icmp ne i8 [[X_0]], [[Y_0]]
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_3:%.*]] = icmp ne i8 [[X_3]], [[Y_3]]
-; CHECK-NEXT: [[C_10:%.*]] = or i1 [[C_0]], [[C_1]]
-; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_10]]
-; CHECK-NEXT: [[C_3210:%.*]] = or i1 [[C_3]], [[C_210]]
-; CHECK-NEXT: ret i1 [[C_3210]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: ret i1 [[TMP1]]
;
%x.0 = trunc i32 %x to i8
%x.321 = lshr i32 %x, 8
@@ -835,18 +723,12 @@ define i1 @ne_3210(i32 %x, i32 %y) {
define i1 @ne_21(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_21(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -866,18 +748,12 @@ define i1 @ne_21(i32 %x, i32 %y) {
define i1 @ne_21_comm_or(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_21_comm_or(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_1]], [[C_2]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -895,18 +771,12 @@ define i1 @ne_21_comm_or(i32 %x, i32 %y) {
define i1 @ne_21_comm_ne(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_21_comm_ne(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[Y_2]], [[X_2]]
-; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -924,18 +794,12 @@ define i1 @ne_21_comm_ne(i32 %x, i32 %y) {
define i1 @ne_21_comm_ne2(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_21_comm_ne2(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8
-; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8
-; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16
-; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[Y_1]], [[X_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i32 %x, 8
%x.1 = trunc i32 %x.321 to i8
@@ -955,18 +819,12 @@ define i1 @ne_21_comm_ne2(i32 %x, i32 %y) {
define <2x i1> @ne_21_vector(<2x i32> %x, <2x i32> %y) {
; CHECK-LABEL: @ne_21_vector(
-; CHECK-NEXT: [[X_321:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 8, i32 8>
-; CHECK-NEXT: [[X_1:%.*]] = trunc <2 x i32> [[X_321]] to <2 x i8>
-; CHECK-NEXT: [[X_32:%.*]] = lshr <2 x i32> [[X]], <i32 16, i32 16>
-; CHECK-NEXT: [[X_2:%.*]] = trunc <2 x i32> [[X_32]] to <2 x i8>
-; CHECK-NEXT: [[Y_321:%.*]] = lshr <2 x i32> [[Y:%.*]], <i32 8, i32 8>
-; CHECK-NEXT: [[Y_1:%.*]] = trunc <2 x i32> [[Y_321]] to <2 x i8>
-; CHECK-NEXT: [[Y_32:%.*]] = lshr <2 x i32> [[Y]], <i32 16, i32 16>
-; CHECK-NEXT: [[Y_2:%.*]] = trunc <2 x i32> [[Y_32]] to <2 x i8>
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne <2 x i8> [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne <2 x i8> [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = or <2 x i1> [[C_2]], [[C_1]]
-; CHECK-NEXT: ret <2 x i1> [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 8, i32 8>
+; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i32> [[TMP1]] to <2 x i16>
+; CHECK-NEXT: [[TMP3:%.*]] = lshr <2 x i32> [[Y:%.*]], <i32 8, i32 8>
+; CHECK-NEXT: [[TMP4:%.*]] = trunc <2 x i32> [[TMP3]] to <2 x i16>
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ne <2 x i16> [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret <2 x i1> [[TMP5]]
;
%x.321 = lshr <2x i32> %x, <i32 8, i32 8>
%x.1 = trunc <2x i32> %x.321 to <2x i8>
@@ -987,18 +845,12 @@ define <2x i1> @ne_21_vector(<2x i32> %x, <2x i32> %y) {
define i1 @ne_irregular_bit_widths(i31 %x, i31 %y) {
; CHECK-LABEL: @ne_irregular_bit_widths(
-; CHECK-NEXT: [[X_321:%.*]] = lshr i31 [[X:%.*]], 7
-; CHECK-NEXT: [[X_1:%.*]] = trunc i31 [[X_321]] to i6
-; CHECK-NEXT: [[X_32:%.*]] = lshr i31 [[X]], 13
-; CHECK-NEXT: [[X_2:%.*]] = trunc i31 [[X_32]] to i5
-; CHECK-NEXT: [[Y_321:%.*]] = lshr i31 [[Y:%.*]], 7
-; CHECK-NEXT: [[Y_1:%.*]] = trunc i31 [[Y_321]] to i6
-; CHECK-NEXT: [[Y_32:%.*]] = lshr i31 [[Y]], 13
-; CHECK-NEXT: [[Y_2:%.*]] = trunc i31 [[Y_32]] to i5
-; CHECK-NEXT: [[C_1:%.*]] = icmp ne i6 [[X_1]], [[Y_1]]
-; CHECK-NEXT: [[C_2:%.*]] = icmp ne i5 [[X_2]], [[Y_2]]
-; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]]
-; CHECK-NEXT: ret i1 [[C_210]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i31 [[X:%.*]], 7
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i31 [[TMP1]] to i11
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i31 [[Y:%.*]], 7
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i31 [[TMP3]] to i11
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i11 [[TMP2]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
;
%x.321 = lshr i31 %x, 7
%x.1 = trunc i31 %x.321 to i6
More information about the llvm-commits
mailing list