Skip to content

Commit 14c3492

Browse files
committed
Move the loop of Rvalue::Repeat codegen out of cg_ssa
This way a codegen backend doesn't need to provide a phi instruction, which codegen backends other than LLVMmay not support easily, because they for example, like cranelift, use basic block parameters.
1 parent a0713cc commit 14c3492

File tree

4 files changed

+65
-53
lines changed

4 files changed

+65
-53
lines changed

src/librustc_codegen_llvm/builder.rs

+53-21
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,38 @@ impl MemoryBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
395395
self.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None);
396396
}
397397

398+
fn write_operand_repeatedly(
399+
mut self,
400+
cg_elem: OperandRef<'tcx, &'ll Value>,
401+
count: u64,
402+
dest: PlaceRef<'tcx, &'ll Value>,
403+
) -> Self {
404+
let zero = self.const_usize(0);
405+
let count = self.const_usize(count);
406+
let start = dest.project_index(&mut self, zero).llval;
407+
let end = dest.project_index(&mut self, count).llval;
408+
409+
let mut header_bx = self.build_sibling_block("repeat_loop_header");
410+
let mut body_bx = self.build_sibling_block("repeat_loop_body");
411+
let next_bx = self.build_sibling_block("repeat_loop_next");
412+
413+
self.br(header_bx.llbb());
414+
let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]);
415+
416+
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
417+
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
418+
419+
let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
420+
cg_elem.val.store(&mut body_bx,
421+
PlaceRef::new_sized(current, cg_elem.layout, align));
422+
423+
let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]);
424+
body_bx.br(header_bx.llbb());
425+
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
426+
427+
next_bx
428+
}
429+
398430
fn atomic_load(
399431
&mut self,
400432
ptr: &'ll Value,
@@ -994,20 +1026,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
9941026
}
9951027

9961028
/* Miscellaneous instructions */
997-
fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
998-
self.count_insn("addincoming");
999-
assert_eq!(vals.len(), bbs.len());
1000-
let phi = unsafe {
1001-
llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
1002-
};
1003-
unsafe {
1004-
llvm::LLVMAddIncoming(phi, vals.as_ptr(),
1005-
bbs.as_ptr(),
1006-
vals.len() as c_uint);
1007-
phi
1008-
}
1009-
}
1010-
10111029
fn inline_asm_call(&mut self, asm: &CStr, cons: &CStr,
10121030
inputs: &[&'ll Value], output: &'ll Type,
10131031
volatile: bool, alignstack: bool,
@@ -1197,13 +1215,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11971215
}
11981216
}
11991217

1200-
fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
1201-
self.count_insn("addincoming");
1202-
unsafe {
1203-
llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
1204-
}
1205-
}
1206-
12071218
fn set_invariant_load(&mut self, load: &'ll Value) {
12081219
unsafe {
12091220
llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
@@ -1518,4 +1529,25 @@ impl Builder<'a, 'll, 'tcx> {
15181529
let ptr = self.pointercast(ptr, self.cx.type_i8p());
15191530
self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
15201531
}
1532+
1533+
fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
1534+
self.count_insn("addincoming");
1535+
assert_eq!(vals.len(), bbs.len());
1536+
let phi = unsafe {
1537+
llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
1538+
};
1539+
unsafe {
1540+
llvm::LLVMAddIncoming(phi, vals.as_ptr(),
1541+
bbs.as_ptr(),
1542+
vals.len() as c_uint);
1543+
phi
1544+
}
1545+
}
1546+
1547+
fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
1548+
self.count_insn("addincoming");
1549+
unsafe {
1550+
llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
1551+
}
1552+
}
15211553
}

src/librustc_codegen_ssa/mir/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
335335
}
336336
}
337337

338-
pub fn project_index<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
338+
pub fn project_index<Bx: MemoryBuilderMethods<'tcx, Value = V>>(
339339
&self,
340340
bx: &mut Bx,
341341
llindex: V

src/librustc_codegen_ssa/mir/rvalue.rs

+3-24
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
8787
if dest.layout.is_zst() {
8888
return bx;
8989
}
90-
let zero = bx.const_usize(0);
91-
let start = dest.project_index(&mut bx, zero).llval;
9290

9391
if let OperandValue::Immediate(v) = cg_elem.val {
92+
let zero = bx.const_usize(0);
93+
let start = dest.project_index(&mut bx, zero).llval;
9494
let size = bx.const_usize(dest.layout.size.bytes());
9595

9696
// Use llvm.memset.p0i8.* to initialize all zero arrays
@@ -108,28 +108,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
108108
}
109109
}
110110

111-
let count = bx.const_usize(count);
112-
let end = dest.project_index(&mut bx, count).llval;
113-
114-
let mut header_bx = bx.build_sibling_block("repeat_loop_header");
115-
let mut body_bx = bx.build_sibling_block("repeat_loop_body");
116-
let next_bx = bx.build_sibling_block("repeat_loop_next");
117-
118-
bx.br(header_bx.llbb());
119-
let current = header_bx.phi(bx.val_ty(start), &[start], &[bx.llbb()]);
120-
121-
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
122-
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
123-
124-
let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size);
125-
cg_elem.val.store(&mut body_bx,
126-
PlaceRef::new_sized(current, cg_elem.layout, align));
127-
128-
let next = body_bx.inbounds_gep(current, &[bx.const_usize(1)]);
129-
body_bx.br(header_bx.llbb());
130-
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
131-
132-
next_bx
111+
bx.write_operand_repeatedly(cg_elem, count, dest)
133112
}
134113

135114
mir::Rvalue::Aggregate(ref kind, ref operands) => {

src/librustc_codegen_ssa/traits/builder.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ pub trait MemoryBuilderMethods<'tcx>: HasCodegen<'tcx> {
8989
flags: MemFlags,
9090
);
9191

92+
/// Called for Rvalue::Repeat when the elem is neither a ZST nor optimizable using memset.
93+
fn write_operand_repeatedly(
94+
self,
95+
elem: OperandRef<'tcx, Self::Value>,
96+
count: u64,
97+
dest: PlaceRef<'tcx, Self::Value>,
98+
) -> Self;
99+
92100
// Atomics
93101
fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value;
94102
fn atomic_store(
@@ -218,12 +226,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
218226
) -> Self::Value;
219227
fn unreachable(&mut self);
220228

221-
fn phi(
222-
&mut self,
223-
ty: Self::Type,
224-
vals: &[Self::Value],
225-
bbs: &[Self::BasicBlock],
226-
) -> Self::Value;
227229
fn inline_asm_call(
228230
&mut self,
229231
asm: &CStr,
@@ -273,7 +275,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
273275
fn set_personality_fn(&mut self, personality: Self::Value);
274276

275277
fn add_case(&mut self, s: Self::Value, on_val: Self::Value, dest: Self::BasicBlock);
276-
fn add_incoming_to_phi(&mut self, phi: Self::Value, val: Self::Value, bb: Self::BasicBlock);
277278
fn set_invariant_load(&mut self, load: Self::Value);
278279

279280
/// Called for `StorageLive`

0 commit comments

Comments
 (0)