Index: llvm/lib/Transforms/Scalar/LICM.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LICM.cpp +++ llvm/lib/Transforms/Scalar/LICM.cpp @@ -1201,6 +1201,18 @@ // Widenable conditions don't actually alias anything or throw return true; + // FIXME: If this call uses tokens, we should not touch it. Currently, + // tokens may penetrate through LCSSA form and lead optimizations that + // believe that *all* in-loop values only go outside through LCSSA phis + // into making incorrect transforms. See one of such examples at PR56243. + // We do not want to make LCSSA even more broken than it used to be. + // + // If the contradiction between definition of LCSSA and ability of tokens + // to violate it will ever be resolved, we can lift this check. + if (any_of(CI->operands(), + [](const Value *V) { return V->getType()->isTokenTy(); })) + return false; + // Handle simple cases by querying alias analysis. FunctionModRefBehavior Behavior = AA->getModRefBehavior(CI); if (Behavior == FMRB_DoesNotAccessMemory) Index: llvm/test/Transforms/LICM/gc-relocate.ll =================================================================== --- llvm/test/Transforms/LICM/gc-relocate.ll +++ llvm/test/Transforms/LICM/gc-relocate.ll @@ -10,10 +10,11 @@ ; CHECK-NEXT: br label [[BB1:%.*]] ; CHECK: bb1: ; CHECK-NEXT: [[TMP:%.*]] = call token (i64, i32, i32 (i32, i8 addrspace(1)*, i32, i32, i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32p1i8i32i32i32f(i64 1, i32 16, i32 (i32, i8 addrspace(1)*, i32, i32, i32)* nonnull elementtype(i32 (i32, i8 addrspace(1)*, i32, i32, i32)) @zot, i32 5, i32 0, i32 undef, i8 addrspace(1)* undef, i32 undef, i32 undef, i32 undef, i32 0, i32 0) [ "deopt"(i32 0, i32 0, i32 0, i32 235, i32 3, i32 32, i32 0, i32 0, i8 addrspace(1)* undef, i32 3, i32 undef, i32 3, float undef, i32 0, i8 addrspace(1)* undef, i32 7, i8* null, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 0, i8 addrspace(1)* undef, i32 4, double undef, i32 7, i8* null, i32 0, i8 addrspace(1)* undef, i32 3, float undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* null, i32 3, i32 -15108, i32 7, i8* null, i32 7, i8* null, i32 7, i8* null, i32 7, i8* null, i32 7, i8* null), "gc-live"(i8 addrspace(1)* [[ARG:%.*]]) ] +; CHECK-NEXT: [[RES:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[TMP]], i32 0, i32 0) #[[ATTR1:[0-9]+]] ; CHECK-NEXT: br i1 false, label [[BB1]], label [[BB2:%.*]] ; CHECK: bb2: -; CHECK-NEXT: [[RES_LE:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[TMP]], i32 0, i32 0) #[[ATTR1:[0-9]+]] -; CHECK-NEXT: ret i8 addrspace(1)* [[RES_LE]] +; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i8 addrspace(1)* [ [[RES]], [[BB1]] ] +; CHECK-NEXT: ret i8 addrspace(1)* [[RES_LCSSA]] ; bb: br label %bb1 Index: llvm/test/Transforms/LICM/pr56243.ll =================================================================== --- llvm/test/Transforms/LICM/pr56243.ll +++ llvm/test/Transforms/LICM/pr56243.ll @@ -1,25 +1,54 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes='loop-mssa(licm,loop-simplifycfg)' < %s | FileCheck %s -; REQUIRES: asserts -; XFAIL: * -; Here we end un sinking a user of token down from the loop, therefore breaching LCSSA form. +; If we end un sinking a user of token down from the loop, therefore breaching LCSSA form. ; Then, LoopSimplifyCFG expcets that LCSSA form is maintained, and remains unaware that ; it may be penetrated by tokens. As result, it may end up breaking dominance between def and ; use by introducing fake temporary edges. - +; Make sure LICM doesn't do it. define i8 addrspace(1)* @test_gc_relocate() gc "statepoint-example" { -; CHECK-LABEL: @test_gc_relocate +; CHECK-LABEL: @test_gc_relocate( +; CHECK-NEXT: switch i32 0, label [[DOTSPLIT:%.*]] [ +; CHECK-NEXT: i32 1, label [[BB57:%.*]] +; CHECK-NEXT: ] +; CHECK: .split: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: switch i32 undef, label [[BB43:%.*]] [ +; CHECK-NEXT: i32 1, label [[BB18:%.*]] +; CHECK-NEXT: ] +; CHECK: bb18: +; CHECK-NEXT: switch i32 undef, label [[BB43]] [ +; CHECK-NEXT: i32 0, label [[BB28:%.*]] +; CHECK-NEXT: ] +; CHECK: bb28: +; CHECK-NEXT: [[TMP34:%.*]] = call token (i64, i32, i8 addrspace(1)* (i64, i32, i32, i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8i64i32i32i32f(i64 2882400000, i32 0, i8 addrspace(1)* (i64, i32, i32, i32)* nonnull elementtype(i8 addrspace(1)* (i64, i32, i32, i32)) @barney.4, i32 4, i32 0, i64 undef, i32 5, i32 5, i32 undef, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* undef) ] +; CHECK-NEXT: [[TMP35:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[TMP34]], i32 0, i32 0) +; CHECK-NEXT: switch i32 undef, label [[BB43]] [ +; CHECK-NEXT: i32 1, label [[BB39:%.*]] +; CHECK-NEXT: ] +; CHECK: bb39: +; CHECK-NEXT: switch i32 undef, label [[BB43]] [ +; CHECK-NEXT: i32 1, label [[BB45:%.*]] +; CHECK-NEXT: ] +; CHECK: bb43: +; CHECK-NEXT: unreachable +; CHECK: bb45: +; CHECK-NEXT: br label [[BB1]] +; CHECK: bb57: +; CHECK-NEXT: ret i8 addrspace(1)* poison +; br label %bb1 bb1: ; preds = %bb45, %0 switch i32 undef, label %bb43 [ - i32 1, label %bb18 + i32 1, label %bb18 ] bb18: ; preds = %bb1 switch i32 undef, label %bb43 [ - i32 0, label %bb28 + i32 0, label %bb28 ] bb28: ; preds = %bb18 @@ -29,12 +58,12 @@ bb36: ; preds = %bb28 switch i32 undef, label %bb43 [ - i32 1, label %bb39 + i32 1, label %bb39 ] bb39: ; preds = %bb36 switch i32 undef, label %bb43 [ - i32 1, label %bb45 + i32 1, label %bb45 ] bb43: ; preds = %bb39, %bb36, %bb18, %bb1