Skip to content

Instantly share code, notes, and snippets.

@bluss
Created October 22, 2016 17:55
Show Gist options
  • Save bluss/3ba866cb973f95e156f446baa94b8d5e to your computer and use it in GitHub Desktop.
Save bluss/3ba866cb973f95e156f446baa94b8d5e to your computer and use it in GitHub Desktop.
; ModuleID = 'chain_two_calls_really.cgu-0.rs'
source_filename = "chain_two_calls_really.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 %bb2.outer
bb2.outer: ; preds = %bb13, %entry-block
%self_.sroa.0.0.ph = phi i64 [ %self_.sroa.0.0.ph3859, %bb13 ], [ 0, %entry-block ]
%self_.sroa.7.0.ph = phi i64 [ %8, %bb13 ], [ 0, %entry-block ]
%self_.sroa.12.0.ph = phi i8 [ %self_.sroa.12.0.lcssa, %bb13 ], [ 0, %entry-block ]
%accum.0.ph = phi i64 [ %9, %bb13 ], [ 0, %entry-block ]
%switch.us = icmp eq i8 %self_.sroa.12.0.ph, 0
%3 = icmp ult i64 %self_.sroa.0.0.ph, %0
br i1 %3, label %bb2.us.preheader, label %bb2.preheader
bb2.us.preheader: ; preds = %bb2.outer
br label %bb2.us
bb2.preheader.loopexit: ; preds = %bb9
br label %bb2.preheader
bb2.preheader: ; preds = %bb2.preheader.loopexit, %bb2.outer
%self_.sroa.0.0.ph38.lcssa = phi i64 [ %self_.sroa.0.0.ph, %bb2.outer ], [ %5, %bb2.preheader.loopexit ]
%accum.0.ph41.lcssa = phi i64 [ %accum.0.ph, %bb2.outer ], [ %6, %bb2.preheader.loopexit ]
br label %bb2
bb2.us: ; preds = %bb2.us.preheader, %bb9
%accum.0.ph4162 = phi i64 [ %6, %bb9 ], [ %accum.0.ph, %bb2.us.preheader ]
%self_.sroa.0.0.ph3861 = phi i64 [ %5, %bb9 ], [ %self_.sroa.0.0.ph, %bb2.us.preheader ]
br i1 %switch.us, label %bb9, label %bb4.loopexit64
bb2: ; preds = %bb2.preheader, %bb2
%self_.sroa.12.0 = phi i8 [ 2, %bb2 ], [ %self_.sroa.12.0.ph, %bb2.preheader ]
%switch = icmp eq i8 %self_.sroa.12.0, 0
br i1 %switch, label %bb2, label %bb4.loopexit
bb4.loopexit: ; preds = %bb2
br label %bb4
bb4.loopexit64: ; preds = %bb2.us
br label %bb4
bb4: ; preds = %bb4.loopexit64, %bb4.loopexit
%self_.sroa.0.0.ph3859 = phi i64 [ %self_.sroa.0.0.ph38.lcssa, %bb4.loopexit ], [ %self_.sroa.0.0.ph3861, %bb4.loopexit64 ]
%accum.0.ph4157 = phi i64 [ %accum.0.ph41.lcssa, %bb4.loopexit ], [ %accum.0.ph4162, %bb4.loopexit64 ]
%self_.sroa.12.0.lcssa = phi i8 [ %self_.sroa.12.0, %bb4.loopexit ], [ %self_.sroa.12.0.ph, %bb4.loopexit64 ]
%4 = icmp ult i64 %self_.sroa.7.0.ph, %1
br i1 %4, label %bb13, label %bb12
bb9: ; preds = %bb2.us
%5 = add i64 %self_.sroa.0.0.ph3861, 1
%6 = tail call i64 %2(i64 %accum.0.ph4162, i64 %self_.sroa.0.0.ph3861)
%7 = icmp ult i64 %5, %0
br i1 %7, label %bb2.us, label %bb2.preheader.loopexit
bb12: ; preds = %bb4
ret i64 %accum.0.ph4157
bb13: ; preds = %bb4
%8 = add i64 %self_.sroa.7.0.ph, 1
%9 = tail call i64 %2(i64 %accum.0.ph4157, i64 %self_.sroa.7.0.ph)
br label %bb2.outer
}
; 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 !0
%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 %_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E.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 !0
%exitcond.i6.i = icmp eq i64 %7, %1
br i1 %exitcond.i6.i, label %_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E.exit.loopexit, label %bb11.i7.i
_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E.exit.loopexit: ; preds = %bb11.i7.i
br label %_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E.exit
_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E.exit: ; preds = %_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E.exit.loopexit, %bb8.i
%accum.1.i = phi i64 [ %accum.0.i, %bb8.i ], [ %8, %_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E.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, !"_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E: argument 0"}
!2 = distinct !{!2, !"_ZN22chain_two_calls_really10chain_fold17h9f158a46f0620884E"}
#![crate_type="lib"]
#[no_mangle]
pub fn range_chain_default_fold(xs: usize, ys: usize, f: fn(usize, usize) -> usize) -> usize {
let mut accum = 0;
let mut self_ = chain(0..xs, 0..ys);
loop {
match self_.state {
ChainState::Both => match self_.a.next() {
Some(elt) => {
accum = f(accum, elt);
}
None => {
self_.state = ChainState::Back;
continue;
}
},
ChainState::Back => {
let value = self_.b.next();
match value {
Some(elt) => accum = f(accum, elt),
None => break,
}
}
ChainState::Front => unreachable!(),
};
}
accum
}
#[no_mangle]
pub fn range_chain_custom_fold(xs: usize, ys: usize, f: fn(usize, usize) -> usize) -> usize {
chain_fold(chain(0..xs, 0..ys), 0, f)
}
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 default_fold<I, Acc, F>(iter: I, init: Acc, mut f: F) -> Acc
where F: FnMut(Acc, I::Item) -> Acc,
I: Iterator,
{
let mut accum = init;
for element in iter {
accum = f(accum, element);
}
accum
}
fn chain_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
}
.text
.file "chain_two_calls_really.cgu-0.rs"
.section .text.range_chain_default_fold,"ax",@progbits
.globl range_chain_default_fold
.p2align 4, 0x90
.type range_chain_default_fold,@function
range_chain_default_fold:
.cfi_startproc
pushq %rbp
.Ltmp0:
.cfi_def_cfa_offset 16
pushq %r15
.Ltmp1:
.cfi_def_cfa_offset 24
pushq %r14
.Ltmp2:
.cfi_def_cfa_offset 32
pushq %r13
.Ltmp3:
.cfi_def_cfa_offset 40
pushq %r12
.Ltmp4:
.cfi_def_cfa_offset 48
pushq %rbx
.Ltmp5:
.cfi_def_cfa_offset 56
pushq %rax
.Ltmp6:
.cfi_def_cfa_offset 64
.Ltmp7:
.cfi_offset %rbx, -56
.Ltmp8:
.cfi_offset %r12, -48
.Ltmp9:
.cfi_offset %r13, -40
.Ltmp10:
.cfi_offset %r14, -32
.Ltmp11:
.cfi_offset %r15, -24
.Ltmp12:
.cfi_offset %rbp, -16
movq %rdx, %r15
movq %rsi, %r14
movq %rdi, %r12
xorl %ebx, %ebx
xorl %r13d, %r13d
xorl %ebp, %ebp
xorl %eax, %eax
jmp .LBB0_1
.p2align 4, 0x90
.LBB0_4:
movq %rax, %rdi
callq *%r15
.LBB0_1:
cmpq %r12, %rbx
jae .LBB0_5
testb %bpl, %bpl
jne .LBB0_7
movq %rbx, %rsi
incq %rbx
jmp .LBB0_4
.p2align 4, 0x90
.LBB0_5:
movl %ebp, %ecx
movb $2, %bpl
testb %cl, %cl
je .LBB0_5
movb %cl, %bpl
.LBB0_7:
cmpq %r14, %r13
jae .LBB0_8
movq %r13, %rsi
incq %r13
jmp .LBB0_4
.LBB0_8:
addq $8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
.Lfunc_end0:
.size range_chain_default_fold, .Lfunc_end0-range_chain_default_fold
.cfi_endproc
.section .text.range_chain_custom_fold,"ax",@progbits
.globl range_chain_custom_fold
.p2align 4, 0x90
.type range_chain_custom_fold,@function
range_chain_custom_fold:
.cfi_startproc
pushq %r15
.Ltmp13:
.cfi_def_cfa_offset 16
pushq %r14
.Ltmp14:
.cfi_def_cfa_offset 24
pushq %r12
.Ltmp15:
.cfi_def_cfa_offset 32
pushq %rbx
.Ltmp16:
.cfi_def_cfa_offset 40
pushq %rax
.Ltmp17:
.cfi_def_cfa_offset 48
.Ltmp18:
.cfi_offset %rbx, -40
.Ltmp19:
.cfi_offset %r12, -32
.Ltmp20:
.cfi_offset %r14, -24
.Ltmp21:
.cfi_offset %r15, -16
movq %rdx, %r12
movq %rsi, %r14
movq %rdi, %r15
xorl %eax, %eax
testq %r15, %r15
je .LBB1_3
xorl %eax, %eax
xorl %ebx, %ebx
.p2align 4, 0x90
.LBB1_2:
movq %rbx, %rsi
incq %rbx
movq %rax, %rdi
callq *%r12
cmpq %rbx, %r15
jne .LBB1_2
.LBB1_3:
testq %r14, %r14
je .LBB1_6
xorl %ebx, %ebx
.p2align 4, 0x90
.LBB1_5:
movq %rbx, %rsi
incq %rbx
movq %rax, %rdi
callq *%r12
cmpq %rbx, %r14
jne .LBB1_5
.LBB1_6:
addq $8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
.Lfunc_end1:
.size range_chain_custom_fold, .Lfunc_end1-range_chain_custom_fold
.cfi_endproc
.section ".note.GNU-stack","",@progbits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment