diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll index 8875ce1c566f3..9733f1b732c3f 100644 --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -877,6 +877,104 @@ exit: ; preds = %loop ret void } +; The recurrence for the GEP offset can't produce poison so the freeze should +; be pushed through to the ptr, but this is not currently supported. +define void @fold_phi_gep_phi_offset(ptr %init, ptr %end, i64 noundef %n) { +; CHECK-LABEL: @fold_phi_gep_phi_offset( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi ptr [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF:%.*]] = phi i64 [ [[N:%.*]], [[ENTRY]] ], [ [[OFF_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF_NEXT]] = shl i64 [[OFF]], 3 +; CHECK-NEXT: [[I_NEXT:%.*]] = getelementptr i8, ptr [[I]], i64 [[OFF_NEXT]] +; CHECK-NEXT: [[I_NEXT_FR]] = freeze ptr [[I_NEXT]] +; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[I_NEXT_FR]], [[END:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %i = phi ptr [ %init, %entry ], [ %i.next.fr, %loop ] + %off = phi i64 [ %n, %entry ], [ %off.next, %loop ] + %off.next = shl i64 %off, 3 + %i.next = getelementptr i8, ptr %i, i64 %off.next + %i.next.fr = freeze ptr %i.next + %cond = icmp eq ptr %i.next.fr, %end + br i1 %cond, label %loop, label %exit + +exit: ; preds = %loop + ret void +} + +; Offset is still guaranteed not to be poison, so the freeze could be moved +; here if we strip inbounds from the GEP, but this is not currently supported. +define void @fold_phi_gep_inbounds_phi_offset(ptr %init, ptr %end, i64 noundef %n) { +; CHECK-LABEL: @fold_phi_gep_inbounds_phi_offset( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi ptr [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF:%.*]] = phi i64 [ [[N:%.*]], [[ENTRY]] ], [ [[OFF_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF_NEXT]] = shl i64 [[OFF]], 3 +; CHECK-NEXT: [[I_NEXT:%.*]] = getelementptr inbounds i8, ptr [[I]], i64 [[OFF_NEXT]] +; CHECK-NEXT: [[I_NEXT_FR]] = freeze ptr [[I_NEXT]] +; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[I_NEXT_FR]], [[END:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %i = phi ptr [ %init, %entry ], [ %i.next.fr, %loop ] + %off = phi i64 [ %n, %entry ], [ %off.next, %loop ] + %off.next = shl i64 %off, 3 + %i.next = getelementptr inbounds i8, ptr %i, i64 %off.next + %i.next.fr = freeze ptr %i.next + %cond = icmp eq ptr %i.next.fr, %end + br i1 %cond, label %loop, label %exit + +exit: ; preds = %loop + ret void +} + +; GEP can produce poison, check freeze isn't moved. +define void @cant_fold_phi_gep_phi_offset(ptr %init, ptr %end, i64 %n) { +; CHECK-LABEL: @cant_fold_phi_gep_phi_offset( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi ptr [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF:%.*]] = phi i64 [ [[N:%.*]], [[ENTRY]] ], [ [[OFF_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF_NEXT]] = shl i64 [[OFF]], 3 +; CHECK-NEXT: [[I_NEXT:%.*]] = getelementptr inbounds i8, ptr [[I]], i64 [[OFF_NEXT]] +; CHECK-NEXT: [[I_NEXT_FR]] = freeze ptr [[I_NEXT]] +; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[I_NEXT_FR]], [[END:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %i = phi ptr [ %init, %entry ], [ %i.next.fr, %loop ] + %off = phi i64 [ %n, %entry ], [ %off.next, %loop ] + %off.next = shl i64 %off, 3 + %i.next = getelementptr inbounds i8, ptr %i, i64 %off.next + %i.next.fr = freeze ptr %i.next + %cond = icmp eq ptr %i.next.fr, %end + br i1 %cond, label %loop, label %exit + +exit: ; preds = %loop + ret void +} + define void @fold_phi_multiple_insts(i32 %init, i32 %n) { ; CHECK-LABEL: @fold_phi_multiple_insts( ; CHECK-NEXT: entry: