[llvm] [SROA]: try converting an alloca to a float vec (PR #223285)

Folkert de Vries via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 13 17:59:42 PDT 2026


https://github.com/folkertdev updated https://github.com/llvm/llvm-project/pull/223285

>From a5d11909f35419ccee47a6bc5fb2d967c6d7425b Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Mon, 14 Sep 2026 02:30:55 +0200
Subject: [PATCH] [SROA]: try converting an alloca to a float vec

---
 llvm/lib/Transforms/Scalar/SROA.cpp           |  18 ++
 .../PhaseOrdering/X86/vec-load-combine.ll     |  18 +-
 llvm/test/Transforms/SROA/basictest.ll        |  22 +--
 llvm/test/Transforms/SROA/phi-and-select.ll   |   8 +-
 llvm/test/Transforms/SROA/vector-promotion.ll | 173 ++++++++++++++++++
 5 files changed, 207 insertions(+), 32 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index c933225c2ad21..e98b5fad2b674 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -2329,6 +2329,24 @@ static VectorType *isVectorPromotionViable(Partition &P, const DataLayout &DL,
       CheckCandidateType(Ty);
   }
 
+  // No access used a vector type, so there is no candidate to widen.
+  // Try forming one from a floating point type that tiles the partition.
+  if (CandidateTys.empty()) {
+    uint64_t PartitionSize = P.size();
+    for (Type *Ty : LoadStoreTys) {
+      if (!Ty->isFloatingPointTy())
+        continue;
+      // Applying this idea for f16 and bf16 is usually not beneficial.
+      if (DL.getTypeSizeInBits(Ty).getFixedValue() < 32)
+        continue;
+      // Require at least two elements that exactly tile the partition.
+      uint64_t EltBytes = DL.getTypeStoreSize(Ty).getFixedValue();
+      if (PartitionSize <= EltBytes || PartitionSize % EltBytes != 0)
+        continue;
+      CheckCandidateType(FixedVectorType::get(Ty, PartitionSize / EltBytes));
+    }
+  }
+
   SmallVector<VectorType *, 4> CandidateTysCopy = CandidateTys;
   if (auto *VTy = createAndCheckVectorTypesForPromotion(
           LoadStoreTys, CandidateTysCopy, CheckCandidateType, P, DL,
diff --git a/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll b/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll
index 86bdd125e5e57..142124f46cded 100644
--- a/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll
+++ b/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll
@@ -47,24 +47,18 @@ define dso_local noundef <4 x float> @ConvertVectors_ByRef(ptr noundef nonnull a
 define noundef <4 x float> @ConvertVectors_ByVal(ptr noundef nonnull align 16 dereferenceable(16) %V) #0 {
 ; SSE-LABEL: @ConvertVectors_ByVal(
 ; SSE-NEXT:  entry:
-; SSE-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[V:%.*]], align 16
+; SSE-NEXT:    [[V_VAL22:%.*]] = load <2 x float>, ptr [[V:%.*]], align 16
 ; SSE-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8
-; SSE-NEXT:    [[V_VAL421:%.*]] = load i64, ptr [[TMP1]], align 8
-; SSE-NEXT:    [[TMP2:%.*]] = trunc i64 [[V_VAL421]] to i32
-; SSE-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
-; SSE-NEXT:    [[VECINIT11:%.*]] = insertelement <4 x float> [[TMP0]], float [[TMP3]], i64 2
-; SSE-NEXT:    [[VECINIT16:%.*]] = insertelement <4 x float> [[VECINIT11]], float [[TMP3]], i64 3
+; SSE-NEXT:    [[V_VAL423:%.*]] = load <2 x float>, ptr [[TMP1]], align 8
+; SSE-NEXT:    [[VECINIT16:%.*]] = shufflevector <2 x float> [[V_VAL22]], <2 x float> [[V_VAL423]], <4 x i32> <i32 0, i32 1, i32 2, i32 2>
 ; SSE-NEXT:    ret <4 x float> [[VECINIT16]]
 ;
 ; AVX-LABEL: @ConvertVectors_ByVal(
 ; AVX-NEXT:  entry:
-; AVX-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[V:%.*]], align 16
+; AVX-NEXT:    [[V_VAL22:%.*]] = load <2 x float>, ptr [[V:%.*]], align 16
 ; AVX-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8
-; AVX-NEXT:    [[V_VAL421:%.*]] = load i64, ptr [[TMP1]], align 8
-; AVX-NEXT:    [[TMP2:%.*]] = trunc i64 [[V_VAL421]] to i32
-; AVX-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
-; AVX-NEXT:    [[VECINIT11:%.*]] = insertelement <4 x float> [[TMP0]], float [[TMP3]], i64 2
-; AVX-NEXT:    [[VECINIT16:%.*]] = insertelement <4 x float> [[VECINIT11]], float [[TMP3]], i64 3
+; AVX-NEXT:    [[V_VAL423:%.*]] = load <2 x float>, ptr [[TMP1]], align 8
+; AVX-NEXT:    [[VECINIT16:%.*]] = shufflevector <2 x float> [[V_VAL22]], <2 x float> [[V_VAL423]], <4 x i32> <i32 0, i32 1, i32 2, i32 2>
 ; AVX-NEXT:    ret <4 x float> [[VECINIT16]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SROA/basictest.ll b/llvm/test/Transforms/SROA/basictest.ll
index bf3aa251b3dfa..f88d708c3235d 100644
--- a/llvm/test/Transforms/SROA/basictest.ll
+++ b/llvm/test/Transforms/SROA/basictest.ll
@@ -1330,10 +1330,10 @@ define void @PR15674(ptr %data, ptr %src, i32 %size) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP_SROA_0:%.*]] = alloca i32, align 4
 ; CHECK-NEXT:    switch i32 [[SIZE:%.*]], label [[END:%.*]] [
-; CHECK-NEXT:    i32 4, label [[BB4:%.*]]
-; CHECK-NEXT:    i32 3, label [[BB3:%.*]]
-; CHECK-NEXT:    i32 2, label [[BB2:%.*]]
-; CHECK-NEXT:    i32 1, label [[BB1:%.*]]
+; CHECK-NEXT:      i32 4, label [[BB4:%.*]]
+; CHECK-NEXT:      i32 3, label [[BB3:%.*]]
+; CHECK-NEXT:      i32 2, label [[BB2:%.*]]
+; CHECK-NEXT:      i32 1, label [[BB1:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       bb4:
 ; CHECK-NEXT:    [[SRC_GEP3:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i32 3
@@ -1794,17 +1794,11 @@ entry:
 define void @PR25873(ptr %outData) {
 ; CHECK-LABEL: @PR25873(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    store i32 1123418112, ptr [[OUTDATA:%.*]], align 4
-; CHECK-NEXT:    [[OUTDATA_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[OUTDATA]], i64 4
-; CHECK-NEXT:    store i32 1139015680, ptr [[OUTDATA_SROA_IDX]], align 4
+; CHECK-NEXT:    [[TMPDATA_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x float> undef, float 1.230000e+02, i64 0
+; CHECK-NEXT:    [[TMPDATA_SROA_0_4_VEC_INSERT:%.*]] = insertelement <2 x float> [[TMPDATA_SROA_0_0_VEC_INSERT]], float 4.560000e+02, i64 1
+; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_0_0_INSERT_INSERT:%.*]] = bitcast <2 x float> [[TMPDATA_SROA_0_4_VEC_INSERT]] to i64
+; CHECK-NEXT:    store <2 x float> [[TMPDATA_SROA_0_4_VEC_INSERT]], ptr [[OUTDATA:%.*]], align 4
 ; CHECK-NEXT:    [[TMPDATA_SROA_6_0_OUTDATA_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[OUTDATA]], i64 8
-; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_4_0_INSERT_EXT:%.*]] = zext i32 1139015680 to i64
-; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_4_0_INSERT_SHIFT:%.*]] = shl i64 [[TMPDATA_SROA_6_SROA_4_0_INSERT_EXT]], 32
-; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_4_0_INSERT_MASK:%.*]] = and i64 undef, 4294967295
-; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_4_0_INSERT_INSERT:%.*]] = or i64 [[TMPDATA_SROA_6_SROA_4_0_INSERT_MASK]], [[TMPDATA_SROA_6_SROA_4_0_INSERT_SHIFT]]
-; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_0_0_INSERT_EXT:%.*]] = zext i32 1123418112 to i64
-; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_0_0_INSERT_MASK:%.*]] = and i64 [[TMPDATA_SROA_6_SROA_4_0_INSERT_INSERT]], -4294967296
-; CHECK-NEXT:    [[TMPDATA_SROA_6_SROA_0_0_INSERT_INSERT:%.*]] = or i64 [[TMPDATA_SROA_6_SROA_0_0_INSERT_MASK]], [[TMPDATA_SROA_6_SROA_0_0_INSERT_EXT]]
 ; CHECK-NEXT:    store i64 [[TMPDATA_SROA_6_SROA_0_0_INSERT_INSERT]], ptr [[TMPDATA_SROA_6_0_OUTDATA_SROA_IDX]], align 4
 ; CHECK-NEXT:    ret void
 ;
