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