[SROA] Add new test cases to cover existing SROA behavior that structs will be scalar...
authorMingming Liu <mingmingl@google.com>
Fri, 19 Nov 2021 18:16:11 +0000 (18:16 +0000)
committerMingming Liu <mingmingl@google.com>
Fri, 19 Nov 2021 18:16:49 +0000 (18:16 +0000)
Add an IR in unit test directory, which demonstrate the scalarization for struct allocations.
This is added to pave the way for an SROA change to skip scalarization for some cases.

Reviewed By: davidxl

Differential Revision: https://reviews.llvm.org/D114128

llvm/test/Transforms/SROA/alloca-struct.ll [new file with mode: 0644]

diff --git a/llvm/test/Transforms/SROA/alloca-struct.ll b/llvm/test/Transforms/SROA/alloca-struct.ll
new file mode 100644 (file)
index 0000000..17257ea
--- /dev/null
@@ -0,0 +1,139 @@
+; 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()