470 changes: 235 additions & 235 deletions llvm/test/CodeGen/RISCV/vararg.ll

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions llvm/test/Other/new-pm-defaults.ll
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-OPTIMIZER-LAST,CHECK-O23SZ

; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
; RUN: -passes='default<O3>' -enable-jump-table-to-switch -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-JUMP-TABLE-TO-SWITCH,CHECK-O23SZ,%llvmcheckext

; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
; RUN: -passes='default<O3>' -enable-matrix -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23SZ,%llvmcheckext,CHECK-MATRIX
Expand Down Expand Up @@ -151,6 +155,7 @@
; CHECK-O23SZ-NEXT: Running analysis: LazyValueAnalysis
; CHECK-O23SZ-NEXT: Running pass: CorrelatedValuePropagationPass
; CHECK-O23SZ-NEXT: Invalidating analysis: LazyValueAnalysis
; CHECK-JUMP-TABLE-TO-SWITCH-NEXT: Running pass: JumpTableToSwitchPass
; CHECK-O-NEXT: Running pass: SimplifyCFGPass
; CHECK-O-NEXT: Running pass: InstCombinePass
; CHECK-O23SZ-NEXT: Running pass: AggressiveInstCombinePass
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/IndVarSimplify/X86/pr27133.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ define i32 @fn2() personality ptr @__CxxFrameHandler3 {
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[INDVARS1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
; CHECK-NEXT: invoke void @fn1(i64 [[INDVARS_IV]])
; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
; CHECK: catch.dispatch:
; CHECK-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ [[INDVARS1]], [[FOR_COND]] ]
; CHECK-NEXT: [[TMP0:%.*]] = catchswitch within none [label %catch] unwind to caller
Expand All @@ -21,7 +21,7 @@ define i32 @fn2() personality ptr @__CxxFrameHandler3 {
; CHECK: exit:
; CHECK-NEXT: ret i32 [[C_0_LCSSA]]
; CHECK: for.inc:
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: br label [[FOR_COND]]
;
entry:
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ define void @guardedloop(ptr %matrix, ptr %vector,
; CHECK-NEXT: [[VECTORP:%.*]] = getelementptr inbounds [0 x double], ptr [[VECTOR:%.*]], i32 0, i64 [[INDVARS_IV2]]
; CHECK-NEXT: [[V2:%.*]] = load double, ptr [[VECTORP]], align 8
; CHECK-NEXT: call void @use(double [[V2]])
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], [[TMP0]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
; CHECK-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT3]], [[WIDE_TRIP_COUNT]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[RETURN_LOOPEXIT:%.*]]
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/IndVarSimplify/pr30806-phi-scev.ll
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ define void @foo(ptr %buf, i32 %denominator, ptr %flag) local_unnamed_addr {
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_LR_PH]] ]
; CHECK-NEXT: [[BUF_ADDR_07:%.*]] = phi ptr [ [[BUF]], [[WHILE_BODY_LR_PH]] ], [ [[CALL:%.*]], [[WHILE_BODY]] ]
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[DIV]] to i64
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], [[TMP2]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP2]]
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr @theSize, align 4
; CHECK-NEXT: store i32 [[TMP3]], ptr [[I]], align 4
; CHECK-NEXT: call void @bar(ptr nonnull [[I]], i64 [[INDVARS_IV_NEXT]])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ define void @test_s172(i32 noundef %xa, i32 noundef %xb, ptr nocapture noundef %
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX2]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], [[TMP2]]
; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX2]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], [[TMP1]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP1]]
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], 32000
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK: for.end.loopexit:
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ define dso_local void @Widen_i32_i8ptr() local_unnamed_addr {
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, ptr [[GID_0]], i64 1
; CHECK-NEXT: [[ARRAYIDX2115:%.*]] = getelementptr inbounds [15 x ptr], ptr [[PTRIDS]], i64 0, i64 [[INDVARS_IV]]
; CHECK-NEXT: store ptr [[GID_0]], ptr [[ARRAYIDX2115]], align 8
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: br label [[FOR_COND2106]]
;
entry:
Expand Down
18 changes: 9 additions & 9 deletions llvm/test/Transforms/InstCombine/fdiv-sqrt.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ declare double @llvm.sqrt.f64(double)
define double @sqrt_div_fast(double %x, double %y, double %z) {
; CHECK-LABEL: @sqrt_div_fast(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = fdiv fast double [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = call fast double @llvm.sqrt.f64(double [[TMP0]])
; CHECK-NEXT: [[DIV1:%.*]] = fmul fast double [[TMP1]], [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv fast double [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT: [[SQRT:%.*]] = call fast double @llvm.sqrt.f64(double [[DIV]])
; CHECK-NEXT: [[DIV1:%.*]] = fdiv fast double [[X:%.*]], [[SQRT]]
; CHECK-NEXT: ret double [[DIV1]]
;
entry:
Expand Down Expand Up @@ -36,9 +36,9 @@ entry:
define double @sqrt_div_reassoc_arcp(double %x, double %y, double %z) {
; CHECK-LABEL: @sqrt_div_reassoc_arcp(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc arcp double [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]])
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]])
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
; CHECK-NEXT: ret double [[DIV1]]
;
entry:
Expand Down Expand Up @@ -96,9 +96,9 @@ entry:
define double @sqrt_div_arcp_missing(double %x, double %y, double %z) {
; CHECK-LABEL: @sqrt_div_arcp_missing(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc double [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]])
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]])
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
; CHECK-NEXT: ret double [[DIV1]]
;
entry:
Expand Down
228 changes: 228 additions & 0 deletions llvm/test/Transforms/JumpTableToSwitch/basic.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt < %s -passes=jump-table-to-switch -verify-dom-info -S | FileCheck %s
; RUN: opt < %s -passes=jump-table-to-switch -jump-table-to-switch-size-threshold=0 -verify-dom-info -S | FileCheck %s --check-prefix=THRESHOLD-0

