Skip to content

Conversation

@topperc
Copy link
Collaborator

@topperc topperc commented Jun 5, 2025

Scalable vectors use insertelt+shufflevector ConstantExpr to
represent a splat.

topperc added 2 commits June 4, 2025 20:31
…aranteedNotToBeUndefOrPoison.

Scalable vectors use insertelt+shufflevector ConstantExpr to
represent a splat.
@topperc topperc requested review from dtcxzyw and preames June 5, 2025 03:36
@topperc topperc requested a review from nikic as a code owner June 5, 2025 03:36
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Jun 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 5, 2025

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Craig Topper (topperc)

Changes

Scalable vectors use insertelt+shufflevector ConstantExpr to
represent a splat.


Full diff: https://github.com/llvm/llvm-project/pull/142894.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+14-7)
  • (modified) llvm/test/Transforms/InstCombine/select-and-or.ll (+28)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0a460786d00ea..b32d206f927ed 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7579,16 +7579,23 @@ static bool isGuaranteedNotToBeUndefOrPoison(
     if (isa<UndefValue>(C))
       return !includesUndef(Kind);
 
-    if (isa<ConstantInt>(C) || isa<GlobalVariable>(C) || isa<ConstantFP>(V) ||
+    if (isa<ConstantInt>(C) || isa<GlobalVariable>(C) || isa<ConstantFP>(C) ||
         isa<ConstantPointerNull>(C) || isa<Function>(C))
       return true;
 
-    if (C->getType()->isVectorTy() && !isa<ConstantExpr>(C)) {
-      if (includesUndef(Kind) && C->containsUndefElement())
-        return false;
-      if (includesPoison(Kind) && C->containsPoisonElement())
-        return false;
-      return !C->containsConstantExpression();
+    if (C->getType()->isVectorTy()) {
+      if (isa<ConstantExpr>(C)) {
+        // Scalable vectors can use a ConstantExpr to build a splat.
+        if (Constant *SplatC = C->getSplatValue())
+          if (isa<ConstantInt>(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/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 <vscale x 2 x i1> @logical_or_implies_scalablevec(<vscale x 2 x i32> %x) {
+; CHECK-LABEL: @logical_or_implies_scalablevec(
+; CHECK-NEXT:    [[C1:%.*]] = icmp eq <vscale x 2 x i32> [[X:%.*]], zeroinitializer
+; CHECK-NEXT:    [[C2:%.*]] = icmp eq <vscale x 2 x i32> [[X]], splat (i32 42)
+; CHECK-NEXT:    [[RES:%.*]] = or <vscale x 2 x i1> [[C1]], [[C2]]
+; CHECK-NEXT:    ret <vscale x 2 x i1> [[RES]]
+;
+  %c1 = icmp eq <vscale x 2 x i32> %x, zeroinitializer
+  %c2 = icmp eq <vscale x 2 x i32> %x, splat (i32 42)
+  %res = select <vscale x 2 x i1> %c1, <vscale x 2 x i1> splat (i1 true), <vscale x 2 x i1> %c2
+  ret <vscale x 2 x i1> %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 <vscale x 2 x i1> @logical_and_implies_scalablevec(<vscale x 2 x i32> %x) {
+; CHECK-LABEL: @logical_and_implies_scalablevec(
+; CHECK-NEXT:    [[C1:%.*]] = icmp ne <vscale x 2 x i32> [[X:%.*]], zeroinitializer
+; CHECK-NEXT:    [[C2:%.*]] = icmp ne <vscale x 2 x i32> [[X]], splat (i32 42)
+; CHECK-NEXT:    [[RES:%.*]] = and <vscale x 2 x i1> [[C1]], [[C2]]
+; CHECK-NEXT:    ret <vscale x 2 x i1> [[RES]]
+;
+  %c1 = icmp ne <vscale x 2 x i32> %x, zeroinitializer
+  %c2 = icmp ne <vscale x 2 x i32> %x, splat (i32 42)
+  %res = select <vscale x 2 x i1> %c1, <vscale x 2 x i1> %c2, <vscale x 2 x i1> zeroinitializer
+  ret <vscale x 2 x i1> %res
+}
+
 ; Will fold after conversion to and.
 define i1 @logical_and_implies_folds(i32 %x) {
 ; CHECK-LABEL: @logical_and_implies_folds(

Comment on lines 7590 to 7591
if (isa<ConstantInt>(SplatC))
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to support fp/ptr splats?

Suggested change
if (isa<ConstantInt>(SplatC))
return true;
return isGuaranteedNotToBeUndefOrPoison(SplatC, ...);

Copy link
Collaborator Author

@topperc topperc Jun 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to support fp/ptr splats?

Just lack of tests. Should we increase the depth on the recursive call to isGuaranteedNotToBeUndefOrPoison or keep the current depth.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latter one is ok.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added ConstantFP and an Attributor test was changed so that has some coverage.

Will a splat of ConstantPointerNull be folded to ConstantAggregateZero at creation?

@topperc topperc changed the title [ValueTracking] Support scalable vector splats of ConstantInt in isGuaranteedNotToBeUndefOrPoison. [ValueTracking] Support scalable vector splats of ConstantInt/ConstantFP in isGuaranteedNotToBeUndefOrPoison. Jun 5, 2025
Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG

@topperc topperc merged commit b8a4a3b into llvm:main Jun 6, 2025
7 checks passed
@topperc topperc deleted the pr/splat-constantint branch June 6, 2025 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:analysis Includes value tracking, cost tables and constant folding llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants