1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature 2target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64" 3; RUN: opt < %s -alignment-from-assumptions -S | FileCheck %s 4; RUN: opt < %s -passes=alignment-from-assumptions -S | FileCheck %s 5 6define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { 7; CHECK-LABEL: define {{[^@]+}}@foo 8; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 9; CHECK-NEXT: entry: 10; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 11; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 32 12; CHECK-NEXT: ret i32 [[TMP0]] 13; 14entry: 15 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 16 %0 = load i32, i32* %a, align 4 17 ret i32 %0 18 19} 20 21define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { 22; CHECK-LABEL: define {{[^@]+}}@foo2 23; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 24; CHECK-NEXT: entry: 25; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 24) ] 26; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 2 27; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16 28; CHECK-NEXT: ret i32 [[TMP0]] 29; 30entry: 31 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 24)] 32 %arrayidx = getelementptr inbounds i32, i32* %a, i64 2 33 %0 = load i32, i32* %arrayidx, align 4 34 ret i32 %0 35 36} 37 38define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { 39; CHECK-LABEL: define {{[^@]+}}@foo2a 40; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 41; CHECK-NEXT: entry: 42; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 28) ] 43; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 -1 44; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32 45; CHECK-NEXT: ret i32 [[TMP0]] 46; 47entry: 48 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 28)] 49 %arrayidx = getelementptr inbounds i32, i32* %a, i64 -1 50 %0 = load i32, i32* %arrayidx, align 4 51 ret i32 %0 52 53} 54 55define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { 56; CHECK-LABEL: define {{[^@]+}}@goo 57; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 58; CHECK-NEXT: entry: 59; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 60; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 32 61; CHECK-NEXT: ret i32 [[TMP0]] 62; 63entry: 64 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 65 %0 = load i32, i32* %a, align 4 66 ret i32 %0 67 68} 69 70define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { 71; CHECK-LABEL: define {{[^@]+}}@hoo 72; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 73; CHECK-NEXT: entry: 74; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 75; CHECK-NEXT: br label [[FOR_BODY:%.*]] 76; CHECK: for.body: 77; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 78; CHECK-NEXT: [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 79; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] 80; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32 81; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP0]], [[R_06]] 82; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 8 83; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 84; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048 85; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 86; CHECK: for.end: 87; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ] 88; CHECK-NEXT: ret i32 [[ADD_LCSSA]] 89; 90entry: 91 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 92 br label %for.body 93 94for.body: ; preds = %entry, %for.body 95 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 96 %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] 97 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv 98 %0 = load i32, i32* %arrayidx, align 4 99 %add = add nsw i32 %0, %r.06 100 %indvars.iv.next = add i64 %indvars.iv, 8 101 %1 = trunc i64 %indvars.iv.next to i32 102 %cmp = icmp slt i32 %1, 2048 103 br i1 %cmp, label %for.body, label %for.end 104 105for.end: ; preds = %for.body 106 %add.lcssa = phi i32 [ %add, %for.body ] 107 ret i32 %add.lcssa 108 109} 110 111define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { 112; CHECK-LABEL: define {{[^@]+}}@joo 113; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 114; CHECK-NEXT: entry: 115; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 116; CHECK-NEXT: br label [[FOR_BODY:%.*]] 117; CHECK: for.body: 118; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 119; CHECK-NEXT: [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 120; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] 121; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16 122; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP0]], [[R_06]] 123; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 8 124; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 125; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048 126; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 127; CHECK: for.end: 128; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ] 129; CHECK-NEXT: ret i32 [[ADD_LCSSA]] 130; 131entry: 132 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 133 br label %for.body 134 135for.body: ; preds = %entry, %for.body 136 %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ] 137 %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] 138 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv 139 %0 = load i32, i32* %arrayidx, align 4 140 %add = add nsw i32 %0, %r.06 141 %indvars.iv.next = add i64 %indvars.iv, 8 142 %1 = trunc i64 %indvars.iv.next to i32 143 %cmp = icmp slt i32 %1, 2048 144 br i1 %cmp, label %for.body, label %for.end 145 146for.end: ; preds = %for.body 147 %add.lcssa = phi i32 [ %add, %for.body ] 148 ret i32 %add.lcssa 149 150} 151 152define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { 153; CHECK-LABEL: define {{[^@]+}}@koo 154; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 155; CHECK-NEXT: entry: 156; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 157; CHECK-NEXT: br label [[FOR_BODY:%.*]] 158; CHECK: for.body: 159; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 160; CHECK-NEXT: [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 161; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] 162; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16 163; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP0]], [[R_06]] 164; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 4 165; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 166; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048 167; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 168; CHECK: for.end: 169; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ] 170; CHECK-NEXT: ret i32 [[ADD_LCSSA]] 171; 172entry: 173 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 174 br label %for.body 175 176for.body: ; preds = %entry, %for.body 177 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 178 %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] 179 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv 180 %0 = load i32, i32* %arrayidx, align 4 181 %add = add nsw i32 %0, %r.06 182 %indvars.iv.next = add i64 %indvars.iv, 4 183 %1 = trunc i64 %indvars.iv.next to i32 184 %cmp = icmp slt i32 %1, 2048 185 br i1 %cmp, label %for.body, label %for.end 186 187for.end: ; preds = %for.body 188 %add.lcssa = phi i32 [ %add, %for.body ] 189 ret i32 %add.lcssa 190 191} 192 193define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { 194; CHECK-LABEL: define {{[^@]+}}@koo2 195; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 196; CHECK-NEXT: entry: 197; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 198; CHECK-NEXT: br label [[FOR_BODY:%.*]] 199; CHECK: for.body: 200; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ -4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 201; CHECK-NEXT: [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 202; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] 203; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16 204; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP0]], [[R_06]] 205; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 4 206; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 207; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048 208; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 209; CHECK: for.end: 210; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ] 211; CHECK-NEXT: ret i32 [[ADD_LCSSA]] 212; 213entry: 214 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 215 br label %for.body 216 217for.body: ; preds = %entry, %for.body 218 %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ] 219 %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] 220 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv 221 %0 = load i32, i32* %arrayidx, align 4 222 %add = add nsw i32 %0, %r.06 223 %indvars.iv.next = add i64 %indvars.iv, 4 224 %1 = trunc i64 %indvars.iv.next to i32 225 %cmp = icmp slt i32 %1, 2048 226 br i1 %cmp, label %for.body, label %for.end 227 228for.end: ; preds = %for.body 229 %add.lcssa = phi i32 [ %add, %for.body ] 230 ret i32 %add.lcssa 231 232} 233 234define i32 @moo(i32* nocapture %a) nounwind uwtable { 235; CHECK-LABEL: define {{[^@]+}}@moo 236; CHECK-SAME: (i32* nocapture [[A:%.*]]) #1 237; CHECK-NEXT: entry: 238; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 239; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* 240; CHECK-NEXT: tail call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP0]], i8 0, i64 64, i1 false) 241; CHECK-NEXT: ret i32 undef 242; 243entry: 244 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 245 %0 = bitcast i32* %a to i8* 246 tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false) 247 ret i32 undef 248 249} 250 251define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { 252; CHECK-LABEL: define {{[^@]+}}@moo2 253; CHECK-SAME: (i32* nocapture [[A:%.*]], i32* nocapture [[B:%.*]]) #1 254; CHECK-NEXT: entry: 255; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] 256; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[B]], i64 128) ] 257; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* 258; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[B]] to i8* 259; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 [[TMP0]], i8* align 128 [[TMP1]], i64 64, i1 false) 260; CHECK-NEXT: ret i32 undef 261; 262entry: 263 call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] 264 call void @llvm.assume(i1 true) ["align"(i32* %b, i64 128)] 265 %0 = bitcast i32* %a to i8* 266 %1 = bitcast i32* %b to i8* 267 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false) 268 ret i32 undef 269 270} 271 272declare void @llvm.assume(i1) nounwind 273 274declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind 275declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind 276 277