|  | 
|  | 1 | +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | 
|  | 2 | +; RUN: opt < %s -S -passes=instcombine | FileCheck %s | 
|  | 3 | +@A = extern_weak global float, align 4 | 
|  | 4 | + | 
|  | 5 | +; %phi.to.remove acts the same as %v1, and can be eliminated with PHI CSE. | 
|  | 6 | +define void @enhanced_phi_cse(ptr %m, ptr %n, i32 %count) { | 
|  | 7 | +; CHECK-LABEL: @enhanced_phi_cse( | 
|  | 8 | +; CHECK-NEXT:  entry: | 
|  | 9 | +; CHECK-NEXT:    br label [[FOR_BODY:%.*]] | 
|  | 10 | +; CHECK:       for.body: | 
|  | 11 | +; CHECK-NEXT:    [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ] | 
|  | 12 | +; CHECK-NEXT:    [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ] | 
|  | 13 | +; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ] | 
|  | 14 | +; CHECK-NEXT:    [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ] | 
|  | 15 | +; CHECK-NEXT:    [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ] | 
|  | 16 | +; CHECK-NEXT:    [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4 | 
|  | 17 | +; CHECK-NEXT:    [[C_LOAD:%.*]] = load float, ptr [[C]], align 4 | 
|  | 18 | +; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]] | 
|  | 19 | +; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]] | 
|  | 20 | +; CHECK-NEXT:    [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]] | 
|  | 21 | +; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]] | 
|  | 22 | +; CHECK-NEXT:    [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]] | 
|  | 23 | +; CHECK-NEXT:    [[INC_I]] = add nuw nsw i32 [[I]], 1 | 
|  | 24 | +; CHECK-NEXT:    [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4 | 
|  | 25 | +; CHECK-NEXT:    [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4 | 
|  | 26 | +; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]] | 
|  | 27 | +; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]] | 
|  | 28 | +; CHECK:       exit: | 
|  | 29 | +; CHECK-NEXT:    store float [[V1_1]], ptr @A, align 4 | 
|  | 30 | +; CHECK-NEXT:    ret void | 
|  | 31 | +; | 
|  | 32 | +entry: | 
|  | 33 | +  br label %for.body | 
|  | 34 | + | 
|  | 35 | +for.body:                                    ; preds = %entry, %for.body | 
|  | 36 | +  %v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ] | 
|  | 37 | +  %v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ] | 
|  | 38 | +  %phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ] | 
|  | 39 | +  %i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ] | 
|  | 40 | +  %q = phi ptr [ %m, %entry ], [ %q.next, %for.body ] | 
|  | 41 | +  %c = phi ptr [ %n, %entry ], [ %c.next, %for.body ] | 
|  | 42 | +  %q.load = load float, ptr %q | 
|  | 43 | +  %c.load = load float, ptr %c | 
|  | 44 | +  %sub = fsub float %q.load, %c.load | 
|  | 45 | +  %cmp1 = fcmp olt float %sub, %v0 | 
|  | 46 | +  %v0.1 = select i1 %cmp1, float %sub, float %v0 | 
|  | 47 | +  %same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove | 
|  | 48 | +  %cmp2 = fcmp ogt float  %sub, %same.as.v1 | 
|  | 49 | +  %v1.1 = select i1 %cmp2, float %sub, float %v1 | 
|  | 50 | +  %phi.to.remove.next = select i1 %cmp2, float %sub, float %same.as.v1 | 
|  | 51 | +  %inc.i = add nuw nsw i32 %i, 1 | 
|  | 52 | +  %q.next = getelementptr inbounds i8, ptr %q, i64 4 | 
|  | 53 | +  %c.next = getelementptr inbounds i8, ptr %c, i64 4 | 
|  | 54 | +  %exitcond = icmp eq i32 %inc.i, %count | 
|  | 55 | +  br i1 %exitcond, label %exit, label %for.body | 
|  | 56 | + | 
|  | 57 | +exit: | 
|  | 58 | +  %vl.1.lcssa = phi float [ %v1.1, %for.body ] | 
|  | 59 | +  store float %vl.1.lcssa, ptr @A | 
|  | 60 | +  ret void | 
|  | 61 | +} | 
0 commit comments