@@ -1143,9 +1143,9 @@ exit:
1143
1143
1144
1144
; We can remove this freeze as the incoming values to the PHI have the same
1145
1145
; well-defined start value and the GEP can't produce poison.
1146
- define void @fold_phi_noundef_start_value (ptr noundef %init , i1 %cond.0 , i1 %cond.1 , i1 %cond.2 ) {
1146
+ define void @fold_phi_noundef_start_value (ptr noundef %init , i1 %cond.0 , i1 %cond.1 ) {
1147
1147
; CHECK-LABEL: define void @fold_phi_noundef_start_value(
1148
- ; CHECK-SAME: ptr noundef [[INIT:%.*]], i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]] ) {
1148
+ ; CHECK-SAME: ptr noundef [[INIT:%.*]], i1 [[COND_0:%.*]], i1 [[COND_1:%.*]]) {
1149
1149
; CHECK-NEXT: [[ENTRY:.*]]:
1150
1150
; CHECK-NEXT: br label %[[LOOP:.*]]
1151
1151
; CHECK: [[LOOP]]:
@@ -1160,7 +1160,7 @@ define void @fold_phi_noundef_start_value(ptr noundef %init, i1 %cond.0, i1 %con
1160
1160
; CHECK-NEXT: [[IV_0_INT:%.*]] = ptrtoint ptr [[IV_0]] to i64
1161
1161
; CHECK-NEXT: [[IDX:%.*]] = sub i64 [[IV_0_INT]], [[IV_2_FR_INT]]
1162
1162
; CHECK-NEXT: [[IV_0_NEXT]] = getelementptr i8, ptr [[IV_0]], i64 [[IDX]]
1163
- ; CHECK-NEXT: br i1 [[COND_2 ]], label %[[EXIT:.*]], label %[[LOOP]]
1163
+ ; CHECK-NEXT: br i1 [[COND_1 ]], label %[[EXIT:.*]], label %[[LOOP]]
1164
1164
; CHECK: [[EXIT]]:
1165
1165
; CHECK-NEXT: ret void
1166
1166
;
@@ -1182,7 +1182,120 @@ loop.latch:
1182
1182
%iv.0.int = ptrtoint ptr %iv.0 to i64
1183
1183
%idx = sub i64 %iv.0.int , %iv.2.fr.int
1184
1184
%iv.0.next = getelementptr i8 , ptr %iv.0 , i64 %idx
1185
- br i1 %cond.2 , label %exit , label %loop
1185
+ br i1 %cond.1 , label %exit , label %loop
1186
+
1187
+ exit:
1188
+ ret void
1189
+ }
1190
+
1191
+ declare ptr @get_ptr ()
1192
+
1193
+ ; When the phi isn't a simple recurrence and has multiple inputs from the same
1194
+ ; predecessor, we need to be careful to avoid iterator invalidation. The phi
1195
+ ; must have identical values for the predecessor and at no point should the
1196
+ ; freeze be pushed to a single one of the uses, e.g.
1197
+ ;
1198
+ ; %iv.2 = phi ptr [ %iv.0, %loop ], [ %iv.1.fr, %if.else ], [ %iv.1, %if.else ]
1199
+ ;
1200
+ ; We simply don't support this case, although it could be handled if there's a
1201
+ ; use case.
1202
+ define void @fold_phi_non_simple_recurrence_multiple_forward_edges (ptr noundef %init , i1 %cond.0 , i1 %cond.1 ) {
1203
+ ; CHECK-LABEL: define void @fold_phi_non_simple_recurrence_multiple_forward_edges(
1204
+ ; CHECK-SAME: ptr noundef [[INIT:%.*]], i1 [[COND_0:%.*]], i1 [[COND_1:%.*]]) {
1205
+ ; CHECK-NEXT: [[ENTRY:.*]]:
1206
+ ; CHECK-NEXT: br label %[[LOOP:.*]]
1207
+ ; CHECK: [[LOOP]]:
1208
+ ; CHECK-NEXT: [[IV_0:%.*]] = phi ptr [ [[INIT]], %[[ENTRY]] ], [ [[IV_0_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1209
+ ; CHECK-NEXT: br i1 [[COND_0]], label %[[LOOP_LATCH]], label %[[IF_ELSE:.*]]
1210
+ ; CHECK: [[IF_ELSE]]:
1211
+ ; CHECK-NEXT: [[IV_1:%.*]] = call ptr @get_ptr()
1212
+ ; CHECK-NEXT: br i1 false, label %[[LOOP_LATCH]], label %[[LOOP_LATCH]]
1213
+ ; CHECK: [[LOOP_LATCH]]:
1214
+ ; CHECK-NEXT: [[IV_2:%.*]] = phi ptr [ [[IV_0]], %[[LOOP]] ], [ [[IV_1]], %[[IF_ELSE]] ], [ [[IV_1]], %[[IF_ELSE]] ]
1215
+ ; CHECK-NEXT: [[IV_2_FR:%.*]] = freeze ptr [[IV_2]]
1216
+ ; CHECK-NEXT: [[IV_2_FR_INT:%.*]] = ptrtoint ptr [[IV_2_FR]] to i64
1217
+ ; CHECK-NEXT: [[IV_0_INT:%.*]] = ptrtoint ptr [[IV_0]] to i64
1218
+ ; CHECK-NEXT: [[IDX:%.*]] = sub i64 [[IV_0_INT]], [[IV_2_FR_INT]]
1219
+ ; CHECK-NEXT: [[IV_0_NEXT]] = getelementptr i8, ptr [[IV_0]], i64 [[IDX]]
1220
+ ; CHECK-NEXT: br i1 [[COND_1]], label %[[EXIT:.*]], label %[[LOOP]]
1221
+ ; CHECK: [[EXIT]]:
1222
+ ; CHECK-NEXT: ret void
1223
+ ;
1224
+ entry:
1225
+ br label %loop
1226
+
1227
+ loop:
1228
+ %iv.0 = phi ptr [ %init , %entry ], [ %iv.0.next , %loop.latch ]
1229
+ br i1 %cond.0 , label %loop.latch , label %if.else
1230
+
1231
+ if.else:
1232
+ %iv.1 = call ptr @get_ptr ()
1233
+ br i1 %cond.0 , label %loop.latch , label %loop.latch
1234
+
1235
+ loop.latch:
1236
+ %iv.2 = phi ptr [ %iv.0 , %loop ], [ %iv.1 , %if.else ], [ %iv.1 , %if.else ]
1237
+ %iv.2.fr = freeze ptr %iv.2
1238
+ %iv.2.fr.int = ptrtoint ptr %iv.2.fr to i64
1239
+ %iv.0.int = ptrtoint ptr %iv.0 to i64
1240
+ %idx = sub i64 %iv.0.int , %iv.2.fr.int
1241
+ %iv.0.next = getelementptr i8 , ptr %iv.0 , i64 %idx
1242
+ br i1 %cond.1 , label %exit , label %loop
1243
+
1244
+ exit:
1245
+ ret void
1246
+ }
1247
+
1248
+ ; When the phi input comes from an invoke, we need to be careful the freeze
1249
+ ; isn't pushed after the invoke.
1250
+ define void @fold_phi_noundef_start_value_with_invoke (ptr noundef %init , i1 %cond.0 , i1 %cond.1 ) personality ptr undef {
1251
+ ; CHECK-LABEL: define void @fold_phi_noundef_start_value_with_invoke(
1252
+ ; CHECK-SAME: ptr noundef [[INIT:%.*]], i1 [[COND_0:%.*]], i1 [[COND_1:%.*]]) personality ptr undef {
1253
+ ; CHECK-NEXT: [[ENTRY:.*]]:
1254
+ ; CHECK-NEXT: br label %[[LOOP:.*]]
1255
+ ; CHECK: [[LOOP]]:
1256
+ ; CHECK-NEXT: [[IV_0:%.*]] = phi ptr [ [[INIT]], %[[ENTRY]] ], [ [[IV_0_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1257
+ ; CHECK-NEXT: br i1 [[COND_0]], label %[[LOOP_LATCH]], label %[[IF_ELSE:.*]]
1258
+ ; CHECK: [[IF_ELSE]]:
1259
+ ; CHECK-NEXT: [[IV_1:%.*]] = invoke ptr @get_ptr()
1260
+ ; CHECK-NEXT: to label %[[LOOP_LATCH]] unwind label %[[UNWIND:.*]]
1261
+ ; CHECK: [[LOOP_LATCH]]:
1262
+ ; CHECK-NEXT: [[IV_2:%.*]] = phi ptr [ [[IV_0]], %[[LOOP]] ], [ [[IV_1]], %[[IF_ELSE]] ]
1263
+ ; CHECK-NEXT: [[IV_2_FR:%.*]] = freeze ptr [[IV_2]]
1264
+ ; CHECK-NEXT: [[IV_2_FR_INT:%.*]] = ptrtoint ptr [[IV_2_FR]] to i64
1265
+ ; CHECK-NEXT: [[IV_0_INT:%.*]] = ptrtoint ptr [[IV_0]] to i64
1266
+ ; CHECK-NEXT: [[IDX:%.*]] = sub i64 [[IV_0_INT]], [[IV_2_FR_INT]]
1267
+ ; CHECK-NEXT: [[IV_0_NEXT]] = getelementptr i8, ptr [[IV_0]], i64 [[IDX]]
1268
+ ; CHECK-NEXT: br i1 [[COND_1]], label %[[EXIT:.*]], label %[[LOOP]]
1269
+ ; CHECK: [[UNWIND]]:
1270
+ ; CHECK-NEXT: [[TMP0:%.*]] = landingpad i8
1271
+ ; CHECK-NEXT: cleanup
1272
+ ; CHECK-NEXT: unreachable
1273
+ ; CHECK: [[EXIT]]:
1274
+ ; CHECK-NEXT: ret void
1275
+ ;
1276
+ entry:
1277
+ br label %loop
1278
+
1279
+ loop:
1280
+ %iv.0 = phi ptr [ %init , %entry ], [ %iv.0.next , %loop.latch ]
1281
+ br i1 %cond.0 , label %loop.latch , label %if.else
1282
+
1283
+ if.else:
1284
+ %iv.1 = invoke ptr @get_ptr ()
1285
+ to label %loop.latch unwind label %unwind
1286
+
1287
+ loop.latch:
1288
+ %iv.2 = phi ptr [ %iv.0 , %loop ], [ %iv.1 , %if.else ]
1289
+ %iv.2.fr = freeze ptr %iv.2
1290
+ %iv.2.fr.int = ptrtoint ptr %iv.2.fr to i64
1291
+ %iv.0.int = ptrtoint ptr %iv.0 to i64
1292
+ %idx = sub i64 %iv.0.int , %iv.2.fr.int
1293
+ %iv.0.next = getelementptr i8 , ptr %iv.0 , i64 %idx
1294
+ br i1 %cond.1 , label %exit , label %loop
1295
+
1296
+ unwind:
1297
+ landingpad i8 cleanup
1298
+ unreachable
1186
1299
1187
1300
exit:
1188
1301
ret void
0 commit comments