From 370cf00c9f685c70ed083b228f4a8e2ea42c294e Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Tue, 19 Jan 2016 00:17:21 +0000 Subject: [PATCH] Make sure we preserve alignment information after hoisting invariant load In Polly, after hoisting loop invariant loads outside loop, the alignment information for hoisted loads are missing, this patch restore them. Contributed-by: Lawrence Hu Differential Revision: http://reviews.llvm.org/D16160 llvm-svn: 258105 --- polly/include/polly/CodeGen/IslNodeBuilder.h | 2 +- polly/lib/CodeGen/IslNodeBuilder.cpp | 15 ++++++--- .../CodeGen/invaraint_load_hoist_alignment.ll | 31 +++++++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 polly/test/Isl/CodeGen/invaraint_load_hoist_alignment.ll diff --git a/polly/include/polly/CodeGen/IslNodeBuilder.h b/polly/include/polly/CodeGen/IslNodeBuilder.h index 30be60a0299fd..330a19862d456 100644 --- a/polly/include/polly/CodeGen/IslNodeBuilder.h +++ b/polly/include/polly/CodeGen/IslNodeBuilder.h @@ -215,7 +215,7 @@ class IslNodeBuilder { /// /// @returns The preloaded value casted to type @p Ty Value *preloadUnconditionally(__isl_take isl_set *AccessRange, - isl_ast_build *Build, Type *Ty); + isl_ast_build *Build, Instruction *AccInst); /// @brief Preload the memory load access @p MA. /// diff --git a/polly/lib/CodeGen/IslNodeBuilder.cpp b/polly/lib/CodeGen/IslNodeBuilder.cpp index f75a304d07b88..ee91a2cf5ae3a 100644 --- a/polly/lib/CodeGen/IslNodeBuilder.cpp +++ b/polly/lib/CodeGen/IslNodeBuilder.cpp @@ -893,15 +893,20 @@ bool IslNodeBuilder::materializeParameters(isl_set *Set, bool All) { } Value *IslNodeBuilder::preloadUnconditionally(isl_set *AccessRange, - isl_ast_build *Build, Type *Ty) { + isl_ast_build *Build, + Instruction *AccInst) { isl_pw_multi_aff *PWAccRel = isl_pw_multi_aff_from_set(AccessRange); PWAccRel = isl_pw_multi_aff_gist_params(PWAccRel, S.getContext()); isl_ast_expr *Access = isl_ast_build_access_from_pw_multi_aff(Build, PWAccRel); Value *PreloadVal = ExprBuilder.create(Access); + if (LoadInst *PreloadInst = dyn_cast(PreloadVal)) + PreloadInst->setAlignment(dyn_cast(AccInst)->getAlignment()); + // Correct the type as the SAI might have a different type than the user // expects, especially if the base pointer is a struct. + Type *Ty = AccInst->getType(); if (Ty == PreloadVal->getType()) return PreloadVal; @@ -916,6 +921,9 @@ Value *IslNodeBuilder::preloadUnconditionally(isl_set *AccessRange, Ptr = Builder.CreatePointerCast(Ptr, Ty->getPointerTo(), Ptr->getName() + ".cast"); PreloadVal = Builder.CreateLoad(Ptr, LInst->getName()); + if (LoadInst *PreloadInst = dyn_cast(PreloadVal)) + PreloadInst->setAlignment(dyn_cast(AccInst)->getAlignment()); + LInst->eraseFromParent(); return PreloadVal; } @@ -940,7 +948,7 @@ Value *IslNodeBuilder::preloadInvariantLoad(const MemoryAccess &MA, Value *PreloadVal = nullptr; if (AlwaysExecuted) { - PreloadVal = preloadUnconditionally(AccessRange, Build, AccInstTy); + PreloadVal = preloadUnconditionally(AccessRange, Build, AccInst); isl_ast_build_free(Build); isl_set_free(Domain); return PreloadVal; @@ -984,8 +992,7 @@ Value *IslNodeBuilder::preloadInvariantLoad(const MemoryAccess &MA, Builder.CreateBr(MergeBB); Builder.SetInsertPoint(ExecBB->getTerminator()); - Value *PreAccInst = preloadUnconditionally(AccessRange, Build, AccInstTy); - + Value *PreAccInst = preloadUnconditionally(AccessRange, Build, AccInst); Builder.SetInsertPoint(MergeBB->getTerminator()); auto *MergePHI = Builder.CreatePHI( AccInstTy, 2, "polly.preload." + AccInst->getName() + ".merge"); diff --git a/polly/test/Isl/CodeGen/invaraint_load_hoist_alignment.ll b/polly/test/Isl/CodeGen/invaraint_load_hoist_alignment.ll new file mode 100644 index 0000000000000..b691c9b041468 --- /dev/null +++ b/polly/test/Isl/CodeGen/invaraint_load_hoist_alignment.ll @@ -0,0 +1,31 @@ +; RUN: opt %loadPolly -basicaa -polly-codegen -polly-vectorizer=polly -S %s | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-unknown-linux-gnu" + +@A = common global [1024 x i32] zeroinitializer, align 16 +@B = common global [1024 x i32] zeroinitializer, align 16 + +declare i32 @foo(i32) readnone + +define void @force_alignment() nounwind { +;CHECK: @force_alignment +;CHECK-FORCED: @force_alignment +entry: + br label %body + +body: + %indvar = phi i64 [ 0, %entry ], [ %indvar_next, %body ] + %scevgep = getelementptr [1024 x i32], [1024 x i32]* @B, i64 0, i64 %indvar +; CHECK: [[T2:%.load]] = load i32, i32* getelementptr inbounds ([1024 x i32], [1024 x i32]* @A, i32 0, i32 0), align 4 +; CHECK: %value_p.splatinsert = insertelement <4 x i32> undef, i32 [[T2]], i32 0 + %value = load i32, i32* getelementptr inbounds ([1024 x i32], [1024 x i32]* @A, i64 0, i64 0), align 4 + %result = tail call i32 @foo(i32 %value) nounwind + store i32 %result, i32* %scevgep, align 4 + %indvar_next = add i64 %indvar, 1 + %exitcond = icmp eq i64 %indvar_next, 4 + br i1 %exitcond, label %return, label %body + +return: + ret void +} +