summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/ADT/APInt.h10
-rw-r--r--lib/Analysis/ConstantFolding.cpp38
-rw-r--r--lib/Support/APInt.cpp12
-rw-r--r--test/CodeGen/X86/constant-pool-sharing.ll5
-rw-r--r--test/Transforms/ConstProp/basictest.ll11
-rw-r--r--test/Transforms/InstCombine/icmp.ll11
6 files changed, 78 insertions, 9 deletions
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index 78119bce2a..82338ed9cb 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 fe28926f1b..121e334c4c 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<IntegerType>(DestTy)) {
+ // FIXME: Remove ConstantVector support.
+ if ((!isa<ConstantDataVector>(C) && !isa<ConstantVector>(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<ConstantInt>(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<VectorType>(DestTy);
if (DestVTy == 0)
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index b5411bec9d..c580dd3ba3 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 a672cc254f..f979945835 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 d0d0a5bb33..09e6e7db43 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> <i32 1073741824, i32 1073741824, i32 1073741824, i32 1073741824> 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 63cbeb7452..1652e71401 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> <i32 1, i32 -1> 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> <i64 36029346783166592> to i64
- %call = call i32 @test58_d( i64 %0) nounwind
+ %cast = bitcast <1 x i64> <i64 36029346783166592> to i64
+ %call = call i32 @test58_d( i64 %cast) nounwind
ret void
}
declare i32 @test58_d(i64)