From 04594aeffa3360882eb09a888a0970321b987b16 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 27 Jan 2012 23:33:07 +0000 Subject: [PATCH] Add r149110 back with a fix for when the vector and the int have the same width. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149151 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APInt.h | 10 ++++++ lib/Analysis/ConstantFolding.cpp | 38 +++++++++++++++++++++++ lib/Support/APInt.cpp | 12 +++++++ test/CodeGen/X86/constant-pool-sharing.ll | 5 ++- test/Transforms/ConstProp/basictest.ll | 11 +++++++ test/Transforms/InstCombine/icmp.ll | 11 +++---- 6 files changed, 78 insertions(+), 9 deletions(-) diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 78119bce2ac..82338ed9cb6 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -1056,6 +1056,16 @@ public: /// @brief Zero extend or truncate to width APInt zextOrTrunc(unsigned width) const; + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, or left alone to make it that width. + /// @brief Sign extend or truncate to width + APInt sextOrSelf(unsigned width) const; + + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, or left alone to make it that width. + /// @brief Zero extend or truncate to width + APInt zextOrSelf(unsigned width) const; + /// @} /// @name Bit Manipulation Operators /// @{ diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index fe28926f1b2..121e334c4cc 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -52,6 +52,44 @@ static Constant *FoldBitCast(Constant *C, Type *DestTy, if (C->isAllOnesValue() && !DestTy->isX86_MMXTy()) return Constant::getAllOnesValue(DestTy); + // Handle a vector->integer cast. + if (IntegerType *IT = dyn_cast(DestTy)) { + // FIXME: Remove ConstantVector support. + if ((!isa(C) && !isa(C)) || + // TODO: Handle big endian someday. + !TD.isLittleEndian()) + return ConstantExpr::getBitCast(C, DestTy); + + unsigned NumSrcElts = C->getType()->getVectorNumElements(); + + // If the vector is a vector of floating point, convert it to vector of int + // to simplify things. + if (C->getType()->getVectorElementType()->isFloatingPointTy()) { + unsigned FPWidth = + C->getType()->getVectorElementType()->getPrimitiveSizeInBits(); + Type *SrcIVTy = + VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumSrcElts); + // Ask VMCore to do the conversion now that #elts line up. + C = ConstantExpr::getBitCast(C, SrcIVTy); + } + + // Now that we know that the input value is a vector of integers, just shift + // and insert them into our result. + unsigned BitShift = + TD.getTypeAllocSizeInBits(C->getType()->getVectorElementType()); + APInt Result(IT->getBitWidth(), 0); + for (unsigned i = 0; i != NumSrcElts; ++i) { + // FIXME: Rework when we have ConstantDataVector. + ConstantInt *Elt=dyn_cast_or_null(C->getAggregateElement(i)); + if (Elt == 0) // Elt must be a constant expr or something. + return ConstantExpr::getBitCast(C, DestTy); + + Result |= Elt->getValue().zextOrSelf(IT->getBitWidth()) << i*BitShift; + } + + return ConstantInt::get(IT, Result); + } + // The code below only handles casts to vectors currently. VectorType *DestVTy = dyn_cast(DestTy); if (DestVTy == 0) diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index b5411bec9d4..c580dd3ba3e 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -1123,6 +1123,18 @@ APInt APInt::sextOrTrunc(unsigned width) const { return *this; } +APInt APInt::zextOrSelf(unsigned width) const { + if (BitWidth < width) + return zext(width); + return *this; +} + +APInt APInt::sextOrSelf(unsigned width) const { + if (BitWidth < width) + return sext(width); + return *this; +} + /// Arithmetic right-shift this APInt by shiftAmt. /// @brief Arithmetic right-shift function. APInt APInt::ashr(const APInt &shiftAmt) const { diff --git a/test/CodeGen/X86/constant-pool-sharing.ll b/test/CodeGen/X86/constant-pool-sharing.ll index a672cc254f4..f979945835f 100644 --- a/test/CodeGen/X86/constant-pool-sharing.ll +++ b/test/CodeGen/X86/constant-pool-sharing.ll @@ -1,6 +1,5 @@ -; RUN-disable: llc < %s -mtriple=x86_64-linux | FileCheck %s -; RUN-disable: llc < %s -mtriple=x86_64-win32 | FileCheck %s -; RUN: true +; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-win32 | FileCheck %s ; llc should share constant pool entries between this integer vector ; and this floating-point vector since they have the same encoding. diff --git a/test/Transforms/ConstProp/basictest.ll b/test/Transforms/ConstProp/basictest.ll index d0d0a5bb335..09e6e7db437 100644 --- a/test/Transforms/ConstProp/basictest.ll +++ b/test/Transforms/ConstProp/basictest.ll @@ -1,5 +1,8 @@ ; RUN: opt < %s -constprop -die -S | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.7.2" + ; This is a basic sanity check for constant propagation. The add instruction ; should be eliminated. define i32 @test1(i1 %B) { @@ -40,3 +43,11 @@ define i1 @TNAN() { %C = or i1 %A, %B ret i1 %C } + +define i128 @vector_to_int_cast() { + %A = bitcast <4 x i32> to i128 + ret i128 %A +; CHECK: @vector_to_int_cast +; CHECK: ret i128 85070591750041656499021422275829170176 +} + \ No newline at end of file diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 63cbeb7452d..1652e714017 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -121,8 +121,8 @@ define i1 @test12(i1 %A) { %B = icmp ne i64 bitcast (<2 x i32> to i64), %S ret i1 %B ; CHECK: @test12 -; CHECK-NEXT: %B = select i1 -; CHECK-NEXT: ret i1 %B +; CHECK-NEXT: = xor i1 %A, true +; CHECK-NEXT: ret i1 } ; PR6481 @@ -581,12 +581,11 @@ define zeroext i1 @cmpabs2(i64 %val) { ret i1 %tobool } -; test that we don't crash ; CHECK: @test58 +; CHECK-NEXT: call i32 @test58_d(i64 36029346783166592) define void @test58() nounwind { -entry: - %0 = bitcast <1 x i64> to i64 - %call = call i32 @test58_d( i64 %0) nounwind + %cast = bitcast <1 x i64> to i64 + %call = call i32 @test58_d( i64 %cast) nounwind ret void } declare i32 @test58_d(i64)