@func_array = constant [2 x ptr] [ptr @func0, ptr @func1]

define i32 @func0() {
ret i32 1
}

define i32 @func1() {
ret i32 2
}

define i32 @function_with_jump_table(i32 %index) {
; CHECK-LABEL: define i32 @function_with_jump_table(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_0:%.*]]
; CHECK-NEXT: i32 1, label [[CALL_1:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable:
; CHECK-NEXT: unreachable
; CHECK: call.0:
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @func0()
; CHECK-NEXT: br label [[DOTTAIL:%.*]]
; CHECK: call.1:
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @func1()
; CHECK-NEXT: br label [[DOTTAIL]]
; CHECK: .tail:
; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP1]], [[CALL_0]] ], [ [[TMP2]], [[CALL_1]] ]
; CHECK-NEXT: ret i32 [[TMP3]]
;
; THRESHOLD-0-LABEL: define i32 @function_with_jump_table(
; THRESHOLD-0-SAME: i32 [[INDEX:%.*]]) {
; THRESHOLD-0-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 [[INDEX]]
; THRESHOLD-0-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; THRESHOLD-0-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]]()
; THRESHOLD-0-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep
%result = call i32 %func_ptr()
ret i32 %result
}

define i32 @basic_block_splitted_twice(i32 %index) {
; CHECK-LABEL: define i32 @basic_block_splitted_twice(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR1:%.*]] = load ptr, ptr [[GEP1]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_0:%.*]]
; CHECK-NEXT: i32 1, label [[CALL_1:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable:
; CHECK-NEXT: unreachable
; CHECK: call.0:
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @func0()
; CHECK-NEXT: br label [[DOTTAIL:%.*]]
; CHECK: call.1:
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @func1()
; CHECK-NEXT: br label [[DOTTAIL]]
; CHECK: .tail:
; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP1]], [[CALL_0]] ], [ [[TMP2]], [[CALL_1]] ]
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR2:%.*]] = load ptr, ptr [[GEP2]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE1:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_02:%.*]]
; CHECK-NEXT: i32 1, label [[CALL_13:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable1:
; CHECK-NEXT: unreachable
; CHECK: call.02:
; CHECK-NEXT: [[TMP4:%.*]] = call i32 @func0()
; CHECK-NEXT: br label [[DOTTAIL_TAIL:%.*]]
; CHECK: call.13:
; CHECK-NEXT: [[TMP5:%.*]] = call i32 @func1()
; CHECK-NEXT: br label [[DOTTAIL_TAIL]]
; CHECK: .tail.tail:
; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP4]], [[CALL_02]] ], [ [[TMP5]], [[CALL_13]] ]
; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[TMP3]], [[TMP6]]
; CHECK-NEXT: ret i32 [[RESULT]]
;
; THRESHOLD-0-LABEL: define i32 @basic_block_splitted_twice(
; THRESHOLD-0-SAME: i32 [[INDEX:%.*]]) {
; THRESHOLD-0-NEXT: [[GEP1:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 [[INDEX]]
; THRESHOLD-0-NEXT: [[FUNC_PTR1:%.*]] = load ptr, ptr [[GEP1]], align 8
; THRESHOLD-0-NEXT: [[RESULT1:%.*]] = call i32 [[FUNC_PTR1]]()
; THRESHOLD-0-NEXT: [[GEP2:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 [[INDEX]]
; THRESHOLD-0-NEXT: [[FUNC_PTR2:%.*]] = load ptr, ptr [[GEP2]], align 8
; THRESHOLD-0-NEXT: [[RESULT2:%.*]] = call i32 [[FUNC_PTR2]]()
; THRESHOLD-0-NEXT: [[RESULT:%.*]] = add i32 [[RESULT1]], [[RESULT2]]
; THRESHOLD-0-NEXT: ret i32 [[RESULT]]
;
%gep1 = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 %index
%func_ptr1 = load ptr, ptr %gep1
%result1 = call i32 %func_ptr1()
%gep2 = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 %index
%func_ptr2 = load ptr, ptr %gep2
%result2 = call i32 %func_ptr2()
%result = add i32 %result1, %result2
ret i32 %result
}

define void @void_func0() {
ret void
}

define void @void_func1() {
ret void
}

@void_func_array = constant [2 x ptr] [ptr @void_func0, ptr @void_func1]

define void @void_function_with_jump_table(i32 %index) {
; CHECK-LABEL: define void @void_function_with_jump_table(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @void_func_array, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_0:%.*]]
; CHECK-NEXT: i32 1, label [[CALL_1:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable:
; CHECK-NEXT: unreachable
; CHECK: call.0:
; CHECK-NEXT: call void @void_func0()
; CHECK-NEXT: br label [[DOTTAIL:%.*]]
; CHECK: call.1:
; CHECK-NEXT: call void @void_func1()
; CHECK-NEXT: br label [[DOTTAIL]]
; CHECK: .tail:
; CHECK-NEXT: ret void
;
; THRESHOLD-0-LABEL: define void @void_function_with_jump_table(
; THRESHOLD-0-SAME: i32 [[INDEX:%.*]]) {
; THRESHOLD-0-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @void_func_array, i32 0, i32 [[INDEX]]
; THRESHOLD-0-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; THRESHOLD-0-NEXT: call void [[FUNC_PTR]]()
; THRESHOLD-0-NEXT: ret void
;
%gep = getelementptr inbounds [2 x ptr], ptr @void_func_array, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep
call void %func_ptr()
ret void
}

define void @void_function_with_jump_table_and_call_site_attr(i32 %index) {
; CHECK-LABEL: define void @void_function_with_jump_table_and_call_site_attr(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @void_func_array, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_0:%.*]]
; CHECK-NEXT: i32 1, label [[CALL_1:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable:
; CHECK-NEXT: unreachable
; CHECK: call.0:
; CHECK-NEXT: call void @void_func0() #[[ATTR0:[0-9]+]]
; CHECK-NEXT: br label [[DOTTAIL:%.*]]
; CHECK: call.1:
; CHECK-NEXT: call void @void_func1() #[[ATTR0]]
; CHECK-NEXT: br label [[DOTTAIL]]
; CHECK: .tail:
; CHECK-NEXT: ret void
;
; THRESHOLD-0-LABEL: define void @void_function_with_jump_table_and_call_site_attr(
; THRESHOLD-0-SAME: i32 [[INDEX:%.*]]) {
; THRESHOLD-0-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @void_func_array, i32 0, i32 [[INDEX]]
; THRESHOLD-0-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; THRESHOLD-0-NEXT: call void [[FUNC_PTR]]() #[[ATTR0:[0-9]+]]
; THRESHOLD-0-NEXT: ret void
;
%gep = getelementptr inbounds [2 x ptr], ptr @void_func_array, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep
call void %func_ptr() nounwind
ret void
}


define i32 @func0_addrspace_42() addrspace(42) {
ret i32 1
}

define i32 @func1_addrspace_42() addrspace(42) {
ret i32 2
}

@func_array_addrspace_42 = addrspace(42) constant [2 x ptr addrspace(42)] [ptr addrspace(42) @func0_addrspace_42, ptr addrspace(42) @func1_addrspace_42]

define i32 @function_with_jump_table_addrspace_42(i32 %index) addrspace(42) {
; CHECK-LABEL: define i32 @function_with_jump_table_addrspace_42(
; CHECK-SAME: i32 [[INDEX:%.*]]) addrspace(42) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr addrspace(42)], ptr addrspace(42) @func_array_addrspace_42, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr addrspace(42), ptr addrspace(42) [[GEP]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_0:%.*]]
; CHECK-NEXT: i32 1, label [[CALL_1:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable:
; CHECK-NEXT: unreachable
; CHECK: call.0:
; CHECK-NEXT: [[TMP1:%.*]] = call addrspace(42) i32 @func0_addrspace_42()
; CHECK-NEXT: br label [[DOTTAIL:%.*]]
; CHECK: call.1:
; CHECK-NEXT: [[TMP2:%.*]] = call addrspace(42) i32 @func1_addrspace_42()
; CHECK-NEXT: br label [[DOTTAIL]]
; CHECK: .tail:
; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP1]], [[CALL_0]] ], [ [[TMP2]], [[CALL_1]] ]
; CHECK-NEXT: ret i32 [[TMP3]]
;
; THRESHOLD-0-LABEL: define i32 @function_with_jump_table_addrspace_42(
; THRESHOLD-0-SAME: i32 [[INDEX:%.*]]) addrspace(42) {
; THRESHOLD-0-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr addrspace(42)], ptr addrspace(42) @func_array_addrspace_42, i32 0, i32 [[INDEX]]
; THRESHOLD-0-NEXT: [[FUNC_PTR:%.*]] = load ptr addrspace(42), ptr addrspace(42) [[GEP]], align 8
; THRESHOLD-0-NEXT: [[RESULT:%.*]] = call addrspace(42) i32 [[FUNC_PTR]]()
; THRESHOLD-0-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [2 x ptr addrspace(42)], ptr addrspace(42) @func_array_addrspace_42, i32 0, i32 %index
%func_ptr = load ptr addrspace(42), ptr addrspace(42) %gep, align 8
%result = call addrspace(42) i32 %func_ptr()
ret i32 %result
}

28 changes: 28 additions & 0 deletions llvm/test/Transforms/JumpTableToSwitch/max_function_size.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt < %s -passes=jump-table-to-switch -jump-table-to-switch-function-size-threshold=1 -verify-dom-info -S | FileCheck %s

@func_array0 = constant [2 x ptr] [ptr @func0, ptr @large_func]

define i32 @func0() {
ret i32 1
}

define i32 @large_func() {
%x = add i32 1, 2
ret i32 %x
}

define i32 @function_with_jump_table_with_large_func(i32 %index) {
; CHECK-LABEL: define i32 @function_with_jump_table_with_large_func(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]]()
; CHECK-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep, align 8
%result = call i32 %func_ptr()
ret i32 %result
}

36 changes: 36 additions & 0 deletions llvm/test/Transforms/JumpTableToSwitch/remarks.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
; RUN: opt < %s -passes=jump-table-to-switch -pass-remarks=jump-table-to-switch -S -o /dev/null 2>&1 | FileCheck %s

; CHECK: remark: /tmp/tmp.cc:2:20: expanded indirect call into switch

@func_array = constant [2 x ptr] [ptr @func0, ptr @func1]

define i32 @func0() {
ret i32 1
}

define i32 @func1() {
ret i32 2
}

define i32 @function_with_jump_table(i32 %index) {
%gep = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep
%result = call i32 %func_ptr(), !dbg !8
ret i32 %result
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
!llvm.ident = !{!5}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 18.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
!1 = !DIFile(filename: "/tmp/tmp.cc", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"PIC Level", i32 2}
!5 = !{!"clang version 18.0.0 "}
!6 = distinct !DISubprogram(name: "success", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!7 = !DISubroutineType(types: !2)
!8 = !DILocation(line: 2, column: 20, scope: !6)
!9 = !DILocation(line: 2, column: 21, scope: !6)
!10 = !DILocation(line: 2, column: 22, scope: !6)
131 changes: 131 additions & 0 deletions llvm/test/Transforms/JumpTableToSwitch/skip.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt < %s -passes=jump-table-to-switch -verify-dom-info -S | FileCheck %s

@func_array0 = constant [2 x ptr] [ptr @func0, ptr @declared_only_func1]

define i32 @func0() {
ret i32 1
}

declare i32 @declared_only_func1()

define i32 @function_with_jump_table_with_a_declared_only_func(i32 %index) {
; CHECK-LABEL: define i32 @function_with_jump_table_with_a_declared_only_func(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]]()
; CHECK-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep, align 8
%result = call i32 %func_ptr()
ret i32 %result
}

declare i32 @__gxx_personality_v0(...)

define i32 @function_with_jump_table_invoke(i32 %index) personality ptr @__gxx_personality_v0 {
; CHECK-LABEL: define i32 @function_with_jump_table_invoke(
; CHECK-SAME: i32 [[INDEX:%.*]]) personality ptr @__gxx_personality_v0 {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: [[RESULT:%.*]] = invoke i32 [[FUNC_PTR]]()
; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTIONAL:%.*]]
; CHECK: normal:
; CHECK-NEXT: ret i32 [[RESULT]]
; CHECK: exceptional:
; CHECK-NEXT: [[LANDING_PAD:%.*]] = landingpad { ptr, i32 }
; CHECK-NEXT: catch ptr null
; CHECK-NEXT: resume { ptr, i32 } [[LANDING_PAD]]
;
%gep = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep, align 8
%result = invoke i32 %func_ptr() to label %normal unwind label %exceptional
normal:
ret i32 %result
exceptional:
%landing_pad = landingpad { ptr, i32 } catch ptr null
resume { ptr, i32 } %landing_pad
}

@func_array1 = constant [1 x ptr] [ptr @func2]

define i32 @func2(i32 %arg) {
ret i32 %arg
}

define i32 @function_with_jump_table_musttail_call(i32 %index) {
; CHECK-LABEL: define i32 @function_with_jump_table_musttail_call(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: [[RESULT:%.*]] = musttail call i32 [[FUNC_PTR]](i32 [[INDEX]])
; CHECK-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep, align 8
%result = musttail call i32 %func_ptr(i32 %index)
ret i32 %result
}

define i32 @function_with_jump_table_and_volatile_load(i32 %index) {
; CHECK-LABEL: define i32 @function_with_jump_table_and_volatile_load(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load volatile ptr, ptr [[GEP]], align 8
; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]])
; CHECK-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 %index
%func_ptr = load volatile ptr, ptr %gep, align 8
%result = call i32 %func_ptr(i32 %index)
ret i32 %result
}

define i32 @function_with_jump_table_and_atomic_load(i32 %index) {
; CHECK-LABEL: define i32 @function_with_jump_table_and_atomic_load(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load atomic ptr, ptr [[GEP]] monotonic, align 8
; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]])
; CHECK-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 %index
%func_ptr = load atomic ptr, ptr %gep monotonic, align 8
%result = call i32 %func_ptr(i32 %index)
ret i32 %result
}

@func_array2 = global [1 x ptr] [ptr @func2]

define i32 @function_with_nonconstant_jump_table(i32 %index) {
; CHECK-LABEL: define i32 @function_with_nonconstant_jump_table(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array2, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]])
; CHECK-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [1 x ptr], ptr @func_array2, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep, align 8
%result = call i32 %func_ptr(i32 %index)
ret i32 %result
}

