diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 5f09fe1fb62..59be6531da3 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -676,6 +676,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with array type with an element + /// count and element type of float with precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getString - This method constructs a CDS and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to /// be placed at the end of the array (increasing the length of the string by @@ -728,6 +737,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with vector type with an element + /// count and element type of float with the precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getSplat - Return a ConstantVector with the specified constant in each /// element. The specified constant has to be a of a compatible type (i8/i16/ /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index 44052b22457..e87aa3d92ed 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -911,23 +911,25 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef V) { if (ConstantFP *CFP = dyn_cast(C)) { if (CFP->getType()->isFloatTy()) { - SmallVector Elts; + SmallVector Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast(V[i])) - Elts.push_back(CFP->getValueAPF().convertToFloat()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); + return ConstantDataArray::getFP(C->getContext(), Elts); } else if (CFP->getType()->isDoubleTy()) { - SmallVector Elts; + SmallVector Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast(V[i])) - Elts.push_back(CFP->getValueAPF().convertToDouble()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); + return ConstantDataArray::getFP(C->getContext(), Elts); } } } @@ -1097,23 +1099,25 @@ Constant *ConstantVector::getImpl(ArrayRef V) { if (ConstantFP *CFP = dyn_cast(C)) { if (CFP->getType()->isFloatTy()) { - SmallVector Elts; + SmallVector Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast(V[i])) - Elts.push_back(CFP->getValueAPF().convertToFloat()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataVector::get(C->getContext(), Elts); + return ConstantDataVector::getFP(C->getContext(), Elts); } else if (CFP->getType()->isDoubleTy()) { - SmallVector Elts; + SmallVector Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast(V[i])) - Elts.push_back(CFP->getValueAPF().convertToDouble()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataVector::get(C->getContext(), Elts); + return ConstantDataVector::getFP(C->getContext(), Elts); } } } @@ -2544,7 +2548,31 @@ Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef Elts) { Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef Elts) { Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size()); const char *Data = reinterpret_cast(Elts.data()); - return getImpl(StringRef(const_cast(Data), Elts.size()*8), Ty); + return getImpl(StringRef(const_cast(Data), Elts.size() * 8), Ty); +} + +/// getFP() constructors - Return a constant with array type with an element +/// count and element type of float with precision matching the number of +/// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, +/// double for 64bits) Note that this can return a ConstantAggregateZero +/// object. +Constant *ConstantDataArray::getFP(LLVMContext &Context, + ArrayRef Elts) { + Type *Ty = VectorType::get(Type::getHalfTy(Context), Elts.size()); + const char *Data = reinterpret_cast(Elts.data()); + return getImpl(StringRef(const_cast(Data), Elts.size() * 2), Ty); +} +Constant *ConstantDataArray::getFP(LLVMContext &Context, + ArrayRef Elts) { + Type *Ty = ArrayType::get(Type::getFloatTy(Context), Elts.size()); + const char *Data = reinterpret_cast(Elts.data()); + return getImpl(StringRef(const_cast(Data), Elts.size() * 4), Ty); +} +Constant *ConstantDataArray::getFP(LLVMContext &Context, + ArrayRef Elts) { + Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size()); + const char *Data = reinterpret_cast(Elts.data()); + return getImpl(StringRef(const_cast(Data), Elts.size() * 8), Ty); } /// getString - This method constructs a CDS and initializes it with a text @@ -2597,7 +2625,31 @@ Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef Elts) { Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef Elts) { Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size()); const char *Data = reinterpret_cast(Elts.data()); - return getImpl(StringRef(const_cast(Data), Elts.size()*8), Ty); + return getImpl(StringRef(const_cast(Data), Elts.size() * 8), Ty); +} + +/// getFP() constructors - Return a constant with vector type with an element +/// count and element type of float with the precision matching the number of +/// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, +/// double for 64bits) Note that this can return a ConstantAggregateZero +/// object. +Constant *ConstantDataVector::getFP(LLVMContext &Context, + ArrayRef Elts) { + Type *Ty = VectorType::get(Type::getHalfTy(Context), Elts.size()); + const char *Data = reinterpret_cast(Elts.data()); + return getImpl(StringRef(const_cast(Data), Elts.size() * 2), Ty); +} +Constant *ConstantDataVector::getFP(LLVMContext &Context, + ArrayRef Elts) { + Type *Ty = VectorType::get(Type::getFloatTy(Context), Elts.size()); + const char *Data = reinterpret_cast(Elts.data()); + return getImpl(StringRef(const_cast(Data), Elts.size() * 4), Ty); +} +Constant *ConstantDataVector::getFP(LLVMContext &Context, + ArrayRef Elts) { + Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size()); + const char *Data = reinterpret_cast(Elts.data()); + return getImpl(StringRef(const_cast(Data), Elts.size() * 8), Ty); } Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) { @@ -2623,13 +2675,14 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) { if (ConstantFP *CFP = dyn_cast(V)) { if (CFP->getType()->isFloatTy()) { - SmallVector Elts(NumElts, CFP->getValueAPF().convertToFloat()); - return get(V->getContext(), Elts); + SmallVector Elts( + NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); + return getFP(V->getContext(), Elts); } if (CFP->getType()->isDoubleTy()) { - SmallVector Elts(NumElts, - CFP->getValueAPF().convertToDouble()); - return get(V->getContext(), Elts); + SmallVector Elts( + NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); + return getFP(V->getContext(), Elts); } } return ConstantVector::getSplat(NumElts, V); diff --git a/test/Transforms/ConstProp/InsertElement.ll b/test/Transforms/ConstProp/InsertElement.ll new file mode 100644 index 00000000000..d249c2eb1c5 --- /dev/null +++ b/test/Transforms/ConstProp/InsertElement.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -constprop -S | FileCheck %s + +define i32 @test1() { + %A = bitcast i32 2139171423 to float + %B = insertelement <1 x float> undef, float %A, i32 0 + %C = extractelement <1 x float> %B, i32 0 + %D = bitcast float %C to i32 + ret i32 %D +; CHECK: @test1 +; CHECK: ret i32 2139171423 +} + diff --git a/test/Transforms/ConstProp/insertvalue.ll b/test/Transforms/ConstProp/insertvalue.ll index 0d288b3841d..dce2b728b93 100644 --- a/test/Transforms/ConstProp/insertvalue.ll +++ b/test/Transforms/ConstProp/insertvalue.ll @@ -65,3 +65,12 @@ define [3 x %struct] @undef-test3() { ; CHECK: ret [3 x %struct] [%struct undef, %struct { i32 0, [4 x i8] undef }, %struct undef] } +define i32 @test-float-Nan() { + %A = bitcast i32 2139171423 to float + %B = insertvalue [1 x float] undef, float %A, 0 + %C = extractvalue [1 x float] %B, 0 + %D = bitcast float %C to i32 + ret i32 %D +; CHECK: @test-float-Nan +; CHECK: ret i32 2139171423 +}