[llvm] handle concat of boolmasks for BE arm (PR #191678)

Takashi Idobe via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 11 19:01:44 PDT 2026


https://github.com/Takashiidobe created https://github.com/llvm/llvm-project/pull/191678

foldConcatOfBoolMasks had a note that it didn't handle BE. 

After canonicalizing, X is the lower bitfield and Y is the higher bitfield. Bitcast maps 0 to low bits on LE but to high bits on BE, so for LE shufflevector(X, Y) is correct (as was already handled). For BE, we just want the reverse, so shufflevector(Y, X) works on BE. 

>From 16d6446896b1baa5cbfc9540e6ee7c41227deb99 Mon Sep 17 00:00:00 2001
From: Takashiidobe <idobetakashi at gmail.com>
Date: Sat, 11 Apr 2026 21:39:56 -0400
Subject: [PATCH] handle concat of boolmasks for BE by flipping the X and Y
 before passing in

---
 .../Transforms/Vectorize/VectorCombine.cpp    |  8 +++----
 .../AArch64/concat-boolmasks-endian.ll        | 23 +++++++++++++++++++
 2 files changed, 26 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/Transforms/VectorCombine/AArch64/concat-boolmasks-endian.ll

diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 194e3477815f4..cfcc4de409261 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -2312,10 +2312,6 @@ bool VectorCombine::foldConcatOfBoolMasks(Instruction &I) {
   if (!Ty->isIntegerTy())
     return false;
 
-  // TODO: Add big endian test coverage
-  if (DL->isBigEndian())
-    return false;
-
   // Restrict to disjoint cases so the mask vectors aren't overlapping.
   Instruction *X, *Y;
   if (!match(&I, m_DisjointOr(m_Instruction(X), m_Instruction(Y))))
@@ -2396,7 +2392,9 @@ bool VectorCombine::foldConcatOfBoolMasks(Instruction &I) {
 
   // Build bool mask concatenation, bitcast back to scalar integer, and perform
   // any residual zero-extension or shifting.
-  Value *Concat = Builder.CreateShuffleVector(SrcX, SrcY, ConcatMask);
+  Value *Concat = DL->isBigEndian()
+                      ? Builder.CreateShuffleVector(SrcY, SrcX, ConcatMask)
+                      : Builder.CreateShuffleVector(SrcX, SrcY, ConcatMask);
   Worklist.pushValue(Concat);
 
   Value *Result = Builder.CreateBitCast(Concat, ConcatIntTy);
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/concat-boolmasks-endian.ll b/llvm/test/Transforms/VectorCombine/AArch64/concat-boolmasks-endian.ll
new file mode 100644
index 0000000000000..703572e70ec3b
--- /dev/null
+++ b/llvm/test/Transforms/VectorCombine/AArch64/concat-boolmasks-endian.ll
@@ -0,0 +1,23 @@
+; RUN: opt -passes='vector-combine' -S -mtriple=aarch64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,LE
+; RUN: opt -passes='vector-combine' -S -mtriple=aarch64_be-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,BE
+
+define i32 @movmsk_i32_v8i32_v4i32(<4 x i32> %v0, <4 x i32> %v1) {
+; CHECK-LABEL: define i32 @movmsk_i32_v8i32_v4i32(
+; CHECK-SAME: <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]]) {
+; LE-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1]], <4 x i32> [[V0]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; BE-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0]], <4 x i32> [[V1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt <8 x i32> [[TMP1]], zeroinitializer
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <8 x i1> [[TMP2]] to i8
+; CHECK-NEXT:    [[OR:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %c0 = icmp slt <4 x i32> %v0, zeroinitializer
+  %c1 = icmp slt <4 x i32> %v1, zeroinitializer
+  %b0 = bitcast <4 x i1> %c0 to i4
+  %b1 = bitcast <4 x i1> %c1 to i4
+  %z0 = zext i4 %b0 to i32
+  %z1 = zext i4 %b1 to i32
+  %s0 = shl nuw i32 %z0, 4
+  %or = or disjoint i32 %s0, %z1
+  ret i32 %or
+}



More information about the llvm-commits mailing list