diff --git a/llvm/test/Transforms/LoopVectorize/X86/predicate-switch.ll b/llvm/test/Transforms/LoopVectorize/X86/predicate-switch.ll index b8ce3c40920a3..46c62e1ea7741 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/predicate-switch.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/predicate-switch.ll @@ -1,49 +1,49 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 -; RUN: opt -p loop-vectorize -mtriple=x86_64-apple-macosx -mcpu=skylake-avx512 -force-vector-interleave=1 -S %s | FileCheck --check-prefixes=IC1 %s -; RUN: opt -p loop-vectorize -mtriple=x86_64-apple-macosx -mcpu=skylake-avx512 -force-vector-interleave=2 -S %s | FileCheck --check-prefixes=IC2 %s +; RUN: opt -p loop-vectorize -mtriple=x86_64-apple-macosx -mcpu=skylake-avx512 -force-vector-interleave=1 -S %s | FileCheck --check-prefixes=COST %s +; RUN: opt -p loop-vectorize -mtriple=x86_64-apple-macosx -mcpu=skylake-avx512 -force-vector-width=4 -force-vector-interleave=2 -S %s | FileCheck --check-prefixes=FORCED %s define void @switch_default_to_latch_common_dest(ptr %start, ptr %end) { -; IC1-LABEL: define void @switch_default_to_latch_common_dest( -; IC1-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0:[0-9]+]] { -; IC1-NEXT: [[ENTRY:.*]]: -; IC1-NEXT: br label %[[LOOP_HEADER:.*]] -; IC1: [[LOOP_HEADER]]: -; IC1-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC1-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC1-NEXT: switch i64 [[L]], label %[[LOOP_LATCH]] [ -; IC1-NEXT: i64 -12, label %[[IF_THEN:.*]] -; IC1-NEXT: i64 13, label %[[IF_THEN]] -; IC1-NEXT: ] -; IC1: [[IF_THEN]]: -; IC1-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[LOOP_LATCH]]: -; IC1-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC1-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC1-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC1: [[EXIT]]: -; IC1-NEXT: ret void +; COST-LABEL: define void @switch_default_to_latch_common_dest( +; COST-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0:[0-9]+]] { +; COST-NEXT: [[ENTRY:.*]]: +; COST-NEXT: br label %[[LOOP_HEADER:.*]] +; COST: [[LOOP_HEADER]]: +; COST-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; COST-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; COST-NEXT: switch i64 [[L]], label %[[LOOP_LATCH]] [ +; COST-NEXT: i64 -12, label %[[IF_THEN:.*]] +; COST-NEXT: i64 13, label %[[IF_THEN]] +; COST-NEXT: ] +; COST: [[IF_THEN]]: +; COST-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[LOOP_LATCH]]: +; COST-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; COST-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; COST-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; COST: [[EXIT]]: +; COST-NEXT: ret void ; -; IC2-LABEL: define void @switch_default_to_latch_common_dest( -; IC2-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0:[0-9]+]] { -; IC2-NEXT: [[ENTRY:.*]]: -; IC2-NEXT: br label %[[LOOP_HEADER:.*]] -; IC2: [[LOOP_HEADER]]: -; IC2-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC2-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC2-NEXT: switch i64 [[L]], label %[[LOOP_LATCH]] [ -; IC2-NEXT: i64 -12, label %[[IF_THEN:.*]] -; IC2-NEXT: i64 13, label %[[IF_THEN]] -; IC2-NEXT: ] -; IC2: [[IF_THEN]]: -; IC2-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[LOOP_LATCH]]: -; IC2-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC2-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC2-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC2: [[EXIT]]: -; IC2-NEXT: ret void +; FORCED-LABEL: define void @switch_default_to_latch_common_dest( +; FORCED-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0:[0-9]+]] { +; FORCED-NEXT: [[ENTRY:.*]]: +; FORCED-NEXT: br label %[[LOOP_HEADER:.*]] +; FORCED: [[LOOP_HEADER]]: +; FORCED-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; FORCED-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: switch i64 [[L]], label %[[LOOP_LATCH]] [ +; FORCED-NEXT: i64 -12, label %[[IF_THEN:.*]] +; FORCED-NEXT: i64 13, label %[[IF_THEN]] +; FORCED-NEXT: ] +; FORCED: [[IF_THEN]]: +; FORCED-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[LOOP_LATCH]]: +; FORCED-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; FORCED-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; FORCED-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; FORCED: [[EXIT]]: +; FORCED-NEXT: ret void ; entry: br label %loop.header @@ -70,67 +70,67 @@ exit: } define void @switch_all_dests_distinct(ptr %start, ptr %end) { -; IC1-LABEL: define void @switch_all_dests_distinct( -; IC1-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { -; IC1-NEXT: [[ENTRY:.*]]: -; IC1-NEXT: br label %[[LOOP_HEADER:.*]] -; IC1: [[LOOP_HEADER]]: -; IC1-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC1-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC1-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC1-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC1-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC1-NEXT: i64 0, label %[[IF_THEN_3:.*]] -; IC1-NEXT: ] -; IC1: [[IF_THEN_1]]: -; IC1-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[IF_THEN_2]]: -; IC1-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[IF_THEN_3]]: -; IC1-NEXT: store i64 1, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[DEFAULT]]: -; IC1-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[LOOP_LATCH]]: -; IC1-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC1-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC1-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC1: [[EXIT]]: -; IC1-NEXT: ret void +; COST-LABEL: define void @switch_all_dests_distinct( +; COST-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; COST-NEXT: [[ENTRY:.*]]: +; COST-NEXT: br label %[[LOOP_HEADER:.*]] +; COST: [[LOOP_HEADER]]: +; COST-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; COST-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; COST-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; COST-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; COST-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; COST-NEXT: i64 0, label %[[IF_THEN_3:.*]] +; COST-NEXT: ] +; COST: [[IF_THEN_1]]: +; COST-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[IF_THEN_2]]: +; COST-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[IF_THEN_3]]: +; COST-NEXT: store i64 1, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[DEFAULT]]: +; COST-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[LOOP_LATCH]]: +; COST-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; COST-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; COST-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; COST: [[EXIT]]: +; COST-NEXT: ret void ; -; IC2-LABEL: define void @switch_all_dests_distinct( -; IC2-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { -; IC2-NEXT: [[ENTRY:.*]]: -; IC2-NEXT: br label %[[LOOP_HEADER:.*]] -; IC2: [[LOOP_HEADER]]: -; IC2-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC2-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC2-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC2-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC2-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC2-NEXT: i64 0, label %[[IF_THEN_3:.*]] -; IC2-NEXT: ] -; IC2: [[IF_THEN_1]]: -; IC2-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[IF_THEN_2]]: -; IC2-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[IF_THEN_3]]: -; IC2-NEXT: store i64 1, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[DEFAULT]]: -; IC2-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[LOOP_LATCH]]: -; IC2-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC2-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC2-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC2: [[EXIT]]: -; IC2-NEXT: ret void +; FORCED-LABEL: define void @switch_all_dests_distinct( +; FORCED-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; FORCED-NEXT: [[ENTRY:.*]]: +; FORCED-NEXT: br label %[[LOOP_HEADER:.*]] +; FORCED: [[LOOP_HEADER]]: +; FORCED-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; FORCED-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; FORCED-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; FORCED-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; FORCED-NEXT: i64 0, label %[[IF_THEN_3:.*]] +; FORCED-NEXT: ] +; FORCED: [[IF_THEN_1]]: +; FORCED-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[IF_THEN_2]]: +; FORCED-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[IF_THEN_3]]: +; FORCED-NEXT: store i64 1, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[DEFAULT]]: +; FORCED-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[LOOP_LATCH]]: +; FORCED-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; FORCED-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; FORCED-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; FORCED: [[EXIT]]: +; FORCED-NEXT: ret void ; entry: br label %loop.header @@ -171,65 +171,65 @@ exit: define void @switch_multiple_common_dests(ptr %start, ptr %end) { -; IC1-LABEL: define void @switch_multiple_common_dests( -; IC1-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { -; IC1-NEXT: [[ENTRY:.*]]: -; IC1-NEXT: br label %[[LOOP_HEADER:.*]] -; IC1: [[LOOP_HEADER]]: -; IC1-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC1-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC1-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC1-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC1-NEXT: i64 0, label %[[IF_THEN_1]] -; IC1-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC1-NEXT: i64 14, label %[[IF_THEN_2]] -; IC1-NEXT: i64 15, label %[[IF_THEN_2]] -; IC1-NEXT: ] -; IC1: [[IF_THEN_1]]: -; IC1-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[IF_THEN_2]]: -; IC1-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[DEFAULT]]: -; IC1-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[LOOP_LATCH]]: -; IC1-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC1-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC1-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC1: [[EXIT]]: -; IC1-NEXT: ret void +; COST-LABEL: define void @switch_multiple_common_dests( +; COST-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; COST-NEXT: [[ENTRY:.*]]: +; COST-NEXT: br label %[[LOOP_HEADER:.*]] +; COST: [[LOOP_HEADER]]: +; COST-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; COST-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; COST-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; COST-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; COST-NEXT: i64 0, label %[[IF_THEN_1]] +; COST-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; COST-NEXT: i64 14, label %[[IF_THEN_2]] +; COST-NEXT: i64 15, label %[[IF_THEN_2]] +; COST-NEXT: ] +; COST: [[IF_THEN_1]]: +; COST-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[IF_THEN_2]]: +; COST-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[DEFAULT]]: +; COST-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[LOOP_LATCH]]: +; COST-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; COST-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; COST-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; COST: [[EXIT]]: +; COST-NEXT: ret void ; -; IC2-LABEL: define void @switch_multiple_common_dests( -; IC2-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { -; IC2-NEXT: [[ENTRY:.*]]: -; IC2-NEXT: br label %[[LOOP_HEADER:.*]] -; IC2: [[LOOP_HEADER]]: -; IC2-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC2-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC2-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC2-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC2-NEXT: i64 0, label %[[IF_THEN_1]] -; IC2-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC2-NEXT: i64 14, label %[[IF_THEN_2]] -; IC2-NEXT: i64 15, label %[[IF_THEN_2]] -; IC2-NEXT: ] -; IC2: [[IF_THEN_1]]: -; IC2-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[IF_THEN_2]]: -; IC2-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[DEFAULT]]: -; IC2-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[LOOP_LATCH]]: -; IC2-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC2-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC2-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC2: [[EXIT]]: -; IC2-NEXT: ret void +; FORCED-LABEL: define void @switch_multiple_common_dests( +; FORCED-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; FORCED-NEXT: [[ENTRY:.*]]: +; FORCED-NEXT: br label %[[LOOP_HEADER:.*]] +; FORCED: [[LOOP_HEADER]]: +; FORCED-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; FORCED-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; FORCED-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; FORCED-NEXT: i64 0, label %[[IF_THEN_1]] +; FORCED-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; FORCED-NEXT: i64 14, label %[[IF_THEN_2]] +; FORCED-NEXT: i64 15, label %[[IF_THEN_2]] +; FORCED-NEXT: ] +; FORCED: [[IF_THEN_1]]: +; FORCED-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[IF_THEN_2]]: +; FORCED-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[DEFAULT]]: +; FORCED-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[LOOP_LATCH]]: +; FORCED-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; FORCED-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; FORCED-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; FORCED: [[EXIT]]: +; FORCED-NEXT: ret void ; entry: br label %loop.header @@ -267,61 +267,61 @@ exit: } define void @switch4_default_common_dest_with_case(ptr %start, ptr %end) { -; IC1-LABEL: define void @switch4_default_common_dest_with_case( -; IC1-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { -; IC1-NEXT: [[ENTRY:.*]]: -; IC1-NEXT: br label %[[LOOP_HEADER:.*]] -; IC1: [[LOOP_HEADER]]: -; IC1-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC1-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC1-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC1-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC1-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC1-NEXT: i64 0, label %[[DEFAULT]] -; IC1-NEXT: ] -; IC1: [[IF_THEN_1]]: -; IC1-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[IF_THEN_2]]: -; IC1-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[DEFAULT]]: -; IC1-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[LOOP_LATCH]]: -; IC1-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC1-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC1-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC1: [[EXIT]]: -; IC1-NEXT: ret void +; COST-LABEL: define void @switch4_default_common_dest_with_case( +; COST-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; COST-NEXT: [[ENTRY:.*]]: +; COST-NEXT: br label %[[LOOP_HEADER:.*]] +; COST: [[LOOP_HEADER]]: +; COST-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; COST-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; COST-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; COST-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; COST-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; COST-NEXT: i64 0, label %[[DEFAULT]] +; COST-NEXT: ] +; COST: [[IF_THEN_1]]: +; COST-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[IF_THEN_2]]: +; COST-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[DEFAULT]]: +; COST-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[LOOP_LATCH]]: +; COST-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; COST-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; COST-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; COST: [[EXIT]]: +; COST-NEXT: ret void ; -; IC2-LABEL: define void @switch4_default_common_dest_with_case( -; IC2-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { -; IC2-NEXT: [[ENTRY:.*]]: -; IC2-NEXT: br label %[[LOOP_HEADER:.*]] -; IC2: [[LOOP_HEADER]]: -; IC2-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC2-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC2-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC2-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC2-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC2-NEXT: i64 0, label %[[DEFAULT]] -; IC2-NEXT: ] -; IC2: [[IF_THEN_1]]: -; IC2-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[IF_THEN_2]]: -; IC2-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[DEFAULT]]: -; IC2-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[LOOP_LATCH]]: -; IC2-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC2-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC2-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC2: [[EXIT]]: -; IC2-NEXT: ret void +; FORCED-LABEL: define void @switch4_default_common_dest_with_case( +; FORCED-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; FORCED-NEXT: [[ENTRY:.*]]: +; FORCED-NEXT: br label %[[LOOP_HEADER:.*]] +; FORCED: [[LOOP_HEADER]]: +; FORCED-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; FORCED-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; FORCED-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; FORCED-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; FORCED-NEXT: i64 0, label %[[DEFAULT]] +; FORCED-NEXT: ] +; FORCED: [[IF_THEN_1]]: +; FORCED-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[IF_THEN_2]]: +; FORCED-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[DEFAULT]]: +; FORCED-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[LOOP_LATCH]]: +; FORCED-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; FORCED-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; FORCED-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; FORCED: [[EXIT]]: +; FORCED-NEXT: ret void ; entry: br label %loop.header @@ -357,67 +357,67 @@ exit: } define void @switch_under_br_default_common_dest_with_case(ptr %start, ptr %end, i64 %x) { -; IC1-LABEL: define void @switch_under_br_default_common_dest_with_case( -; IC1-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { -; IC1-NEXT: [[ENTRY:.*]]: -; IC1-NEXT: br label %[[LOOP_HEADER:.*]] -; IC1: [[LOOP_HEADER]]: -; IC1-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC1-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC1-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] -; IC1-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[LOOP_LATCH]] -; IC1: [[THEN]]: -; IC1-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC1-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC1-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC1-NEXT: i64 0, label %[[DEFAULT]] -; IC1-NEXT: ] -; IC1: [[IF_THEN_1]]: -; IC1-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[IF_THEN_2]]: -; IC1-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[DEFAULT]]: -; IC1-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[LOOP_LATCH]]: -; IC1-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC1-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC1-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC1: [[EXIT]]: -; IC1-NEXT: ret void +; COST-LABEL: define void @switch_under_br_default_common_dest_with_case( +; COST-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { +; COST-NEXT: [[ENTRY:.*]]: +; COST-NEXT: br label %[[LOOP_HEADER:.*]] +; COST: [[LOOP_HEADER]]: +; COST-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; COST-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; COST-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] +; COST-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[LOOP_LATCH]] +; COST: [[THEN]]: +; COST-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; COST-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; COST-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; COST-NEXT: i64 0, label %[[DEFAULT]] +; COST-NEXT: ] +; COST: [[IF_THEN_1]]: +; COST-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[IF_THEN_2]]: +; COST-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[DEFAULT]]: +; COST-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[LOOP_LATCH]]: +; COST-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; COST-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; COST-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; COST: [[EXIT]]: +; COST-NEXT: ret void ; -; IC2-LABEL: define void @switch_under_br_default_common_dest_with_case( -; IC2-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { -; IC2-NEXT: [[ENTRY:.*]]: -; IC2-NEXT: br label %[[LOOP_HEADER:.*]] -; IC2: [[LOOP_HEADER]]: -; IC2-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC2-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC2-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] -; IC2-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[LOOP_LATCH]] -; IC2: [[THEN]]: -; IC2-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC2-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC2-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC2-NEXT: i64 0, label %[[DEFAULT]] -; IC2-NEXT: ] -; IC2: [[IF_THEN_1]]: -; IC2-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[IF_THEN_2]]: -; IC2-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[DEFAULT]]: -; IC2-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[LOOP_LATCH]]: -; IC2-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC2-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC2-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC2: [[EXIT]]: -; IC2-NEXT: ret void +; FORCED-LABEL: define void @switch_under_br_default_common_dest_with_case( +; FORCED-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { +; FORCED-NEXT: [[ENTRY:.*]]: +; FORCED-NEXT: br label %[[LOOP_HEADER:.*]] +; FORCED: [[LOOP_HEADER]]: +; FORCED-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; FORCED-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] +; FORCED-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[LOOP_LATCH]] +; FORCED: [[THEN]]: +; FORCED-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; FORCED-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; FORCED-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; FORCED-NEXT: i64 0, label %[[DEFAULT]] +; FORCED-NEXT: ] +; FORCED: [[IF_THEN_1]]: +; FORCED-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[IF_THEN_2]]: +; FORCED-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[DEFAULT]]: +; FORCED-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[LOOP_LATCH]]: +; FORCED-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; FORCED-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; FORCED-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; FORCED: [[EXIT]]: +; FORCED-NEXT: ret void ; entry: br label %loop.header @@ -457,67 +457,67 @@ exit: } define void @br_under_switch_default_common_dest_with_case(ptr %start, ptr %end, i64 %x) { -; IC1-LABEL: define void @br_under_switch_default_common_dest_with_case( -; IC1-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { -; IC1-NEXT: [[ENTRY:.*]]: -; IC1-NEXT: br label %[[LOOP_HEADER:.*]] -; IC1: [[LOOP_HEADER]]: -; IC1-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC1-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC1-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC1-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC1-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC1-NEXT: i64 0, label %[[DEFAULT]] -; IC1-NEXT: ] -; IC1: [[IF_THEN_1]]: -; IC1-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] -; IC1-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[IF_THEN_2]] -; IC1: [[THEN]]: -; IC1-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[DEFAULT]] -; IC1: [[IF_THEN_2]]: -; IC1-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[DEFAULT]]: -; IC1-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC1-NEXT: br label %[[LOOP_LATCH]] -; IC1: [[LOOP_LATCH]]: -; IC1-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC1-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC1-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC1: [[EXIT]]: -; IC1-NEXT: ret void +; COST-LABEL: define void @br_under_switch_default_common_dest_with_case( +; COST-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { +; COST-NEXT: [[ENTRY:.*]]: +; COST-NEXT: br label %[[LOOP_HEADER:.*]] +; COST: [[LOOP_HEADER]]: +; COST-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; COST-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; COST-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; COST-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; COST-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; COST-NEXT: i64 0, label %[[DEFAULT]] +; COST-NEXT: ] +; COST: [[IF_THEN_1]]: +; COST-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] +; COST-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[IF_THEN_2]] +; COST: [[THEN]]: +; COST-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[DEFAULT]] +; COST: [[IF_THEN_2]]: +; COST-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[DEFAULT]]: +; COST-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[LOOP_LATCH]]: +; COST-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; COST-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; COST-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; COST: [[EXIT]]: +; COST-NEXT: ret void ; -; IC2-LABEL: define void @br_under_switch_default_common_dest_with_case( -; IC2-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { -; IC2-NEXT: [[ENTRY:.*]]: -; IC2-NEXT: br label %[[LOOP_HEADER:.*]] -; IC2: [[LOOP_HEADER]]: -; IC2-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] -; IC2-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 -; IC2-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ -; IC2-NEXT: i64 -12, label %[[IF_THEN_1:.*]] -; IC2-NEXT: i64 13, label %[[IF_THEN_2:.*]] -; IC2-NEXT: i64 0, label %[[DEFAULT]] -; IC2-NEXT: ] -; IC2: [[IF_THEN_1]]: -; IC2-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] -; IC2-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[IF_THEN_2]] -; IC2: [[THEN]]: -; IC2-NEXT: store i64 42, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[DEFAULT]] -; IC2: [[IF_THEN_2]]: -; IC2-NEXT: store i64 0, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[DEFAULT]]: -; IC2-NEXT: store i64 2, ptr [[PTR_IV]], align 1 -; IC2-NEXT: br label %[[LOOP_LATCH]] -; IC2: [[LOOP_LATCH]]: -; IC2-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 -; IC2-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] -; IC2-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] -; IC2: [[EXIT]]: -; IC2-NEXT: ret void +; FORCED-LABEL: define void @br_under_switch_default_common_dest_with_case( +; FORCED-SAME: ptr [[START:%.*]], ptr [[END:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { +; FORCED-NEXT: [[ENTRY:.*]]: +; FORCED-NEXT: br label %[[LOOP_HEADER:.*]] +; FORCED: [[LOOP_HEADER]]: +; FORCED-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; FORCED-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: switch i64 [[L]], label %[[DEFAULT:.*]] [ +; FORCED-NEXT: i64 -12, label %[[IF_THEN_1:.*]] +; FORCED-NEXT: i64 13, label %[[IF_THEN_2:.*]] +; FORCED-NEXT: i64 0, label %[[DEFAULT]] +; FORCED-NEXT: ] +; FORCED: [[IF_THEN_1]]: +; FORCED-NEXT: [[C:%.*]] = icmp ule i64 [[L]], [[X]] +; FORCED-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[IF_THEN_2]] +; FORCED: [[THEN]]: +; FORCED-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[DEFAULT]] +; FORCED: [[IF_THEN_2]]: +; FORCED-NEXT: store i64 0, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[DEFAULT]]: +; FORCED-NEXT: store i64 2, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[LOOP_LATCH]]: +; FORCED-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; FORCED-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; FORCED-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; FORCED: [[EXIT]]: +; FORCED-NEXT: ret void ; entry: br label %loop.header @@ -555,3 +555,92 @@ loop.latch: exit: ret void } + +define void @large_number_of_cases(ptr %start, ptr %end) { +; COST-LABEL: define void @large_number_of_cases( +; COST-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; COST-NEXT: [[ENTRY:.*]]: +; COST-NEXT: br label %[[LOOP_HEADER:.*]] +; COST: [[LOOP_HEADER]]: +; COST-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; COST-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; COST-NEXT: switch i64 [[L]], label %[[LOOP_LATCH]] [ +; COST-NEXT: i64 1, label %[[IF_THEN:.*]] +; COST-NEXT: i64 3, label %[[IF_THEN]] +; COST-NEXT: i64 11, label %[[IF_THEN]] +; COST-NEXT: i64 99, label %[[IF_THEN]] +; COST-NEXT: i64 213, label %[[IF_THEN]] +; COST-NEXT: i64 238, label %[[IF_THEN]] +; COST-NEXT: i64 513, label %[[IF_THEN]] +; COST-NEXT: i64 791, label %[[IF_THEN]] +; COST-NEXT: i64 899, label %[[IF_THEN]] +; COST-NEXT: ] +; COST: [[IF_THEN]]: +; COST-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; COST-NEXT: br label %[[LOOP_LATCH]] +; COST: [[LOOP_LATCH]]: +; COST-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; COST-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; COST-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; COST: [[EXIT]]: +; COST-NEXT: ret void +; +; FORCED-LABEL: define void @large_number_of_cases( +; FORCED-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) #[[ATTR0]] { +; FORCED-NEXT: [[ENTRY:.*]]: +; FORCED-NEXT: br label %[[LOOP_HEADER:.*]] +; FORCED: [[LOOP_HEADER]]: +; FORCED-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; FORCED-NEXT: [[L:%.*]] = load i64, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: switch i64 [[L]], label %[[LOOP_LATCH]] [ +; FORCED-NEXT: i64 1, label %[[IF_THEN:.*]] +; FORCED-NEXT: i64 3, label %[[IF_THEN]] +; FORCED-NEXT: i64 11, label %[[IF_THEN]] +; FORCED-NEXT: i64 99, label %[[IF_THEN]] +; FORCED-NEXT: i64 213, label %[[IF_THEN]] +; FORCED-NEXT: i64 238, label %[[IF_THEN]] +; FORCED-NEXT: i64 513, label %[[IF_THEN]] +; FORCED-NEXT: i64 791, label %[[IF_THEN]] +; FORCED-NEXT: i64 899, label %[[IF_THEN]] +; FORCED-NEXT: ] +; FORCED: [[IF_THEN]]: +; FORCED-NEXT: store i64 42, ptr [[PTR_IV]], align 1 +; FORCED-NEXT: br label %[[LOOP_LATCH]] +; FORCED: [[LOOP_LATCH]]: +; FORCED-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i64 1 +; FORCED-NEXT: [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] +; FORCED-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; FORCED: [[EXIT]]: +; FORCED-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ] + %l = load i64, ptr %ptr.iv, align 1 + switch i64 %l, label %loop.latch [ + i64 1, label %if.then + i64 3, label %if.then + i64 11, label %if.then + i64 99, label %if.then + i64 213, label %if.then + i64 238, label %if.then + i64 513, label %if.then + i64 791, label %if.then + i64 899, label %if.then + ] + +if.then: + store i64 42, ptr %ptr.iv, align 1 + br label %loop.latch + +loop.latch: + %ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i64 1 + %ec = icmp eq ptr %ptr.iv.next, %end + br i1 %ec, label %exit, label %loop.header + +exit: + ret void +} + diff --git a/llvm/test/Transforms/LoopVectorize/predicate-switch.ll b/llvm/test/Transforms/LoopVectorize/predicate-switch.ll index dba53c8717f59..4fe971f5afc0c 100644 --- a/llvm/test/Transforms/LoopVectorize/predicate-switch.ll +++ b/llvm/test/Transforms/LoopVectorize/predicate-switch.ll @@ -91,3 +91,198 @@ loop.latch: exit: ret void } + +define void @switch_exiting(ptr %start) { +; IC1-LABEL: define void @switch_exiting( +; IC1-SAME: ptr [[START:%.*]]) { +; IC1-NEXT: [[ENTRY:.*]]: +; IC1-NEXT: br label %[[LOOP_HEADER:.*]] +; IC1: [[LOOP_HEADER]]: +; IC1-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; IC1-NEXT: switch i64 [[IV]], label %[[LOOP_LATCH]] [ +; IC1-NEXT: i64 -12, label %[[IF_THEN:.*]] +; IC1-NEXT: i64 100, label %[[EXIT:.*]] +; IC1-NEXT: ] +; IC1: [[IF_THEN]]: +; IC1-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[START]], i64 [[IV]] +; IC1-NEXT: store i64 42, ptr [[GEP]], align 1 +; IC1-NEXT: br label %[[LOOP_LATCH]] +; IC1: [[LOOP_LATCH]]: +; IC1-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; IC1-NEXT: br label %[[LOOP_HEADER]] +; IC1: [[EXIT]]: +; IC1-NEXT: ret void +; +; IC2-LABEL: define void @switch_exiting( +; IC2-SAME: ptr [[START:%.*]]) { +; IC2-NEXT: [[ENTRY:.*]]: +; IC2-NEXT: br label %[[LOOP_HEADER:.*]] +; IC2: [[LOOP_HEADER]]: +; IC2-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; IC2-NEXT: switch i64 [[IV]], label %[[LOOP_LATCH]] [ +; IC2-NEXT: i64 -12, label %[[IF_THEN:.*]] +; IC2-NEXT: i64 100, label %[[EXIT:.*]] +; IC2-NEXT: ] +; IC2: [[IF_THEN]]: +; IC2-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[START]], i64 [[IV]] +; IC2-NEXT: store i64 42, ptr [[GEP]], align 1 +; IC2-NEXT: br label %[[LOOP_LATCH]] +; IC2: [[LOOP_LATCH]]: +; IC2-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; IC2-NEXT: br label %[[LOOP_HEADER]] +; IC2: [[EXIT]]: +; IC2-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + switch i64 %iv, label %loop.latch [ + i64 -12, label %if.then + i64 100, label %exit + ] + +if.then: + %gep = getelementptr inbounds i64, ptr %start, i64 %iv + store i64 42, ptr %gep, align 1 + br label %loop.latch + +loop.latch: + %iv.next = add i64 %iv, 1 + br label %loop.header + +exit: + ret void +} + +define void @switch_to_header(ptr %start) { +; IC1-LABEL: define void @switch_to_header( +; IC1-SAME: ptr [[START:%.*]]) { +; IC1-NEXT: [[ENTRY:.*]]: +; IC1-NEXT: br label %[[LOOP_HEADER:.*]] +; IC1: [[LOOP_HEADER]]: +; IC1-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_HEADER_BACKEDGE:.*]] ] +; IC1-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; IC1-NEXT: switch i64 [[IV]], label %[[LOOP_LATCH:.*]] [ +; IC1-NEXT: i64 120, label %[[LOOP_HEADER_BACKEDGE]] +; IC1-NEXT: i64 100, label %[[LOOP_LATCH]] +; IC1-NEXT: ] +; IC1: [[LOOP_HEADER_BACKEDGE]]: +; IC1-NEXT: br label %[[LOOP_HEADER]] +; IC1: [[IF_THEN:.*:]] +; IC1-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[START]], i64 poison +; IC1-NEXT: store i64 42, ptr [[GEP]], align 1 +; IC1-NEXT: unreachable +; IC1: [[LOOP_LATCH]]: +; IC1-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], 100 +; IC1-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[LOOP_HEADER_BACKEDGE]] +; IC1: [[EXIT]]: +; IC1-NEXT: ret void +; +; IC2-LABEL: define void @switch_to_header( +; IC2-SAME: ptr [[START:%.*]]) { +; IC2-NEXT: [[ENTRY:.*]]: +; IC2-NEXT: br label %[[LOOP_HEADER:.*]] +; IC2: [[LOOP_HEADER]]: +; IC2-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_HEADER_BACKEDGE:.*]] ] +; IC2-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; IC2-NEXT: switch i64 [[IV]], label %[[LOOP_LATCH:.*]] [ +; IC2-NEXT: i64 120, label %[[LOOP_HEADER_BACKEDGE]] +; IC2-NEXT: i64 100, label %[[LOOP_LATCH]] +; IC2-NEXT: ] +; IC2: [[LOOP_HEADER_BACKEDGE]]: +; IC2-NEXT: br label %[[LOOP_HEADER]] +; IC2: [[IF_THEN:.*:]] +; IC2-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[START]], i64 poison +; IC2-NEXT: store i64 42, ptr [[GEP]], align 1 +; IC2-NEXT: unreachable +; IC2: [[LOOP_LATCH]]: +; IC2-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], 100 +; IC2-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[LOOP_HEADER_BACKEDGE]] +; IC2: [[EXIT]]: +; IC2-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ], [ %iv.next, %loop.header ] + %iv.next = add i64 %iv, 1 + switch i64 %iv, label %loop.latch [ + i64 120, label %loop.header + i64 100, label %loop.latch + ] + +if.then: + %gep = getelementptr inbounds i64, ptr %start, i64 %iv + store i64 42, ptr %gep, align 1 + br label %loop.latch + +loop.latch: + %cmp = icmp eq i64 %iv.next, 100 + br i1 %cmp, label %exit, label %loop.header + +exit: + ret void +} + +define void @switch_all_to_default(ptr %start) { +; IC1-LABEL: define void @switch_all_to_default( +; IC1-SAME: ptr [[START:%.*]]) { +; IC1-NEXT: [[ENTRY:.*]]: +; IC1-NEXT: br label %[[LOOP_HEADER:.*]] +; IC1: [[LOOP_HEADER]]: +; IC1-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; IC1-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; IC1-NEXT: switch i64 [[IV]], label %[[LOOP_LATCH]] [ +; IC1-NEXT: i64 120, label %[[LOOP_LATCH]] +; IC1-NEXT: i64 100, label %[[LOOP_LATCH]] +; IC1-NEXT: ] +; IC1: [[LOOP_LATCH]]: +; IC1-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[START]], i64 [[IV]] +; IC1-NEXT: store i64 42, ptr [[GEP]], align 1 +; IC1-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], 100 +; IC1-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; IC1: [[EXIT]]: +; IC1-NEXT: ret void +; +; IC2-LABEL: define void @switch_all_to_default( +; IC2-SAME: ptr [[START:%.*]]) { +; IC2-NEXT: [[ENTRY:.*]]: +; IC2-NEXT: br label %[[LOOP_HEADER:.*]] +; IC2: [[LOOP_HEADER]]: +; IC2-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; IC2-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; IC2-NEXT: switch i64 [[IV]], label %[[LOOP_LATCH]] [ +; IC2-NEXT: i64 120, label %[[LOOP_LATCH]] +; IC2-NEXT: i64 100, label %[[LOOP_LATCH]] +; IC2-NEXT: ] +; IC2: [[LOOP_LATCH]]: +; IC2-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[START]], i64 [[IV]] +; IC2-NEXT: store i64 42, ptr [[GEP]], align 1 +; IC2-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], 100 +; IC2-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[LOOP_HEADER]] +; IC2: [[EXIT]]: +; IC2-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %iv.next = add i64 %iv, 1 + switch i64 %iv, label %loop.latch [ + i64 120, label %loop.latch + i64 100, label %loop.latch + ] + +loop.latch: + %gep = getelementptr inbounds i64, ptr %start, i64 %iv + store i64 42, ptr %gep, align 1 + %cmp = icmp eq i64 %iv.next, 100 + br i1 %cmp, label %exit, label %loop.header + +exit: + ret void +} diff --git a/llvm/test/Transforms/LoopVectorize/vplan-predicate-switch.ll b/llvm/test/Transforms/LoopVectorize/vplan-predicate-switch.ll new file mode 100644 index 0000000000000..6e3e55a319ec2 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/vplan-predicate-switch.ll @@ -0,0 +1,38 @@ +; REQUIRES: asserts +; RUN: opt -p loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -debug -disable-output %s 2>&1 | FileCheck %s + +define void @switch4_default_common_dest_with_case(ptr %start, ptr %end) { +; CHECK-NOT: VPlan +; +entry: + br label %loop.header + +loop.header: + %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ] + %l = load i8, ptr %ptr.iv, align 1 + switch i8 %l, label %default [ + i8 -12, label %if.then.1 + i8 13, label %if.then.2 + i8 0, label %default + ] + +if.then.1: + store i8 42, ptr %ptr.iv, align 1 + br label %loop.latch + +if.then.2: + store i8 0, ptr %ptr.iv, align 1 + br label %loop.latch + +default: + store i8 2, ptr %ptr.iv, align 1 + br label %loop.latch + +loop.latch: + %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i64 1 + %ec = icmp eq ptr %ptr.iv.next, %end + br i1 %ec, label %exit, label %loop.header + +exit: + ret void +}