Skip to content

Commit 5db6c9d

Browse files
nikictstellar
authored andcommitted
[SimplifyCFG] Don't merge invoke if this makes immarg non-constant (PR61265)
Don't merge invokes if this replaces constant operands with phis in a place where this is not legal. This also disallows converting operand bundles from constant to non-constant, in line with the restriction we use in other transforms. Fixes #61265. Differential Revision: https://reviews.llvm.org/D146723 (cherry picked from commit 1131310)
1 parent 33b41a6 commit 5db6c9d

File tree

3 files changed

+67
-19
lines changed

3 files changed

+67
-19
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,9 +2455,13 @@ bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
24552455

24562456
// Can we theoretically form the data operands for the merged `invoke`?
24572457
auto IsIllegalToMergeArguments = [](auto Ops) {
2458-
Type *Ty = std::get<0>(Ops)->getType();
2459-
assert(Ty == std::get<1>(Ops)->getType() && "Incompatible types?");
2460-
return Ty->isTokenTy() && std::get<0>(Ops) != std::get<1>(Ops);
2458+
Use &U0 = std::get<0>(Ops);
2459+
Use &U1 = std::get<1>(Ops);
2460+
if (U0 == U1)
2461+
return false;
2462+
return U0->getType()->isTokenTy() ||
2463+
!canReplaceOperandWithVariable(cast<Instruction>(U0.getUser()),
2464+
U0.getOperandNo());
24612465
};
24622466
assert(Invokes.size() == 2 && "Always called with exactly two candidates.");
24632467
if (any_of(zip(Invokes[0]->data_ops(), Invokes[1]->data_ops()),

llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ if.end:
12321232
}
12331233

12341234
; We need to PHI together the arguments of the operand bundles.
1235-
define void @t21_semicompatible_operand_bundle() personality ptr @__gxx_personality_v0 {
1235+
define void @t21_semicompatible_operand_bundle(i32 %a, i32 %b) personality ptr @__gxx_personality_v0 {
12361236
; CHECK-LABEL: @t21_semicompatible_operand_bundle(
12371237
; CHECK-NEXT: entry:
12381238
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
@@ -1246,7 +1246,7 @@ define void @t21_semicompatible_operand_bundle() personality ptr @__gxx_personal
12461246
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
12471247
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
12481248
; CHECK: if.then1.invoke:
1249-
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[IF_ELSE]] ], [ 42, [[ENTRY:%.*]] ]
1249+
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[B:%.*]], [[IF_ELSE]] ], [ [[A:%.*]], [[ENTRY:%.*]] ]
12501250
; CHECK-NEXT: invoke void @simple_throw() [ "abc"(i32 [[TMP0]]) ]
12511251
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
12521252
; CHECK: if.then1.cont:
@@ -1260,7 +1260,7 @@ entry:
12601260
br i1 %c0, label %if.then0, label %if.else
12611261

12621262
if.then0:
1263-
invoke void @simple_throw() [ "abc"(i32 42) ] to label %invoke.cont0 unwind label %lpad
1263+
invoke void @simple_throw() [ "abc"(i32 %a) ] to label %invoke.cont0 unwind label %lpad
12641264

12651265
invoke.cont0:
12661266
unreachable
@@ -1275,7 +1275,7 @@ if.else:
12751275
br i1 %c1, label %if.then1, label %if.end
12761276

12771277
if.then1:
1278-
invoke void @simple_throw() [ "abc"(i32 0) ] to label %invoke.cont2 unwind label %lpad
1278+
invoke void @simple_throw() [ "abc"(i32 %b) ] to label %invoke.cont2 unwind label %lpad
12791279

12801280
invoke.cont2:
12811281
unreachable
@@ -2342,7 +2342,7 @@ if.end:
23422342
}
23432343

