Skip to content

Commit fa45bf4

Browse files
authored
InstCombine: Fix a crash in PointerReplacer when constructing a new PHI (#130256)
When constructing a PHI node in `PointerReplacer::replace`, the incoming operands are expected to have already been replaced and in the replacement map. However, when one of the incoming operands is a load, the search of the map is unsuccessful, and a nullptr is returned from `getReplacement`. The reason is that, when a load is replaced, all the uses of the load has been actually replaced by the new load. It is useless to insert the original load into the map. Instead, we should place the new load into the map to meet the expectation of the later map search. Fixes: SWDEV-516420
1 parent 64c73d5 commit fa45bf4

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,10 @@ void PointerReplacer::replace(Instruction *I) {
360360

361361
IC.InsertNewInstWith(NewI, LT->getIterator());
362362
IC.replaceInstUsesWith(*LT, NewI);
363-
WorkMap[LT] = NewI;
363+
// LT has actually been replaced by NewI. It is useless to insert LT into
364+
// the map. Instead, we insert NewI into the map to indicate this is the
365+
// replacement (new value).
366+
WorkMap[NewI] = NewI;
364367
} else if (auto *PHI = dyn_cast<PHINode>(I)) {
365368
Type *NewTy = getReplacement(PHI->getIncomingValue(0))->getType();
366369
auto *NewPHI = PHINode::Create(NewTy, PHI->getNumIncomingValues(),
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=instcombine -S -o - %s | FileCheck %s
3+
4+
target triple = "amdgcn-amd-amdhsa"
5+
6+
%double_double = type { double, double }
7+
8+
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
9+
10+
define void @_test(ptr addrspace(4) byref(%double_double) align 8 %in) {
11+
; CHECK-LABEL: define void @_test(
12+
; CHECK-SAME: ptr addrspace(4) byref([[DOUBLE_DOUBLE:%.*]]) align 8 [[IN:%.*]]) {
13+
; CHECK-NEXT: [[ENTRY:.*]]:
14+
; CHECK-NEXT: [[ALPHA_UNION:%.*]] = addrspacecast ptr addrspace(4) [[IN]] to ptr
15+
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(5) null, align 1
16+
; CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[LOAD]] to i1
17+
; CHECK-NEXT: br i1 [[LOADEDV]], label %[[COND_END:.*]], label %[[COND_FALSE:.*]]
18+
; CHECK: [[COND_FALSE]]:
19+
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr addrspace(4) [[IN]], align 8
20+
; CHECK-NEXT: br label %[[COND_END]]
21+
; CHECK: [[COND_END]]:
22+
; CHECK-NEXT: [[COND1:%.*]] = phi ptr [ [[TMP0]], %[[COND_FALSE]] ], [ [[ALPHA_UNION]], %[[ENTRY]] ]
23+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(16) poison, ptr noundef nonnull align 1 dereferenceable(16) [[COND1]], i64 16, i1 false)
24+
; CHECK-NEXT: ret void
25+
;
26+
entry:
27+
%coerce = alloca %double_double, align 8, addrspace(5)
28+
%alpha_union = addrspacecast ptr addrspace(5) %coerce to ptr
29+
call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) align 8 %coerce, ptr addrspace(4) align 8 %in, i64 16, i1 false)
30+
%load1 = load i8, ptr addrspace(5) null, align 1
31+
%loadedv = trunc i8 %load1 to i1
32+
br i1 %loadedv, label %cond.end, label %cond.false
33+
34+
cond.false:
35+
%load2 = load ptr, ptr addrspace(5) %coerce, align 8
36+
br label %cond.end
37+
38+
cond.end:
39+
%cond = phi ptr [ %load2, %cond.false ], [ %alpha_union, %entry ]
40+
call void @llvm.memcpy.p0.p0.i64(ptr poison, ptr %cond, i64 16, i1 false)
41+
ret void
42+
}

0 commit comments

Comments
 (0)