From f0687b47a0ce82da07127fee4fe6af801df54ca6 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 24 May 2023 20:16:41 +0100 Subject: [PATCH] [IRGen] Handle infinite cycles in findDominatingStoreToReturnValue. If there is an infinite cycle in the IR, the loop will never exit. Keep track of visited basic blocks in a set and return nullptr if a block is visited again. Fixes #62830. Reviewed By: rjmccall Differential Revision: https://reviews.llvm.org/D151076 --- clang/lib/CodeGen/CGCall.cpp | 3 +- .../test/CodeGen/dominating-store-infinite-cycle.c | 33 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/dominating-store-infinite-cycle.c diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6a1d549..ec28c1d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3461,8 +3461,9 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { // single-predecessors chain from the current insertion point. llvm::BasicBlock *StoreBB = store->getParent(); llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); + llvm::SmallPtrSet SeenBBs; while (IP != StoreBB) { - if (!(IP = IP->getSinglePredecessor())) + if (!SeenBBs.insert(IP).second || !(IP = IP->getSinglePredecessor())) return nullptr; } diff --git a/clang/test/CodeGen/dominating-store-infinite-cycle.c b/clang/test/CodeGen/dominating-store-infinite-cycle.c new file mode 100644 index 0000000..cedd9be --- /dev/null +++ b/clang/test/CodeGen/dominating-store-infinite-cycle.c @@ -0,0 +1,33 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s + +// Test for PR62830 where there are 2 infinite cycles using goto. Make sure +// clang codegen doesn't hang. +int a; + +// CHECK-LABEL: define dso_local i32 @main +// CHECK-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-NEXT: br label [[L1:%.*]] +// CHECK: L1: +// CHECK-NEXT: br label [[L1]] +// CHECK: L2: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @a, align 4 +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 +// CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] +// CHECK: if.then: +// CHECK-NEXT: br label [[L2:%.*]] +// CHECK: if.end: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK-NEXT: ret i32 [[TMP1]] +// +int main() { +L1: + goto L1; + +L2: + if (!a) + goto L2; +} -- 2.7.4