Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4548,6 +4548,36 @@ break; } + case Instruction::ShuffleVector: { + // For undef elements, we don't know anything about the common state of + // the shuffle result. + APInt DemandedLHS, DemandedRHS; + auto *Shuf = dyn_cast(Op); + if (!Shuf || !getShuffleDemandedElts(Shuf, DemandedElts, DemandedLHS, DemandedRHS)) + return; + + if (!!DemandedLHS) { + const Value *LHS = Shuf->getOperand(0); + computeKnownFPClass(LHS, DemandedLHS, InterestedClasses, Known, + Depth + 1, Q, TLI); + + // If we don't know any bits, early out. + if (Known.isUnknown()) + break; + } else { + Known.KnownFPClasses = fcNone; + } + + if (!!DemandedRHS) { + KnownFPClass Known2; + const Value *RHS = Shuf->getOperand(1); + computeKnownFPClass(RHS, DemandedRHS, InterestedClasses, Known2, + Depth + 1, Q, TLI); + Known |= Known2; + } + + break; + } case Instruction::ExtractValue: { computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses, Known, Depth + 1, Q, TLI); Index: llvm/test/Transforms/Attributor/nofpclass.ll =================================================================== --- llvm/test/Transforms/Attributor/nofpclass.ll +++ llvm/test/Transforms/Attributor/nofpclass.ll @@ -910,3 +910,142 @@ %ins.1 = insertelement <2 x float> %ins.0, float %extract2, i32 1 ret <2 x float> %ins.1 } + +; FIXME: Doesn't actually reach computeKnownFPClass +define <4 x float> @shufflevector_constexpr() { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define <4 x float> @shufflevector_constexpr +; CHECK-SAME: () #[[ATTR2]] { +; CHECK-NEXT: ret <4 x float> +; + ret <4 x float> shufflevector (<2 x float> , <2 x float> , <4 x i32> ) +} + +define <4 x float> @shufflevector_concat_disjoint(<2 x float> nofpclass(nan) %arg0, <2 x float> nofpclass(inf) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define <4 x float> @shufflevector_concat_disjoint +; CHECK-SAME: (<2 x float> nofpclass(nan) [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + ret <4 x float> %shuffle +} + +define <4 x float> @shufflevector_concat_overlap(<2 x float> nofpclass(nan norm psub) %arg0, <2 x float> nofpclass(inf nan sub) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define nofpclass(nan psub) <4 x float> @shufflevector_concat_overlap +; CHECK-SAME: (<2 x float> nofpclass(nan psub norm) [[ARG0:%.*]], <2 x float> nofpclass(nan inf sub) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + ret <4 x float> %shuffle +} + +define <4 x float> @shufflevector_unknown_lhs(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define <4 x float> @shufflevector_unknown_lhs +; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + ret <4 x float> %shuffle +} + +define <4 x float> @shufflevector_unknown_rhs(<2 x float> nofpclass(inf) %arg0, <2 x float> %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define <4 x float> @shufflevector_unknown_rhs +; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + ret <4 x float> %shuffle +} + +define <4 x float> @shufflevector_unknown_all(<2 x float> %arg0, <2 x float> %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define <4 x float> @shufflevector_unknown_all +; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + ret <4 x float> %shuffle +} + +define <4 x float> @shufflevector_only_demand_lhs(<2 x float> nofpclass(inf) %arg0, <2 x float> %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define nofpclass(inf) <4 x float> @shufflevector_only_demand_lhs +; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + ret <4 x float> %shuffle +} + +define <4 x float> @shufflevector_only_demand_rhs(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define nofpclass(inf) <4 x float> @shufflevector_only_demand_rhs +; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + ret <4 x float> %shuffle +} + +define float @shufflevector_extractelt0(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define float @shufflevector_extractelt0 +; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 0 +; CHECK-NEXT: ret float [[EXTRACT]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + %extract = extractelement <4 x float> %shuffle, i32 0 + ret float %extract +} + +define float @shufflevector_extractelt1(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define nofpclass(inf) float @shufflevector_extractelt1 +; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 1 +; CHECK-NEXT: ret float [[EXTRACT]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + %extract = extractelement <4 x float> %shuffle, i32 1 + ret float %extract +} + +define float @shufflevector_extractelt2(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define float @shufflevector_extractelt2 +; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 2 +; CHECK-NEXT: ret float [[EXTRACT]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + %extract = extractelement <4 x float> %shuffle, i32 2 + ret float %extract +} + +define float @shufflevector_extractelt3(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define float @shufflevector_extractelt3 +; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> +; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 3 +; CHECK-NEXT: ret float [[EXTRACT]] +; + %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> + %extract = extractelement <4 x float> %shuffle, i32 3 + ret float %extract +}