-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[ReplaceConstant] Don't create instructions for the same constant multiple times in the same basic block #169141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -91,6 +91,11 @@ bool llvm::convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts, | |
|
|
||
| // Replace those expandable operands with instructions | ||
| bool Changed = false; | ||
| // We need to cache the instructions we've already expanded to avoid expanding | ||
| // the same constant multiple times in the same basic block, which is | ||
| // problematic when the same constant is used in a phi node multiple times. | ||
| DenseMap<std::pair<Constant *, BasicBlock *>, SmallVector<Instruction *, 4>> | ||
| ConstantToInstructionMap; | ||
| while (!InstructionWorklist.empty()) { | ||
| Instruction *I = InstructionWorklist.pop_back_val(); | ||
| DebugLoc Loc = I->getDebugLoc(); | ||
|
|
@@ -105,7 +110,10 @@ bool llvm::convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts, | |
| if (auto *C = dyn_cast<Constant>(U.get())) { | ||
| if (ExpandableUsers.contains(C)) { | ||
| Changed = true; | ||
| auto NewInsts = expandUser(BI, C); | ||
| SmallVector<Instruction *, 4> &NewInsts = | ||
| ConstantToInstructionMap[std::make_pair(C, BI->getParent())]; | ||
| if (NewInsts.empty()) | ||
| NewInsts = expandUser(BI, C); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when NewInsts.empty() is true, there will be a copy to NewInsts after it is default constructed. Can we avoid the copy? |
||
| for (auto *NI : NewInsts) | ||
| NI->setDebugLoc(Loc); | ||
| InstructionWorklist.insert_range(NewInsts); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | ||
| ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -amdgpu-lower-module-lds %s -o - | FileCheck %s | ||
| ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-lower-module-lds %s -o - | FileCheck %s | ||
|
|
||
| @lds = internal unnamed_addr addrspace(3) global [6144 x half] poison, align 2 | ||
|
|
||
| define amdgpu_kernel void @test(ptr addrspace(1) %out) { | ||
| ; CHECK-LABEL: define amdgpu_kernel void @test( | ||
| ; CHECK-SAME: ptr addrspace(1) [[OUT:%.*]]) #[[ATTR0:[0-9]+]] { | ||
| ; CHECK-NEXT: [[ENTRY:.*]]: | ||
| ; CHECK-NEXT: switch i32 0, label %[[BB_3:.*]] [ | ||
| ; CHECK-NEXT: i32 18, label %[[BB_2:.*]] | ||
| ; CHECK-NEXT: i32 1, label %[[BB_2]] | ||
| ; CHECK-NEXT: i32 0, label %[[BB_3]] | ||
| ; CHECK-NEXT: ] | ||
| ; CHECK: [[BB_1:.*]]: | ||
| ; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr addrspace(3) @llvm.amdgcn.kernel.test.lds to ptr | ||
| ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64 | ||
| ; CHECK-NEXT: switch i32 0, label %[[BB_3]] [ | ||
| ; CHECK-NEXT: i32 18, label %[[BB_2]] | ||
| ; CHECK-NEXT: i32 1, label %[[BB_2]] | ||
| ; CHECK-NEXT: i32 0, label %[[BB_3]] | ||
| ; CHECK-NEXT: ] | ||
| ; CHECK: [[BB_2]]: | ||
| ; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[TMP1]], %[[BB_1]] ], [ [[TMP1]], %[[BB_1]] ], [ 10, %[[ENTRY]] ], [ 10, %[[ENTRY]] ] | ||
| ; CHECK-NEXT: store i64 [[PHI]], ptr addrspace(1) [[OUT]], align 8 | ||
| ; CHECK-NEXT: br label %[[BB_3]] | ||
| ; CHECK: [[BB_3]]: | ||
| ; CHECK-NEXT: ret void | ||
| ; | ||
| entry: | ||
| switch i32 0, label %bb.3 [ | ||
| i32 18, label %bb.2 | ||
| i32 1, label %bb.2 | ||
| i32 0, label %bb.3 | ||
| ] | ||
| bb.1: | ||
| switch i32 0, label %bb.3 [ | ||
| i32 18, label %bb.2 | ||
| i32 1, label %bb.2 | ||
| i32 0, label %bb.3 | ||
| ] | ||
|
|
||
| bb.2: | ||
| %phi = phi i64 [ ptrtoint (ptr addrspacecast (ptr addrspace(3) @lds to ptr) to i64), %bb.1 ], [ ptrtoint (ptr addrspacecast (ptr addrspace(3) @lds to ptr) to i64), %bb.1 ], [10, %entry], [10, %entry] | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On a second thought, should we deduplicate the incoming BBs when we construct a phi node? In this way we don't need to fix anything else. |
||
| store i64 %phi, ptr addrspace(1) %out, align 8 | ||
| br label %bb.3 | ||
|
|
||
| bb.3: | ||
| ret void | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose the expansion of the
SmallVectorwill not cause any trouble in the map, since it is fixed size, and when it needs expansion, it uses heap and its original location will not be moved.