From 1ce1525ed453aea78d17f28ec3c353d0cde5341f Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 21 Sep 2013 20:36:04 +0000 Subject: [PATCH] SROA: Handle casts involving vectors of pointers and integer scalars. SROA wants to convert any types of equivalent widths but it's not possible to convert vectors of pointers to an integer scalar with a single cast. As a workaround we add a bitcast to the corresponding int ptr type first. This type of cast used to be an edge case but has become common with SLP vectorization. Fixes PR17271. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191143 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SROA.cpp | 58 ++++++++++++++++++----- test/Transforms/SROA/vector-conversion.ll | 53 +++++++++++++++++++++ 2 files changed, 100 insertions(+), 11 deletions(-) create mode 100644 test/Transforms/SROA/vector-conversion.ll diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index da441dc00a6..16464d9af82 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -1452,6 +1452,10 @@ static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy) { if (!NewTy->isSingleValueType() || !OldTy->isSingleValueType()) return false; + // We handle can convert pointers to integers and vice-versa. Same for vectors + // of pointers and integers. + OldTy = OldTy->getScalarType(); + NewTy = NewTy->getScalarType(); if (NewTy->isPointerTy() || OldTy->isPointerTy()) { if (NewTy->isPointerTy() && OldTy->isPointerTy()) return true; @@ -1470,21 +1474,53 @@ static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy) { /// inttoptr, and ptrtoint casts. Use the \c canConvertValue predicate to test /// two types for viability with this routine. static Value *convertValue(const DataLayout &DL, IRBuilderTy &IRB, Value *V, - Type *Ty) { - assert(canConvertValue(DL, V->getType(), Ty) && - "Value not convertable to type"); - if (V->getType() == Ty) + Type *NewTy) { + Type *OldTy = V->getType(); + assert(canConvertValue(DL, OldTy, NewTy) && "Value not convertable to type"); + + if (OldTy == NewTy) return V; - if (IntegerType *OldITy = dyn_cast(V->getType())) - if (IntegerType *NewITy = dyn_cast(Ty)) + + if (IntegerType *OldITy = dyn_cast(OldTy)) + if (IntegerType *NewITy = dyn_cast(NewTy)) if (NewITy->getBitWidth() > OldITy->getBitWidth()) return IRB.CreateZExt(V, NewITy); - if (V->getType()->isIntegerTy() && Ty->isPointerTy()) - return IRB.CreateIntToPtr(V, Ty); - if (V->getType()->isPointerTy() && Ty->isIntegerTy()) - return IRB.CreatePtrToInt(V, Ty); - return IRB.CreateBitCast(V, Ty); + // See if we need inttoptr for this type pair. A cast involving both scalars + // and vectors requires and additional bitcast. + if (OldTy->getScalarType()->isIntegerTy() && + NewTy->getScalarType()->isPointerTy()) { + // Expand <2 x i32> to i8* --> <2 x i32> to i64 to i8* + if (OldTy->isVectorTy() && !NewTy->isVectorTy()) + return IRB.CreateIntToPtr(IRB.CreateBitCast(V, DL.getIntPtrType(NewTy)), + NewTy); + + // Expand i128 to <2 x i8*> --> i128 to <2 x i64> to <2 x i8*> + if (!OldTy->isVectorTy() && NewTy->isVectorTy()) + return IRB.CreateIntToPtr(IRB.CreateBitCast(V, DL.getIntPtrType(NewTy)), + NewTy); + + return IRB.CreateIntToPtr(V, NewTy); + } + + // See if we need ptrtoint for this type pair. A cast involving both scalars + // and vectors requires and additional bitcast. + if (OldTy->getScalarType()->isPointerTy() && + NewTy->getScalarType()->isIntegerTy()) { + // Expand <2 x i8*> to i128 --> <2 x i8*> to <2 x i64> to i128 + if (OldTy->isVectorTy() && !NewTy->isVectorTy()) + return IRB.CreateBitCast(IRB.CreatePtrToInt(V, DL.getIntPtrType(OldTy)), + NewTy); + + // Expand i8* to <2 x i32> --> i8* to i64 to <2 x i32> + if (!OldTy->isVectorTy() && NewTy->isVectorTy()) + return IRB.CreateBitCast(IRB.CreatePtrToInt(V, DL.getIntPtrType(OldTy)), + NewTy); + + return IRB.CreatePtrToInt(V, NewTy); + } + + return IRB.CreateBitCast(V, NewTy); } /// \brief Test whether the given slice use can be promoted to a vector. diff --git a/test/Transforms/SROA/vector-conversion.ll b/test/Transforms/SROA/vector-conversion.ll new file mode 100644 index 00000000000..08d79608731 --- /dev/null +++ b/test/Transforms/SROA/vector-conversion.ll @@ -0,0 +1,53 @@ +; RUN: opt < %s -sroa -S | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64" + +define <4 x i64> @vector_ptrtoint({<2 x i32*>, <2 x i32*>} %x) { +; CHECK-LABEL: @vector_ptrtoint + %a = alloca {<2 x i32*>, <2 x i32*>} +; CHECK-NOT: alloca + + store {<2 x i32*>, <2 x i32*>} %x, {<2 x i32*>, <2 x i32*>}* %a +; CHECK-NOT: store + + %cast = bitcast {<2 x i32*>, <2 x i32*>}* %a to <4 x i64>* + %vec = load <4 x i64>* %cast +; CHECK-NOT: load +; CHECK: ptrtoint + + ret <4 x i64> %vec +} + +define <4 x i32*> @vector_inttoptr({<2 x i64>, <2 x i64>} %x) { +; CHECK-LABEL: @vector_inttoptr + %a = alloca {<2 x i64>, <2 x i64>} +; CHECK-NOT: alloca + + store {<2 x i64>, <2 x i64>} %x, {<2 x i64>, <2 x i64>}* %a +; CHECK-NOT: store + + %cast = bitcast {<2 x i64>, <2 x i64>}* %a to <4 x i32*>* + %vec = load <4 x i32*>* %cast +; CHECK-NOT: load +; CHECK: inttoptr + + ret <4 x i32*> %vec +} + +define <2 x i64> @vector_ptrtointbitcast({<1 x i32*>, <1 x i32*>} %x) { +; CHECK-LABEL: @vector_ptrtointbitcast + %a = alloca {<1 x i32*>, <1 x i32*>} +; CHECK-NOT: alloca + + store {<1 x i32*>, <1 x i32*>} %x, {<1 x i32*>, <1 x i32*>}* %a +; CHECK-NOT: store + + %cast = bitcast {<1 x i32*>, <1 x i32*>}* %a to <2 x i64>* + %vec = load <2 x i64>* %cast +; CHECK-NOT: load +; CHECK: ptrtoint +; CHECK: bitcast +; CHECK: ptrtoint +; CHECK: bitcast + + ret <2 x i64> %vec +} -- 2.34.1