diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index 5c60fad6f91aa..f348bf2ca7353 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -5234,14 +5234,16 @@ AllocaInst *SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, SliceTy = TypePartitionTy; // If still not, can we use the largest bitwidth integer type used? - if (!SliceTy && CommonUseTy.second) + // If SliceTy is a non-promotable aggregate, prefer to represent as an integer + // type because it's more likely to be promotable. + if ((!SliceTy || !SliceTy->isSingleValueType()) && CommonUseTy.second) if (DL.getTypeAllocSize(CommonUseTy.second).getFixedValue() >= P.size()) { SliceTy = CommonUseTy.second; SliceVecTy = dyn_cast(SliceTy); } - if ((!SliceTy || (SliceTy->isArrayTy() && - SliceTy->getArrayElementType()->isIntegerTy())) && - DL.isLegalInteger(P.size() * 8)) { + // Try representing the partition as a legal integer type of the same size as + // the alloca. + if ((!SliceTy || SliceTy->isArrayTy()) && DL.isLegalInteger(P.size() * 8)) { SliceTy = Type::getIntNTy(*C, P.size() * 8); } diff --git a/llvm/test/Transforms/SROA/prefer-integer-partition.ll b/llvm/test/Transforms/SROA/prefer-integer-partition.ll new file mode 100644 index 0000000000000..78d3b22d3fdc0 --- /dev/null +++ b/llvm/test/Transforms/SROA/prefer-integer-partition.ll @@ -0,0 +1,46 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=sroa -S | FileCheck %s + +; Test that SROA converts array types to integer types for promotion. + +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32-ni:10:11:12:13" + +define void @test_float_array_only_intrinsics() { +; CHECK-LABEL: @test_float_array_only_intrinsics( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void +; +entry: + %src = alloca [2 x float], align 4 + %dst = alloca [2 x float], align 4 + + call void @llvm.lifetime.start.p0(i64 8, ptr %src) + call void @llvm.lifetime.start.p0(i64 8, ptr %dst) + + ; Only intrinsic uses - no scalar loads/stores to establish common type + call void @llvm.memset.p0.i64(ptr %src, i8 42, i64 8, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 8, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr %src, ptr %dst, i64 8, i1 false) + + call void @llvm.lifetime.end.p0(i64 8, ptr %dst) + call void @llvm.lifetime.end.p0(i64 8, ptr %src) + ret void +} + +define void @test_mixed_types() { +; CHECK-LABEL: @test_mixed_types( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32 42 to float +; CHECK-NEXT: ret void +; +entry: + %alloca = alloca [2 x half] + store i32 42, ptr %alloca + %val = load float, ptr %alloca + ret void +} + +declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) +declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) +declare void @llvm.lifetime.start.p0(i64, ptr nocapture) +declare void @llvm.lifetime.end.p0(i64, ptr nocapture)