diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2276,7 +2276,8 @@ // Match select ?, TC, FC where the constants are equal but negated. // TODO: Generalize to handle a negated variable operand? const APFloat *TC, *FC; - if (!match(TVal, m_APFloat(TC)) || !match(FVal, m_APFloat(FC)) || + if (!match(TVal, m_APFloatAllowUndef(TC)) || + !match(FVal, m_APFloatAllowUndef(FC)) || !abs(*TC).bitwiseIsEqual(abs(*FC))) return nullptr; @@ -2302,7 +2303,7 @@ // Canonicalize the magnitude argument as the positive constant since we do // not care about its sign. - Value *MagArg = TC->isNegative() ? FVal : TVal; + Value *MagArg = ConstantFP::get(SelType, abs(*TC)); Function *F = Intrinsic::getDeclaration(Sel.getModule(), Intrinsic::copysign, Sel.getType()); return CallInst::Create(F, { MagArg, X }); diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -1689,13 +1689,10 @@ ret float %r } -; TODO: Allow undefs when matching vectors. - define <2 x float> @copysign_vec_undef(<2 x float> %x) { ; CHECK-LABEL: @copysign_vec_undef( -; CHECK-NEXT: [[I:%.*]] = bitcast <2 x float> [[X:%.*]] to <2 x i32> -; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[I]], zeroinitializer -; CHECK-NEXT: [[R:%.*]] = select nnan arcp <2 x i1> [[ISNEG]], <2 x float> , <2 x float> +; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x float> [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> , <2 x float> [[TMP1]]) ; CHECK-NEXT: ret <2 x float> [[R]] ; %i = bitcast <2 x float> %x to <2 x i32> @@ -1706,27 +1703,23 @@ define <2 x float> @copysign_vec_undef1(<2 x float> %x) { ; CHECK-LABEL: @copysign_vec_undef1( -; CHECK-NEXT: [[I:%.*]] = bitcast <2 x float> [[X:%.*]] to <2 x i32> -; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[I]], zeroinitializer -; CHECK-NEXT: [[R:%.*]] = select nnan arcp <2 x i1> [[ISNEG]], <2 x float> , <2 x float> +; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> , <2 x float> [[X:%.*]]) ; CHECK-NEXT: ret <2 x float> [[R]] ; %i = bitcast <2 x float> %x to <2 x i32> - %isneg = icmp ugt <2 x i32> %i, + %isneg = icmp ult <2 x i32> %i, %r = select arcp nnan <2 x i1> %isneg, <2 x float> , <2 x float> ret <2 x float> %r } define <2 x float> @copysign_vec_undef3(<2 x float> %x) { ; CHECK-LABEL: @copysign_vec_undef3( -; CHECK-NEXT: [[I:%.*]] = bitcast <2 x float> [[X:%.*]] to <2 x i32> -; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[I]], zeroinitializer -; CHECK-NEXT: [[R:%.*]] = select nnan arcp <2 x i1> [[ISNEG]], <2 x float> , <2 x float> +; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> , <2 x float> [[X:%.*]]) ; CHECK-NEXT: ret <2 x float> [[R]] ; %i = bitcast <2 x float> %x to <2 x i32> %isneg = icmp ugt <2 x i32> %i, - %r = select arcp nnan <2 x i1> %isneg, <2 x float> , <2 x float> + %r = select arcp nnan <2 x i1> %isneg, <2 x float> , <2 x float> ret <2 x float> %r }