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