From fa45bf430081ed5a37c50719dfd3a8ca32271126 Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Sun, 9 Mar 2025 20:21:36 -0700 Subject: [PATCH] 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 --- .../InstCombineLoadStoreAlloca.cpp | 5 ++- .../AMDGPU/phi-with-incoming-from-load.ll | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/phi-with-incoming-from-load.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index c1f5e286ab3e..c29cba6f675c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -360,7 +360,10 @@ void PointerReplacer::replace(Instruction *I) { IC.InsertNewInstWith(NewI, LT->getIterator()); IC.replaceInstUsesWith(*LT, NewI); - WorkMap[LT] = NewI; + // LT has actually been replaced by NewI. It is useless to insert LT into + // the map. Instead, we insert NewI into the map to indicate this is the + // replacement (new value). + WorkMap[NewI] = NewI; } else if (auto *PHI = dyn_cast(I)) { Type *NewTy = getReplacement(PHI->getIncomingValue(0))->getType(); auto *NewPHI = PHINode::Create(NewTy, PHI->getNumIncomingValues(), diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/phi-with-incoming-from-load.ll b/llvm/test/Transforms/InstCombine/AMDGPU/phi-with-incoming-from-load.ll new file mode 100644 index 000000000000..14fb45e43af8 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/AMDGPU/phi-with-incoming-from-load.ll @@ -0,0 +1,42 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -passes=instcombine -S -o - %s | FileCheck %s + +target triple = "amdgcn-amd-amdhsa" + +%double_double = type { double, double } + +declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1) + +define void @_test(ptr addrspace(4) byref(%double_double) align 8 %in) { +; CHECK-LABEL: define void @_test( +; CHECK-SAME: ptr addrspace(4) byref([[DOUBLE_DOUBLE:%.*]]) align 8 [[IN:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[ALPHA_UNION:%.*]] = addrspacecast ptr addrspace(4) [[IN]] to ptr +; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(5) null, align 1 +; CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[LOAD]] to i1 +; CHECK-NEXT: br i1 [[LOADEDV]], label %[[COND_END:.*]], label %[[COND_FALSE:.*]] +; CHECK: [[COND_FALSE]]: +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr addrspace(4) [[IN]], align 8 +; CHECK-NEXT: br label %[[COND_END]] +; CHECK: [[COND_END]]: +; CHECK-NEXT: [[COND1:%.*]] = phi ptr [ [[TMP0]], %[[COND_FALSE]] ], [ [[ALPHA_UNION]], %[[ENTRY]] ] +; 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) +; CHECK-NEXT: ret void +; +entry: + %coerce = alloca %double_double, align 8, addrspace(5) + %alpha_union = addrspacecast ptr addrspace(5) %coerce to ptr + call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) align 8 %coerce, ptr addrspace(4) align 8 %in, i64 16, i1 false) + %load1 = load i8, ptr addrspace(5) null, align 1 + %loadedv = trunc i8 %load1 to i1 + br i1 %loadedv, label %cond.end, label %cond.false + +cond.false: + %load2 = load ptr, ptr addrspace(5) %coerce, align 8 + br label %cond.end + +cond.end: + %cond = phi ptr [ %load2, %cond.false ], [ %alpha_union, %entry ] + call void @llvm.memcpy.p0.p0.i64(ptr poison, ptr %cond, i64 16, i1 false) + ret void +}