Index: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopUnswitch.cpp +++ llvm/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -661,7 +661,7 @@ // FIXME: Use Function::hasOptSize(). if (OptimizeForSize || LoopHeader->getParent()->hasFnAttribute(Attribute::OptimizeForSize)) - return false; + return Changed; // Run through the instructions in the loop, keeping track of three things: // @@ -685,10 +685,10 @@ if (!CB) continue; if (CB->isConvergent()) - return false; + return Changed; if (auto *II = dyn_cast(&I)) if (!II->getUnwindDest()->canSplitPredecessors()) - return false; + return Changed; if (auto *II = dyn_cast(&I)) if (II->getIntrinsicID() == Intrinsic::experimental_guard) Guards.push_back(II); Index: llvm/test/Transforms/LoopUnswitch/optsize-hoist-modified.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/LoopUnswitch/optsize-hoist-modified.ll @@ -0,0 +1,41 @@ +; RUN: opt -loop-unswitch -enable-new-pm=0 %s -S | FileCheck %s + +; When hoisting simple values out from a loop, and not being able to attempt to +; non-trivally unswitch the loop, due to the optsize attribute, the pass would +; return an incorrect Modified status. + +; CHECK-LABEL: entry: +; CHECK-NEXT: %0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false) +; CHECK-NEXT: %1 = icmp uge i32 %0, 1 +; CHECK-NEXT: br label %for.cond + +%struct.anon = type { i16 } + +@b = global %struct.anon zeroinitializer, align 1 +@.src = private unnamed_addr constant [4 x i8] c"foo\00", align 1 +@0 = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 0, i16 9, [4 x i8] c"bar\00" } +@1 = private unnamed_addr global { { [4 x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8, i8 } { { [4 x i8]*, i32, i32 } { [4 x i8]* @.src, i32 5, i32 13 }, { i16, i16, [4 x i8] }* @0, i8 0, i8 0 } + +; Function Attrs: minsize nounwind optsize +define i16 @c() #0 { +entry: + br label %for.cond + +for.cond: ; preds = %cont, %entry + br label %for.inc + +for.inc: ; preds = %for.cond + %0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false) + %1 = icmp uge i32 %0, 1 + br i1 %1, label %cont, label %cont + +cont: ; preds = %for.inc + %2 = load i16, i16* getelementptr inbounds (%struct.anon, %struct.anon* @b, i32 0, i32 0), align 1 + br label %for.cond +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare i32 @llvm.objectsize.i32.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #1 + +attributes #0 = { minsize nounwind optsize } +attributes #1 = { nounwind readnone speculatable willreturn }