--- /dev/null
+; RUN: opt < %s -sroa -S | FileCheck %s
+; RUN: opt < %s -passes=sroa -S | FileCheck %s
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.RetValIntChar = type { i32, i8 }
+%struct.RetValTwoInts = type { i32, i32 }
+%struct.RetValOneIntTwoChar = type { i32, i8 }
+
+; Tests that a struct of type {i32, i8} is scalarized by SROA.
+; FIXME: SROA should skip scalarization since there is no scalar access.
+; Currently scalarization happens due to the mismatch of allocated size
+; and the actual structure size.
+define i64 @test_struct_of_int_char(i1 zeroext %test, i64 ()* %p) {
+; CHECK-LABEL: @test_struct_of_int_char(
+; CHECK-NEXT: entry:
+; COM: Check that registers are used and alloca instructions are eliminated.
+; CHECK-NOT: alloca
+; CHECK: if.then:
+; CHECK-NEXT: br label [[RETURN:%.*]]
+; CHECK: if.end:
+; CHECK-NEXT: call i64 [[P:%.*]]()
+; CHECK: br label [[RETURN]]
+; CHECK: return:
+; COM: Check there are more than one PHI nodes to select scalarized values.
+; CHECK-COUNT-3: phi
+; CHECK: ret i64
+;
+entry:
+ %retval = alloca %struct.RetValIntChar, align 4
+ br i1 %test, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ %x = getelementptr inbounds %struct.RetValIntChar, %struct.RetValIntChar* %retval, i32 0, i32 0
+ store i32 0, i32* %x, align 4
+ %y = getelementptr inbounds %struct.RetValIntChar, %struct.RetValIntChar* %retval, i32 0, i32 1
+ store i8 0, i8* %y, align 4
+ br label %return
+
+if.end: ; preds = %entry
+ %call = call i64 %p()
+ %0 = bitcast %struct.RetValIntChar* %retval to i64*
+ store i64 %call, i64* %0, align 4
+ br label %return
+
+return: ; preds = %if.end, %if.then
+ %1 = bitcast %struct.RetValIntChar* %retval to i64*
+ %2 = load i64, i64* %1, align 4
+ ret i64 %2
+}
+
+; Test that the alloca of struct{int, int} will be scalarized by SROA.
+define i64 @test_struct_of_two_int(i1 zeroext %test, i64 ()* %p) {
+; CHECK-LABEL: @test_struct_of_two_int(
+; CHECK-NEXT: entry:
+; CHECK-NOT: alloca
+; CHECK: if.then:
+; CHECK-NEXT: br label [[RETURN:%.*]]
+; CHECK: if.end:
+; CHECK-NEXT: call i64
+; CHECK: return:
+; COM: Check that there are more than one PHI nodes to select the scalarized values.
+; CHECK-COUNT-2: phi
+; CHECK: ret i64
+;
+entry:
+ %retval = alloca %struct.RetValTwoInts, align 4
+ br i1 %test, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ %x = getelementptr inbounds %struct.RetValTwoInts, %struct.RetValTwoInts* %retval, i32 0, i32 0
+ store i32 0, i32* %x, align 4
+ %y = getelementptr inbounds %struct.RetValTwoInts, %struct.RetValTwoInts* %retval, i32 0, i32 1
+ store i32 0, i32* %y, align 4
+ br label %return
+
+if.end: ; preds = %entry
+ %call = call i64 %p()
+ %0 = bitcast %struct.RetValTwoInts* %retval to i64*
+ store i64 %call, i64* %0, align 4
+ br label %return
+
+return: ; preds = %if.end, %if.then
+ %1 = bitcast %struct.RetValTwoInts* %retval to i64*
+ %2 = load i64, i64* %1, align 4
+ ret i64 %2
+}
+
+; Tests that allocated struct type is scalarized when non-constant values are
+; stored into its fields.
+define i64 @test_one_field_has_runtime_value(i1 zeroext %test, i64 ()* %p) {
+; CHECK-LABEL: @test_one_field_has_runtime_value(
+; CHECK-NEXT: entry:
+; CHECK-NOT: alloca
+; CHECK: call void @srand
+; CHECK: if.then:
+; CHECK-NEXT: call i32 @rand()
+; CHECK-NEXT: br label
+; CHECK: if.end:
+; CHECK-NEXT: call i64
+; CHECK: return:
+; CHECK-COUNT-2: phi i32
+; CHECK: ret i64
+;
+entry:
+ %retval = alloca %struct.RetValTwoInts, align 4
+ %call = call i64 @time(i64* null)
+ %conv = trunc i64 %call to i32
+ call void @srand(i32 %conv)
+ br i1 %test, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ %x = getelementptr inbounds %struct.RetValTwoInts, %struct.RetValTwoInts* %retval, i32 0, i32 0
+ %call1 = call i32 @rand()
+ store i32 %call1, i32* %x, align 4
+ %y = getelementptr inbounds %struct.RetValTwoInts, %struct.RetValTwoInts* %retval, i32 0, i32 1
+ store i32 1, i32* %y, align 4
+ br label %return
+
+if.end: ; preds = %entry
+ %call2 = call i64 %p()
+ %0 = bitcast %struct.RetValTwoInts* %retval to i64*
+ store i64 %call2, i64* %0, align 4
+ br label %return
+
+return: ; preds = %if.end, %if.then
+ %1 = bitcast %struct.RetValTwoInts* %retval to i64*
+ %2 = load i64, i64* %1, align 4
+ ret i64 %2
+}
+
+; Function Attrs: nounwind
+declare void @srand(i32)
+
+; Function Attrs: nounwind
+declare i64 @time(i64*)
+
+; Function Attrs: nounwind
+declare i32 @rand()