diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 0a460786d00ea..7df58fa55d0d7 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -7579,16 +7579,23 @@ static bool isGuaranteedNotToBeUndefOrPoison( if (isa(C)) return !includesUndef(Kind); - if (isa(C) || isa(C) || isa(V) || + if (isa(C) || isa(C) || isa(C) || isa(C) || isa(C)) return true; - if (C->getType()->isVectorTy() && !isa(C)) { - if (includesUndef(Kind) && C->containsUndefElement()) - return false; - if (includesPoison(Kind) && C->containsPoisonElement()) - return false; - return !C->containsConstantExpression(); + if (C->getType()->isVectorTy()) { + if (isa(C)) { + // Scalable vectors can use a ConstantExpr to build a splat. + if (Constant *SplatC = C->getSplatValue()) + if (isa(SplatC) || isa(SplatC)) + return true; + } else { + if (includesUndef(Kind) && C->containsUndefElement()) + return false; + if (includesPoison(Kind) && C->containsPoisonElement()) + return false; + return !C->containsConstantExpression(); + } } } diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll index cfc7877383881..6d720ca9d0eac 100644 --- a/llvm/test/Transforms/Attributor/nofpclass.ll +++ b/llvm/test/Transforms/Attributor/nofpclass.ll @@ -2665,7 +2665,7 @@ define [4 x float] @constant_aggregate_zero() { define @scalable_splat_pnorm() { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define @scalable_splat_pnorm +; CHECK-LABEL: define noundef @scalable_splat_pnorm ; CHECK-SAME: () #[[ATTR3]] { ; CHECK-NEXT: ret splat (float 1.000000e+00) ; diff --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll index b14186d737e98..453ca666a7477 100644 --- a/llvm/test/Transforms/InstCombine/select-and-or.ll +++ b/llvm/test/Transforms/InstCombine/select-and-or.ll @@ -104,6 +104,20 @@ define i1 @logical_or_implies(i32 %x) { ret i1 %res } +; Safe to convert to or due to poison implication. +define @logical_or_implies_scalablevec( %x) { +; CHECK-LABEL: @logical_or_implies_scalablevec( +; CHECK-NEXT: [[C1:%.*]] = icmp eq [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[C2:%.*]] = icmp eq [[X]], splat (i32 42) +; CHECK-NEXT: [[RES:%.*]] = or [[C1]], [[C2]] +; CHECK-NEXT: ret [[RES]] +; + %c1 = icmp eq %x, zeroinitializer + %c2 = icmp eq %x, splat (i32 42) + %res = select %c1, splat (i1 true), %c2 + ret %res +} + ; Will fold after conversion to or. define i1 @logical_or_implies_folds(i32 %x) { ; CHECK-LABEL: @logical_or_implies_folds( @@ -129,6 +143,20 @@ define i1 @logical_and_implies(i32 %x) { ret i1 %res } +; Safe to convert to and due to poison implication. +define @logical_and_implies_scalablevec( %x) { +; CHECK-LABEL: @logical_and_implies_scalablevec( +; CHECK-NEXT: [[C1:%.*]] = icmp ne [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[C2:%.*]] = icmp ne [[X]], splat (i32 42) +; CHECK-NEXT: [[RES:%.*]] = and [[C1]], [[C2]] +; CHECK-NEXT: ret [[RES]] +; + %c1 = icmp ne %x, zeroinitializer + %c2 = icmp ne %x, splat (i32 42) + %res = select %c1, %c2, zeroinitializer + ret %res +} + ; Will fold after conversion to and. define i1 @logical_and_implies_folds(i32 %x) { ; CHECK-LABEL: @logical_and_implies_folds(