1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
; 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 ptr
%__begin1 = alloca ptr
%__end1 = alloca ptr
%elt = alloca ptr
%__range12 = alloca ptr
%__begin13 = alloca ptr
%__end15 = alloca ptr
%elt11 = alloca ptr
store i32 %cnt, ptr %cnt.addr
call void @llvm.lifetime.start.p0(i64 24, ptr %arr)
call void @llvm.lifetime.start.p0(i64 8, ptr %__range1)
store ptr %arr, ptr %__range1
call void @llvm.lifetime.start.p0(i64 8, ptr %__begin1)
%0 = load ptr, ptr %__range1
%call = call ptr @_ZNSt5arrayIiLm6EE5beginEv(ptr %0)
store ptr %call, ptr %__begin1
call void @llvm.lifetime.start.p0(i64 8, ptr %__end1)
%1 = load ptr, ptr %__range1
%call1 = call ptr @_ZNSt5arrayIiLm6EE3endEv(ptr %1)
store ptr %call1, ptr %__end1
br label %for.cond
for.cond:
%2 = load ptr, ptr %__begin1
%3 = load ptr, ptr %__end1
%cmp = icmp ne ptr %2, %3
br i1 %cmp, label %for.body, label %for.cond.cleanup
for.cond.cleanup:
call void @llvm.lifetime.end.p0(i64 8, ptr %__end1)
call void @llvm.lifetime.end.p0(i64 8, ptr %__begin1)
call void @llvm.lifetime.end.p0(i64 8, ptr %__range1)
br label %for.end
for.body:
call void @llvm.lifetime.start.p0(i64 8, ptr %elt)
%4 = load ptr, ptr %__begin1
store ptr %4, ptr %elt
%5 = load i32, ptr %cnt.addr
%inc = add nsw i32 %5, 1
store i32 %inc, ptr %cnt.addr
%6 = load ptr, ptr %elt
store i32 %inc, ptr %6
call void @llvm.lifetime.end.p0(i64 8, ptr %elt)
br label %for.inc
for.inc:
%7 = load ptr, ptr %__begin1
%incdec.ptr = getelementptr inbounds i32, ptr %7, i32 1
store ptr %incdec.ptr, ptr %__begin1
br label %for.cond
for.end:
call void @llvm.lifetime.start.p0(i64 8, ptr %__range12)
store ptr %arr, ptr %__range12
call void @llvm.lifetime.start.p0(i64 8, ptr %__begin13)
%8 = load ptr, ptr %__range12
%call4 = call ptr @_ZNSt5arrayIiLm6EE5beginEv(ptr %8)
store ptr %call4, ptr %__begin13
call void @llvm.lifetime.start.p0(i64 8, ptr %__end15)
%9 = load ptr, ptr %__range12
%call6 = call ptr @_ZNSt5arrayIiLm6EE3endEv(ptr %9)
store ptr %call6, ptr %__end15
br label %for.cond7
for.cond7:
%10 = load ptr, ptr %__begin13
%11 = load ptr, ptr %__end15
%cmp8 = icmp ne ptr %10, %11
br i1 %cmp8, label %for.body10, label %for.cond.cleanup9
for.cond.cleanup9:
call void @llvm.lifetime.end.p0(i64 8, ptr %__end15)
call void @llvm.lifetime.end.p0(i64 8, ptr %__begin13)
call void @llvm.lifetime.end.p0(i64 8, ptr %__range12)
br label %for.end14
for.body10:
call void @llvm.lifetime.start.p0(i64 8, ptr %elt11)
%12 = load ptr, ptr %__begin13
store ptr %12, ptr %elt11
%13 = load ptr, ptr %elt11
%14 = load i32, ptr %13
call void @_Z3usei(i32 %14)
call void @llvm.lifetime.end.p0(i64 8, ptr %elt11)
br label %for.inc12
for.inc12:
%15 = load ptr, ptr %__begin13
%incdec.ptr13 = getelementptr inbounds i32, ptr %15, i32 1
store ptr %incdec.ptr13, ptr %__begin13
br label %for.cond7
for.end14:
call void @llvm.lifetime.end.p0(i64 24, ptr %arr)
ret void
}
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
define linkonce_odr dso_local ptr @_ZNSt5arrayIiLm6EE5beginEv(ptr %this) {
entry:
%this.addr = alloca ptr
store ptr %this, ptr %this.addr
%this1 = load ptr, ptr %this.addr
%call = call ptr @_ZNSt5arrayIiLm6EE4dataEv(ptr %this1)
ret ptr %call
}
define linkonce_odr dso_local ptr @_ZNSt5arrayIiLm6EE3endEv(ptr %this) {
entry:
%this.addr = alloca ptr
store ptr %this, ptr %this.addr
%this1 = load ptr, ptr %this.addr
%call = call ptr @_ZNSt5arrayIiLm6EE4dataEv(ptr %this1)
%add.ptr = getelementptr inbounds i32, ptr %call, i64 6
ret ptr %add.ptr
}
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
declare dso_local void @_Z3usei(i32)
define linkonce_odr dso_local ptr @_ZNSt5arrayIiLm6EE4dataEv(ptr %this) {
entry:
%this.addr = alloca ptr
store ptr %this, ptr %this.addr
%this1 = load ptr, ptr %this.addr
%call = call ptr @_ZNSt14__array_traitsIiLm6EE6_S_ptrERA6_Ki(ptr nonnull align 4 dereferenceable(24) %this1)
ret ptr %call
}
define linkonce_odr dso_local ptr @_ZNSt14__array_traitsIiLm6EE6_S_ptrERA6_Ki(ptr nonnull align 4 dereferenceable(24) %__t) {
entry:
%__t.addr = alloca ptr
store ptr %__t, ptr %__t.addr
%0 = load ptr, ptr %__t.addr
ret ptr %0
}
|