; Pin: W65816SplitLoopExits gives a critical edge out of a loop into a ; block with PHIs a block of its own, so PHI elimination's copies run once ; per exit instead of on every trip. LLVM does that split in PHI ; elimination only through MachineBasicBlock::SplitCriticalEdge, which ; needs analyzeBranch to understand the conditional branch -- this target ; keeps conditional branches opaque. A search loop's two exits (found: ; return p; end of list: return NULL) copied p into the return value's ; words and zero into them on every trip (CoreMark's core_list_find: ; -27% with the copies gone). ; ; RUN: llc -mtriple=w65816 -O2 -print-after=w65816-split-loop-exits -o /dev/null < %s 2>&1 | FileCheck %s --check-prefix=IR ; RUN: llc -mtriple=w65816 -O2 < %s | FileCheck %s target datalayout = "e-m:e-p:32:16-i16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16" %struct.node = type { ptr, ptr } ; IR-LABEL: define {{.*}}@find( ; IR: br i1 %cmp.not, label %land.rhs.while.end_crit_edge, label %while.body ; IR: land.rhs.while.end_crit_edge: ; IR-NEXT: br label %while.end ; IR: br i1 %tobool.not, label %while.body.while.end_crit_edge, label %land.rhs ; IR: while.body.while.end_crit_edge: ; IR-NEXT: br label %while.end ; IR: %r = phi ptr [ null, %entry ], [ %list.addr.05, %land.rhs.while.end_crit_edge ], [ null, %while.body.while.end_crit_edge ] ; The loop keeps neither the return value's copy of p nor its zero; the ; copies sit in the exit blocks. ; CHECK-LABEL: find: ; CHECK: Loop Header ; CHECK-NOT: lda #0x0 ; CHECK: bne .LBB0_[[LOOP:[0-9]+]] ; CHECK-NEXT: ; %bb.{{[0-9]+}}: ; %while.body.while.end_crit_edge ; CHECK-NEXT: lda #0x0 define ptr @find(ptr %list, i16 %want) { entry: %tobool.not4 = icmp eq ptr %list, null br i1 %tobool.not4, label %while.end, label %land.rhs land.rhs: %list.addr.05 = phi ptr [ %next, %while.body ], [ %list, %entry ] %info = getelementptr inbounds nuw i8, ptr %list.addr.05, i32 4 %0 = load ptr, ptr %info, align 2 %idx = getelementptr inbounds nuw i8, ptr %0, i32 2 %1 = load i16, ptr %idx, align 2 %cmp.not = icmp eq i16 %1, %want br i1 %cmp.not, label %while.end, label %while.body while.body: %next = load ptr, ptr %list.addr.05, align 2 %tobool.not = icmp eq ptr %next, null br i1 %tobool.not, label %while.end, label %land.rhs while.end: %r = phi ptr [ null, %entry ], [ null, %while.body ], [ %list.addr.05, %land.rhs ] ret ptr %r } ; A running total leaves the loop as the value the loop carries: that ; copy coalesces into the loop's own register wherever it sits, so the ; edge stays as it is (splitting it cost sumOfSquares a store a trip). ; IR-LABEL: define {{.*}}@total( ; IR-NOT: crit_edge ; IR: ret i32 define i32 @total(i16 %n) { entry: %z = icmp eq i16 %n, 0 br i1 %z, label %done, label %loop loop: %i = phi i16 [ 1, %entry ], [ %i1, %loop ] %t = phi i32 [ 0, %entry ], [ %t1, %loop ] %w = zext i16 %i to i32 %sq = mul nuw i32 %w, %w %t1 = add i32 %t, %sq %i1 = add i16 %i, 1 %c = icmp ugt i16 %i1, %n br i1 %c, label %done, label %loop done: %r = phi i32 [ 0, %entry ], [ %t1, %loop ] ret i32 %r }