[llvm] 700d241 - [CodeExtractor] Replace uses of extracted bitcasts in out-of-region lifetime markers
Giorgis Georgakoudis via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 5 17:01:15 PST 2020
Author: Giorgis Georgakoudis
Date: 2020-11-05T17:01:08-08:00
New Revision: 700d2417d8281ea56dfd7ac72d1a1473d03d2d59
URL: https://github.com/llvm/llvm-project/commit/700d2417d8281ea56dfd7ac72d1a1473d03d2d59
DIFF: https://github.com/llvm/llvm-project/commit/700d2417d8281ea56dfd7ac72d1a1473d03d2d59.diff
LOG: [CodeExtractor] Replace uses of extracted bitcasts in out-of-region lifetime markers
CodeExtractor handles bitcasts in the extracted region that have
lifetime markers users in the outer region as outputs. That
creates unnecessary alloca/reload instructions and extra lifetime
markers. The patch identifies those cases, and replaces uses in
out-of-region lifetime markers with new bitcasts in the outer region.
**Example**
```
define void @foo() {
entry:
%0 = alloca i32
br label %extract
extract:
%1 = bitcast i32* %0 to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* %1)
call void @use(i32* %0)
br label %exit
exit:
call void @use(i32* %0)
call void @llvm.lifetime.end.p0i8(i64 4, i8* %1)
ret void
}
```
**Current extraction**
```
define void @foo() {
entry:
%.loc = alloca i8*, align 8
%0 = alloca i32, align 4
br label %codeRepl
codeRepl: ; preds = %entry
%lt.cast = bitcast i8** %.loc to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* %lt.cast)
%lt.cast1 = bitcast i32* %0 to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* %lt.cast1)
call void @foo.extract(i32* %0, i8** %.loc)
%.reload = load i8*, i8** %.loc, align 8
call void @llvm.lifetime.end.p0i8(i64 -1, i8* %lt.cast)
br label %exit
exit: ; preds = %codeRepl
call void @use(i32* %0)
call void @llvm.lifetime.end.p0i8(i64 4, i8* %.reload)
ret void
}
define internal void @foo.extract(i32* %0, i8** %.out) {
newFuncRoot:
br label %extract
exit.exitStub: ; preds = %extract
ret void
extract: ; preds = %newFuncRoot
%1 = bitcast i32* %0 to i8*
store i8* %1, i8** %.out, align 8
call void @use(i32* %0)
br label %exit.exitStub
}
```
**Extraction with patch**
```
define void @foo() {
entry:
%0 = alloca i32, align 4
br label %codeRepl
codeRepl: ; preds = %entry
%lt.cast1 = bitcast i32* %0 to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* %lt.cast1)
call void @foo.extract(i32* %0)
br label %exit
exit: ; preds = %codeRepl
call void @use(i32* %0)
%lt.cast = bitcast i32* %0 to i8*
call void @llvm.lifetime.end.p0i8(i64 4, i8* %lt.cast)
ret void
}
define internal void @foo.extract(i32* %0) {
newFuncRoot:
br label %extract
exit.exitStub: ; preds = %extract
ret void
extract: ; preds = %newFuncRoot
%1 = bitcast i32* %0 to i8*
call void @use(i32* %0)
br label %exit.exitStub
}
```
Reviewed By: vsk
Differential Revision: https://reviews.llvm.org/D90689
Added:
Modified:
llvm/lib/Transforms/Utils/CodeExtractor.cpp
llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
index 34a5499879ba..dc3c6bd2ac3b 100644
--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -535,6 +535,46 @@ void CodeExtractor::findAllocas(const CodeExtractorAnalysisCache &CEAC,
continue;
}
+ // Find bitcasts in the outlined region that have lifetime marker users
+ // outside that region. Replace the lifetime marker use with an
+ // outside region bitcast to avoid unnecessary alloca/reload instructions
+ // and extra lifetime markers.
+ SmallVector<Instruction *, 2> LifetimeBitcastUsers;
+ for (User *U : AI->users()) {
+ if (!definedInRegion(Blocks, U))
+ continue;
+
+ if (U->stripInBoundsConstantOffsets() != AI)
+ continue;
+
+ Instruction *Bitcast = cast<Instruction>(U);
+ for (User *BU : Bitcast->users()) {
+ IntrinsicInst *IntrInst = dyn_cast<IntrinsicInst>(BU);
+ if (!IntrInst)
+ continue;
+
+ if (!IntrInst->isLifetimeStartOrEnd())
+ continue;
+
+ if (definedInRegion(Blocks, IntrInst))
+ continue;
+
+ LLVM_DEBUG(dbgs() << "Replace use of extracted region bitcast"
+ << *Bitcast << " in out-of-region lifetime marker "
+ << *IntrInst << "\n");
+ LifetimeBitcastUsers.push_back(IntrInst);
+ }
+ }
+
+ for (Instruction *I : LifetimeBitcastUsers) {
+ Module *M = AIFunc->getParent();
+ LLVMContext &Ctx = M->getContext();
+ auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
+ CastInst *CastI =
+ CastInst::CreatePointerCast(AI, Int8PtrTy, "lt.cast", I);
+ I->replaceUsesOfWith(I->getOperand(1), CastI);
+ }
+
// Follow any bitcasts.
SmallVector<Instruction *, 2> Bitcasts;
SmallVector<LifetimeMarkerInfo, 2> BitcastLifetimeInfo;
diff --git a/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp b/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp
index 4b8cf8017096..a6fb926aec39 100644
--- a/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp
+++ b/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp
@@ -282,4 +282,53 @@ TEST(CodeExtractor, ExtractAndInvalidateAssumptionCache) {
EXPECT_FALSE(verifyFunction(*Func));
EXPECT_FALSE(CE.verifyAssumptionCache(*Func, *Outlined, &AC));
}
+
+TEST(CodeExtractor, RemoveBitcastUsesFromOuterLifetimeMarkers) {
+ LLVMContext Ctx;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M(parseAssemblyString(R"ir(
+ 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"
+
+ declare void @use(i32*)
+ declare void @llvm.lifetime.start.p0i8(i64, i8*)
+ declare void @llvm.lifetime.end.p0i8(i64, i8*)
+
+ define void @foo() {
+ entry:
+ %0 = alloca i32
+ br label %extract
+
+ extract:
+ %1 = bitcast i32* %0 to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %1)
+ call void @use(i32* %0)
+ br label %exit
+
+ exit:
+ call void @use(i32* %0)
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %1)
+ ret void
+ }
+ )ir",
+ Err, Ctx));
+
+ Function *Func = M->getFunction("foo");
+ SmallVector<BasicBlock *, 1> Blocks{getBlockByName(Func, "extract")};
+
+ CodeExtractor CE(Blocks);
+ EXPECT_TRUE(CE.isEligible());
+
+ CodeExtractorAnalysisCache CEAC(*Func);
+ SetVector<Value *> Inputs, Outputs, SinkingCands, HoistingCands;
+ BasicBlock *CommonExit = nullptr;
+ CE.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
+ CE.findInputsOutputs(Inputs, Outputs, SinkingCands);
+ EXPECT_EQ(Outputs.size(), 0U);
+
+ Function *Outlined = CE.extractCodeRegion(CEAC);
+ EXPECT_TRUE(Outlined);
+ EXPECT_FALSE(verifyFunction(*Outlined));
+ EXPECT_FALSE(verifyFunction(*Func));
+}
} // end anonymous namespace
More information about the llvm-commits
mailing list