<div dir="ltr">Using LLVM ToT and Hal's helpful slide deck [1], I've been trying to use `llvm.assume` to communicate pointer alignment guarantees to vector load and store instructions. For example, in [2] %5 and %9 are guaranteed to be 32-byte aligned. However, if I run this IR through `opt -O3 -datalayout -S`, the vectorized loads and stores are still 1-byte aligned [3]. What's going wrong? Do I have to move the `llvm.assume` into the loop body?<div><br></div><div>v/r,</div><div>Josh<br><div><br></div><div><br></div><div>[1] <a href="http://llvm.org/devmtg/2014-10/Slides/Finkel-IntrinsicsMetadataAttributes.pdf" target="_blank">http://llvm.org/devmtg/2014-10/Slides/Finkel-IntrinsicsMetadataAttributes.pdf</a></div><div><br></div><div>[2]</div><div>; ModuleID = 'align.ll'</div><div><br></div><div>%u8XY = type { i32, i32, i32, i32, i32, i32, [0 x i8] }</div><div><br></div><div>; Function Attrs: noduplicate nounwind readonly</div><div>declare noalias %u8XY* @likely_new(i32 zeroext, i32 zeroext, i32 zeroext, i32 zeroext, i32 zeroext, i8* noalias nocapture) #0</div><div><br></div><div>; Function Attrs: nounwind</div><div>declare void @llvm.assume(i1) #1</div><div><br></div><div>; Function Attrs: nounwind</div><div>define %u8XY* @benchmark(%u8XY*) #1 {</div><div>entry:</div><div>  %1 = getelementptr inbounds %u8XY* %0, i64 0, i32 3</div><div>  %columns = load i32* %1, align 4, !range !0</div><div>  %2 = getelementptr inbounds %u8XY* %0, i64 0, i32 4</div><div>  %rows = load i32* %2, align 4, !range !0</div><div>  %3 = tail call %u8XY* @likely_new(i32 24584, i32 1, i32 %columns, i32 %rows, i32 1, i8* null)</div><div>  %4 = zext i32 %rows to i64</div><div>  %dst_y_step = zext i32 %columns to i64</div><div>  %5 = getelementptr inbounds %u8XY* %3, i64 0, i32 6, i64 0</div><div>  %6 = ptrtoint i8* %5 to i64</div><div>  %7 = and i64 %6, 31</div><div>  %8 = icmp eq i64 %7, 0</div><div>  tail call void @llvm.assume(i1 %8)</div><div>  %9 = getelementptr inbounds %u8XY* %0, i64 0, i32 6, i64 0</div><div>  %10 = ptrtoint i8* %9 to i64</div><div>  %11 = and i64 %10, 31</div><div>  %12 = icmp eq i64 %11, 0</div><div>  tail call void @llvm.assume(i1 %12)</div><div>  %13 = mul nuw nsw i64 %4, %dst_y_step</div><div>  br label %x_body</div><div><br></div><div>x_body:                                           ; preds = %x_body, %entry</div><div>  %y = phi i64 [ 0, %entry ], [ %y_increment, %x_body ]</div><div>  %14 = getelementptr %u8XY* %0, i64 0, i32 6, i64 %y</div><div>  %15 = load i8* %14, align 1, !llvm.mem.parallel_loop_access !1</div><div>  %.lobit = lshr i8 %15, 7</div><div>  %16 = getelementptr %u8XY* %3, i64 0, i32 6, i64 %y</div><div>  store i8 %.lobit, i8* %16, align 1, !llvm.mem.parallel_loop_access !1</div><div>  %y_increment = add nuw nsw i64 %y, 1</div><div>  %y_postcondition = icmp eq i64 %y_increment, %13</div><div>  br i1 %y_postcondition, label %y_exit, label %x_body, !llvm.loop !2</div><div><br></div><div>y_exit:                                           ; preds = %x_body</div><div>  ret %u8XY* %3</div><div>}</div><div><br></div><div>attributes #0 = { noduplicate nounwind readonly }</div><div>attributes #1 = { nounwind }</div><div><br></div><div>!0 = !{i32 1, i32 -1}</div><div>!1 = !{!1}</div><div>!2 = !{!2}</div><div><br></div><div>[3]</div><div>; ModuleID = 'align.ll'</div><div><br></div><div>%u8XY = type { i32, i32, i32, i32, i32, i32, [0 x i8] }</div><div><br></div><div>; Function Attrs: noduplicate nounwind readonly</div><div>declare noalias %u8XY* @likely_new(i32 zeroext, i32 zeroext, i32 zeroext, i32 zeroext, i32 zeroext, i8* noalias nocapture) #0</div><div><br></div><div>; Function Attrs: nounwind</div><div>declare void @llvm.assume(i1) #1</div><div><br></div><div>; Function Attrs: nounwind</div><div>define %u8XY* @benchmark(%u8XY*) #1 {</div><div>entry:</div><div>  %1 = getelementptr inbounds %u8XY* %0, i64 0, i32 3</div><div>  %columns = load i32* %1, align 4, !range !0</div><div>  %2 = getelementptr inbounds %u8XY* %0, i64 0, i32 4</div><div>  %rows = load i32* %2, align 4, !range !0</div><div>  %3 = tail call %u8XY* @likely_new(i32 24584, i32 1, i32 %columns, i32 %rows, i32 1, i8* null)</div><div>  %4 = zext i32 %rows to i64</div><div>  %dst_y_step = zext i32 %columns to i64</div><div>  %5 = getelementptr inbounds %u8XY* %3, i64 0, i32 6, i64 0</div><div>  %6 = ptrtoint i8* %5 to i64</div><div>  %7 = and i64 %6, 31</div><div>  %8 = icmp eq i64 %7, 0</div><div>  tail call void @llvm.assume(i1 %8)</div><div>  %9 = getelementptr inbounds %u8XY* %0, i64 0, i32 6, i64 0</div><div>  %10 = ptrtoint i8* %9 to i64</div><div>  %11 = and i64 %10, 31</div><div>  %12 = icmp eq i64 %11, 0</div><div>  tail call void @llvm.assume(i1 %12)</div><div>  %13 = mul nuw nsw i64 %4, %dst_y_step</div><div>  %14 = zext i32 %rows to i64</div><div>  %15 = zext i32 %columns to i64</div><div>  %16 = mul nuw i64 %14, %15</div><div>  %n.vec = and i64 %16, -4</div><div>  %cmp.zero = icmp eq i64 %n.vec, 0</div><div>  br i1 %cmp.zero, label %middle.block, label %vector.body.preheader</div><div><br></div><div>vector.body.preheader:                            ; preds = %entry</div><div>  br label %vector.body</div><div><br></div><div>vector.body:                                      ; preds = %vector.body.preheader, %vector.body</div><div>  %index = phi i64 [ %index.next, %vector.body ], [ 0, %vector.body.preheader ]</div><div>  %17 = getelementptr %u8XY* %0, i64 0, i32 6, i64 %index</div><div>  %18 = bitcast i8* %17 to <4 x i8>*</div><div>  %wide.load = load <4 x i8>* %18, align 1</div><div>  %19 = lshr <4 x i8> %wide.load, <i8 7, i8 7, i8 7, i8 7></div><div>  %20 = getelementptr %u8XY* %3, i64 0, i32 6, i64 %index</div><div>  %21 = bitcast i8* %20 to <4 x i8>*</div><div>  store <4 x i8> %19, <4 x i8>* %21, align 1</div><div>  %index.next = add i64 %index, 4</div><div>  %22 = icmp eq i64 %index.next, %n.vec</div><div>  br i1 %22, label %middle.block.loopexit, label %vector.body, !llvm.loop !1</div><div><br></div><div>middle.block.loopexit:                            ; preds = %vector.body</div><div>  br label %middle.block</div><div><br></div><div>middle.block:                                     ; preds = %middle.block.loopexit, %entry</div><div>  %resume.val = phi i64 [ 0, %entry ], [ %n.vec, %middle.block.loopexit ]</div><div>  %cmp.n = icmp eq i64 %16, %resume.val</div><div>  br i1 %cmp.n, label %y_exit, label %x_body.preheader</div><div><br></div><div>x_body.preheader:                                 ; preds = %middle.block</div><div>  br label %x_body</div><div><br></div><div>x_body:                                           ; preds = %x_body.preheader, %x_body</div><div>  %y = phi i64 [ %y_increment, %x_body ], [ %resume.val, %x_body.preheader ]</div><div>  %23 = getelementptr %u8XY* %0, i64 0, i32 6, i64 %y</div><div>  %24 = load i8* %23, align 1, !llvm.mem.parallel_loop_access !4</div><div>  %.lobit = lshr i8 %24, 7</div><div>  %25 = getelementptr %u8XY* %3, i64 0, i32 6, i64 %y</div><div>  store i8 %.lobit, i8* %25, align 1, !llvm.mem.parallel_loop_access !4</div><div>  %y_increment = add nuw nsw i64 %y, 1</div><div>  %y_postcondition = icmp eq i64 %y_increment, %13</div><div>  br i1 %y_postcondition, label %y_exit.loopexit, label %x_body, !llvm.loop !5</div><div><br></div><div>y_exit.loopexit:                                  ; preds = %x_body</div><div>  br label %y_exit</div><div><br></div><div>y_exit:                                           ; preds = %y_exit.loopexit, %middle.block</div><div>  ret %u8XY* %3</div><div>}</div><div><br></div><div>attributes #0 = { noduplicate nounwind readonly }</div><div>attributes #1 = { nounwind }</div><div><br></div><div>!0 = !{i32 1, i32 -1}</div><div>!1 = !{!1, !2, !3}</div><div>!2 = !{!"llvm.loop.vectorize.width", i32 1}</div><div>!3 = !{!"llvm.loop.interleave.count", i32 1}</div><div>!4 = !{!4}</div><div>!5 = !{!5, !2, !3}</div></div></div>