diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -487,10 +487,18 @@ return nullptr; assert(instMap.count(i)); + // If we don't remove entry of `i` here, it's totally possible that the + // next time llvm::ConstantExpr::getAsInstruction is called again, which + // always allocates a new Instruction, memory address of the newly + // created Instruction might be the same as `i`. Making processInstruction + // falsely believe that the new Instruction has been processed before + // and raised an assertion error. + Value value = instMap[i]; + instMap.erase(i); // Remove this zombie LLVM instruction now, leaving us only with the MLIR // op. i->deleteValue(); - return instMap[c] = instMap[i]; + return instMap[c] = value; } if (auto *ue = dyn_cast(c)) { Type type = processType(ue->getType()); diff --git a/mlir/test/Target/LLVMIR/Import/incorrect-constexpr-inst-caching.ll b/mlir/test/Target/LLVMIR/Import/incorrect-constexpr-inst-caching.ll new file mode 100644 --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/incorrect-constexpr-inst-caching.ll @@ -0,0 +1,31 @@ +; RUN: mlir-translate --import-llvm %s | FileCheck %s +; REQUIRES: asserts + +; This test is primarily used to make sure an assertion is not triggered. +; Thus, we only wrote minimum level of checks. + +%my_struct = type {i32, i8*} +; CHECK: llvm.mlir.constant(3 : i32) : i32 +; CHECK: llvm.mlir.constant(2 : i32) : i32 +; CHECK: llvm.mlir.addressof @str1 : !llvm.ptr> +; CHECK: llvm.getelementptr +; CHECK: llvm.mlir.constant(7 : i32) : i32 +; CHECK: llvm.mlir.undef : !llvm.struct<"my_struct", (i32, ptr)> +; CHECK: llvm.insertvalue +; CHECK: llvm.insertvalue +; CHECK: llvm.mlir.constant(1 : i32) : i32 +; CHECK: llvm.mlir.constant(0 : i32) : i32 +; CHECK: llvm.mlir.addressof @str0 : !llvm.ptr> +; CHECK: llvm.getelementptr +; CHECK: llvm.mlir.constant(8 : i32) : i32 +; CHECK: llvm.mlir.undef : !llvm.struct<"my_struct", (i32, ptr)> +; CHECK: llvm.insertvalue +; CHECK: llvm.insertvalue +; CHECK: llvm.mlir.undef : !llvm.array<2 x struct<"my_struct", (i32, ptr)>> +; CHECK: llvm.insertvalue +; CHECK: llvm.insertvalue +; CHECK: llvm.return +@str0 = private unnamed_addr constant [5 x i8] c"aaaa\00" +@str1 = private unnamed_addr constant [5 x i8] c"bbbb\00" +@g = global [2 x %my_struct] [%my_struct {i32 8, i8* getelementptr ([5 x i8], [5 x i8]* @str0, i32 0, i32 1)}, %my_struct {i32 7, i8* getelementptr ([5 x i8], [5 x i8]* @str1, i32 2, i32 3)}] +