1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt < %s -passes=jump-table-to-switch -verify-dom-info -S | FileCheck %s 3 4@func_array0 = constant [2 x ptr] [ptr @func0, ptr @declared_only_func1] 5 6define i32 @func0() { 7 ret i32 1 8} 9 10declare i32 @declared_only_func1() 11 12define i32 @function_with_jump_table_with_a_declared_only_func(i32 %index) { 13; CHECK-LABEL: define i32 @function_with_jump_table_with_a_declared_only_func( 14; CHECK-SAME: i32 [[INDEX:%.*]]) { 15; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 [[INDEX]] 16; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8 17; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]]() 18; CHECK-NEXT: ret i32 [[RESULT]] 19; 20 %gep = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 %index 21 %func_ptr = load ptr, ptr %gep, align 8 22 %result = call i32 %func_ptr() 23 ret i32 %result 24} 25 26declare i32 @__gxx_personality_v0(...) 27 28define i32 @function_with_jump_table_invoke(i32 %index) personality ptr @__gxx_personality_v0 { 29; CHECK-LABEL: define i32 @function_with_jump_table_invoke( 30; CHECK-SAME: i32 [[INDEX:%.*]]) personality ptr @__gxx_personality_v0 { 31; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 [[INDEX]] 32; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8 33; CHECK-NEXT: [[RESULT:%.*]] = invoke i32 [[FUNC_PTR]]() 34; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTIONAL:%.*]] 35; CHECK: normal: 36; CHECK-NEXT: ret i32 [[RESULT]] 37; CHECK: exceptional: 38; CHECK-NEXT: [[LANDING_PAD:%.*]] = landingpad { ptr, i32 } 39; CHECK-NEXT: catch ptr null 40; CHECK-NEXT: resume { ptr, i32 } [[LANDING_PAD]] 41; 42 %gep = getelementptr inbounds [2 x ptr], ptr @func_array0, i32 0, i32 %index 43 %func_ptr = load ptr, ptr %gep, align 8 44 %result = invoke i32 %func_ptr() to label %normal unwind label %exceptional 45normal: 46 ret i32 %result 47exceptional: 48 %landing_pad = landingpad { ptr, i32 } catch ptr null 49 resume { ptr, i32 } %landing_pad 50} 51 52@func_array1 = constant [1 x ptr] [ptr @func2] 53 54define i32 @func2(i32 %arg) { 55 ret i32 %arg 56} 57 58define i32 @function_with_jump_table_musttail_call(i32 %index) { 59; CHECK-LABEL: define i32 @function_with_jump_table_musttail_call( 60; CHECK-SAME: i32 [[INDEX:%.*]]) { 61; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 [[INDEX]] 62; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8 63; CHECK-NEXT: [[RESULT:%.*]] = musttail call i32 [[FUNC_PTR]](i32 [[INDEX]]) 64; CHECK-NEXT: ret i32 [[RESULT]] 65; 66 %gep = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 %index 67 %func_ptr = load ptr, ptr %gep, align 8 68 %result = musttail call i32 %func_ptr(i32 %index) 69 ret i32 %result 70} 71 72define i32 @function_with_jump_table_and_volatile_load(i32 %index) { 73; CHECK-LABEL: define i32 @function_with_jump_table_and_volatile_load( 74; CHECK-SAME: i32 [[INDEX:%.*]]) { 75; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 [[INDEX]] 76; CHECK-NEXT: [[FUNC_PTR:%.*]] = load volatile ptr, ptr [[GEP]], align 8 77; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]]) 78; CHECK-NEXT: ret i32 [[RESULT]] 79; 80 %gep = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 %index 81 %func_ptr = load volatile ptr, ptr %gep, align 8 82 %result = call i32 %func_ptr(i32 %index) 83 ret i32 %result 84} 85 86define i32 @function_with_jump_table_and_atomic_load(i32 %index) { 87; CHECK-LABEL: define i32 @function_with_jump_table_and_atomic_load( 88; CHECK-SAME: i32 [[INDEX:%.*]]) { 89; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 [[INDEX]] 90; CHECK-NEXT: [[FUNC_PTR:%.*]] = load atomic ptr, ptr [[GEP]] monotonic, align 8 91; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]]) 92; CHECK-NEXT: ret i32 [[RESULT]] 93; 94 %gep = getelementptr inbounds [1 x ptr], ptr @func_array1, i32 0, i32 %index 95 %func_ptr = load atomic ptr, ptr %gep monotonic, align 8 96 %result = call i32 %func_ptr(i32 %index) 97 ret i32 %result 98} 99 100@func_array2 = global [1 x ptr] [ptr @func2] 101 102define i32 @function_with_nonconstant_jump_table(i32 %index) { 103; CHECK-LABEL: define i32 @function_with_nonconstant_jump_table( 104; CHECK-SAME: i32 [[INDEX:%.*]]) { 105; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array2, i32 0, i32 [[INDEX]] 106; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8 107; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]]) 108; CHECK-NEXT: ret i32 [[RESULT]] 109; 110 %gep = getelementptr inbounds [1 x ptr], ptr @func_array2, i32 0, i32 %index 111 %func_ptr = load ptr, ptr %gep, align 8 112 %result = call i32 %func_ptr(i32 %index) 113 ret i32 %result 114} 115 116@func_array3 = weak constant [1 x ptr] [ptr @func2] 117 118define i32 @function_with_constant_weak_jump_table(i32 %index) { 119; CHECK-LABEL: define i32 @function_with_constant_weak_jump_table( 120; CHECK-SAME: i32 [[INDEX:%.*]]) { 121; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x ptr], ptr @func_array3, i32 0, i32 [[INDEX]] 122; CHECK-NEXT: [[FUNC_PTR:%.*]] = load ptr, ptr [[GEP]], align 8 123; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FUNC_PTR]](i32 [[INDEX]]) 124; CHECK-NEXT: ret i32 [[RESULT]] 125; 126 %gep = getelementptr inbounds [1 x ptr], ptr @func_array3, i32 0, i32 %index 127 %func_ptr = load ptr, ptr %gep, align 8 128 %result = call i32 %func_ptr(i32 %index) 129 ret i32 %result 130} 131 132