summaryrefslogtreecommitdiff
path: root/test/Transforms/SROA
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-10-13 10:49:33 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-10-13 10:49:33 +0000
commit07525a6be6bce604f3b528c91973ac4e66742266 (patch)
tree96d66d8fdab7bb502cd9042ed36a58796b180e45 /test/Transforms/SROA
parentac104272d9fc42af8dc6853853b96d489685e5a7 (diff)
downloadllvm-07525a6be6bce604f3b528c91973ac4e66742266.tar.gz
llvm-07525a6be6bce604f3b528c91973ac4e66742266.tar.bz2
llvm-07525a6be6bce604f3b528c91973ac4e66742266.tar.xz
Teach SROA to cope with wrapper aggregates. These show up a lot in ABI
type coercion code, especially when targetting ARM. Things like [1 x i32] instead of i32 are very common there. The goal of this logic is to ensure that when we are picking an alloca type, we look through such wrapper aggregates and across any zero-length aggregate elements to find the simplest type possible to form a type partition. This logic should (generally speaking) rarely fire. It only ends up kicking in when an alloca is accessed using two different types (for instance, i32 and float), and the underlying alloca type has wrapper aggregates around it. I noticed a significant amount of this occurring looking at stepanov_abstraction generated code for arm, and suspect it happens elsewhere as well. Note that this doesn't yet address truly heinous IR productions such as PR14059 is concerning. Those result in mismatched *sizes* of types in addition to mismatched access and alloca types. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165870 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Transforms/SROA')
-rw-r--r--test/Transforms/SROA/alignment.ll31
-rw-r--r--test/Transforms/SROA/basictest.ll44
2 files changed, 44 insertions, 31 deletions
diff --git a/test/Transforms/SROA/alignment.ll b/test/Transforms/SROA/alignment.ll
index 945ad91002..ad5fb6c4a5 100644
--- a/test/Transforms/SROA/alignment.ll
+++ b/test/Transforms/SROA/alignment.ll
@@ -84,37 +84,6 @@ entry:
ret void
}
-%struct.S = type { i8, { i64 } }
-
-define void @test4() {
-; This test case triggered very strange alignment behavior with memcpy due to
-; strange splitting. Reported by Duncan.
-; CHECK: @test4
-
-entry:
- %D.2113 = alloca %struct.S
- %Op = alloca %struct.S
- %D.2114 = alloca %struct.S
- %gep1 = getelementptr inbounds %struct.S* %Op, i32 0, i32 0
- store i8 0, i8* %gep1, align 8
- %gep2 = getelementptr inbounds %struct.S* %Op, i32 0, i32 1, i32 0
- %cast = bitcast i64* %gep2 to double*
- store double 0.000000e+00, double* %cast, align 8
- store i64 0, i64* %gep2, align 8
- %dst1 = bitcast %struct.S* %D.2114 to i8*
- %src1 = bitcast %struct.S* %Op to i8*
- call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst1, i8* %src1, i32 16, i32 8, i1 false)
- %dst2 = bitcast %struct.S* %D.2113 to i8*
- %src2 = bitcast %struct.S* %D.2114 to i8*
- call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst2, i8* %src2, i32 16, i32 8, i1 false)
-; We get 3 memcpy calls with various reasons to shrink their alignment to 1.
-; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 3, i32 1, i1 false)
-; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 8, i32 1, i1 false)
-; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 11, i32 1, i1 false)
-
- ret void
-}
-
define void @test5() {
; Test that we preserve underaligned loads and stores when splitting.
; CHECK: @test5
diff --git a/test/Transforms/SROA/basictest.ll b/test/Transforms/SROA/basictest.ll
index e7767ef5e9..7d8e5cdf86 100644
--- a/test/Transforms/SROA/basictest.ll
+++ b/test/Transforms/SROA/basictest.ll
@@ -968,3 +968,47 @@ entry:
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %cast0, i8* %cast1, i32 12, i32 0, i1 false)
ret void
}
+
+define i32 @test22(i32 %x) {
+; Test that SROA and promotion is not confused by a grab bax mixture of pointer
+; types involving wrapper aggregates and zero-length aggregate members.
+; CHECK: @test22
+
+entry:
+ %a1 = alloca { { [1 x { i32 }] } }
+ %a2 = alloca { {}, { float }, [0 x i8] }
+ %a3 = alloca { [0 x i8], { [0 x double], [1 x [1 x <4 x i8>]], {} }, { { {} } } }
+; CHECK-NOT: alloca
+
+ %wrap1 = insertvalue [1 x { i32 }] undef, i32 %x, 0, 0
+ %gep1 = getelementptr { { [1 x { i32 }] } }* %a1, i32 0, i32 0, i32 0
+ store [1 x { i32 }] %wrap1, [1 x { i32 }]* %gep1
+
+ %gep2 = getelementptr { { [1 x { i32 }] } }* %a1, i32 0, i32 0
+ %ptrcast1 = bitcast { [1 x { i32 }] }* %gep2 to { [1 x { float }] }*
+ %load1 = load { [1 x { float }] }* %ptrcast1
+ %unwrap1 = extractvalue { [1 x { float }] } %load1, 0, 0
+
+ %wrap2 = insertvalue { {}, { float }, [0 x i8] } undef, { float } %unwrap1, 1
+ store { {}, { float }, [0 x i8] } %wrap2, { {}, { float }, [0 x i8] }* %a2
+
+ %gep3 = getelementptr { {}, { float }, [0 x i8] }* %a2, i32 0, i32 1, i32 0
+ %ptrcast2 = bitcast float* %gep3 to <4 x i8>*
+ %load3 = load <4 x i8>* %ptrcast2
+ %valcast1 = bitcast <4 x i8> %load3 to i32
+
+ %wrap3 = insertvalue [1 x [1 x i32]] undef, i32 %valcast1, 0, 0
+ %wrap4 = insertvalue { [1 x [1 x i32]], {} } undef, [1 x [1 x i32]] %wrap3, 0
+ %gep4 = getelementptr { [0 x i8], { [0 x double], [1 x [1 x <4 x i8>]], {} }, { { {} } } }* %a3, i32 0, i32 1
+ %ptrcast3 = bitcast { [0 x double], [1 x [1 x <4 x i8>]], {} }* %gep4 to { [1 x [1 x i32]], {} }*
+ store { [1 x [1 x i32]], {} } %wrap4, { [1 x [1 x i32]], {} }* %ptrcast3
+
+ %gep5 = getelementptr { [0 x i8], { [0 x double], [1 x [1 x <4 x i8>]], {} }, { { {} } } }* %a3, i32 0, i32 1, i32 1, i32 0
+ %ptrcast4 = bitcast [1 x <4 x i8>]* %gep5 to { {}, float, {} }*
+ %load4 = load { {}, float, {} }* %ptrcast4
+ %unwrap2 = extractvalue { {}, float, {} } %load4, 1
+ %valcast2 = bitcast float %unwrap2 to i32
+
+ ret i32 %valcast2
+; CHECK: ret i32
+}