From 87ddf1f4fad01bccb70f10a3ee5c5ad5b20e4de4 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Sat, 25 Jan 2020 20:21:41 -0600 Subject: [PATCH] [Attributor] Simple casts preserve no-alias property This is a minimal but important advancement over the existing code. A cast with an operand that is only used in the cast retains the no-alias property of the operand. --- llvm/lib/Transforms/IPO/Attributor.cpp | 20 +++++++++++-- llvm/test/Transforms/Attributor/noalias.ll | 35 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 91eb561901c0..31a7e93b239a 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -2496,13 +2496,29 @@ struct AANoAliasFloating final : AANoAliasImpl { /// See AbstractAttribute::initialize(...). void initialize(Attributor &A) override { AANoAliasImpl::initialize(A); - Value &Val = getAssociatedValue(); + Value *Val = &getAssociatedValue(); + do { + CastInst *CI = dyn_cast(Val); + if (!CI) + break; + Value *Base = CI->getOperand(0); + if (Base->getNumUses() != 1) + break; + Val = Base; + } while (true); + if (isa(Val)) indicateOptimisticFixpoint(); else if (isa(Val) && !NullPointerIsDefined(getAnchorScope(), - Val.getType()->getPointerAddressSpace())) + Val->getType()->getPointerAddressSpace())) indicateOptimisticFixpoint(); + else if (Val != &getAssociatedValue()) { + const auto &ValNoAliasAA = + A.getAAFor(*this, IRPosition::value(*Val)); + if (ValNoAliasAA.isKnownNoAlias()) + indicateOptimisticFixpoint(); + } } /// See AbstractAttribute::updateImpl(...). diff --git a/llvm/test/Transforms/Attributor/noalias.ll b/llvm/test/Transforms/Attributor/noalias.ll index f22b66a12d1f..0e95d546ea95 100644 --- a/llvm/test/Transforms/Attributor/noalias.ll +++ b/llvm/test/Transforms/Attributor/noalias.ll @@ -40,6 +40,13 @@ define i8* @return_noalias_looks_like_capture(){ ret i8* %1 } +; CHECK: define noalias i16* @return_noalias_casted() +define i16* @return_noalias_casted(){ + %1 = tail call noalias i8* @malloc(i64 4) + %c = bitcast i8* %1 to i16* + ret i16* %c +} + declare i8* @alias() ; TEST 3 @@ -294,3 +301,31 @@ define void @test12_4(){ tail call void @two_args(i8* %A_0, i8* %B_0) ret void } + +; TEST 13 +define void @use_i8_internal(i8* %a) { + call void @use_i8(i8* %a) + ret void +} + +define void @test13_use_noalias(){ + %m1 = tail call noalias i8* @malloc(i64 4) + %c1 = bitcast i8* %m1 to i16* + %c2 = bitcast i16* %c1 to i8* +; CHECK: call void @use_i8_internal(i8* noalias nocapture %c2) + call void @use_i8_internal(i8* %c2) + ret void +} + +define void @test13_use_alias(){ + %m1 = tail call noalias i8* @malloc(i64 4) + %c1 = bitcast i8* %m1 to i16* + %c2a = bitcast i16* %c1 to i8* + %c2b = bitcast i16* %c1 to i8* +; CHECK: call void @use_i8_internal(i8* nocapture %c2a) +; CHECK: call void @use_i8_internal(i8* nocapture %c2b) + call void @use_i8_internal(i8* %c2a) + call void @use_i8_internal(i8* %c2b) + ret void +} +