Skip to content

Commit 29dd7e0

Browse files
committed
trans: support simd_shuffle using MIR constants for indices.
1 parent 8679df8 commit 29dd7e0

File tree

5 files changed

+51
-45
lines changed

5 files changed

+51
-45
lines changed

src/librustc_trans/intrinsic.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -1482,28 +1482,23 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
14821482

14831483
let total_len = in_len as u64 * 2;
14841484

1485-
let (vector, indirect) = match args {
1485+
let vector = match args {
14861486
Some(args) => {
14871487
match consts::const_expr(bcx.ccx(), &args[2], substs, None,
14881488
// this should probably help simd error reporting
14891489
consts::TrueConst::Yes) {
1490-
Ok((vector, _)) => (vector, false),
1490+
Ok((vector, _)) => vector,
14911491
Err(err) => bcx.sess().span_fatal(span, &err.description()),
14921492
}
14931493
}
1494-
None => (llargs[2], !type_is_immediate(bcx.ccx(), arg_tys[2]))
1494+
None => llargs[2]
14951495
};
14961496

14971497
let indices: Option<Vec<_>> = (0..n)
14981498
.map(|i| {
14991499
let arg_idx = i;
1500-
let val = if indirect {
1501-
Load(bcx, StructGEP(bcx, vector, i))
1502-
} else {
1503-
const_get_elt(vector, &[i as libc::c_uint])
1504-
};
1505-
let c = const_to_opt_uint(val);
1506-
match c {
1500+
let val = const_get_elt(vector, &[i as libc::c_uint]);
1501+
match const_to_opt_uint(val) {
15071502
None => {
15081503
emit_error!("shuffle index #{} is not a constant", arg_idx);
15091504
None

src/librustc_trans/mir/block.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use glue;
2626
use type_::Type;
2727

2828
use super::{MirContext, TempRef, drop};
29+
use super::constant::Const;
2930
use super::lvalue::{LvalueRef, load_fat_ptr};
3031
use super::operand::OperandRef;
3132
use super::operand::OperandValue::{self, FatPtr, Immediate, Ref};
@@ -114,16 +115,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
114115
let discr = bcx.with_block(|bcx| base::to_immediate(bcx, discr, switch_ty));
115116
let switch = bcx.switch(discr, self.llblock(*otherwise), values.len());
116117
for (value, target) in values.iter().zip(targets) {
117-
let constant = mir::Constant {
118-
literal: mir::Literal::Value {
119-
value: value.clone()
120-
},
121-
ty: switch_ty,
122-
span: terminator.span
123-
};
124-
let val = self.trans_constant(&bcx, &constant).immediate();
118+
let val = Const::from_constval(bcx.ccx(), value.clone(), switch_ty);
125119
let llbb = self.llblock(*target);
126-
build::AddCase(switch, val, llbb)
120+
build::AddCase(switch, val.llval, llbb)
127121
}
128122
}
129123

@@ -247,8 +241,30 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
247241
(&args[..], None)
248242
};
249243

244+
let is_shuffle = intrinsic.map_or(false, |name| {
245+
name.starts_with("simd_shuffle")
246+
});
250247
let mut idx = 0;
251248
for arg in first_args {
249+
// The indices passed to simd_shuffle* in the
250+
// third argument must be constant. This is
251+
// checked by const-qualification, which also
252+
// promotes any complex rvalues to constants.
253+
if is_shuffle && idx == 2 {
254+
match *arg {
255+
mir::Operand::Consume(_) => {
256+
span_bug!(terminator.span,
257+
"shuffle indices must be constant");
258+
}
259+
mir::Operand::Constant(ref constant) => {
260+
let val = self.trans_constant(&bcx, constant);
261+
llargs.push(val.llval);
262+
idx += 1;
263+
continue;
264+
}
265+
}
266+
}
267+
252268
let val = self.trans_operand(&bcx, arg).val;
253269
self.trans_argument(&bcx, val, &mut llargs, &fn_ty,
254270
&mut idx, &mut callee.data);

src/librustc_trans/mir/constant.rs

+12-23
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,24 @@ use super::MirContext;
4141
/// The LLVM type might not be the same for a single Rust type,
4242
/// e.g. each enum variant would have its own LLVM struct type.
4343
#[derive(Copy, Clone)]
44-
struct Const<'tcx> {
45-
llval: ValueRef,
46-
ty: Ty<'tcx>
44+
pub struct Const<'tcx> {
45+
pub llval: ValueRef,
46+
pub ty: Ty<'tcx>
4747
}
4848

4949
impl<'tcx> Const<'tcx> {
50-
fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
50+
pub fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
5151
Const {
5252
llval: llval,
5353
ty: ty
5454
}
5555
}
5656

5757
/// Translate ConstVal into a LLVM constant value.
58-
fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
59-
cv: ConstVal,
60-
ty: Ty<'tcx>)
61-
-> Const<'tcx> {
58+
pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
59+
cv: ConstVal,
60+
ty: Ty<'tcx>)
61+
-> Const<'tcx> {
6262
let llty = type_of::type_of(ccx, ty);
6363
let val = match cv {
6464
ConstVal::Float(v) => C_floating_f64(v, llty),
@@ -110,7 +110,7 @@ impl<'tcx> Const<'tcx> {
110110
}
111111
}
112112

113-
fn to_operand<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
113+
pub fn to_operand<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
114114
let llty = type_of::immediate_type_of(ccx, self.ty);
115115
let llvalty = val_ty(self.llval);
116116

@@ -799,7 +799,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
799799
pub fn trans_constant(&mut self,
800800
bcx: &BlockAndBuilder<'bcx, 'tcx>,
801801
constant: &mir::Constant<'tcx>)
802-
-> OperandRef<'tcx>
802+
-> Const<'tcx>
803803
{
804804
let ty = bcx.monomorphize(&constant.ty);
805805
let result = match constant.literal.clone() {
@@ -808,10 +808,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
808808
// types, which would not work with MirConstContext.
809809
if common::type_is_zero_size(bcx.ccx(), ty) {
810810
let llty = type_of::type_of(bcx.ccx(), ty);
811-
return OperandRef {
812-
val: OperandValue::Immediate(C_null(llty)),
813-
ty: ty
814-
};
811+
return Const::new(C_null(llty), ty);
815812
}
816813

817814
let substs = bcx.tcx().mk_substs(bcx.monomorphize(substs));
@@ -827,7 +824,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
827824
}
828825
};
829826

830-
let val = match result {
827+
match result {
831828
Ok(v) => v,
832829
Err(ConstEvalFailure::Compiletime(_)) => {
833830
// We've errored, so we don't have to produce working code.
@@ -839,14 +836,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
839836
"MIR constant {:?} results in runtime panic: {}",
840837
constant, err.description())
841838
}
842-
};
843-
844-
let operand = val.to_operand(bcx.ccx());
845-
if let OperandValue::Ref(ptr) = operand.val {
846-
// If this is a OperandValue::Ref to an immediate constant, load it.
847-
self.trans_load(bcx, ptr, operand.ty)
848-
} else {
849-
operand
850839
}
851840
}
852841
}

src/librustc_trans/mir/operand.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
140140
}
141141

142142
mir::Operand::Constant(ref constant) => {
143-
self.trans_constant(bcx, constant)
143+
let val = self.trans_constant(bcx, constant);
144+
let operand = val.to_operand(bcx.ccx());
145+
if let OperandValue::Ref(ptr) = operand.val {
146+
// If this is a OperandValue::Ref to an immediate constant, load it.
147+
self.trans_load(bcx, ptr, operand.ty)
148+
} else {
149+
operand
150+
}
144151
}
145152
}
146153
}

src/test/run-pass/simd-intrinsic-generic-elements.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#![feature(repr_simd, rustc_attrs, platform_intrinsics)]
11+
#![feature(repr_simd, platform_intrinsics)]
1212

1313
// ignore-pretty : (#23623) problems when ending with // comments
1414

@@ -52,7 +52,6 @@ macro_rules! all_eq {
5252
}}
5353
}
5454

55-
#[rustc_no_mir] // FIXME #27840 MIR doesn't handle shuffle constants.
5655
fn main() {
5756
let x2 = i32x2(20, 21);
5857
let x3 = i32x3(30, 31, 32);

0 commit comments

Comments
 (0)