Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -3976,9 +3976,11 @@ array_pod_sort(Values.begin(), Values.end(), ConstantIntSortPredicate); Values.erase(std::unique(Values.begin(), Values.end()), Values.end()); - // If Extra was used, we require at least two switch values to do the - // transformation. A switch with one value is just a conditional branch. - if (ExtraCase && Values.size() < 2) + // We require at least three switch values to do the transformation. With + // only two values, the transform is likely not profitable, either because + // the condition can be folded, or because other passes like loop rotation + // and vectorization do not handle switches. + if (Values.size() < 3) return false; // TODO: Preserve branch weight metadata, similarly to how Index: llvm/test/Transforms/PGOProfile/chr.ll =================================================================== --- llvm/test/Transforms/PGOProfile/chr.ll +++ llvm/test/Transforms/PGOProfile/chr.ll @@ -1909,14 +1909,14 @@ ; CHECK-NEXT: br i1 [[TMP1]], label [[BB1:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15 ; CHECK: bb1: ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i64 [[I]], 2 -; CHECK-NEXT: switch i64 [[I]], label [[BB2:%.*]] [ -; CHECK-NEXT: i64 2, label [[BB3_NONCHR2:%.*]] -; CHECK-NEXT: i64 86, label [[BB2_NONCHR1:%.*]] -; CHECK-NEXT: ], !prof !20 +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[CMP2]], [[CMP_I]] +; CHECK-NEXT: br i1 [[TMP2]], label [[BB2:%.*]], label [[BB1_SPLIT_NONCHR:%.*]], !prof !15 ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB7:%.*]] +; CHECK: bb1.split.nonchr: +; CHECK-NEXT: br i1 [[CMP2]], label [[BB2_NONCHR1:%.*]], label [[BB3_NONCHR2:%.*]], !prof !18 ; CHECK: bb2.nonchr1: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3_NONCHR2]] @@ -2489,14 +2489,14 @@ ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 -; CHECK-NEXT: br i1 [[TMP2]], label [[BB1:%.*]], label [[BB0:%.*]], !prof !21 +; CHECK-NEXT: br i1 [[TMP2]], label [[BB1:%.*]], label [[BB0:%.*]], !prof !20 ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[BB3:%.*]], label [[BB2:%.*]], !prof !21 +; CHECK-NEXT: br i1 [[TMP4]], label [[BB3:%.*]], label [[BB2:%.*]], !prof !20 ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] Index: llvm/test/Transforms/PhaseOrdering/X86/pr48844-br-to-switch-vectorization.ll =================================================================== --- llvm/test/Transforms/PhaseOrdering/X86/pr48844-br-to-switch-vectorization.ll +++ llvm/test/Transforms/PhaseOrdering/X86/pr48844-br-to-switch-vectorization.ll @@ -11,21 +11,77 @@ ; CHECK-LABEL: @test( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[I11_NOT1:%.*]] = icmp eq i32* [[START:%.*]], [[END:%.*]] -; CHECK-NEXT: br i1 [[I11_NOT1]], label [[EXIT:%.*]], label [[BB12:%.*]] +; CHECK-NEXT: br i1 [[I11_NOT1]], label [[EXIT:%.*]], label [[BB12_PREHEADER:%.*]] +; CHECK: bb12.preheader: +; CHECK-NEXT: [[START5:%.*]] = ptrtoint i32* [[START]] to i64 +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i32, i32* [[END]], i64 -1 +; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint i32* [[SCEVGEP]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[START5]] +; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 2 +; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 124 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[BB12_PREHEADER13:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP3]], 9223372036854775776 +; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i32, i32* [[START]], i64 [[N_VEC]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i32, i32* [[START]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[NEXT_GEP]] to <8 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, <8 x i32>* [[TMP4]], align 4 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, i32* [[NEXT_GEP]], i64 8 +; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <8 x i32>* +; CHECK-NEXT: [[WIDE_LOAD10:%.*]] = load <8 x i32>, <8 x i32>* [[TMP6]], align 4 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, i32* [[NEXT_GEP]], i64 16 +; CHECK-NEXT: [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <8 x i32>* +; CHECK-NEXT: [[WIDE_LOAD11:%.*]] = load <8 x i32>, <8 x i32>* [[TMP8]], align 4 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i32, i32* [[NEXT_GEP]], i64 24 +; CHECK-NEXT: [[TMP10:%.*]] = bitcast i32* [[TMP9]] to <8 x i32>* +; CHECK-NEXT: [[WIDE_LOAD12:%.*]] = load <8 x i32>, <8 x i32>* [[TMP10]], align 4 +; CHECK-NEXT: [[TMP11:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD]], +; CHECK-NEXT: [[TMP12:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD10]], +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD11]], +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD12]], +; CHECK-NEXT: [[TMP15:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD]], +; CHECK-NEXT: [[TMP16:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD10]], +; CHECK-NEXT: [[TMP17:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD11]], +; CHECK-NEXT: [[TMP18:%.*]] = icmp eq <8 x i32> [[WIDE_LOAD12]], +; CHECK-NEXT: [[TMP19:%.*]] = or <8 x i1> [[TMP11]], [[TMP15]] +; CHECK-NEXT: [[TMP20:%.*]] = or <8 x i1> [[TMP12]], [[TMP16]] +; CHECK-NEXT: [[TMP21:%.*]] = or <8 x i1> [[TMP13]], [[TMP17]] +; CHECK-NEXT: [[TMP22:%.*]] = or <8 x i1> [[TMP14]], [[TMP18]] +; CHECK-NEXT: [[TMP23:%.*]] = bitcast i32* [[NEXT_GEP]] to <8 x i32>* +; CHECK-NEXT: call void @llvm.masked.store.v8i32.p0v8i32(<8 x i32> , <8 x i32>* [[TMP23]], i32 4, <8 x i1> [[TMP19]]) +; CHECK-NEXT: [[TMP24:%.*]] = bitcast i32* [[TMP5]] to <8 x i32>* +; CHECK-NEXT: call void @llvm.masked.store.v8i32.p0v8i32(<8 x i32> , <8 x i32>* [[TMP24]], i32 4, <8 x i1> [[TMP20]]) +; CHECK-NEXT: [[TMP25:%.*]] = bitcast i32* [[TMP7]] to <8 x i32>* +; CHECK-NEXT: call void @llvm.masked.store.v8i32.p0v8i32(<8 x i32> , <8 x i32>* [[TMP25]], i32 4, <8 x i1> [[TMP21]]) +; CHECK-NEXT: [[TMP26:%.*]] = bitcast i32* [[TMP9]] to <8 x i32>* +; CHECK-NEXT: call void @llvm.masked.store.v8i32.p0v8i32(<8 x i32> , <8 x i32>* [[TMP26]], i32 4, <8 x i1> [[TMP22]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 32 +; CHECK-NEXT: [[TMP27:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP27]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], [[LOOP0:!llvm.loop !.*]] +; CHECK: middle.block: +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT]], label [[BB12_PREHEADER13]] +; CHECK: bb12.preheader13: +; CHECK-NEXT: [[PTR2_PH:%.*]] = phi i32* [ [[START]], [[BB12_PREHEADER]] ], [ [[IND_END]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[BB12:%.*]] ; CHECK: bb12: -; CHECK-NEXT: [[PTR2:%.*]] = phi i32* [ [[PTR_NEXT:%.*]], [[LATCH:%.*]] ], [ [[START]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[PTR2:%.*]] = phi i32* [ [[PTR_NEXT:%.*]], [[LATCH:%.*]] ], [ [[PTR2_PH]], [[BB12_PREHEADER13]] ] ; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[PTR2]], align 4 -; CHECK-NEXT: switch i32 [[VAL]], label [[LATCH]] [ -; CHECK-NEXT: i32 -12, label [[STORE:%.*]] -; CHECK-NEXT: i32 13, label [[STORE]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[VAL]], 13 +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[VAL]], -12 +; CHECK-NEXT: [[C3:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[C3]], label [[STORE:%.*]], label [[LATCH]] ; CHECK: store: ; CHECK-NEXT: store i32 42, i32* [[PTR2]], align 4 ; CHECK-NEXT: br label [[LATCH]] ; CHECK: latch: ; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds i32, i32* [[PTR2]], i64 1 ; CHECK-NEXT: [[I11_NOT:%.*]] = icmp eq i32* [[PTR_NEXT]], [[END]] -; CHECK-NEXT: br i1 [[I11_NOT]], label [[EXIT]], label [[BB12]] +; CHECK-NEXT: br i1 [[I11_NOT]], label [[EXIT]], label [[BB12]], [[LOOP2:!llvm.loop !.*]] ; CHECK: exit: ; CHECK-NEXT: ret void ; Index: llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll =================================================================== --- llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll +++ llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll @@ -1,30 +1,38 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -O2 < %s | FileCheck %s -; RUN: opt -S -passes='default' < %s | FileCheck %s +; RUN: opt -S -O2 < %s | FileCheck %s --check-prefix=LPM +; RUN: opt -S -passes='default' < %s | FileCheck %s --check-prefix=NPM ; FIXME: The br -> switch conversion blocks loop rotation. define i64 @test() { -; CHECK-LABEL: @test( -; CHECK-NEXT: start: -; CHECK-NEXT: br label [[BB10:%.*]] -; CHECK: bb10: -; CHECK-NEXT: [[ITER1_SROA_5_0:%.*]] = phi i64 [ 100000, [[START:%.*]] ], [ [[SPEC_SELECT:%.*]], [[BB3_I_I:%.*]] ] -; CHECK-NEXT: [[ITER1_SROA_9_0:%.*]] = phi i2 [ -2, [[START]] ], [ [[TMP3:%.*]], [[BB3_I_I]] ] -; CHECK-NEXT: [[COUNT_1:%.*]] = phi i64 [ 0, [[START]] ], [ [[TMP4:%.*]], [[BB3_I_I]] ] -; CHECK-NEXT: switch i2 [[ITER1_SROA_9_0]], label [[BB12:%.*]] [ -; CHECK-NEXT: i2 -2, label [[BB3_I_I]] -; CHECK-NEXT: i2 0, label [[BB3_I_I]] -; CHECK-NEXT: ] -; CHECK: bb3.i.i: -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[ITER1_SROA_5_0]], 0 -; CHECK-NEXT: [[TMP3]] = zext i1 [[TMP2]] to i2 -; CHECK-NEXT: [[_5_0_I_I_I_I:%.*]] = add i64 [[ITER1_SROA_5_0]], -1 -; CHECK-NEXT: [[SPEC_SELECT]] = select i1 [[TMP2]], i64 0, i64 [[_5_0_I_I_I_I]] -; CHECK-NEXT: [[TMP4]] = add i64 [[COUNT_1]], [[ITER1_SROA_5_0]] -; CHECK-NEXT: br label [[BB10]] -; CHECK: bb12: -; CHECK-NEXT: ret i64 [[COUNT_1]] +; LPM-LABEL: @test( +; LPM-NEXT: start: +; LPM-NEXT: br label [[BB3_I_I:%.*]] +; LPM: bb3.i.i: +; LPM-NEXT: [[COUNT_12:%.*]] = phi i64 [ 0, [[START:%.*]] ], [ [[TMP4:%.*]], [[BB3_I_I]] ] +; LPM-NEXT: [[ITER1_SROA_5_01:%.*]] = phi i64 [ 100000, [[START]] ], [ [[_5_0_I_I_I_I:%.*]], [[BB3_I_I]] ] +; LPM-NEXT: [[TMP2:%.*]] = icmp eq i64 [[ITER1_SROA_5_01]], 0 +; LPM-NEXT: [[_5_0_I_I_I_I]] = add i64 [[ITER1_SROA_5_01]], -1 +; LPM-NEXT: [[TMP4]] = add i64 [[COUNT_12]], [[ITER1_SROA_5_01]] +; LPM-NEXT: br i1 [[TMP2]], label [[BB12:%.*]], label [[BB3_I_I]] +; LPM: bb12: +; LPM-NEXT: ret i64 [[TMP4]] +; +; NPM-LABEL: @test( +; NPM-NEXT: start: +; NPM-NEXT: [[TMP4_0:%.*]] = add i64 0, 100000 +; NPM-NEXT: br label [[BB3_I_I:%.*]] +; NPM: bb3.i.i: +; NPM-NEXT: [[TMP4_PHI:%.*]] = phi i64 [ [[TMP4_0]], [[START:%.*]] ], [ [[TMP4_1:%.*]], [[BB3_I_I_BB3_I_I_CRIT_EDGE:%.*]] ] +; NPM-NEXT: [[ITER1_SROA_5_01:%.*]] = phi i64 [ 100000, [[START]] ], [ [[_5_0_I_I_I_I:%.*]], [[BB3_I_I_BB3_I_I_CRIT_EDGE]] ] +; NPM-NEXT: [[TMP2:%.*]] = icmp eq i64 [[ITER1_SROA_5_01]], 0 +; NPM-NEXT: [[_5_0_I_I_I_I]] = add i64 [[ITER1_SROA_5_01]], -1 +; NPM-NEXT: br i1 [[TMP2]], label [[BB12:%.*]], label [[BB3_I_I_BB3_I_I_CRIT_EDGE]] +; NPM: bb3.i.i.bb3.i.i_crit_edge: +; NPM-NEXT: [[TMP4_1]] = add i64 [[TMP4_PHI]], [[_5_0_I_I_I_I]] +; NPM-NEXT: br label [[BB3_I_I]] +; NPM: bb12: +; NPM-NEXT: ret i64 [[TMP4_PHI]] ; start: br label %bb10 Index: llvm/test/Transforms/SimplifyCFG/DeadSetCC.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/DeadSetCC.ll +++ llvm/test/Transforms/SimplifyCFG/DeadSetCC.ll @@ -10,9 +10,14 @@ define void @testcfg(i32 %V) { ; CHECK-LABEL: @testcfg( -; CHECK-NEXT: [[V_OFF:%.*]] = add i32 [[V:%.*]], -15 +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[V:%.*]], 18 +; CHECK-NEXT: [[D:%.*]] = icmp eq i32 [[V]], 180 +; CHECK-NEXT: [[E:%.*]] = or i1 [[C]], [[D]] +; CHECK-NEXT: [[E_NOT:%.*]] = xor i1 [[E]], true +; CHECK-NEXT: [[V_OFF:%.*]] = add i32 [[V]], -15 ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[V_OFF]], 2 -; CHECK-NEXT: br i1 [[SWITCH]], label [[L2:%.*]], label [[L1:%.*]] +; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[E_NOT]], [[SWITCH]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[L2:%.*]], label [[L1:%.*]] ; CHECK: L1: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: ret void Index: llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll +++ llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll @@ -8,10 +8,10 @@ define void @test1(i32 %V) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ -; CHECK-NEXT: i32 17, label [[T:%.*]] -; CHECK-NEXT: i32 4, label [[T]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[V:%.*]], 4 +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[V]], 17 +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -33,11 +33,10 @@ define void @test1_ptr(i32* %V) { ; CHECK-LABEL: @test1_ptr( -; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32* [[V:%.*]] to i40 -; CHECK-NEXT: switch i40 [[MAGICPTR]], label [[F:%.*]] [ -; CHECK-NEXT: i40 17, label [[T:%.*]] -; CHECK-NEXT: i40 4, label [[T]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32* [[V:%.*]], inttoptr (i32 4 to i32*) +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32* [[V]], inttoptr (i32 17 to i32*) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -59,11 +58,10 @@ define void @test1_ptr_as1(i32 addrspace(1)* %V) { ; CHECK-LABEL: @test1_ptr_as1( -; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32 addrspace(1)* [[V:%.*]] to i40 -; CHECK-NEXT: switch i40 [[MAGICPTR]], label [[F:%.*]] [ -; CHECK-NEXT: i40 17, label [[T:%.*]] -; CHECK-NEXT: i40 4, label [[T]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 addrspace(1)* [[V:%.*]], inttoptr (i32 4 to i32 addrspace(1)*) +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 addrspace(1)* [[V]], inttoptr (i32 17 to i32 addrspace(1)*) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -85,10 +83,10 @@ define void @test2(i32 %V) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 17, label [[F:%.*]] -; CHECK-NEXT: i32 4, label [[F]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[V:%.*]], 4 +; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[V]], 17 +; CHECK-NEXT: [[CN:%.*]] = and i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -246,12 +244,11 @@ ; CHECK-LABEL: @test7( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i8 [[C:%.*]], 97 +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP]], [[CMP4]] +; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[C]], 99 +; CHECK-NEXT: [[OR_COND11:%.*]] = or i1 [[OR_COND]], [[CMP9]] +; CHECK-NEXT: br i1 [[OR_COND11]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: tail call void @foo1() [[ATTR2:#.*]] ; CHECK-NEXT: ret void @@ -281,14 +278,13 @@ ; CHECK-NEXT: br i1 [[C:%.*]], label [[N:%.*]], label [[IF_THEN:%.*]] ; CHECK: N: ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i8 [[C:%.*]], 97 +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP]], [[CMP4]] +; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[C]], 99 +; CHECK-NEXT: [[OR_COND11:%.*]] = or i1 [[OR_COND]], [[CMP9]] +; CHECK-NEXT: br i1 [[OR_COND11]], label [[IF_THEN]], label [[IF_END:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[SWITCH_EARLY_TEST]] ], [ 42, [[N]] ], [ 42, [[SWITCH_EARLY_TEST]] ] +; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[N]] ] ; CHECK-NEXT: tail call void @foo1() [[ATTR2]] ; CHECK-NEXT: ret i32 [[A]] ; CHECK: if.end: @@ -389,17 +385,13 @@ define i32 @test10(i32 %mode, i1 %Cond) { ; CHECK-LABEL: @test10( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 51, label [[F]] -; CHECK-NEXT: i32 0, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] -; CHECK-NEXT: ret i32 [[MERGE]] -; CHECK: F: -; CHECK-NEXT: br label [[T]] +; CHECK-NEXT: T: +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 +; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 +; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]] +; CHECK-NEXT: [[D:%.*]] = and i1 [[C]], [[COND:%.*]] +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -465,8 +457,8 @@ define void @test12() nounwind { ; CHECK-LABEL: @test12( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DOTOLD:%.*]] = icmp eq i32 undef, undef -; CHECK-NEXT: br i1 [[DOTOLD]], label [[BB55_US_US:%.*]], label [[MALFORMED:%.*]] +; CHECK-NEXT: [[A_OLD:%.*]] = icmp eq i32 undef, undef +; CHECK-NEXT: br i1 [[A_OLD]], label [[BB55_US_US:%.*]], label [[MALFORMED:%.*]] ; CHECK: bb55.us.us: ; CHECK-NEXT: [[B:%.*]] = icmp ugt i32 undef, undef ; CHECK-NEXT: [[A:%.*]] = icmp eq i32 undef, undef Index: llvm/test/Transforms/SimplifyCFG/switch_create.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/switch_create.ll +++ llvm/test/Transforms/SimplifyCFG/switch_create.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s -; RUN: opt -S -data-layout="p:32:32-p1:16:16" -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s +; RUN: opt -S -data-layout="p:32:32-p1:16:16" -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck -check-prefix=CHECK %s declare void @foo1() @@ -8,10 +8,10 @@ define void @test1(i32 %V) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ -; CHECK-NEXT: i32 17, label [[T:%.*]] -; CHECK-NEXT: i32 4, label [[T]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[V:%.*]], 4 +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[V]], 17 +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -33,10 +33,10 @@ define void @test1_select(i32 %V) { ; CHECK-LABEL: @test1_select( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ -; CHECK-NEXT: i32 17, label [[T:%.*]] -; CHECK-NEXT: i32 4, label [[T]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[V:%.*]], 4 +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[V]], 17 +; CHECK-NEXT: [[CN:%.*]] = select i1 [[C1]], i1 true, i1 [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -57,18 +57,17 @@ } define void @test1_ptr(i32* %V) { -; DL-LABEL: @test1_ptr( -; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32* [[V:%.*]] to i32 -; DL-NEXT: switch i32 [[MAGICPTR]], label [[F:%.*]] [ -; DL-NEXT: i32 17, label [[T:%.*]] -; DL-NEXT: i32 4, label [[T]] -; DL-NEXT: ] -; DL: T: -; DL-NEXT: call void @foo1() -; DL-NEXT: ret void -; DL: F: -; DL-NEXT: call void @foo2() -; DL-NEXT: ret void +; CHECK-LABEL: @test1_ptr( +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32* [[V:%.*]], inttoptr (i32 4 to i32*) +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32* [[V]], inttoptr (i32 17 to i32*) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] +; CHECK: T: +; CHECK-NEXT: call void @foo1() +; CHECK-NEXT: ret void +; CHECK: F: +; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: ret void ; %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*) %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*) @@ -83,18 +82,17 @@ } define void @test1_ptr_as1(i32 addrspace(1)* %V) { -; DL-LABEL: @test1_ptr_as1( -; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32 addrspace(1)* [[V:%.*]] to i16 -; DL-NEXT: switch i16 [[MAGICPTR]], label [[F:%.*]] [ -; DL-NEXT: i16 17, label [[T:%.*]] -; DL-NEXT: i16 4, label [[T]] -; DL-NEXT: ] -; DL: T: -; DL-NEXT: call void @foo1() -; DL-NEXT: ret void -; DL: F: -; DL-NEXT: call void @foo2() -; DL-NEXT: ret void +; CHECK-LABEL: @test1_ptr_as1( +; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 addrspace(1)* [[V:%.*]], inttoptr (i32 4 to i32 addrspace(1)*) +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 addrspace(1)* [[V]], inttoptr (i32 17 to i32 addrspace(1)*) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] +; CHECK: T: +; CHECK-NEXT: call void @foo1() +; CHECK-NEXT: ret void +; CHECK: F: +; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: ret void ; %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*) %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*) @@ -110,10 +108,10 @@ define void @test2(i32 %V) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 17, label [[F:%.*]] -; CHECK-NEXT: i32 4, label [[F]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[V:%.*]], 4 +; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[V]], 17 +; CHECK-NEXT: [[CN:%.*]] = and i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -135,10 +133,10 @@ define void @test2_select(i32 %V) { ; CHECK-LABEL: @test2_select( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 17, label [[F:%.*]] -; CHECK-NEXT: i32 4, label [[F]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[V:%.*]], 4 +; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[V]], 17 +; CHECK-NEXT: [[CN:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -296,12 +294,11 @@ ; CHECK-LABEL: @test7( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i8 [[C:%.*]], 97 +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP]], [[CMP4]] +; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[C]], 99 +; CHECK-NEXT: [[OR_COND11:%.*]] = or i1 [[OR_COND]], [[CMP9]] +; CHECK-NEXT: br i1 [[OR_COND11]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: tail call void @foo1() [[ATTR2:#.*]] ; CHECK-NEXT: ret void @@ -331,14 +328,13 @@ ; CHECK-NEXT: br i1 [[C:%.*]], label [[N:%.*]], label [[IF_THEN:%.*]] ; CHECK: N: ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i8 [[C:%.*]], 97 +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP]], [[CMP4]] +; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[C]], 99 +; CHECK-NEXT: [[OR_COND11:%.*]] = or i1 [[OR_COND]], [[CMP9]] +; CHECK-NEXT: br i1 [[OR_COND11]], label [[IF_THEN]], label [[IF_END:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[SWITCH_EARLY_TEST]] ], [ 42, [[N]] ], [ 42, [[SWITCH_EARLY_TEST]] ] +; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[N]] ] ; CHECK-NEXT: tail call void @foo1() [[ATTR2]] ; CHECK-NEXT: ret i32 [[A]] ; CHECK: if.end: @@ -439,17 +435,13 @@ define i32 @test10(i32 %mode, i1 %Cond) { ; CHECK-LABEL: @test10( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 51, label [[F]] -; CHECK-NEXT: i32 0, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] -; CHECK-NEXT: ret i32 [[MERGE]] -; CHECK: F: -; CHECK-NEXT: br label [[T]] +; CHECK-NEXT: T: +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 +; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 +; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]] +; CHECK-NEXT: [[D:%.*]] = and i1 [[C]], [[COND:%.*]] +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -465,17 +457,13 @@ define i32 @test10_select(i32 %mode, i1 %Cond) { ; CHECK-LABEL: @test10_select( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 51, label [[F]] -; CHECK-NEXT: i32 0, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] -; CHECK-NEXT: ret i32 [[MERGE]] -; CHECK: F: -; CHECK-NEXT: br label [[T]] +; CHECK-NEXT: T: +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 +; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 +; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false +; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i1 [[COND:%.*]], i1 false +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -492,17 +480,13 @@ ; TODO: %Cond doesn't need freeze define i32 @test10_select_and(i32 %mode, i1 %Cond) { ; CHECK-LABEL: @test10_select_and( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 51, label [[F]] -; CHECK-NEXT: i32 0, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] -; CHECK-NEXT: ret i32 [[MERGE]] -; CHECK: F: -; CHECK-NEXT: br label [[T]] +; CHECK-NEXT: T: +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 +; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 +; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false +; CHECK-NEXT: [[D:%.*]] = and i1 [[C]], [[COND:%.*]] +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -518,17 +502,13 @@ define i32 @test10_select_nofreeze(i32 %mode, i1 noundef %Cond) { ; CHECK-LABEL: @test10_select_nofreeze( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 51, label [[F]] -; CHECK-NEXT: i32 0, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] -; CHECK-NEXT: ret i32 [[MERGE]] -; CHECK: F: -; CHECK-NEXT: br label [[T]] +; CHECK-NEXT: T: +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 +; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 +; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false +; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i1 [[COND:%.*]], i1 false +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -594,8 +574,8 @@ define void @test12() nounwind { ; CHECK-LABEL: @test12( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DOTOLD:%.*]] = icmp eq i32 undef, undef -; CHECK-NEXT: br i1 [[DOTOLD]], label [[BB55_US_US:%.*]], label [[MALFORMED:%.*]] +; CHECK-NEXT: [[A_OLD:%.*]] = icmp eq i32 undef, undef +; CHECK-NEXT: br i1 [[A_OLD]], label [[BB55_US_US:%.*]], label [[MALFORMED:%.*]] ; CHECK: bb55.us.us: ; CHECK-NEXT: [[B:%.*]] = icmp ugt i32 undef, undef ; CHECK-NEXT: [[A:%.*]] = icmp eq i32 undef, undef Index: llvm/test/Transforms/SimplifyCFG/switch_msan.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/switch_msan.ll +++ llvm/test/Transforms/SimplifyCFG/switch_msan.ll @@ -19,12 +19,7 @@ ; CHECK-NEXT: [[C_NOT_10_OR_13:%.*]] = xor i1 [[C_10_OR_13]], true ; CHECK-NEXT: br i1 [[C_NOT_10_OR_13]], label [[WHILE_BODY_I]], label [[WHILE_BODY_I_BREAK:%.*]] ; CHECK: while.body.i.break: -; CHECK-NEXT: br i1 [[MAYBE_UNDEF]], label [[WHILE_BODY]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C]], label [[RETURN:%.*]] [ -; CHECK-NEXT: i8 13, label [[WHILE_BODY]] -; CHECK-NEXT: i8 10, label [[WHILE_BODY]] -; CHECK-NEXT: ] +; CHECK-NEXT: br i1 [[NEXT_MAYBE_UNDEF]], label [[WHILE_BODY]], label [[RETURN:%.*]] ; CHECK: return: ; CHECK-NEXT: ret void ;