@func_array3 = weak constant [1 x ptr] [ptr @func2]

define i32 @function_with_constant_weak_jump_table(i32 %index) {
; CHECK-LABEL: define i32 @function_with_constant_weak_jump_table(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array3, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]])
; CHECK-NEXT: ret i32 [[RESULT]]
;
%gep = getelementptr inbounds [1 x ptr], ptr @func_array3, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep, align 8
%result = call i32 %func_ptr(i32 %index)
ret i32 %result
}

36 changes: 36 additions & 0 deletions llvm/test/Transforms/JumpTableToSwitch/stride.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt < %s -passes=jump-table-to-switch -verify-dom-info -S | FileCheck %s

@func_array = constant [2 x ptr] [ptr @func0, ptr @func1]

define i32 @func0() {
ret i32 1
}

define i32 @func1() {
ret i32 2
}

define i32 @check_stride(i32 %index) {
; CHECK-LABEL: define i32 @check_stride(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x { ptr, ptr }], ptr @func_array, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_0:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable:
; CHECK-NEXT: unreachable
; CHECK: call.0:
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @func0()
; CHECK-NEXT: br label [[DOTTAIL:%.*]]
; CHECK: .tail:
; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[CALL_0]] ]
; CHECK-NEXT: ret i32 [[TMP2]]
;
%gep = getelementptr inbounds [2 x { ptr, ptr }], ptr @func_array, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep
%result = call i32 %func_ptr()
ret i32 %result
}

