[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 18:22:21 PDT 2026
https://github.com/folkertdev updated https://github.com/llvm/llvm-project/pull/223285
>From 6f3a1aee39110651076fc731e557693e33287c1e 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 | 167 ++++++++++++++++++
5 files changed, 201 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..c273597886bb7 100644
--- a/llvm/test/Transforms/SROA/vector-promotion.ll
+++ b/llvm/test/Transforms/SROA/vector-promotion.ll
@@ -1533,6 +1533,173 @@ bb.5:
br label %bb.5
}
+define double @FloatTilesDoubleInsert(double %init, float %a, float %b) {
+; CHECK-LABEL: @FloatTilesDoubleInsert(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast double [[INIT:%.*]] to <2 x float>
+; CHECK-NEXT: [[P_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x float> [[TMP1]], 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: [[TMP0:%.*]] = bitcast double [[INIT:%.*]] to <2 x float>, !dbg [[DBG589:![0-9]+]]
+; DEBUG-NEXT: [[P_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x float> [[TMP0]], float [[A:%.*]], i64 0, !dbg [[DBG590:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META586:![0-9]+]], !DIExpression(), [[META591:![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 [[DBG592:![0-9]+]]
+; DEBUG-NEXT: [[TMP1:%.*]] = bitcast <2 x float> [[P_SROA_0_4_VEC_INSERT]] to double, !dbg [[DBG593:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(double [[TMP1]], [[META587:![0-9]+]], !DIExpression(), [[DBG593]])
+; DEBUG-NEXT: ret double [[TMP1]], !dbg [[DBG594:![0-9]+]]
+;
+entry:
+ %p = alloca double, align 8
+ store double %init, ptr %p, 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, [[META597:![0-9]+]], !DIExpression(), [[META600:![0-9]+]])
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META597]], !DIExpression(), [[META600]])
+; DEBUG-NEXT: [[TMP0:%.*]] = bitcast double [[X:%.*]] to <2 x float>, !dbg [[DBG601:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META598:![0-9]+]], !DIExpression(), [[META602:![0-9]+]])
+; DEBUG-NEXT: [[P_SROA_0_4_VEC_EXTRACT:%.*]] = extractelement <2 x float> [[TMP0]], i64 1, !dbg [[DBG603:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(float [[P_SROA_0_4_VEC_EXTRACT]], [[META599:![0-9]+]], !DIExpression(), [[DBG603]])
+; DEBUG-NEXT: ret float [[P_SROA_0_4_VEC_EXTRACT]], !dbg [[DBG604:![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 [[DBG611:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(ptr [[P]], [[META607:![0-9]+]], !DIExpression(), [[DBG611]])
+; DEBUG-NEXT: store x86_fp80 [[A:%.*]], ptr [[P]], align 2, !dbg [[DBG612:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META608:![0-9]+]], !DIExpression(), [[META613:![0-9]+]])
+; DEBUG-NEXT: [[P_10_Q_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 10, !dbg [[DBG614:![0-9]+]]
+; DEBUG-NEXT: store x86_fp80 [[B:%.*]], ptr [[P_10_Q_SROA_IDX]], align 2, !dbg [[DBG614]]
+; DEBUG-NEXT: [[P_0_R:%.*]] = load volatile i160, ptr [[P]], align 2, !dbg [[DBG615:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(i160 [[P_0_R]], [[META609:![0-9]+]], !DIExpression(), [[DBG615]])
+; DEBUG-NEXT: store i160 [[P_0_R]], ptr [[OUT:%.*]], align 2, !dbg [[DBG616:![0-9]+]]
+; DEBUG-NEXT: ret void, !dbg [[DBG617:![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 [[DBG625:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(ptr [[P]], [[META620:![0-9]+]], !DIExpression(), [[DBG625]])
+; DEBUG-NEXT: store half [[A:%.*]], ptr [[P]], align 8, !dbg [[DBG626:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META621:![0-9]+]], !DIExpression(), [[META627:![0-9]+]])
+; DEBUG-NEXT: [[P_2_Q1_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2, !dbg [[DBG628:![0-9]+]]
+; DEBUG-NEXT: store half [[B:%.*]], ptr [[P_2_Q1_SROA_IDX]], align 2, !dbg [[DBG628]]
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META622:![0-9]+]], !DIExpression(), [[META629:![0-9]+]])
+; DEBUG-NEXT: [[P_4_Q2_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4, !dbg [[DBG630:![0-9]+]]
+; DEBUG-NEXT: store half [[C:%.*]], ptr [[P_4_Q2_SROA_IDX]], align 4, !dbg [[DBG630]]
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META623:![0-9]+]], !DIExpression(), [[META631:![0-9]+]])
+; DEBUG-NEXT: [[P_6_Q3_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 6, !dbg [[DBG632:![0-9]+]]
+; DEBUG-NEXT: store half [[D:%.*]], ptr [[P_6_Q3_SROA_IDX]], align 2, !dbg [[DBG632]]
+; DEBUG-NEXT: [[P_0_R:%.*]] = load double, ptr [[P]], align 8, !dbg [[DBG633:![0-9]+]]
+; DEBUG-NEXT: #dbg_value(double [[P_0_R]], [[META624:![0-9]+]], !DIExpression(), [[DBG633]])
+; DEBUG-NEXT: ret double [[P_0_R]], !dbg [[DBG634:![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 i32 @IntDoesNotTile(i64 %x) {
+; CHECK-LABEL: @IntDoesNotTile(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[P_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[X:%.*]] to i32
+; CHECK-NEXT: [[P_SROA_1_0_EXTRACT_SHIFT:%.*]] = lshr i64 [[X]], 32
+; CHECK-NEXT: [[P_SROA_1_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[P_SROA_1_0_EXTRACT_SHIFT]] to i32
+; CHECK-NEXT: ret i32 [[P_SROA_1_0_EXTRACT_TRUNC]]
+;
+; DEBUG-LABEL: @IntDoesNotTile(
+; DEBUG-NEXT: entry:
+; DEBUG-NEXT: #dbg_value(ptr poison, [[META637:![0-9]+]], !DIExpression(DW_OP_LLVM_fragment, 0, 32), [[META640:![0-9]+]])
+; DEBUG-NEXT: #dbg_value(ptr poison, [[META637]], !DIExpression(DW_OP_LLVM_fragment, 32, 32), [[META640]])
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META637]], !DIExpression(), [[META640]])
+; DEBUG-NEXT: [[P_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[X:%.*]] to i32, !dbg [[DBG641:![0-9]+]]
+; DEBUG-NEXT: [[P_SROA_1_0_EXTRACT_SHIFT:%.*]] = lshr i64 [[X]], 32, !dbg [[DBG641]]
+; DEBUG-NEXT: [[P_SROA_1_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[P_SROA_1_0_EXTRACT_SHIFT]] to i32, !dbg [[DBG641]]
+; DEBUG-NEXT: #dbg_value(ptr undef, [[META638:![0-9]+]], !DIExpression(), [[META642:![0-9]+]])
+; DEBUG-NEXT: #dbg_value(i32 [[P_SROA_1_0_EXTRACT_TRUNC]], [[META639:![0-9]+]], !DIExpression(), [[META643:![0-9]+]])
+; DEBUG-NEXT: ret i32 [[P_SROA_1_0_EXTRACT_TRUNC]], !dbg [[DBG644:![0-9]+]]
+;
+entry:
+ %p = alloca i64, align 8
+ store i64 %x, ptr %p, align 8
+ %q = getelementptr inbounds i8, ptr %p, i64 4
+ %r = load i32, ptr %q, align 4
+ ret i32 %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