23442344
; For indirect invokes, different operand bundle arguments are fine.
2345-
define void @t39_different_arguments_and_operand_bundes_are_fine(ptr %callee0, ptr %callee1) personality ptr @__gxx_personality_v0 {
2345+
define void @t39_different_arguments_and_operand_bundes_are_fine(ptr %callee0, ptr %callee1, i32 %a, i32 %b) personality ptr @__gxx_personality_v0 {
23462346
; CHECK-LABEL: @t39_different_arguments_and_operand_bundes_are_fine(
23472347
; CHECK-NEXT: entry:
23482348
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
@@ -2356,7 +2356,7 @@ define void @t39_different_arguments_and_operand_bundes_are_fine(ptr %callee0, p
23562356
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
23572357
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
23582358
; CHECK: if.then1.invoke:
2359-
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[IF_ELSE]] ], [ 42, [[ENTRY:%.*]] ]
2359+
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[B:%.*]], [[IF_ELSE]] ], [ [[A:%.*]], [[ENTRY:%.*]] ]
23602360
; CHECK-NEXT: [[TMP1:%.*]] = phi ptr [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
23612361
; CHECK-NEXT: invoke void [[TMP1]]() [ "abc"(i32 [[TMP0]]) ]
23622362
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
@@ -2371,7 +2371,7 @@ entry:
23712371
br i1 %c0, label %if.then0, label %if.else
23722372

23732373
if.then0:
2374-
invoke void %callee0() [ "abc"(i32 42) ] to label %invoke.cont0 unwind label %lpad
2374+
invoke void %callee0() [ "abc"(i32 %a) ] to label %invoke.cont0 unwind label %lpad
23752375

23762376
invoke.cont0:
23772377
unreachable
@@ -2386,7 +2386,7 @@ if.else:
23862386
br i1 %c1, label %if.then1, label %if.end
23872387

23882388
if.then1:
2389-
invoke void %callee1() [ "abc"(i32 0) ] to label %invoke.cont2 unwind label %lpad
2389+
invoke void %callee1() [ "abc"(i32 %b) ] to label %invoke.cont2 unwind label %lpad
23902390

23912391
invoke.cont2:
23922392
unreachable
@@ -2397,7 +2397,7 @@ if.end:
23972397
}
23982398

23992399
; For indirect invokes, both different arguments and operand bundle arguments are fine.
2400-
define void @t40_different_arguments_and_operand_bundes_are_fine(ptr %callee0, ptr %callee1) personality ptr @__gxx_personality_v0 {
2400+
define void @t40_different_arguments_and_operand_bundes_are_fine(ptr %callee0, ptr %callee1, i32 %a, i32 %b) personality ptr @__gxx_personality_v0 {
24012401
; CHECK-LABEL: @t40_different_arguments_and_operand_bundes_are_fine(
24022402
; CHECK-NEXT: entry:
24032403
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
@@ -2412,7 +2412,7 @@ define void @t40_different_arguments_and_operand_bundes_are_fine(ptr %callee0, p
24122412
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
24132413
; CHECK: if.then1.invoke:
24142414
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, [[IF_ELSE]] ], [ 0, [[ENTRY:%.*]] ]
2415-
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ 0, [[IF_ELSE]] ], [ 42, [[ENTRY]] ]
2415+
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[B:%.*]], [[IF_ELSE]] ], [ [[A:%.*]], [[ENTRY]] ]
24162416
; CHECK-NEXT: [[TMP2:%.*]] = phi ptr [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
24172417
; CHECK-NEXT: invoke void [[TMP2]](i32 [[TMP0]]) [ "abc"(i32 [[TMP1]]) ]
24182418
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
@@ -2427,7 +2427,7 @@ entry:
24272427
br i1 %c0, label %if.then0, label %if.else
24282428

24292429
if.then0:
2430-
invoke void %callee0(i32 0) [ "abc"(i32 42) ] to label %invoke.cont0 unwind label %lpad
2430+
invoke void %callee0(i32 0) [ "abc"(i32 %a) ] to label %invoke.cont0 unwind label %lpad
24312431

24322432
invoke.cont0:
24332433
unreachable
@@ -2442,7 +2442,7 @@ if.else:
24422442
br i1 %c1, label %if.then1, label %if.end
24432443

24442444
if.then1:
2445-
invoke void %callee1(i32 42) [ "abc"(i32 0) ] to label %invoke.cont2 unwind label %lpad
2445+
invoke void %callee1(i32 42) [ "abc"(i32 %b) ] to label %invoke.cont2 unwind label %lpad
24462446

24472447
invoke.cont2:
24482448
unreachable
@@ -2452,6 +2452,43 @@ if.end:
24522452
ret void
24532453
}
24542454