42 changes: 42 additions & 0 deletions llvm/test/Transforms/JumpTableToSwitch/struct.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt < %s -passes=jump-table-to-switch -verify-dom-info -S | FileCheck %s

%"struct_ty" = type { [2 x ptr] }

@func_array = constant %"struct_ty" { [2 x ptr] [ptr @func0, ptr @func1] }

define i32 @func0() {
ret i32 1
}

define i32 @func1() {
ret i32 2
}

define i32 @function_with_jump_table(i32 %index) {
; CHECK-LABEL: define i32 @function_with_jump_table(
; CHECK-SAME: i32 [[INDEX:%.*]]) {
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 [[INDEX]]
; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8
; CHECK-NEXT: switch i32 [[INDEX]], label [[DEFAULT_SWITCH_CASE_UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 0, label [[CALL_0:%.*]]
; CHECK-NEXT: i32 1, label [[CALL_1:%.*]]
; CHECK-NEXT: ]
; CHECK: default.switch.case.unreachable:
; CHECK-NEXT: unreachable
; CHECK: call.0:
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @func0()
; CHECK-NEXT: br label [[DOTTAIL:%.*]]
; CHECK: call.1:
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @func1()
; CHECK-NEXT: br label [[DOTTAIL]]
; CHECK: .tail:
; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP1]], [[CALL_0]] ], [ [[TMP2]], [[CALL_1]] ]
; CHECK-NEXT: ret i32 [[TMP3]]
;
%gep = getelementptr inbounds [2 x ptr], ptr @func_array, i32 0, i32 %index
%func_ptr = load ptr, ptr %gep
%result = call i32 %func_ptr()
ret i32 %result
}