diff --git a/llvm/test/Transforms/SROA/phi-and-select.ll b/llvm/test/Transforms/SROA/phi-and-select.ll
index 6d079394ab084..67cc37ae7d39e 100644
--- a/llvm/test/Transforms/SROA/phi-and-select.ll
+++ b/llvm/test/Transforms/SROA/phi-and-select.ll
@@ -385,15 +385,13 @@ define float @test10(i32 %b, ptr %ptr) {
 ;
 ; CHECK-LABEL: @test10(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[F:%.*]] = alloca double, align 8
-; CHECK-NEXT:    store double 0.000000e+00, ptr [[F]], align 8
 ; CHECK-NEXT:    [[TEST:%.*]] = icmp ne i32 [[B:%.*]], 0
 ; CHECK-NEXT:    br i1 [[TEST]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    [[PHI_SROA_SPECULATE_LOAD_THEN:%.*]] = load float, ptr [[PTR:%.*]], align 4
 ; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       else:
-; CHECK-NEXT:    [[F_0_PHI_SROA_SPECULATE_LOAD_ELSE:%.*]] = load float, ptr [[F]], align 8
+; CHECK-NEXT:    [[F_0_PHI_SROA_SPECULATE_LOAD_ELSE:%.*]] = extractelement <2 x float> zeroinitializer, i64 0
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    [[PHI_SROA_SPECULATED:%.*]] = phi float [ [[F_0_PHI_SROA_SPECULATE_LOAD_ELSE]], [[ELSE]] ], [ [[PHI_SROA_SPECULATE_LOAD_THEN]], [[THEN]] ]
@@ -422,11 +420,9 @@ define float @test11(i32 %b, ptr %ptr) {
 ;
 ; CHECK-LABEL: @test11(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[F:%.*]] = alloca double, align 8
-; CHECK-NEXT:    store double 0.000000e+00, ptr [[F]], align 8
 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[PTR:%.*]], align 4
 ; CHECK-NEXT:    [[TEST:%.*]] = icmp ne i32 [[B:%.*]], 0
-; CHECK-NEXT:    [[F_0_LOADED_SROA_SPECULATE_LOAD_TRUE:%.*]] = load float, ptr [[F]], align 8
+; CHECK-NEXT:    [[F_0_LOADED_SROA_SPECULATE_LOAD_TRUE:%.*]] = extractelement <2 x float> zeroinitializer, i64 0
 ; CHECK-NEXT:    [[LOADED_SROA_SPECULATE_LOAD_FALSE:%.*]] = load float, ptr [[PTR]], align 4
 ; CHECK-NEXT:    [[LOADED_SROA_SPECULATED:%.*]] = select i1 [[TEST]], float [[F_0_LOADED_SROA_SPECULATE_LOAD_TRUE]], float [[LOADED_SROA_SPECULATE_LOAD_FALSE]]
 ; CHECK-NEXT:    ret float [[LOADED_SROA_SPECULATED]]
diff --git a/llvm/test/Transforms/SROA/vector-promotion.ll b/llvm/test/Transforms/SROA/vector-promotion.ll
index 19674e24d8e73..283a68a0157ea 100644
--- a/llvm/test/Transforms/SROA/vector-promotion.ll
+++ b/llvm/test/Transforms/SROA/vector-promotion.ll
@@ -1533,6 +1533,179 @@ bb.5:
   br label %bb.5
 }
 
+define double @FloatTilesDoubleInsert(float %a, float %b) {
+; CHECK-LABEL: @FloatTilesDoubleInsert(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x float> undef, float [[A:%.*]], i64 0
+; CHECK-NEXT:    [[P_SROA_0_4_VEC_INSERT:%.*]] = insertelement <2 x float> [[P_SROA_0_0_VEC_INSERT]], float [[B:%.*]], i64 1
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[P_SROA_0_4_VEC_INSERT]] to double
+; CHECK-NEXT:    ret double [[TMP0]]
+;
+; DEBUG-LABEL: @FloatTilesDoubleInsert(
+; DEBUG-NEXT:  entry:
+; DEBUG-NEXT:      #dbg_value(ptr poison, [[META585:![0-9]+]], !DIExpression(), [[META588:![0-9]+]])
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META585]], !DIExpression(), [[META588]])
+; DEBUG-NEXT:    [[P_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x float> undef, float [[A:%.*]], i64 0, !dbg [[DBG589:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META586:![0-9]+]], !DIExpression(), [[META590:![0-9]+]])
+; DEBUG-NEXT:    [[P_SROA_0_4_VEC_INSERT:%.*]] = insertelement <2 x float> [[P_SROA_0_0_VEC_INSERT]], float [[B:%.*]], i64 1, !dbg [[DBG591:![0-9]+]]
+; DEBUG-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[P_SROA_0_4_VEC_INSERT]] to double, !dbg [[DBG592:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(double [[TMP0]], [[META587:![0-9]+]], !DIExpression(), [[DBG592]])
+; DEBUG-NEXT:    ret double [[TMP0]], !dbg [[DBG593:![0-9]+]]
+;
+entry:
+  %p = alloca double, align 8
+  store float %a, ptr %p, align 8
+  %q = getelementptr inbounds i8, ptr %p, i64 4
+  store float %b, ptr %q, align 4
+  %r = load double, ptr %p, align 8
+  ret double %r
+}
+
+define float @FloatTilesDoubleExtract(double %x) {
+; CHECK-LABEL: @FloatTilesDoubleExtract(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double [[X:%.*]] to <2 x float>
+; CHECK-NEXT:    [[P_SROA_0_4_VEC_EXTRACT:%.*]] = extractelement <2 x float> [[TMP0]], i64 1
+; CHECK-NEXT:    ret float [[P_SROA_0_4_VEC_EXTRACT]]
+;
+; DEBUG-LABEL: @FloatTilesDoubleExtract(
+; DEBUG-NEXT:  entry:
+; DEBUG-NEXT:      #dbg_value(ptr poison, [[META596:![0-9]+]], !DIExpression(), [[META599:![0-9]+]])
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META596]], !DIExpression(), [[META599]])
+; DEBUG-NEXT:    [[TMP0:%.*]] = bitcast double [[X:%.*]] to <2 x float>, !dbg [[DBG600:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META597:![0-9]+]], !DIExpression(), [[META601:![0-9]+]])
+; DEBUG-NEXT:    [[P_SROA_0_4_VEC_EXTRACT:%.*]] = extractelement <2 x float> [[TMP0]], i64 1, !dbg [[DBG602:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(float [[P_SROA_0_4_VEC_EXTRACT]], [[META598:![0-9]+]], !DIExpression(), [[DBG602]])
+; DEBUG-NEXT:    ret float [[P_SROA_0_4_VEC_EXTRACT]], !dbg [[DBG603:![0-9]+]]
+;
+entry:
+  %p = alloca double, align 8
+  store double %x, ptr %p, align 8
+  %q = getelementptr inbounds i8, ptr %p, i64 4
+  %r = load float, ptr %q, align 4
+  ret float %r
+}
+
+; Negative test: x86_fp80 tiles the partition by store size, but its store and
+; allocation size are different, so the vector would not match the scalar accesses.
+define void @F80DoesNotTile(x86_fp80 %a, x86_fp80 %b, ptr %out) {
+; CHECK-LABEL: @F80DoesNotTile(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P:%.*]] = alloca i160, align 2
+; CHECK-NEXT:    store x86_fp80 [[A:%.*]], ptr [[P]], align 2
+; CHECK-NEXT:    [[P_10_Q_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 10
+; CHECK-NEXT:    store x86_fp80 [[B:%.*]], ptr [[P_10_Q_SROA_IDX]], align 2
+; CHECK-NEXT:    [[P_0_R:%.*]] = load volatile i160, ptr [[P]], align 2
+; CHECK-NEXT:    store i160 [[P_0_R]], ptr [[OUT:%.*]], align 2
+; CHECK-NEXT:    ret void
+;
+; DEBUG-LABEL: @F80DoesNotTile(
+; DEBUG-NEXT:  entry:
+; DEBUG-NEXT:    [[P:%.*]] = alloca i160, align 2, !dbg [[DBG610:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(ptr [[P]], [[META606:![0-9]+]], !DIExpression(), [[DBG610]])
+; DEBUG-NEXT:    store x86_fp80 [[A:%.*]], ptr [[P]], align 2, !dbg [[DBG611:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META607:![0-9]+]], !DIExpression(), [[META612:![0-9]+]])
+; DEBUG-NEXT:    [[P_10_Q_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 10, !dbg [[DBG613:![0-9]+]]
+; DEBUG-NEXT:    store x86_fp80 [[B:%.*]], ptr [[P_10_Q_SROA_IDX]], align 2, !dbg [[DBG613]]
+; DEBUG-NEXT:    [[P_0_R:%.*]] = load volatile i160, ptr [[P]], align 2, !dbg [[DBG614:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(i160 [[P_0_R]], [[META608:![0-9]+]], !DIExpression(), [[DBG614]])
+; DEBUG-NEXT:    store i160 [[P_0_R]], ptr [[OUT:%.*]], align 2, !dbg [[DBG615:![0-9]+]]
+; DEBUG-NEXT:    ret void, !dbg [[DBG616:![0-9]+]]
+;
+entry:
+  %p = alloca i160, align 2
+  store x86_fp80 %a, ptr %p, align 2
+  %q = getelementptr inbounds i8, ptr %p, i64 10
+  store x86_fp80 %b, ptr %q, align 2
+  %r = load volatile i160, ptr %p, align 2
+  store i160 %r, ptr %out, align 2
+  ret void
+}
+
+; Negative test: using f16 (or bf16) tiles is usually not beneficial.
+define double @F16DoesNotTile(half %a, half %b, half %c, half %d) {
+; CHECK-LABEL: @F16DoesNotTile(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P:%.*]] = alloca double, align 8
+; CHECK-NEXT:    store half [[A:%.*]], ptr [[P]], align 8
+; CHECK-NEXT:    [[P_2_Q1_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2
+; CHECK-NEXT:    store half [[B:%.*]], ptr [[P_2_Q1_SROA_IDX]], align 2
+; CHECK-NEXT:    [[P_4_Q2_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4
+; CHECK-NEXT:    store half [[C:%.*]], ptr [[P_4_Q2_SROA_IDX]], align 4
+; CHECK-NEXT:    [[P_6_Q3_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 6
+; CHECK-NEXT:    store half [[D:%.*]], ptr [[P_6_Q3_SROA_IDX]], align 2
+; CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr [[P]], align 8
+; CHECK-NEXT:    ret double [[TMP0]]
+;
+; DEBUG-LABEL: @F16DoesNotTile(
+; DEBUG-NEXT:  entry:
+; DEBUG-NEXT:    [[P:%.*]] = alloca double, align 8, !dbg [[DBG624:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(ptr [[P]], [[META619:![0-9]+]], !DIExpression(), [[DBG624]])
+; DEBUG-NEXT:    store half [[A:%.*]], ptr [[P]], align 8, !dbg [[DBG625:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META620:![0-9]+]], !DIExpression(), [[META626:![0-9]+]])
+; DEBUG-NEXT:    [[P_2_Q1_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2, !dbg [[DBG627:![0-9]+]]
+; DEBUG-NEXT:    store half [[B:%.*]], ptr [[P_2_Q1_SROA_IDX]], align 2, !dbg [[DBG627]]
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META621:![0-9]+]], !DIExpression(), [[META628:![0-9]+]])
+; DEBUG-NEXT:    [[P_4_Q2_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4, !dbg [[DBG629:![0-9]+]]
+; DEBUG-NEXT:    store half [[C:%.*]], ptr [[P_4_Q2_SROA_IDX]], align 4, !dbg [[DBG629]]
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META622:![0-9]+]], !DIExpression(), [[META630:![0-9]+]])
+; DEBUG-NEXT:    [[P_6_Q3_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 6, !dbg [[DBG631:![0-9]+]]
+; DEBUG-NEXT:    store half [[D:%.*]], ptr [[P_6_Q3_SROA_IDX]], align 2, !dbg [[DBG631]]
+; DEBUG-NEXT:    [[P_0_R:%.*]] = load double, ptr [[P]], align 8, !dbg [[DBG632:![0-9]+]]
+; DEBUG-NEXT:      #dbg_value(double [[P_0_R]], [[META623:![0-9]+]], !DIExpression(), [[DBG632]])
+; DEBUG-NEXT:    ret double [[P_0_R]], !dbg [[DBG633:![0-9]+]]
+;
+entry:
+  %p = alloca double, align 8
+  store half %a, ptr %p, align 8
+  %q1 = getelementptr inbounds i8, ptr %p, i64 2
+  store half %b, ptr %q1, align 2
+  %q2 = getelementptr inbounds i8, ptr %p, i64 4
+  store half %c, ptr %q2, align 4
+  %q3 = getelementptr inbounds i8, ptr %p, i64 6
+  store half %d, ptr %q3, align 2
+  %r = load double, ptr %p, align 8
+  ret double %r
+}
+
+; Negative test: don't tile integers, scalar operations are usually cheaper.
+define i64 @IntDoesNotTile(i32 %a, i32 %b) {
+; CHECK-LABEL: @IntDoesNotTile(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P_SROA_2_0_INSERT_EXT:%.*]] = zext i32 [[B:%.*]] to i64
+; CHECK-NEXT:    [[P_SROA_2_0_INSERT_SHIFT:%.*]] = shl i64 [[P_SROA_2_0_INSERT_EXT]], 32
+; CHECK-NEXT:    [[P_SROA_2_0_INSERT_MASK:%.*]] = and i64 undef, 4294967295
+; CHECK-NEXT:    [[P_SROA_2_0_INSERT_INSERT:%.*]] = or i64 [[P_SROA_2_0_INSERT_MASK]], [[P_SROA_2_0_INSERT_SHIFT]]
+; CHECK-NEXT:    [[P_SROA_0_0_INSERT_EXT:%.*]] = zext i32 [[A:%.*]] to i64
+; CHECK-NEXT:    [[P_SROA_0_0_INSERT_MASK:%.*]] = and i64 [[P_SROA_2_0_INSERT_INSERT]], -4294967296
+; CHECK-NEXT:    [[P_SROA_0_0_INSERT_INSERT:%.*]] = or i64 [[P_SROA_0_0_INSERT_MASK]], [[P_SROA_0_0_INSERT_EXT]]
+; CHECK-NEXT:    ret i64 [[P_SROA_0_0_INSERT_INSERT]]
+;
+; DEBUG-LABEL: @IntDoesNotTile(
+; DEBUG-NEXT:  entry:
+; DEBUG-NEXT:      #dbg_value(ptr poison, [[META636:![0-9]+]], !DIExpression(DW_OP_LLVM_fragment, 0, 32), [[META639:![0-9]+]])
+; DEBUG-NEXT:      #dbg_value(ptr poison, [[META636]], !DIExpression(DW_OP_LLVM_fragment, 32, 32), [[META639]])
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META636]], !DIExpression(), [[META639]])
+; DEBUG-NEXT:      #dbg_value(ptr undef, [[META637:![0-9]+]], !DIExpression(), [[META640:![0-9]+]])
+; DEBUG-NEXT:    [[P_SROA_2_0_INSERT_EXT:%.*]] = zext i32 [[B:%.*]] to i64, !dbg [[DBG641:![0-9]+]]
+; DEBUG-NEXT:    [[P_SROA_2_0_INSERT_SHIFT:%.*]] = shl i64 [[P_SROA_2_0_INSERT_EXT]], 32, !dbg [[DBG641]]
+; DEBUG-NEXT:    [[P_SROA_2_0_INSERT_MASK:%.*]] = and i64 undef, 4294967295, !dbg [[DBG641]]
+; DEBUG-NEXT:    [[P_SROA_2_0_INSERT_INSERT:%.*]] = or i64 [[P_SROA_2_0_INSERT_MASK]], [[P_SROA_2_0_INSERT_SHIFT]], !dbg [[DBG641]]
+; DEBUG-NEXT:    [[P_SROA_0_0_INSERT_EXT:%.*]] = zext i32 [[A:%.*]] to i64, !dbg [[DBG641]]
+; DEBUG-NEXT:    [[P_SROA_0_0_INSERT_MASK:%.*]] = and i64 [[P_SROA_2_0_INSERT_INSERT]], -4294967296, !dbg [[DBG641]]
+; DEBUG-NEXT:    [[P_SROA_0_0_INSERT_INSERT:%.*]] = or i64 [[P_SROA_0_0_INSERT_MASK]], [[P_SROA_0_0_INSERT_EXT]], !dbg [[DBG641]]
+; DEBUG-NEXT:      #dbg_value(i64 [[P_SROA_0_0_INSERT_INSERT]], [[META638:![0-9]+]], !DIExpression(), [[META642:![0-9]+]])
+; DEBUG-NEXT:    ret i64 [[P_SROA_0_0_INSERT_INSERT]], !dbg [[DBG641]]
+;
+entry:
+  %p = alloca i64, align 8
+  store i32 %a, ptr %p, align 8
+  %q = getelementptr inbounds i8, ptr %p, i64 4
+  store i32 %b, ptr %q, align 4
+  %r = load i64, ptr %p, align 8
+  ret i64 %r
+}
+
 declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
 declare void @llvm.lifetime.end.p0(ptr)
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:



More information about the llvm-commits mailing list