| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -S -passes=instcombine | FileCheck %s |
| @A = extern_weak global float, align 4 |
| |
| ; %same.as.v1 is a select with two phis %v1 and %phi.to.remove as the true |
| ; and false values, while %v1 and %phi.to.remove are actually the same. |
| ; Fold the selection instruction %same.as.v1 to %v1. |
| define void @select_with_identical_phi(ptr %m, ptr %n, i32 %count) { |
| ; CHECK-LABEL: @select_with_identical_phi( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4 |
| ; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4 |
| ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]] |
| ; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]] |
| ; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]] |
| ; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4 |
| ; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ] |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %q = phi ptr [ %m, %entry ], [ %q.next, %for.body ] |
| %c = phi ptr [ %n, %entry ], [ %c.next, %for.body ] |
| %q.load = load float, ptr %q |
| %c.load = load float, ptr %c |
| %sub = fsub float %q.load, %c.load |
| %cmp1 = fcmp olt float %sub, %v0 |
| %v0.1 = select i1 %cmp1, float %sub, float %v0 |
| %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove |
| %cmp2 = fcmp ogt float %sub, %same.as.v1 |
| %v1.1 = select i1 %cmp2, float %sub, float %v1 |
| %phi.to.remove.next = select i1 %cmp2, float %sub, float %same.as.v1 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %q.next = getelementptr inbounds i8, ptr %q, i64 4 |
| %c.next = getelementptr inbounds i8, ptr %c, i64 4 |
| %exitcond = icmp eq i32 %inc.i, %count |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; Reduced from select_with_identical_phi(). |
| ; Check that %same.as.v1 can be folded. |
| define void @select_with_identical_phi_2(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove |
| %v1.1 = select i1 %cmp2, float %x, float %v1 |
| %phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; The difference from select_with_identical_phi_2() is that the true and false values in |
| ; %phi.to.remove.next and %v1.1 are swapped. |
| ; Check that %same.as.v1 can be folded. |
| define void @select_with_identical_phi_3(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[V1]], float [[X:%.*]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove |
| %v1.1 = select i1 %cmp2, float %v1, float %x |
| %phi.to.remove.next = select i1 %cmp2, float %same.as.v1, float %x |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; The difference from select_with_identical_phi_2() is that the true and false values in |
| ; same.as.v1 are swapped. |
| ; Check that %same.as.v1 can be folded. |
| define void @select_with_identical_phi_4(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_4( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %phi.to.remove, float %v1 |
| %v1.1 = select i1 %cmp2, float %x, float %v1 |
| %phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; The difference from select_with_identical_phi() is that the true and false values in |
| ; %same.as.v1, %phi.to.remove.next and %v1.1 are swapped. |
| ; Check that %same.as.v1 can be folded. |
| define void @select_with_identical_phi_5(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_5( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[V1]], float [[X:%.*]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %phi.to.remove, float %v1 |
| %v1.1 = select i1 %cmp2, float %v1, float %x |
| %phi.to.remove.next = select i1 %cmp2, float %same.as.v1, float %x |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; The difference from select_with_identical_phi_2() is that not all phis are sorted with |
| ; the same order of incoming BBs. |
| ; Check that %same.as.v1 can be folded. |
| define void @select_with_identical_phi_6(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_6( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ %phi.to.remove.next, %for.body ], [ 0xC415AF1D80000000, %entry ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove |
| %v1.1 = select i1 %cmp2, float %x, float %v1 |
| %phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; %v1 and %phi.to.remove do not have the same start value. |
| ; Cannot fold %same.as.v1. |
| define void @select_with_identical_phi_negative_1(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_negative_1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V1]], float [[PHI_TO_REMOVE]] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[X]], float [[SAME_AS_V1]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0x4415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove |
| %v1.1 = select i1 %cmp2, float %x, float %v1 |
| %phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; %v1 and %phi.to.remove do not act as the same phi since %v1.1 and %phi.to.remove.next do not evolve the same. |
| ; Cannot fold %same.as.v1. |
| define void @select_with_identical_phi_negative_2(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_negative_2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V1]], float [[PHI_TO_REMOVE]] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[V1]], float [[X:%.*]] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[X]], float [[SAME_AS_V1]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove |
| %v1.1 = select i1 %cmp2, float %v1, float %x |
| %phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; %v1 and %phi.to.remove do not act as the same phi since %v1.1 and %phi.to.remove.next do not |
| ; have the same condition. |
| ; Cannot fold %same.as.v1. |
| define void @select_with_identical_phi_negative_3(i1 %cmp1, i1 %cmp2, i1 %cmp3, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_negative_3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V1]], float [[PHI_TO_REMOVE]] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP3:%.*]], float [[V1]], float [[X:%.*]] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2:%.*]], float [[X]], float [[SAME_AS_V1]] |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove |
| %v1.1 = select i1 %cmp3, float %v1, float %x |
| %phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |
| |
| ; The true and false values of %same.as.v1 are not really the same phi. |
| ; Cannot fold %same.as.v1. |
| define void @select_with_identical_phi_negative_4(i1 %cmp1, i1 %cmp2, float %x) { |
| ; CHECK-LABEL: @select_with_identical_phi_negative_4( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V0]], float [[PHI_TO_REMOVE]] |
| ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]] |
| ; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[X]], float [[SAME_AS_V1]] |
| ; CHECK-NEXT: [[V0_1]] = fadd float [[V0]], 1.000000e+00 |
| ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %entry, %for.body |
| %v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ] |
| %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] |
| %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] |
| %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] |
| %same.as.v1 = select i1 %cmp1, float %v0, float %phi.to.remove |
| %v1.1 = select i1 %cmp2, float %x, float %v1 |
| %phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1 |
| %v0.1 = fadd float %v0, 1.0 |
| %inc.i = add nuw nsw i32 %i, 1 |
| %exitcond = icmp eq i32 %inc.i, 100 |
| br i1 %exitcond, label %exit, label %for.body |
| |
| exit: |
| %vl.1.lcssa = phi float [ %v1.1, %for.body ] |
| store float %vl.1.lcssa, ptr @A |
| ret void |
| } |