6 changes: 3 additions & 3 deletions llvm/test/Transforms/LoopFlatten/widen-iv.ll
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ define void @foo(ptr %A, i32 %N, i32 %M) {
; CHECK-NEXT: tail call void @f(ptr [[ARRAYIDX_US]])
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us:
; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1
; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i64 [[INDVAR2]], 1
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]]
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
; CHECK: for.cond.cleanup.loopexit:
Expand Down Expand Up @@ -143,7 +143,7 @@ define void @foo2_sext(ptr nocapture readonly %A, i32 %N, i32 %M) {
; CHECK-NEXT: tail call void @g(i32 [[TMP2]])
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us:
; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1
; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i64 [[INDVAR2]], 1
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]]
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
; CHECK: for.cond1.preheader:
Expand Down Expand Up @@ -1005,7 +1005,7 @@ define void @foo_M_sext(ptr %A, i32 %N, i16 %M) {
; CHECK-NEXT: tail call void @f(ptr [[ARRAYIDX_US]])
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us:
; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1
; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i64 [[INDVAR2]], 1
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]]
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
; CHECK: for.cond.cleanup.loopexit:
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/LoopFlatten/widen-iv2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ define dso_local i32 @fn1() local_unnamed_addr #0 {
; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64
; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 [[TMP7]]
; CHECK-NEXT: store i32 32, ptr [[ARRAYIDX_US]], align 4
; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1
; CHECK-NEXT: [[INDVAR_NEXT]] = add nuw nsw i64 [[INDVAR]], 1
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[J_014_US]], 1
; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP1]]
; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY3_US]], label [[FOR_COND1_FOR_INC4_CRIT_EDGE_US]]
; CHECK: for.cond1.for.inc4_crit_edge.us:
; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1
; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i64 [[INDVAR2]], 1
; CHECK-NEXT: [[INC5_US]] = add nuw nsw i32 [[I_016_US]], 1
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[TMP3]]
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_END6_LOOPEXIT:%.*]]
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/LoopFlatten/widen-iv3.ll
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ define i16 @foo() {
; CHECK-NEXT: ret i16 [[ADD5_LCSSA_LCSSA]]
; CHECK: for.cond.cleanup3:
; CHECK-NEXT: [[ADD5_LCSSA]] = phi i16 [ [[ADD5:%.*]], [[FOR_BODY4]] ]
; CHECK-NEXT: [[INDVAR_NEXT3]] = add i32 [[INDVAR2]], 1
; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i32 [[INDVAR2]], 1
; CHECK-NEXT: [[INC7]] = add nuw nsw i16 [[I_013]], 1
; CHECK-NEXT: [[EXITCOND14_NOT:%.*]] = icmp eq i32 [[INDVAR_NEXT3]], 4
; CHECK-NEXT: br i1 [[EXITCOND14_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND1_PREHEADER]]
Expand All @@ -39,7 +39,7 @@ define i16 @foo() {
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [64 x i16], ptr @v, i16 0, i16 [[TMP3]]
; CHECK-NEXT: [[TMP4:%.*]] = load i16, ptr [[ARRAYIDX]], align 1
; CHECK-NEXT: [[ADD5]] = add nsw i16 [[TMP4]], [[SUM_110]]
; CHECK-NEXT: [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1
; CHECK-NEXT: [[INDVAR_NEXT]] = add nuw nsw i32 [[INDVAR]], 1
; CHECK-NEXT: [[INC]] = add nuw nsw i16 [[J_011]], 1
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INDVAR_NEXT]], 16
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP3]], label [[FOR_BODY4]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,81 @@ define void @s172(i32 noundef %xa, i32 noundef %xb, ptr noundef %a, ptr noundef
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[XA]], -1
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[SUB]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[XB]] to i64
; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[TMP1]], [[TMP0]]
; CHECK-NEXT: [[SMAX7:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP2]], i64 32000)
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i64 [[TMP2]], 32000
; CHECK-NEXT: [[UMIN8:%.*]] = zext i1 [[TMP3]] to i64
; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[TMP2]], [[UMIN8]]
; CHECK-NEXT: [[TMP5:%.*]] = sub i64 [[SMAX7]], [[TMP4]]
; CHECK-NEXT: [[UMAX9:%.*]] = tail call i64 @llvm.umax.i64(i64 [[TMP1]], i64 1)
; CHECK-NEXT: [[TMP6:%.*]] = udiv i64 [[TMP5]], [[UMAX9]]
; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[TMP6]], [[UMIN8]]
; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[TMP7]], 1
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ugt i64 [[TMP8]], 23
; CHECK-NEXT: [[IDENT_CHECK_NOT:%.*]] = icmp eq i32 [[XB]], 1
; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[MIN_ITERS_CHECK]], [[IDENT_CHECK_NOT]]
; CHECK-NEXT: br i1 [[OR_COND]], label [[VECTOR_MEMCHECK:%.*]], label [[FOR_BODY_PREHEADER13:%.*]]
; CHECK: vector.memcheck:
; CHECK-NEXT: [[TMP9:%.*]] = shl nsw i64 [[TMP0]], 2
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP9]]
; CHECK-NEXT: [[TMP10:%.*]] = add nsw i64 [[TMP1]], [[TMP0]]
; CHECK-NEXT: [[SMAX:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP10]], i64 32000)
; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i64 [[TMP10]], 32000
; CHECK-NEXT: [[UMIN:%.*]] = zext i1 [[TMP11]] to i64
; CHECK-NEXT: [[TMP12:%.*]] = add nsw i64 [[TMP10]], [[UMIN]]
; CHECK-NEXT: [[TMP13:%.*]] = sub i64 [[SMAX]], [[TMP12]]
; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[TMP13]], [[UMIN]]
; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[TMP14]], [[TMP0]]
; CHECK-NEXT: [[TMP16:%.*]] = shl i64 [[TMP15]], 2
; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[TMP16]], 4
; CHECK-NEXT: [[SCEVGEP4:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP17]]
; CHECK-NEXT: [[SCEVGEP5:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP9]]
; CHECK-NEXT: [[SCEVGEP6:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP17]]
; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[SCEVGEP]], [[SCEVGEP6]]
; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[SCEVGEP5]], [[SCEVGEP4]]
; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[FOR_BODY_PREHEADER13]], label [[VECTOR_PH:%.*]]
; CHECK: vector.ph:
; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP8]], -8
; CHECK-NEXT: [[TMP18:%.*]] = mul nuw i64 [[N_VEC]], [[TMP1]]
; CHECK-NEXT: [[IND_END:%.*]] = add i64 [[TMP18]], [[TMP0]]
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP19:%.*]] = mul nuw i64 [[INDEX]], [[TMP1]]
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i64 [[TMP19]], [[TMP0]]
; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[OFFSET_IDX]]
; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds i8, ptr [[TMP20]], i64 16
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP20]], align 4, !alias.scope [[META0:![0-9]+]]
; CHECK-NEXT: [[WIDE_LOAD10:%.*]] = load <4 x i32>, ptr [[TMP21]], align 4, !alias.scope [[META0]]
; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[OFFSET_IDX]]
; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds i8, ptr [[TMP22]], i64 16
; CHECK-NEXT: [[WIDE_LOAD11:%.*]] = load <4 x i32>, ptr [[TMP22]], align 4, !alias.scope [[META3:![0-9]+]], !noalias [[META0]]
; CHECK-NEXT: [[WIDE_LOAD12:%.*]] = load <4 x i32>, ptr [[TMP23]], align 4, !alias.scope [[META3]], !noalias [[META0]]
; CHECK-NEXT: [[TMP24:%.*]] = add nsw <4 x i32> [[WIDE_LOAD11]], [[WIDE_LOAD]]
; CHECK-NEXT: [[TMP25:%.*]] = add nsw <4 x i32> [[WIDE_LOAD12]], [[WIDE_LOAD10]]
; CHECK-NEXT: store <4 x i32> [[TMP24]], ptr [[TMP22]], align 4, !alias.scope [[META3]], !noalias [[META0]]
; CHECK-NEXT: store <4 x i32> [[TMP25]], ptr [[TMP23]], align 4, !alias.scope [[META3]], !noalias [[META0]]
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8
; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
; CHECK-NEXT: br i1 [[TMP26]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
; CHECK: middle.block:
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP8]], [[N_VEC]]
; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END]], label [[FOR_BODY_PREHEADER13]]
; CHECK: for.body.preheader13:
; CHECK-NEXT: [[INDVARS_IV_PH:%.*]] = phi i64 [ [[TMP0]], [[VECTOR_MEMCHECK]] ], [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[IND_END]], [[MIDDLE_BLOCK]] ]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[INDVARS_IV_PH]], [[FOR_BODY_PREHEADER13]] ]
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[L_A]], [[L_B]]
; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP_A]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], [[TMP1]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP1]]
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], 32000
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]], !llvm.loop [[LOOP9:![0-9]+]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
Expand Down Expand Up @@ -63,6 +126,14 @@ for.end:
!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.mustprogress"}
;.
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]]}
; CHECK: [[META1]] = !{!"llvm.loop.mustprogress"}
; CHECK: [[META0]] = !{[[META1:![0-9]+]]}
; CHECK: [[META1]] = distinct !{[[META1]], [[META2:![0-9]+]]}
; CHECK: [[META2]] = distinct !{[[META2]], !"LVerDomain"}
; CHECK: [[META3]] = !{[[META4:![0-9]+]]}
; CHECK: [[META4]] = distinct !{[[META4]], [[META2]]}
; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META6:![0-9]+]], [[META7:![0-9]+]], [[META8:![0-9]+]]}
; CHECK: [[META6]] = !{!"llvm.loop.mustprogress"}
; CHECK: [[META7]] = !{!"llvm.loop.isvectorized", i32 1}
; CHECK: [[META8]] = !{!"llvm.loop.unroll.runtime.disable"}
; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META6]], [[META7]]}
;.
2 changes: 1 addition & 1 deletion llvm/test/Transforms/PhaseOrdering/AArch64/loopflatten.ll
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ define dso_local void @_Z3fooPiii(ptr %A, i32 %N, i32 %M) #0 {
; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVAR6]]
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX_US]], align 4
; CHECK-NEXT: tail call void @_Z1fi(i32 [[TMP2]])
; CHECK-NEXT: [[INDVAR_NEXT7]] = add nuw nsw i64 [[INDVAR6]], 1
; CHECK-NEXT: [[INDVAR_NEXT7]] = add nuw i64 [[INDVAR6]], 1
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVAR_NEXT7]], [[FLATTEN_TRIPCOUNT]]
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_COND1_PREHEADER_US]]
; CHECK: for.cond.cleanup:
Expand Down
141 changes: 140 additions & 1 deletion llvm/test/tools/llvm-lib/arm64ec-implib.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,23 @@ ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll
ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll
ARMAP-EMPTY:
ARMAP-NEXT: Archive EC map
ARMAP-NEXT: #expname in test.dll
ARMAP-NEXT: #funcexp in test.dll
ARMAP-NEXT: #mangledfunc in test.dll
ARMAP-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll
ARMAP-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll
ARMAP-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll
ARMAP-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll
ARMAP-NEXT: __imp_aux_expname in test.dll
ARMAP-NEXT: __imp_aux_funcexp in test.dll
ARMAP-NEXT: __imp_aux_mangledfunc in test.dll
ARMAP-NEXT: __imp_dataexp in test.dll
ARMAP-NEXT: __imp_expname in test.dll
ARMAP-NEXT: __imp_funcexp in test.dll
ARMAP-NEXT: __imp_mangledfunc in test.dll
ARMAP-NEXT: expname in test.dll
ARMAP-NEXT: funcexp in test.dll
ARMAP-NEXT: mangledfunc in test.dll

