We tend to assume that the AA pipeline is by default the default AA pipeline and it's confusing when it's empty instead. PR48779 Initially reverted due to BasicAA running analyses in an unspecified order (multiple function calls as parameters), fixed by fetching analyses before the call to construct BasicAA. Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D95117
203 lines
7.4 KiB
LLVM
203 lines
7.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -O3 -S | FileCheck %s
|
|
; RUN: opt < %s -passes='default<O3>' -S | FileCheck %s
|
|
|
|
; This is based on the following most basic C++ code:
|
|
;
|
|
; #include <array>
|
|
; void use(int);
|
|
; void foo(int cnt) {
|
|
; std::array<int, 6> arr;
|
|
; for(int& elt : arr)
|
|
; elt = ++cnt;
|
|
; for(int& elt : arr)
|
|
; use(elt);
|
|
; }
|
|
;
|
|
; Not only should the loops be unrolled, no alloca's should be left there.
|
|
|
|
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.std::array" = type { [6 x i32] }
|
|
|
|
define dso_local void @_Z3fooi(i32 %cnt) {
|
|
; CHECK-LABEL: @_Z3fooi(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[CNT:%.*]], 1
|
|
; CHECK-NEXT: [[INC_1:%.*]] = add nsw i32 [[CNT]], 2
|
|
; CHECK-NEXT: [[INC_2:%.*]] = add nsw i32 [[CNT]], 3
|
|
; CHECK-NEXT: [[INC_3:%.*]] = add nsw i32 [[CNT]], 4
|
|
; CHECK-NEXT: [[INC_4:%.*]] = add nsw i32 [[CNT]], 5
|
|
; CHECK-NEXT: [[INC_5:%.*]] = add nsw i32 [[CNT]], 6
|
|
; CHECK-NEXT: call void @_Z3usei(i32 [[INC]])
|
|
; CHECK-NEXT: call void @_Z3usei(i32 [[INC_1]])
|
|
; CHECK-NEXT: call void @_Z3usei(i32 [[INC_2]])
|
|
; CHECK-NEXT: call void @_Z3usei(i32 [[INC_3]])
|
|
; CHECK-NEXT: call void @_Z3usei(i32 [[INC_4]])
|
|
; CHECK-NEXT: call void @_Z3usei(i32 [[INC_5]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cnt.addr = alloca i32
|
|
%arr = alloca %"struct.std::array"
|
|
%__range1 = alloca %"struct.std::array"*
|
|
%__begin1 = alloca i32*
|
|
%__end1 = alloca i32*
|
|
%elt = alloca i32*
|
|
%__range12 = alloca %"struct.std::array"*
|
|
%__begin13 = alloca i32*
|
|
%__end15 = alloca i32*
|
|
%elt11 = alloca i32*
|
|
store i32 %cnt, i32* %cnt.addr
|
|
%0 = bitcast %"struct.std::array"* %arr to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 24, i8* %0)
|
|
%1 = bitcast %"struct.std::array"** %__range1 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %1)
|
|
store %"struct.std::array"* %arr, %"struct.std::array"** %__range1
|
|
%2 = bitcast i32** %__begin1 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
|
|
%3 = load %"struct.std::array"*, %"struct.std::array"** %__range1
|
|
%call = call i32* @_ZNSt5arrayIiLm6EE5beginEv(%"struct.std::array"* %3)
|
|
store i32* %call, i32** %__begin1
|
|
%4 = bitcast i32** %__end1 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %4)
|
|
%5 = load %"struct.std::array"*, %"struct.std::array"** %__range1
|
|
%call1 = call i32* @_ZNSt5arrayIiLm6EE3endEv(%"struct.std::array"* %5)
|
|
store i32* %call1, i32** %__end1
|
|
br label %for.cond
|
|
|
|
for.cond:
|
|
%6 = load i32*, i32** %__begin1
|
|
%7 = load i32*, i32** %__end1
|
|
%cmp = icmp ne i32* %6, %7
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup:
|
|
%8 = bitcast i32** %__end1 to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
|
|
%9 = bitcast i32** %__begin1 to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %9)
|
|
%10 = bitcast %"struct.std::array"** %__range1 to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %10)
|
|
br label %for.end
|
|
|
|
for.body:
|
|
%11 = bitcast i32** %elt to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %11)
|
|
%12 = load i32*, i32** %__begin1
|
|
store i32* %12, i32** %elt
|
|
%13 = load i32, i32* %cnt.addr
|
|
%inc = add nsw i32 %13, 1
|
|
store i32 %inc, i32* %cnt.addr
|
|
%14 = load i32*, i32** %elt
|
|
store i32 %inc, i32* %14
|
|
%15 = bitcast i32** %elt to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %15)
|
|
br label %for.inc
|
|
|
|
for.inc:
|
|
%16 = load i32*, i32** %__begin1
|
|
%incdec.ptr = getelementptr inbounds i32, i32* %16, i32 1
|
|
store i32* %incdec.ptr, i32** %__begin1
|
|
br label %for.cond
|
|
|
|
for.end:
|
|
%17 = bitcast %"struct.std::array"** %__range12 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %17)
|
|
store %"struct.std::array"* %arr, %"struct.std::array"** %__range12
|
|
%18 = bitcast i32** %__begin13 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %18)
|
|
%19 = load %"struct.std::array"*, %"struct.std::array"** %__range12
|
|
%call4 = call i32* @_ZNSt5arrayIiLm6EE5beginEv(%"struct.std::array"* %19)
|
|
store i32* %call4, i32** %__begin13
|
|
%20 = bitcast i32** %__end15 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %20)
|
|
%21 = load %"struct.std::array"*, %"struct.std::array"** %__range12
|
|
%call6 = call i32* @_ZNSt5arrayIiLm6EE3endEv(%"struct.std::array"* %21)
|
|
store i32* %call6, i32** %__end15
|
|
br label %for.cond7
|
|
|
|
for.cond7:
|
|
%22 = load i32*, i32** %__begin13
|
|
%23 = load i32*, i32** %__end15
|
|
%cmp8 = icmp ne i32* %22, %23
|
|
br i1 %cmp8, label %for.body10, label %for.cond.cleanup9
|
|
|
|
for.cond.cleanup9:
|
|
%24 = bitcast i32** %__end15 to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %24)
|
|
%25 = bitcast i32** %__begin13 to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %25)
|
|
%26 = bitcast %"struct.std::array"** %__range12 to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %26)
|
|
br label %for.end14
|
|
|
|
for.body10:
|
|
%27 = bitcast i32** %elt11 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 8, i8* %27)
|
|
%28 = load i32*, i32** %__begin13
|
|
store i32* %28, i32** %elt11
|
|
%29 = load i32*, i32** %elt11
|
|
%30 = load i32, i32* %29
|
|
call void @_Z3usei(i32 %30)
|
|
%31 = bitcast i32** %elt11 to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 8, i8* %31)
|
|
br label %for.inc12
|
|
|
|
for.inc12:
|
|
%32 = load i32*, i32** %__begin13
|
|
%incdec.ptr13 = getelementptr inbounds i32, i32* %32, i32 1
|
|
store i32* %incdec.ptr13, i32** %__begin13
|
|
br label %for.cond7
|
|
|
|
for.end14:
|
|
%33 = bitcast %"struct.std::array"* %arr to i8*
|
|
call void @llvm.lifetime.end.p0i8(i64 24, i8* %33)
|
|
ret void
|
|
}
|
|
|
|
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
|
|
|
|
define linkonce_odr dso_local i32* @_ZNSt5arrayIiLm6EE5beginEv(%"struct.std::array"* %this) {
|
|
entry:
|
|
%this.addr = alloca %"struct.std::array"*
|
|
store %"struct.std::array"* %this, %"struct.std::array"** %this.addr
|
|
%this1 = load %"struct.std::array"*, %"struct.std::array"** %this.addr
|
|
%call = call i32* @_ZNSt5arrayIiLm6EE4dataEv(%"struct.std::array"* %this1)
|
|
ret i32* %call
|
|
}
|
|
|
|
define linkonce_odr dso_local i32* @_ZNSt5arrayIiLm6EE3endEv(%"struct.std::array"* %this) {
|
|
entry:
|
|
%this.addr = alloca %"struct.std::array"*
|
|
store %"struct.std::array"* %this, %"struct.std::array"** %this.addr
|
|
%this1 = load %"struct.std::array"*, %"struct.std::array"** %this.addr
|
|
%call = call i32* @_ZNSt5arrayIiLm6EE4dataEv(%"struct.std::array"* %this1)
|
|
%add.ptr = getelementptr inbounds i32, i32* %call, i64 6
|
|
ret i32* %add.ptr
|
|
}
|
|
|
|
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
|
|
|
|
declare dso_local void @_Z3usei(i32)
|
|
|
|
define linkonce_odr dso_local i32* @_ZNSt5arrayIiLm6EE4dataEv(%"struct.std::array"* %this) {
|
|
entry:
|
|
%this.addr = alloca %"struct.std::array"*
|
|
store %"struct.std::array"* %this, %"struct.std::array"** %this.addr
|
|
%this1 = load %"struct.std::array"*, %"struct.std::array"** %this.addr
|
|
%_M_elems = getelementptr inbounds %"struct.std::array", %"struct.std::array"* %this1, i32 0, i32 0
|
|
%call = call i32* @_ZNSt14__array_traitsIiLm6EE6_S_ptrERA6_Ki([6 x i32]* nonnull align 4 dereferenceable(24) %_M_elems)
|
|
ret i32* %call
|
|
}
|
|
|
|
define linkonce_odr dso_local i32* @_ZNSt14__array_traitsIiLm6EE6_S_ptrERA6_Ki([6 x i32]* nonnull align 4 dereferenceable(24) %__t) {
|
|
entry:
|
|
%__t.addr = alloca [6 x i32]*
|
|
store [6 x i32]* %__t, [6 x i32]** %__t.addr
|
|
%0 = load [6 x i32]*, [6 x i32]** %__t.addr
|
|
%arraydecay = getelementptr inbounds [6 x i32], [6 x i32]* %0, i64 0, i64 0
|
|
ret i32* %arraydecay
|
|
}
|