diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 57d9a03c9c22b..07dfbc41e79b0 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -581,26 +581,27 @@ Constant *llvm::ConstantFoldUnaryInstruction(unsigned Opcode, Constant *C) { case Instruction::FNeg: return ConstantFP::get(C->getContext(), neg(CV)); } - } else if (auto *VTy = dyn_cast(C->getType())) { - - Type *Ty = IntegerType::get(VTy->getContext(), 32); + } else if (auto *VTy = dyn_cast(C->getType())) { // Fast path for splatted constants. if (Constant *Splat = C->getSplatValue()) if (Constant *Elt = ConstantFoldUnaryInstruction(Opcode, Splat)) return ConstantVector::getSplat(VTy->getElementCount(), Elt); - // Fold each element and create a vector constant from those constants. - SmallVector Result; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) { - Constant *ExtractIdx = ConstantInt::get(Ty, i); - Constant *Elt = ConstantExpr::getExtractElement(C, ExtractIdx); - Constant *Res = ConstantFoldUnaryInstruction(Opcode, Elt); - if (!Res) - return nullptr; - Result.push_back(Res); - } + if (auto *FVTy = dyn_cast(VTy)) { + // Fold each element and create a vector constant from those constants. + Type *Ty = IntegerType::get(FVTy->getContext(), 32); + SmallVector Result; + for (unsigned i = 0, e = FVTy->getNumElements(); i != e; ++i) { + Constant *ExtractIdx = ConstantInt::get(Ty, i); + Constant *Elt = ConstantExpr::getExtractElement(C, ExtractIdx); + Constant *Res = ConstantFoldUnaryInstruction(Opcode, Elt); + if (!Res) + return nullptr; + Result.push_back(Res); + } - return ConstantVector::get(Result); + return ConstantVector::get(Result); + } } // We don't know how to fold this. diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll index 3c4088832feaa..6a9b3309bb347 100644 --- a/llvm/test/Transforms/InstCombine/fneg.ll +++ b/llvm/test/Transforms/InstCombine/fneg.ll @@ -1109,4 +1109,36 @@ define float @test_fneg_select_maxnum(float %x) { ret float %neg } +; Check that there's no infinite loop. +define @test_fneg_select_svec( %cond, %b) { +; CHECK-LABEL: @test_fneg_select_svec( +; CHECK-NEXT: [[TMP2:%.*]] = fneg fast [[TMP1:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = select fast [[COND:%.*]], shufflevector ( insertelement ( poison, double -0.000000e+00, i64 0), poison, zeroinitializer), [[TMP2]] +; CHECK-NEXT: ret [[TMP3]] +; + %1 = select %cond, zeroinitializer, %b + %2 = fneg fast %1 + ret %2 +} + +define @test_fneg_select_svec_2( %cond, %a) { +; CHECK-LABEL: @test_fneg_select_svec_2( +; CHECK-NEXT: [[A_NEG:%.*]] = fneg fast [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = select fast [[COND:%.*]], [[A_NEG]], shufflevector ( insertelement ( poison, double -0.000000e+00, i64 0), poison, zeroinitializer) +; CHECK-NEXT: ret [[TMP1]] +; + %1 = select %cond, %a, zeroinitializer + %2 = fneg fast %1 + ret %2 +} + +define @test_fneg_select_svec_3( %cond, %b) { +; CHECK-LABEL: @test_fneg_select_svec_3( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double -0.000000e+00, i64 0), poison, zeroinitializer) +; + %1 = select %cond, zeroinitializer, zeroinitializer + %2 = fneg fast %1 + ret %2 +} + !0 = !{} diff --git a/llvm/test/Transforms/InstSimplify/fp-nan.ll b/llvm/test/Transforms/InstSimplify/fp-nan.ll index bb557500822c1..06b23200bafff 100644 --- a/llvm/test/Transforms/InstSimplify/fp-nan.ll +++ b/llvm/test/Transforms/InstSimplify/fp-nan.ll @@ -237,8 +237,7 @@ define <2 x double> @unary_fneg_nan_2(<2 x double> %x) { ; FIXME: This doesn't behave the same way as the fixed-length vectors above define @unary_fneg_nan_2_scalable_vec_0() { ; CHECK-LABEL: @unary_fneg_nan_2_scalable_vec_0( -; CHECK-NEXT: [[R:%.*]] = fneg shufflevector ( insertelement ( poison, double 0xFFF1234567890ABC, i64 0), poison, zeroinitializer) -; CHECK-NEXT: ret [[R]] +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double 0x7FF1234567890ABC, i64 0), poison, zeroinitializer) ; %r = fneg splat (double 0xFFF1234567890ABC) ret %r @@ -247,8 +246,7 @@ define @unary_fneg_nan_2_scalable_vec_0() { ; FIXME: This doesn't behave the same way as the fixed-length vectors above define @unary_fneg_nan_2_scalable_vec_1() { ; CHECK-LABEL: @unary_fneg_nan_2_scalable_vec_1( -; CHECK-NEXT: [[R:%.*]] = fneg shufflevector ( insertelement ( poison, double 0x7FF0000000000001, i64 0), poison, zeroinitializer) -; CHECK-NEXT: ret [[R]] +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double 0xFFF0000000000001, i64 0), poison, zeroinitializer) ; %r = fneg splat (double 0x7FF0000000000001) ret %r