RUN: llvm-readobj test.lib | FileCheck -check-prefix=READOBJ %s

Expand All @@ -35,10 +49,42 @@ READOBJ-EMPTY:
READOBJ-NEXT: File: test.dll
READOBJ-NEXT: Format: COFF-import-file-ARM64EC
READOBJ-NEXT: Type: code
READOBJ-NEXT: Name type: name
READOBJ-NEXT: Name type: export as
READOBJ-NEXT: Export name: funcexp
READOBJ-NEXT: Symbol: __imp_funcexp
READOBJ-NEXT: Symbol: funcexp
READOBJ-NEXT: Symbol: __imp_aux_funcexp
READOBJ-NEXT: Symbol: #funcexp
READOBJ-EMPTY:
READOBJ-NEXT: File: test.dll
READOBJ-NEXT: Format: COFF-import-file-ARM64EC
READOBJ-NEXT: Type: code
READOBJ-NEXT: Name type: export as
READOBJ-NEXT: Export name: mangledfunc
READOBJ-NEXT: Symbol: __imp_mangledfunc
READOBJ-NEXT: Symbol: mangledfunc
READOBJ-NEXT: Symbol: __imp_aux_mangledfunc
READOBJ-NEXT: Symbol: #mangledfunc
READOBJ-EMPTY:
READOBJ-NEXT: File: test.dll
READOBJ-NEXT: Format: COFF-import-file-ARM64EC
READOBJ-NEXT: Type: code
READOBJ-NEXT: Name type: export as
READOBJ-NEXT: Export name: ?test_cpp_func@@YAHPEAX@Z
READOBJ-NEXT: Symbol: __imp_?test_cpp_func@@YAHPEAX@Z
READOBJ-NEXT: Symbol: ?test_cpp_func@@YAHPEAX@Z
READOBJ-NEXT: Symbol: __imp_aux_?test_cpp_func@@YAHPEAX@Z
READOBJ-NEXT: Symbol: ?test_cpp_func@@$$hYAHPEAX@Z
READOBJ-EMPTY:
READOBJ-NEXT: File: test.dll
READOBJ-NEXT: Format: COFF-import-file-ARM64EC
READOBJ-NEXT: Type: code
READOBJ-NEXT: Name type: export as
READOBJ-NEXT: Export name: expname
READOBJ-NEXT: Symbol: __imp_expname
READOBJ-NEXT: Symbol: expname
READOBJ-NEXT: Symbol: __imp_aux_expname
READOBJ-NEXT: Symbol: #expname
READOBJ-EMPTY:
READOBJ-NEXT: File: test.dll
READOBJ-NEXT: Format: COFF-import-file-ARM64EC
Expand All @@ -51,8 +97,101 @@ Creating a new lib containing the existing lib:
RUN: llvm-lib -machine:arm64ec test.lib -out:test2.lib
RUN: llvm-nm --print-armap test2.lib | FileCheck -check-prefix=ARMAP %s


