summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCInstrVSX.td
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2014-03-30 13:22:59 +0000
committerHal Finkel <hfinkel@anl.gov>2014-03-30 13:22:59 +0000
commitee8e48d4c9e834a05cea36bb83b2df6b718aaaa4 (patch)
tree4d9dea3fa5a39fab5f38b6bede3cd3e5fabcaf91 /lib/Target/PowerPC/PPCInstrVSX.td
parent368a97729890a878389a9995e426c1042947f37a (diff)
downloadllvm-ee8e48d4c9e834a05cea36bb83b2df6b718aaaa4.tar.gz
llvm-ee8e48d4c9e834a05cea36bb83b2df6b718aaaa4.tar.bz2
llvm-ee8e48d4c9e834a05cea36bb83b2df6b718aaaa4.tar.xz
[PowerPC] Handle VSX v2i64 SIGN_EXTEND_INREG
sitofp from v2i32 to v2f64 ends up generating a SIGN_EXTEND_INREG v2i64 node (and similarly for v2i16 and v2i8). Even though there are no sign-extension (or algebraic shifts) for v2i64 types, we can handle v2i32 sign extensions by converting two and from v2i64. The small trick necessary here is to shift the i32 elements into the right lanes before the i32 -> f64 step. This is because of the big Endian nature of the system, we need the i32 portion in the high word of the i64 elements. For v2i16 and v2i8 we can do the same, but we first use the default Altivec shift-based expansion from v2i16 or v2i8 to v2i32 (by casting to v4i32) and then apply the above procedure. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205146 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/PowerPC/PPCInstrVSX.td')
-rw-r--r--lib/Target/PowerPC/PPCInstrVSX.td12
1 files changed, 12 insertions, 0 deletions
diff --git a/lib/Target/PowerPC/PPCInstrVSX.td b/lib/Target/PowerPC/PPCInstrVSX.td
index 9fdfacfb0e..baf07cbe7b 100644
--- a/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/lib/Target/PowerPC/PPCInstrVSX.td
@@ -791,6 +791,18 @@ def : Pat<(v2f64 (bitconvert v2i64:$A)),
def : Pat<(v2i64 (bitconvert v2f64:$A)),
(COPY_TO_REGCLASS $A, VRRC)>;
+// sign extension patterns
+// To extend "in place" from v2i32 to v2i64, we have input data like:
+// | undef | i32 | undef | i32 |
+// but xvcvsxwdp expects the input in big-Endian format:
+// | i32 | undef | i32 | undef |
+// so we need to shift everything to the left by one i32 (word) before
+// the conversion.
+def : Pat<(sext_inreg v2i64:$C, v2i32),
+ (XVCVDPSXDS (XVCVSXWDP (XXSLDWI $C, $C, 1)))>;
+def : Pat<(v2f64 (sint_to_fp (sext_inreg v2i64:$C, v2i32))),
+ (XVCVSXWDP (XXSLDWI $C, $C, 1))>;
+
} // AddedComplexity
} // HasVSX