diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 7be8a18dd7271..7cc2c2e5ebcb5 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1684,6 +1684,8 @@ static void computeKnownBitsFromOperator(const Operator *I, computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); Known = KnownBits::ssub_sat(Known, Known2); break; + // Vec reverse preserves bits from input vec. + case Intrinsic::vector_reverse: // for min/max/and/or reduce, any bit common to each element in the // input vec is set in the output. case Intrinsic::vector_reduce_and: @@ -3026,6 +3028,8 @@ static bool isKnownNonZeroFromOperator(const Operator *I, return isNonZeroAdd(DemandedElts, Depth, Q, BitWidth, II->getArgOperand(0), II->getArgOperand(1), /*NSW=*/true, /* NUW=*/false); + // Vec reverse preserves zero/non-zero status from input vec. + case Intrinsic::vector_reverse: // umin/smin/smax/smin/or of all non-zero elements is always non-zero. case Intrinsic::vector_reduce_or: case Intrinsic::vector_reduce_umax: @@ -5163,6 +5167,11 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, Known.SignBit.reset(); break; } + // reverse preserves all characteristics of the input vec's element. + case Intrinsic::vector_reverse: + Known = computeKnownFPClass(II->getArgOperand(0), II->getFastMathFlags(), + InterestedClasses, Depth + 1, Q); + break; case Intrinsic::trunc: case Intrinsic::floor: case Intrinsic::ceil: diff --git a/llvm/test/Analysis/ValueTracking/known-bits.ll b/llvm/test/Analysis/ValueTracking/known-bits.ll new file mode 100644 index 0000000000000..035ccf8d42d13 --- /dev/null +++ b/llvm/test/Analysis/ValueTracking/known-bits.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=instsimplify < %s -S | FileCheck %s + +define <4 x i1> @vec_reverse_known_bits(<4 x i8> %xx) { +; CHECK-LABEL: @vec_reverse_known_bits( +; CHECK-NEXT: ret <4 x i1> +; + %x = or <4 x i8> %xx, + %rev = call <4 x i8> @llvm.vector.reverse(<4 x i8> %x) + %r = icmp slt <4 x i8> %rev, zeroinitializer + ret <4 x i1> %r +} + +define <4 x i1> @vec_reverse_known_bits_fail(<4 x i8> %xx) { +; CHECK-LABEL: @vec_reverse_known_bits_fail( +; CHECK-NEXT: [[X:%.*]] = or <4 x i8> [[XX:%.*]], +; CHECK-NEXT: [[REV:%.*]] = call <4 x i8> @llvm.vector.reverse.v4i8(<4 x i8> [[X]]) +; CHECK-NEXT: [[R:%.*]] = icmp slt <4 x i8> [[REV]], zeroinitializer +; CHECK-NEXT: ret <4 x i1> [[R]] +; + %x = or <4 x i8> %xx, + %rev = call <4 x i8> @llvm.vector.reverse(<4 x i8> %x) + %r = icmp slt <4 x i8> %rev, zeroinitializer + ret <4 x i1> %r +} diff --git a/llvm/test/Analysis/ValueTracking/known-fpclass.ll b/llvm/test/Analysis/ValueTracking/known-fpclass.ll new file mode 100644 index 0000000000000..59f3eed715b52 --- /dev/null +++ b/llvm/test/Analysis/ValueTracking/known-fpclass.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=instsimplify < %s -S | FileCheck %s + +define <4 x i1> @vector_reverse_fpclass(<4 x double> nofpclass(nzero nan) %x) { +; CHECK-LABEL: @vector_reverse_fpclass( +; CHECK-NEXT: ret <4 x i1> +; + %x.abs = call <4 x double> @llvm.fabs.v4f64(<4 x double> %x) + %op = call <4 x double> @llvm.vector.reverse(<4 x double> %x.abs) + %cmp = fcmp oge <4 x double> %op, + ret <4 x i1> %cmp +} + +define <4 x i1> @vector_reverse_fpclass2(<4 x double> nofpclass(nzero) %x) { +; CHECK-LABEL: @vector_reverse_fpclass2( +; CHECK-NEXT: [[X_ABS:%.*]] = call <4 x double> @llvm.fabs.v4f64(<4 x double> [[X:%.*]]) +; CHECK-NEXT: [[OP:%.*]] = call <4 x double> @llvm.vector.reverse.v4f64(<4 x double> [[X_ABS]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp oge <4 x double> [[OP]], zeroinitializer +; CHECK-NEXT: ret <4 x i1> [[CMP]] +; + %x.abs = call <4 x double> @llvm.fabs.v4f64(<4 x double> %x) + %op = call <4 x double> @llvm.vector.reverse(<4 x double> %x.abs) + %cmp = fcmp oge <4 x double> %op, + ret <4 x i1> %cmp +} + diff --git a/llvm/test/Analysis/ValueTracking/known-non-zero.ll b/llvm/test/Analysis/ValueTracking/known-non-zero.ll index c00e47fba8c72..5704586d92300 100644 --- a/llvm/test/Analysis/ValueTracking/known-non-zero.ll +++ b/llvm/test/Analysis/ValueTracking/known-non-zero.ll @@ -1497,4 +1497,27 @@ define i1 @trunc_nsw_nuw_non_zero_fail(i8 %xx) { ret i1 %r } +define <4 x i1> @vec_reverse_non_zero(<4 x i8> %xx) { +; CHECK-LABEL: @vec_reverse_non_zero( +; CHECK-NEXT: ret <4 x i1> zeroinitializer +; + %x = add nuw <4 x i8> %xx, + %rev = call <4 x i8> @llvm.vector.reverse(<4 x i8> %x) + %r = icmp eq <4 x i8> %rev, zeroinitializer + ret <4 x i1> %r +} + +define <4 x i1> @vec_reverse_non_zero_fail(<4 x i8> %xx) { +; CHECK-LABEL: @vec_reverse_non_zero_fail( +; CHECK-NEXT: [[X:%.*]] = add nuw <4 x i8> [[XX:%.*]], +; CHECK-NEXT: [[REV:%.*]] = call <4 x i8> @llvm.vector.reverse.v4i8(<4 x i8> [[X]]) +; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i8> [[REV]], zeroinitializer +; CHECK-NEXT: ret <4 x i1> [[R]] +; + %x = add nuw <4 x i8> %xx, + %rev = call <4 x i8> @llvm.vector.reverse(<4 x i8> %x) + %r = icmp eq <4 x i8> %rev, zeroinitializer + ret <4 x i1> %r +} + declare i32 @llvm.experimental.get.vector.length.i32(i32, i32, i1)