RUN: llvm-lib -machine:arm64ec -def:exportas.def -out:exportas.lib
RUN: llvm-nm --print-armap exportas.lib | FileCheck -check-prefix=EXPAS-ARMAP %s
RUN: llvm-readobj exportas.lib | FileCheck -check-prefix=EXPAS-READOBJ %s

EXPAS-ARMAP: Archive EC map
EXPAS-ARMAP-NEXT: #func1 in test.dll
EXPAS-ARMAP-NEXT: #func2 in test.dll
EXPAS-ARMAP-NEXT: #func3 in test.dll
EXPAS-ARMAP-NEXT: #func4 in test.dll
EXPAS-ARMAP-NEXT: __imp_aux_func1 in test.dll
EXPAS-ARMAP-NEXT: __imp_aux_func2 in test.dll
EXPAS-ARMAP-NEXT: __imp_aux_func3 in test.dll
EXPAS-ARMAP-NEXT: __imp_aux_func4 in test.dll
EXPAS-ARMAP-NEXT: __imp_data1 in test.dll
EXPAS-ARMAP-NEXT: __imp_data2 in test.dll
EXPAS-ARMAP-NEXT: __imp_func1 in test.dll
EXPAS-ARMAP-NEXT: __imp_func2 in test.dll
EXPAS-ARMAP-NEXT: __imp_func3 in test.dll
EXPAS-ARMAP-NEXT: __imp_func4 in test.dll
EXPAS-ARMAP-NEXT: func1 in test.dll
EXPAS-ARMAP-NEXT: func2 in test.dll
EXPAS-ARMAP-NEXT: func3 in test.dll
EXPAS-ARMAP-NEXT: func4 in test.dll

