[llvm] r321603 - [SimplifyCFG] Stop hoisting musttail calls incorrectly.
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 31 08:47:17 PST 2017
Author: davide
Date: Sun Dec 31 08:47:16 2017
New Revision: 321603
URL: http://llvm.org/viewvc/llvm-project?rev=321603&view=rev
Log:
[SimplifyCFG] Stop hoisting musttail calls incorrectly.
PR35774.
Added:
llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll
Modified:
llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=321603&r1=321602&r2=321603&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Sun Dec 31 08:47:16 2017
@@ -1276,6 +1276,17 @@ static bool HoistThenElseCodeToIf(Branch
if (isa<TerminatorInst>(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<CallInst>(I1);
+ auto *C2 = dyn_cast<CallInst>(I2);
+ if (C1 && C2)
+ if (C1->isMustTailCall() != C2->isMustTailCall())
+ return false;
+
if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2))
return Changed;
Added: llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll?rev=321603&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll Sun Dec 31 08:47:16 2017
@@ -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
+}
More information about the llvm-commits
mailing list