2455+
define void @dont_merge_different_immargs(i1 %c1) gc "statepoint-example" personality ptr null {
2456+
; CHECK-LABEL: @dont_merge_different_immargs(
2457+
; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
2458+
; CHECK: if:
2459+
; CHECK-NEXT: [[T1:%.*]] = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 1, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2460+
; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
2461+
; CHECK: else:
2462+
; CHECK-NEXT: [[T2:%.*]] = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2463+
; CHECK-NEXT: to label [[UNREACHABLE]] unwind label [[LPAD]]
2464+
; CHECK: unreachable:
2465+
; CHECK-NEXT: unreachable
2466+
; CHECK: lpad:
2467+
; CHECK-NEXT: [[T3:%.*]] = landingpad token
2468+
; CHECK-NEXT: cleanup
2469+
; CHECK-NEXT: ret void
2470+
;
2471+
br i1 %c1, label %if, label %else
2472+
2473+
if:
2474+
%t1 = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 1, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2475+
to label %unreachable unwind label %lpad
2476+
2477+
else:
2478+
%t2 = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2479+
to label %unreachable unwind label %lpad
2480+
2481+
unreachable:
2482+
unreachable
2483+
2484+
lpad:
2485+
%t3 = landingpad token
2486+
cleanup
2487+
ret void
2488+
}
2489+
2490+
declare token @llvm.experimental.gc.statepoint.p0(i64 immarg, i32 immarg, ptr, i32 immarg, i32 immarg, ...)
2491+
24552492
declare i1 @cond()
24562493

24572494
declare void @sideeffect()

llvm/test/Transforms/SimplifyCFG/merge-deopt-bundle-constants.ll

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@ target triple = "x86_64-unknown-linux-gnu"
77
define void @test_01(i1 %cond) gc "statepoint-example" personality ptr @zot {
88
; CHECK-LABEL: @test_01(
99
; CHECK-NEXT: bb:
10-
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[COND:%.*]], i32 0, i32 1
10+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB3:%.*]], label [[BB8:%.*]]
11+
; CHECK: bb3:
1112
; CHECK-NEXT: [[TMP4:%.*]] = call ptr @wibble()
12-
; CHECK-NEXT: [[TMP0:%.*]] = invoke align 8 dereferenceable_or_null(8) ptr addrspace(1) [[TMP4]](ptr addrspace(1) undef) [ "deopt"(i32 [[DOT]]) ]
13-
; CHECK-NEXT: to label [[BB8_CONT:%.*]] unwind label [[BB13:%.*]]
14-
; CHECK: bb8.cont:
13+
; CHECK-NEXT: [[TMP6:%.*]] = invoke align 8 dereferenceable_or_null(8) ptr addrspace(1) [[TMP4]](ptr addrspace(1) undef) [ "deopt"(i32 0) ]
14+
; CHECK-NEXT: to label [[BB7:%.*]] unwind label [[BB13:%.*]]
15+
; CHECK: bb7:
16+
; CHECK-NEXT: unreachable
17+
; CHECK: bb8:
18+
; CHECK-NEXT: [[TMP9:%.*]] = call ptr @wibble()
19+
; CHECK-NEXT: [[TMP11:%.*]] = invoke align 8 dereferenceable_or_null(8) ptr addrspace(1) [[TMP9]](ptr addrspace(1) undef) [ "deopt"(i32 1) ]
20+
; CHECK-NEXT: to label [[BB12:%.*]] unwind label [[BB13]]
21+
; CHECK: bb12:
1522
; CHECK-NEXT: unreachable
1623
; CHECK: bb13:
1724
; CHECK-NEXT: [[TMP14:%.*]] = landingpad { ptr, i32 }

0 commit comments

Comments
 (0)