diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 736803c573e..1140edeaec0 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -1506,22 +1506,26 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
 
         let total_len = in_len as u64 * 2;
 
-        let vector = match args {
-            Some(args) => &args[2],
-            None => bcx.sess().span_bug(span,
-                                        "intrinsic call with unexpected argument shape"),
-        };
-        let vector = match consts::const_expr(bcx.ccx(), vector, substs, None,
-            consts::TrueConst::Yes, // this should probably help simd error reporting
-        ) {
-            Ok((vector, _)) => vector,
-            Err(err) => bcx.sess().span_fatal(span, &err.description()),
+        let (vector, indirect) = match args {
+            Some(args) => {
+                match consts::const_expr(bcx.ccx(), &args[2], substs, None,
+                                         // this should probably help simd error reporting
+                                         consts::TrueConst::Yes) {
+                    Ok((vector, _)) => (vector, false),
+                    Err(err) => bcx.sess().span_fatal(span, &err.description()),
+                }
+            }
+            None => (llargs[2], !type_is_immediate(bcx.ccx(), arg_tys[2]))
         };
 
         let indices: Option<Vec<_>> = (0..n)
             .map(|i| {
                 let arg_idx = i;
-                let val = const_get_elt(vector, &[i as libc::c_uint]);
+                let val = if indirect {
+                    Load(bcx, StructGEP(bcx, vector, i))
+                } else {
+                    const_get_elt(vector, &[i as libc::c_uint])
+                };
                 let c = const_to_opt_uint(val);
                 match c {
                     None => {