diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h --- a/llvm/include/llvm/IR/Value.h +++ b/llvm/include/llvm/IR/Value.h @@ -484,7 +484,7 @@ void dropDroppableUsesIn(User &Usr); /// Remove the droppable use \p U. - void dropDroppableUse(Use &U); + static void dropDroppableUse(Use &U); /// Check if this value is used in the specified basic block. bool isUsedInBasicBlock(const BasicBlock *BB) const; diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -205,7 +205,7 @@ else { U.set(UndefValue::get(U.get()->getType())); CallInst::BundleOpInfo &BOI = Assume->getBundleOpInfoForOperand(OpNo); - BOI.Tag = getContext().pImpl->getOrInsertBundleTag("ignore"); + BOI.Tag = Assume->getContext().pImpl->getOrInsertBundleTag("ignore"); } return; } diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -268,6 +268,11 @@ /// Access the dead users for this alloca. ArrayRef getDeadUsers() const { return DeadUsers; } + /// Access Uses that should be dropped if the alloca is promotable. + ArrayRef getDeadUsesIfPromotable() const { + return DeadUseIfPromotable; + } + /// Access the dead operands referring to this alloca. /// /// These are operands which have cannot actually be used to refer to the @@ -322,6 +327,9 @@ /// they come from outside of the allocated space. SmallVector DeadUsers; + /// Uses which will become dead if can promote the alloca. + SmallVector DeadUseIfPromotable; + /// Operands which will become dead if we rewrite the alloca. /// /// These are operands that in their particular use can be replaced with @@ -926,8 +934,10 @@ // FIXME: What about debug intrinsics? This matches old behavior, but // doesn't make sense. void visitIntrinsicInst(IntrinsicInst &II) { - if (II.isDroppable()) + if (II.isDroppable()) { + AS.DeadUseIfPromotable.push_back(U); return; + } if (!IsOffsetKnown) return PI.setAborted(&II); @@ -4350,6 +4360,13 @@ } if (Promotable) { + for (Use *U : AS.getDeadUsesIfPromotable()) { + auto *OldInst = dyn_cast(U->get()); + Value::dropDroppableUse(*U); + if (OldInst) + if (isInstructionTriviallyDead(OldInst)) + DeadInsts.insert(OldInst); + } if (PHIUsers.empty() && SelectUsers.empty()) { // Promote the alloca. PromotableAllocas.push_back(NewAI); diff --git a/llvm/test/Transforms/SROA/assume.ll b/llvm/test/Transforms/SROA/assume.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SROA/assume.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -sroa -S | FileCheck %s + +source_filename = "tmp.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.n.2 = type { i8 } +%struct.bi = type { %class.as } +%class.as = type { %class.ao } +%class.ao = type { %class.ai } +%class.ai = type { i32, i32 } + +define linkonce_odr dso_local void @_ZN2bg2baIiEC2ES_() unnamed_addr align 2 { +; CHECK-LABEL: @_ZN2bg2baIiEC2ES_( +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"(%struct.bi* undef) ] +; CHECK-NEXT: ret void +; +entry: + %y = alloca i64, align 8 + store i64 undef, i64* %y, align 8 + %0 = bitcast i64* %y to %struct.n.2* + %1 = bitcast %struct.n.2* %0 to %struct.bi* + call void @llvm.assume(i1 true) [ "nonnull"(%struct.bi* %1) ] + ret void +} + +; Function Attrs: nofree norecurse nounwind willreturn +declare void @llvm.assume(i1) #0 + +attributes #0 = { nofree norecurse nounwind willreturn } diff --git a/llvm/test/Transforms/SROA/ignore-droppable.ll b/llvm/test/Transforms/SROA/ignore-droppable.ll --- a/llvm/test/Transforms/SROA/ignore-droppable.ll +++ b/llvm/test/Transforms/SROA/ignore-droppable.ll @@ -38,9 +38,8 @@ define void @positive_multiple_assume_uses() { ; CHECK-LABEL: @positive_multiple_assume_uses( -; CHECK-NEXT: [[A:%.*]] = alloca { i8, i16 }, align 8 -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"({ i8, i16 }* [[A]], i64 8), "align"({ i8, i16 }* [[A]], i64 16) ] -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"({ i8, i16 }* [[A]]), "align"({ i8, i16 }* [[A]], i64 2) ] +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"({ i8, i16 }* undef, i64 8), "ignore"({ i8, i16 }* undef, i64 16) ] +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"({ i8, i16 }* undef), "ignore"({ i8, i16 }* undef, i64 2) ] ; CHECK-NEXT: ret void ; %A = alloca {i8, i16} @@ -52,10 +51,8 @@ define void @positive_gep_assume_uses() { ; CHECK-LABEL: @positive_gep_assume_uses( -; CHECK-NEXT: [[A:%.*]] = alloca { i8, i16 }, align 8 -; CHECK-NEXT: [[B:%.*]] = getelementptr { i8, i16 }, { i8, i16 }* [[A]], i32 0, i32 0 -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[B]], i64 8), "align"(i8* [[B]], i64 16) ] -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i8* [[B]]), "align"(i8* [[B]], i64 2) ] +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"(i8* undef, i64 8), "ignore"(i8* undef, i64 16) ] +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"(i8* undef), "ignore"(i8* undef, i64 2) ] ; CHECK-NEXT: ret void ; %A = alloca {i8, i16}