brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · c8d2563 Raw
192 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; Verify that strlen calls with conditional expressions involving constant3; string arguments with nonconstant offsets are folded as expected.4;5; RUN: opt < %s -passes=instcombine -S | FileCheck %s6 7declare i64 @strlen(ptr)8 9@sx = external global [0 x i8]10@s3 = constant [4 x i8] c"123\00"11@s5 = constant [6 x i8] c"12345\00"12@s7 = constant [8 x i8] c"1234567\00"13 14@s5_3 = constant [10 x i8] c"12345\00123\00"15 16 17; Fold strlen (x ? s3 + i : s5) to x ? 3 - i : 5.18 19define i64 @fold_strlen_s3_pi_s5(i1 %X, i64 %I) {20; CHECK-LABEL: @fold_strlen_s3_pi_s5(21; CHECK-NEXT:    [[PS3_PI:%.*]] = getelementptr inbounds i8, ptr @s3, i64 [[I:%.*]]22; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[X:%.*]], ptr [[PS3_PI]], ptr @s523; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])24; CHECK-NEXT:    ret i64 [[LEN]]25;26 27  %ps3_pi = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 %I28  %sel = select i1 %X, ptr %ps3_pi, ptr @s529  %len = tail call i64 @strlen(ptr %sel)30  ret i64 %len31}32 33 34; More complex expressions like the one below are not handled yet.35; Fold: strlen (x ? s3 + i + 1 : s5) to x ? 2 - i : 5.36 37define i64 @fold_strlen_s3_pi_p1_s5(i1 %0, i64 %1) {38; XFAIL-CHECK-LABEL: @fold_strlen_s3_pi_p1_s5(39; XFAIL-CHECK-NEXT:    [[DIF_I:%.*]] = sub i64 2, %140; XFAIL-CHECK-NEXT:    [[SEL:%.*]] = select i1 %0, i64 [[DIF_I]], i64 541; XFAIL-CHECK-NEXT:    ret i64 [[SEL]]42; CHECK-LABEL: @fold_strlen_s3_pi_p1_s5(43; CHECK-NEXT:    [[PS3_PI:%.*]] = getelementptr inbounds i8, ptr @s3, i64 [[TMP1:%.*]]44; CHECK-NEXT:    [[PS3_PI_P1:%.*]] = getelementptr i8, ptr [[PS3_PI]], i64 145; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS3_PI_P1]], ptr @s546; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])47; CHECK-NEXT:    ret i64 [[LEN]]48;49 50  %ps3_pi = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 %151  %ps3_pi_p1 = getelementptr i8, ptr %ps3_pi, i64 152  %sel = select i1 %0, ptr %ps3_pi_p1, ptr @s553  %len = tail call i64 @strlen(ptr %sel)54  ret i64 %len55}56 57 58; Avoid folding calls with conditional expressions involving constant59; string arguments with embedded nuls such as:60;   strlen (x ? s5_3 + i : s5).61 62define i64 @call_strlen_s5_3_pi_s5(i1 %0, i64 %1) {63; CHECK-LABEL: @call_strlen_s5_3_pi_s5(64; CHECK-NEXT:    [[PS5_3_PI:%.*]] = getelementptr inbounds i8, ptr @s5_3, i64 [[TMP1:%.*]]65; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS5_3_PI]], ptr @s566; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])67; CHECK-NEXT:    ret i64 [[LEN]]68;69 70  %ps5_3_pi = getelementptr inbounds [10 x i8], ptr @s5_3, i64 0, i64 %171  %sel = select i1 %0, ptr %ps5_3_pi, ptr @s572  %len = tail call i64 @strlen(ptr %sel)73  ret i64 %len74}75 76 77; But do fold strlen (x ? s5_3 : s5 + j) to x ? 5 : 5 - j.78 79define i64 @call_strlen_s5_3_s5_pj(i1 %X, i64 %J) {80; CHECK-LABEL: @call_strlen_s5_3_s5_pj(81; CHECK-NEXT:    [[PS5:%.*]] = getelementptr inbounds i8, ptr @s5, i64 [[J:%.*]]82; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[X:%.*]], ptr @s5_3, ptr [[PS5]]83; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])84; CHECK-NEXT:    ret i64 [[LEN]]85;86 87  %ps5 = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 %J88  %sel = select i1 %X, ptr @s5_3, ptr %ps589  %len = tail call i64 @strlen(ptr %sel)90  ret i64 %len91}92 93 94; Fold strlen (x ? s3: s5 + j) to x ? 3 : 5 - j.95 96define i64 @fold_strlen_s3_s5_pj(i1 %X, i64 %J) {97; CHECK-LABEL: @fold_strlen_s3_s5_pj(98; CHECK-NEXT:    [[PS5_PJ:%.*]] = getelementptr inbounds i8, ptr @s5, i64 [[J:%.*]]99; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[X:%.*]], ptr @s3, ptr [[PS5_PJ]]100; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])101; CHECK-NEXT:    ret i64 [[LEN]]102;103 104  %ps5_pj = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 %J105  %sel = select i1 %X, ptr @s3, ptr %ps5_pj106  %len = tail call i64 @strlen(ptr %sel)107  ret i64 %len108}109 110 111; Same as above, avoid folding calls with conditional expressions involving112; constant string arguments with embedded nuls such as:113;   strlen (x ? s3 : s5_3 + j).114 115define i64 @call_strlen_s3_s5_3_pj(i1 %0, i64 %1) {116; CHECK-LABEL: @call_strlen_s3_s5_3_pj(117; CHECK-NEXT:    [[PS5_3_PJ:%.*]] = getelementptr inbounds i8, ptr @s5_3, i64 [[TMP1:%.*]]118; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr @s3, ptr [[PS5_3_PJ]]119; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])120; CHECK-NEXT:    ret i64 [[LEN]]121;122 123  %ps5_3_pj = getelementptr inbounds [10 x i8], ptr @s5_3, i64 0, i64 %1124  %sel = select i1 %0, ptr @s3, ptr %ps5_3_pj125  %len = tail call i64 @strlen(ptr %sel)126  ret i64 %len127}128 129 130; Fold strlen (x ? s3 + i: s5 + j) to x ? 3 - i : 5 - j.131 132define i64 @fold_strlen_s3_pi_s5_pj(i1 %X, i64 %I, i64 %J) {133; CHECK-LABEL: @fold_strlen_s3_pi_s5_pj(134; CHECK-NEXT:    [[PS3_PI:%.*]] = getelementptr inbounds i8, ptr @s3, i64 [[I:%.*]]135; CHECK-NEXT:    [[PS5_PJ:%.*]] = getelementptr inbounds i8, ptr @s5, i64 [[J:%.*]]136; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[X:%.*]], ptr [[PS3_PI]], ptr [[PS5_PJ]]137; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])138; CHECK-NEXT:    ret i64 [[LEN]]139;140; Use CHECK-DAG since the two instructions below might be emitted in reverse141; order.142 143  %ps3_pi = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 %I144  %ps5_pj = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 %J145  %sel = select i1 %X, ptr %ps3_pi, ptr %ps5_pj146  %len = tail call i64 @strlen(ptr %sel)147  ret i64 %len148}149 150 151; Fold strlen(E) with E being two conditional expressions:152;   strlen (x == 3 ? s3 : x == 5 ? s5 : s7) to x == 3 ? 3 : x == 5 ? 5 : 7.153 154define i64 @fold_strlen_s3_s5_s7(i32 %X) {155; CHECK-LABEL: @fold_strlen_s3_s5_s7(156; CHECK-NEXT:    [[X_EQ_3:%.*]] = icmp eq i32 [[X:%.*]], 3157; CHECK-NEXT:    [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5158; CHECK-NEXT:    [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], ptr @s5, ptr @s7159; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[X_EQ_3]], ptr @s3, ptr [[SEL_X_EQ_5]]160; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])161; CHECK-NEXT:    ret i64 [[LEN]]162;163 164  %x_eq_3 = icmp eq i32 %X, 3165  %x_eq_5 = icmp eq i32 %X, 5166  %sel_x_eq_5 = select i1 %x_eq_5, ptr @s5, ptr @s7167  %sel = select i1 %x_eq_3, ptr @s3, ptr %sel_x_eq_5168  %len = tail call i64 @strlen(ptr %sel)169  ret i64 %len170}171 172 173; Do not fold strlen (x == 3 ? sx : x == 5 ? s5 : s7).174 175define i64 @call_strlen_sx_s5_s7(i32 %X) {176; CHECK-LABEL: @call_strlen_sx_s5_s7(177; CHECK-NEXT:    [[X_EQ_3:%.*]] = icmp eq i32 [[X:%.*]], 3178; CHECK-NEXT:    [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5179; CHECK-NEXT:    [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], ptr @s5, ptr @s7180; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[X_EQ_3]], ptr @sx, ptr [[SEL_X_EQ_5]]181; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[SEL]])182; CHECK-NEXT:    ret i64 [[LEN]]183;184 185  %x_eq_3 = icmp eq i32 %X, 3186  %x_eq_5 = icmp eq i32 %X, 5187  %sel_x_eq_5 = select i1 %x_eq_5, ptr @s5, ptr @s7188  %sel = select i1 %x_eq_3, ptr @sx, ptr %sel_x_eq_5189  %len = tail call i64 @strlen(ptr %sel)190  ret i64 %len191}192