From 8bb867a7399fbfa3483e64c15bb06f1cd67ae262 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Sun, 31 Dec 2017 16:47:16 +0000 Subject: [PATCH] [SimplifyCFG] Stop hoisting musttail calls incorrectly. PR35774. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321603 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 11 ++++++++ test/Transforms/SimplifyCFG/pr35774.ll | 35 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 test/Transforms/SimplifyCFG/pr35774.ll diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 58f1e8008ea..5d5300368cc 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1276,6 +1276,17 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, if (isa(I1)) goto HoistTerminator; + // If we're going to hoist a call, make sure that the two instructions we're + // commoning/hoisting are both marked with musttail, or neither of them is + // marked as such. Otherwise, we might end up in a situation where we hoist + // from a block where the terminator is a `ret` to a block where the terminator + // is a `br`, and `musttail` calls expect to be followed by a return. + auto *C1 = dyn_cast(I1); + auto *C2 = dyn_cast(I2); + if (C1 && C2) + if (C1->isMustTailCall() != C2->isMustTailCall()) + return false; + if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2)) return Changed; diff --git a/test/Transforms/SimplifyCFG/pr35774.ll b/test/Transforms/SimplifyCFG/pr35774.ll new file mode 100644 index 00000000000..149252085d5 --- /dev/null +++ b/test/Transforms/SimplifyCFG/pr35774.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -simplifycfg -S %s | FileCheck %s + +%foo = type { i32 (%foo)*, i32 } + +declare i32 @putchar(i32) + +define i32 @intercept(%foo %f) { +; CHECK-LABEL: @intercept( +; CHECK-NEXT: [[FN:%.*]] = extractvalue [[FOO:%.*]] %f, 0 +; CHECK-NEXT: [[X:%.*]] = extractvalue [[FOO]] %f, 1 +; CHECK-NEXT: [[X0:%.*]] = icmp eq i32 [[X]], 0 +; CHECK-NEXT: br i1 [[X0]], label [[ZERO:%.*]], label [[NONZERO:%.*]] +; CHECK: Zero: +; CHECK-NEXT: [[R0:%.*]] = musttail call i32 [[FN]](%foo [[F:%.*]]) +; CHECK-NEXT: ret i32 [[R0]] +; CHECK: Nonzero: +; CHECK-NEXT: [[R1:%.*]] = tail call i32 [[FN]](%foo [[F]]) +; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @putchar(i32 [[R1]]) +; CHECK-NEXT: ret i32 [[R1]] +; + %fn = extractvalue %foo %f, 0 + %x = extractvalue %foo %f, 1 + %x0 = icmp eq i32 %x, 0 + br i1 %x0, label %Zero, label %Nonzero + +Zero: + %r0 = musttail call i32 %fn(%foo %f) + ret i32 %r0 + +Nonzero: + %r1 = tail call i32 %fn(%foo %f) + %1 = tail call i32 @putchar(i32 %r1) + ret i32 %r1 +} -- 2.49.0