1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Verify that wcslen calls with conditional expressions involving constant 3; string arguments with nonconstant offsets are folded as expected. See 4; strlen-4.ll for the corresponding strlen test. 5; 6; RUN: opt < %s -passes=instcombine -S | FileCheck %s 7 8declare i64 @wcslen(ptr) 9 10!0 = !{i32 1, !"wchar_size", i32 4} 11!llvm.module.flags = !{!0} 12 13@ws3 = constant [4 x i32] [i32 1, i32 2, i32 3, i32 0] 14@ws5 = constant [6 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 0] 15@ws5_3 = constant [10 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 0, i32 6, i32 7, i32 8, i32 0] 16 17 18; Fold wcslen (x ? s3 + i: s5) to x ? 3 - i : 5. 19 20define dso_local i64 @fold_wcslen_s3_pi_s5(i1 zeroext %0, i64 %1) { 21; CHECK-LABEL: @fold_wcslen_s3_pi_s5( 22; CHECK-NEXT: [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 [[TMP1:%.*]] 23; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS3_PI]], ptr @ws5 24; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]]) 25; CHECK-NEXT: ret i64 [[LEN]] 26; 27 28 %ps3_pi = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 %1 29 %sel = select i1 %0, ptr %ps3_pi, ptr @ws5 30 %len = tail call i64 @wcslen(ptr %sel) 31 ret i64 %len 32} 33 34 35; More complex expressions like the one below are not handled yet. 36; Fold: wcslen (x ? s3 + i + 1 : s5 + j + 2) to x ? 2 - i : 3 - j. 37 38define dso_local i64 @fold_wcslen_s3_pi_p1_s5(i1 zeroext %0, i64 %1) { 39; XFAIL-CHECK-LABEL: @fold_wcslen_s3_pi_p1_s5( 40; XFAIL-CHECK-NEXT: [[DIF_I:%.*]] = sub i64 2, %1 41; XFAIL-CHECK-NEXT: [[SEL:%.*]] = select i1 %0, i64 [[DIF_I]], i64 5 42; XFAIL-CHECK-NEXT: ret i64 [[SEL]] 43; CHECK-LABEL: @fold_wcslen_s3_pi_p1_s5( 44; CHECK-NEXT: [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 [[TMP1:%.*]] 45; CHECK-NEXT: [[PS3_PI_P1:%.*]] = getelementptr inbounds nuw i8, ptr [[PS3_PI]], i64 4 46; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS3_PI_P1]], ptr @ws5 47; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]]) 48; CHECK-NEXT: ret i64 [[LEN]] 49; 50 51 %ps3_pi = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 %1 52 %ps3_pi_p1 = getelementptr inbounds i32, ptr %ps3_pi, i64 1 53 %sel = select i1 %0, ptr %ps3_pi_p1, ptr @ws5 54 %len = tail call i64 @wcslen(ptr %sel) 55 ret i64 %len 56} 57 58 59; Avoid folding calls with conditional expressions involving constant 60; string arguments with embedded nuls such as: 61; wcslen (x ? s5_3 + i : s5). 62 63define dso_local i64 @call_wcslen_s5_3_pi_s5(i1 zeroext %0, i64 %1) { 64; CHECK-LABEL: @call_wcslen_s5_3_pi_s5( 65; CHECK-NEXT: [[PS5_3_PI:%.*]] = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 [[TMP1:%.*]] 66; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS5_3_PI]], ptr @ws5 67; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]]) 68; CHECK-NEXT: ret i64 [[LEN]] 69; 70 71 %ps5_3_pi = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 %1 72 %sel = select i1 %0, ptr %ps5_3_pi, ptr @ws5 73 %len = tail call i64 @wcslen(ptr %sel) 74 ret i64 %len 75} 76 77 78; But do fold wcslen (x ? s5_3 : s5 + j) to x ? 5 : 5 - j. 79 80define dso_local i64 @call_wcslen_s5_3_s5_pj(i1 zeroext %0, i64 %1) { 81; CHECK-LABEL: @call_wcslen_s5_3_s5_pj( 82; CHECK-NEXT: [[PS5:%.*]] = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 [[TMP1:%.*]] 83; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr @ws5_3, ptr [[PS5]] 84; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]]) 85; CHECK-NEXT: ret i64 [[LEN]] 86; 87 88 %ps5 = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 %1 89 %sel = select i1 %0, ptr @ws5_3, ptr %ps5 90 %len = tail call i64 @wcslen(ptr %sel) 91 ret i64 %len 92} 93 94 95; Fold wcslen (x ? s3: s5 + j) to x ? 3 : 5 - j. 96 97define dso_local i64 @fold_wcslen_s3_s5_pj(i1 zeroext %0, i64 %1) { 98; CHECK-LABEL: @fold_wcslen_s3_s5_pj( 99; CHECK-NEXT: [[PS5_PJ:%.*]] = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 [[TMP1:%.*]] 100; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr @ws3, ptr [[PS5_PJ]] 101; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]]) 102; CHECK-NEXT: ret i64 [[LEN]] 103; 104 105 %ps5_pj = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 %1 106 %sel = select i1 %0, ptr @ws3, ptr %ps5_pj 107 %len = tail call i64 @wcslen(ptr %sel) 108 ret i64 %len 109} 110 111 112; Same as above, avoid folding calls with conditional expressions involving 113; constant string arguments with embedded nuls such as: 114; wcslen (x ? s3 : s5_3 + j). 115 116define dso_local i64 @call_wcslen_s3_s5_3_pj(i1 zeroext %0, i64 %1) { 117; CHECK-LABEL: @call_wcslen_s3_s5_3_pj( 118; CHECK-NEXT: [[PS5_3_PJ:%.*]] = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 [[TMP1:%.*]] 119; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr @ws3, ptr [[PS5_3_PJ]] 120; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]]) 121; CHECK-NEXT: ret i64 [[LEN]] 122; 123 124 %ps5_3_pj = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 %1 125 %sel = select i1 %0, ptr @ws3, ptr %ps5_3_pj 126 %len = tail call i64 @wcslen(ptr %sel) 127 ret i64 %len 128} 129 130 131; Fold wcslen (x ? s3 + i: s5 + j) to x ? 3 - i : 5 - j. 132 133define dso_local i64 @fold_wcslen_s3_pi_s5_pj(i1 zeroext %0, i64 %1, i64 %2) { 134; CHECK-LABEL: @fold_wcslen_s3_pi_s5_pj( 135; CHECK-NEXT: [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 [[TMP1:%.*]] 136; CHECK-NEXT: [[PS5_PJ:%.*]] = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 [[TMP2:%.*]] 137; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS3_PI]], ptr [[PS5_PJ]] 138; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]]) 139; CHECK-NEXT: ret i64 [[LEN]] 140; 141 142 %ps3_pi = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 %1 143 %ps5_pj = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 %2 144 %sel = select i1 %0, ptr %ps3_pi, ptr %ps5_pj 145 %len = tail call i64 @wcslen(ptr %sel) 146 ret i64 %len 147} 148