EXPAS-READOBJ: File: test.dll
EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC
EXPAS-READOBJ-NEXT: Type: code
EXPAS-READOBJ-NEXT: Name type: export as
EXPAS-READOBJ-NEXT: Export name: func1
EXPAS-READOBJ-NEXT: Symbol: __imp_func1
EXPAS-READOBJ-NEXT: Symbol: func1
EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func1
EXPAS-READOBJ-NEXT: Symbol: #func1
EXPAS-READOBJ-EMPTY:
EXPAS-READOBJ-NEXT: File: test.dll
EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC
EXPAS-READOBJ-NEXT: Type: code
EXPAS-READOBJ-NEXT: Name type: export as
EXPAS-READOBJ-NEXT: Export name: func2
EXPAS-READOBJ-NEXT: Symbol: __imp_func2
EXPAS-READOBJ-NEXT: Symbol: func2
EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func2
EXPAS-READOBJ-NEXT: Symbol: #func2
EXPAS-READOBJ-EMPTY:
EXPAS-READOBJ-NEXT: File: test.dll
EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC
EXPAS-READOBJ-NEXT: Type: code
EXPAS-READOBJ-NEXT: Name type: export as
EXPAS-READOBJ-NEXT: Export name: #func3
EXPAS-READOBJ-NEXT: Symbol: __imp_func3
EXPAS-READOBJ-NEXT: Symbol: func3
EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func3
EXPAS-READOBJ-NEXT: Symbol: #func3
EXPAS-READOBJ-EMPTY:
EXPAS-READOBJ-NEXT: File: test.dll
EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC
EXPAS-READOBJ-NEXT: Type: code
EXPAS-READOBJ-NEXT: Name type: export as
EXPAS-READOBJ-NEXT: Export name: #func4
EXPAS-READOBJ-NEXT: Symbol: __imp_func4
EXPAS-READOBJ-NEXT: Symbol: func4
EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func4
EXPAS-READOBJ-NEXT: Symbol: #func4
EXPAS-READOBJ-EMPTY:
EXPAS-READOBJ-NEXT: File: test.dll
EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC
EXPAS-READOBJ-NEXT: Type: data
EXPAS-READOBJ-NEXT: Name type: export as
EXPAS-READOBJ-NEXT: Export name: #data1
EXPAS-READOBJ-NEXT: Symbol: __imp_data1
EXPAS-READOBJ-EMPTY:
EXPAS-READOBJ-NEXT: File: test.dll
EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC
EXPAS-READOBJ-NEXT: Type: data
EXPAS-READOBJ-NEXT: Name type: export as
EXPAS-READOBJ-NEXT: Export name: data2
EXPAS-READOBJ-NEXT: Symbol: __imp_data2


#--- test.def
LIBRARY test.dll
EXPORTS
funcexp
#mangledfunc
?test_cpp_func@@YAHPEAX@Z
expname=impname
dataexp DATA

#--- exportas.def
LIBRARY test.dll
EXPORTS
#func1 EXPORTAS func1
func2 EXPORTAS func2
func3 EXPORTAS #func3
#func4 EXPORTAS #func4
data1 DATA EXPORTAS #data1
#data2 DATA EXPORTAS data2
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ static_library("Scalar") {
"InferAddressSpaces.cpp",
"InferAlignment.cpp",
"InstSimplifyPass.cpp",
"JumpTableToSwitch.cpp",
"JumpThreading.cpp",
"LICM.cpp",
"LoopAccessAnalysisPrinter.cpp",
Expand Down