Skip to content

Instantly share code, notes, and snippets.

@bluss
Created October 22, 2016 17:15
Show Gist options
  • Save bluss/f4a203aa86fbb041e4f6ee61b712bee1 to your computer and use it in GitHub Desktop.
Save bluss/f4a203aa86fbb041e4f6ee61b712bee1 to your computer and use it in GitHub Desktop.
; ModuleID = 'chain_more_codegen.cgu-0.rs'
source_filename = "chain_more_codegen.cgu-0.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
%"8.unwind::libunwind::_Unwind_Exception" = type { i64, void (i32, %"8.unwind::libunwind::_Unwind_Exception"*)*, [6 x i64] }
%"8.unwind::libunwind::_Unwind_Context" = type {}
; Function Attrs: uwtable
define i64 @range_chain_default_fold(i64, i64, i64 (i64, i64)* nocapture) unnamed_addr #0 personality i32 (i32, i32, i64, %"8.unwind::libunwind::_Unwind_Exception"*, %"8.unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
entry-block:
br label %bb6.i
bb6.i: ; preds = %bb11.i, %entry-block
%iter.sroa.9.0.i = phi i64 [ 0, %entry-block ], [ %iter.sroa.9.3.ph.i, %bb11.i ]
%iter.sroa.15.0.i = phi i8 [ 0, %entry-block ], [ %iter.sroa.15.1.ph.i, %bb11.i ]
%iter.sroa.0.0.i = phi i64 [ 0, %entry-block ], [ %iter.sroa.0.2.ph.i, %bb11.i ]
%accum.0.i = phi i64 [ 0, %entry-block ], [ %11, %bb11.i ]
%trunc.i.i = trunc i8 %iter.sroa.15.0.i to i2
switch i2 %trunc.i.i, label %unreachable.i.i [
i2 0, label %bb1.i.i
i2 1, label %bb2.i.i
i2 -2, label %bb3.i.i
]
bb1.i.i: ; preds = %bb6.i
%3 = icmp ult i64 %iter.sroa.0.0.i, %0
br i1 %3, label %bb9.i.i, label %bb8.i.i
bb2.i.i: ; preds = %bb6.i
%4 = icmp ult i64 %iter.sroa.0.0.i, %0
br i1 %4, label %bb2.i21.i.i, label %_ZN4core4iter8iterator8Iterator4fold17h2dd9e388c2016361E.exit
bb2.i21.i.i: ; preds = %bb2.i.i
%5 = add i64 %iter.sroa.0.0.i, 1
br label %bb11.i
bb3.i.i: ; preds = %bb6.i
%6 = icmp ult i64 %iter.sroa.9.0.i, %1
br i1 %6, label %bb2.i16.i.i, label %_ZN4core4iter8iterator8Iterator4fold17h2dd9e388c2016361E.exit
bb2.i16.i.i: ; preds = %bb3.i.i
%7 = add i64 %iter.sroa.9.0.i, 1
br label %bb11.i
bb8.i.i: ; preds = %bb1.i.i
%8 = icmp ult i64 %iter.sroa.9.0.i, %1
br i1 %8, label %bb2.i11.i.i, label %_ZN4core4iter8iterator8Iterator4fold17h2dd9e388c2016361E.exit
bb2.i11.i.i: ; preds = %bb8.i.i
%9 = add i64 %iter.sroa.9.0.i, 1
br label %bb11.i
bb9.i.i: ; preds = %bb1.i.i
%10 = add i64 %iter.sroa.0.0.i, 1
br label %bb11.i
unreachable.i.i: ; preds = %bb6.i
unreachable
bb11.i: ; preds = %bb9.i.i, %bb2.i11.i.i, %bb2.i16.i.i, %bb2.i21.i.i
%iter.sroa.9.3.ph.i = phi i64 [ %9, %bb2.i11.i.i ], [ %7, %bb2.i16.i.i ], [ %iter.sroa.9.0.i, %bb2.i21.i.i ], [ %iter.sroa.9.0.i, %bb9.i.i ]
%iter.sroa.15.1.ph.i = phi i8 [ 2, %bb2.i11.i.i ], [ %iter.sroa.15.0.i, %bb2.i16.i.i ], [ %iter.sroa.15.0.i, %bb2.i21.i.i ], [ %iter.sroa.15.0.i, %bb9.i.i ]
%iter.sroa.0.2.ph.i = phi i64 [ %iter.sroa.0.0.i, %bb2.i11.i.i ], [ %iter.sroa.0.0.i, %bb2.i16.i.i ], [ %5, %bb2.i21.i.i ], [ %10, %bb9.i.i ]
%_15.sroa.8.4.ph.i = phi i64 [ %iter.sroa.9.0.i, %bb2.i11.i.i ], [ %iter.sroa.9.0.i, %bb2.i16.i.i ], [ %iter.sroa.0.0.i, %bb2.i21.i.i ], [ %iter.sroa.0.0.i, %bb9.i.i ]
%11 = tail call i64 %2(i64 %accum.0.i, i64 %_15.sroa.8.4.ph.i), !noalias !0
br label %bb6.i
_ZN4core4iter8iterator8Iterator4fold17h2dd9e388c2016361E.exit: ; preds = %bb2.i.i, %bb3.i.i, %bb8.i.i
ret i64 %accum.0.i
}
; Function Attrs: uwtable
define i64 @range_chain_custom_fold(i64, i64, i64 (i64, i64)* nocapture) unnamed_addr #0 personality i32 (i32, i32, i64, %"8.unwind::libunwind::_Unwind_Exception"*, %"8.unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
bb5.i:
%3 = icmp eq i64 %0, 0
br i1 %3, label %bb8.i, label %bb11.i.i.preheader
bb11.i.i.preheader: ; preds = %bb5.i
br label %bb11.i.i
bb11.i.i: ; preds = %bb11.i.i.preheader, %bb11.i.i
%accum.012.i.i = phi i64 [ %5, %bb11.i.i ], [ 0, %bb11.i.i.preheader ]
%iter.sroa.0.011.i.i = phi i64 [ %4, %bb11.i.i ], [ 0, %bb11.i.i.preheader ]
%4 = add nuw i64 %iter.sroa.0.011.i.i, 1
%5 = tail call i64 %2(i64 %accum.012.i.i, i64 %iter.sroa.0.011.i.i), !noalias !3
%exitcond.i.i = icmp eq i64 %4, %0
br i1 %exitcond.i.i, label %bb8.i.loopexit, label %bb11.i.i
bb8.i.loopexit: ; preds = %bb11.i.i
br label %bb8.i
bb8.i: ; preds = %bb8.i.loopexit, %bb5.i
%accum.0.i = phi i64 [ 0, %bb5.i ], [ %5, %bb8.i.loopexit ]
%6 = icmp eq i64 %1, 0
br i1 %6, label %_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E.exit, label %bb11.i7.i.preheader
bb11.i7.i.preheader: ; preds = %bb8.i
br label %bb11.i7.i
bb11.i7.i: ; preds = %bb11.i7.i.preheader, %bb11.i7.i
%accum.012.i3.i = phi i64 [ %8, %bb11.i7.i ], [ %accum.0.i, %bb11.i7.i.preheader ]
%iter.sroa.0.011.i4.i = phi i64 [ %7, %bb11.i7.i ], [ 0, %bb11.i7.i.preheader ]
%7 = add nuw i64 %iter.sroa.0.011.i4.i, 1
%8 = tail call i64 %2(i64 %accum.012.i3.i, i64 %iter.sroa.0.011.i4.i), !noalias !3
%exitcond.i6.i = icmp eq i64 %7, %1
br i1 %exitcond.i6.i, label %_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E.exit.loopexit, label %bb11.i7.i
_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E.exit.loopexit: ; preds = %bb11.i7.i
br label %_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E.exit
_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E.exit: ; preds = %_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E.exit.loopexit, %bb8.i
%accum.1.i = phi i64 [ %accum.0.i, %bb8.i ], [ %8, %_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E.exit.loopexit ]
ret i64 %accum.1.i
}
; Function Attrs: nounwind
declare i32 @rust_eh_personality(i32, i32, i64, %"8.unwind::libunwind::_Unwind_Exception"*, %"8.unwind::libunwind::_Unwind_Context"*) unnamed_addr #1
attributes #0 = { uwtable }
attributes #1 = { nounwind }
!0 = !{!1}
!1 = distinct !{!1, !2, !"_ZN4core4iter8iterator8Iterator4fold17h2dd9e388c2016361E: argument 0"}
!2 = distinct !{!2, !"_ZN4core4iter8iterator8Iterator4fold17h2dd9e388c2016361E"}
!3 = !{!4}
!4 = distinct !{!4, !5, !"_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E: argument 0"}
!5 = distinct !{!5, !"_ZN18chain_more_codegen4fold17h9ac2aaed4568fdf9E"}
#![crate_type="lib"]
#[no_mangle]
pub fn range_chain_default_fold(xs: usize, ys: usize, f: fn(usize, usize) -> usize) -> usize {
chain(0..xs, 0..ys).fold(0, f)
}
#[no_mangle]
pub fn range_chain_custom_fold(xs: usize, ys: usize, f: fn(usize, usize) -> usize) -> usize {
fold(chain(0..xs, 0..ys), 0, f)
}
pub struct Chain<A, B> {
a: A,
b: B,
state: ChainState,
}
fn chain<A, B>(a: A, b: B) -> Chain<A::IntoIter, B::IntoIter>
where A: IntoIterator, B: IntoIterator<Item=A::Item>,
{
Chain {
a: a.into_iter(),
b: b.into_iter(),
state: ChainState::Both,
}
}
// The iterator protocol specifies that iteration ends with the return value
// `None` from `.next()` (or `.next_back()`) and it is unspecified what
// further calls return. The chain adaptor must account for this since it uses
// two subiterators.
//
// It uses three states:
//
// - Both: `a` and `b` are remaining
// - Front: `a` remaining
// - Back: `b` remaining
//
// The fourth state (neither iterator is remaining) only occurs after Chain has
// returned None once, so we don't need to store this state.
enum ChainState {
// both front and back iterator are remaining
Both,
// only front is remaining
Front,
// only back is remaining
Back,
}
impl<A, B> Iterator for Chain<A, B> where
A: Iterator,
B: Iterator<Item = A::Item>
{
type Item = A::Item;
#[inline]
fn next(&mut self) -> Option<A::Item> {
match self.state {
ChainState::Both => match self.a.next() {
elt @ Some(..) => elt,
None => {
self.state = ChainState::Back;
self.b.next()
}
},
ChainState::Front => self.a.next(),
ChainState::Back => self.b.next(),
}
}
}
fn fold<A, B, Acc, F>(self_: Chain<A, B>, init: Acc, mut f: F) -> Acc
where F: FnMut(Acc, A::Item) -> Acc,
A: Iterator,
B: Iterator<Item=A::Item>,
{
let mut accum = init;
match self_.state {
ChainState::Both | ChainState::Front => {
accum = self_.a.fold(accum, &mut f);
}
_ => { }
}
match self_.state {
ChainState::Both | ChainState::Back => {
accum = self_.b.fold(accum, &mut f);
}
_ => { }
}
accum
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment