ConstantVector::get(Mask));
}
+/// Reuse bitcasted operands between a compare and select:
+/// select (cmp (bitcast C), (bitcast D)), (bitcast' C), (bitcast' D) -->
+/// bitcast (select (cmp (bitcast C), (bitcast D)), (bitcast C), (bitcast D))
+static Instruction *foldSelectCmpBitcasts(SelectInst &Sel,
+ InstCombiner::BuilderTy &Builder) {
+ Value *Cond = Sel.getCondition();
+ Value *TVal = Sel.getTrueValue();
+ Value *FVal = Sel.getFalseValue();
+
+ CmpInst::Predicate Pred;
+ Value *A, *B;
+ if (!match(Cond, m_Cmp(Pred, m_Value(A), m_Value(B))))
+ return nullptr;
+
+ // The select condition is a compare instruction. If the select's true/false
+ // values are already the same as the compare operands, there's nothing to do.
+ if (TVal == A || TVal == B || FVal == A || FVal == B)
+ return nullptr;
+
+ Value *C, *D;
+ if (!match(A, m_BitCast(m_Value(C))) || !match(B, m_BitCast(m_Value(D))))
+ return nullptr;
+
+ // select (cmp (bitcast C), (bitcast D)), (bitcast TSrc), (bitcast FSrc)
+ Value *TSrc, *FSrc;
+ if (!match(TVal, m_BitCast(m_Value(TSrc))) ||
+ !match(FVal, m_BitCast(m_Value(FSrc))))
+ return nullptr;
+
+ // If the select true/false values are *different bitcasts* of the same source
+ // operands, make the select operands the same as the compare operands and
+ // cast the result. This is the canonical select form for min/max.
+ Value *NewSel;
+ if (TSrc == C && FSrc == D) {
+ // select (cmp (bitcast C), (bitcast D)), (bitcast' C), (bitcast' D) -->
+ // bitcast (select (cmp A, B), A, B)
+ NewSel = Builder.CreateSelect(Cond, A, B, "", &Sel);
+ } else if (TSrc == D && FSrc == C) {
+ // select (cmp (bitcast C), (bitcast D)), (bitcast' D), (bitcast' C) -->
+ // bitcast (select (cmp A, B), B, A)
+ NewSel = Builder.CreateSelect(Cond, B, A, "", &Sel);
+ } else {
+ return nullptr;
+ }
+ return CastInst::CreateBitOrPointerCast(NewSel, Sel.getType());
+}
+
Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
Value *CondVal = SI.getCondition();
Value *TrueVal = SI.getTrueValue();
}
}
+ if (Instruction *BitCastSel = foldSelectCmpBitcasts(SI, *Builder))
+ return BitCastSel;
+
return nullptr;
}
; CHECK-NEXT: [[T0:%.*]] = bitcast <2 x i64> %a to <4 x float>
; CHECK-NEXT: [[T1:%.*]] = bitcast <2 x i64> %b to <4 x float>
; CHECK-NEXT: [[T2:%.*]] = fcmp olt <4 x float> [[T1]], [[T0]]
-; CHECK-NEXT: [[T3:%.*]] = bitcast <2 x i64> %a to <4 x i32>
-; CHECK-NEXT: [[T4:%.*]] = bitcast <2 x i64> %b to <4 x i32>
-; CHECK-NEXT: [[T5:%.*]] = select <4 x i1> [[T2]], <4 x i32> [[T3]], <4 x i32> [[T4]]
+; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[T2]], <4 x float> [[T0]], <4 x float> [[T1]]
+; CHECK-NEXT: [[T5:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32>
; CHECK-NEXT: ret <4 x i32> [[T5]]
;
%t0 = bitcast <2 x i64> %a to <4 x float>
; CHECK-NEXT: [[T0:%.*]] = bitcast <2 x i64> %a to <4 x float>
; CHECK-NEXT: [[T1:%.*]] = bitcast <2 x i64> %b to <4 x float>
; CHECK-NEXT: [[T2:%.*]] = fcmp olt <4 x float> [[T0]], [[T1]]
-; CHECK-NEXT: [[T3:%.*]] = bitcast <2 x i64> %a to <4 x i32>
-; CHECK-NEXT: [[T4:%.*]] = bitcast <2 x i64> %b to <4 x i32>
-; CHECK-NEXT: [[T5:%.*]] = select <4 x i1> [[T2]], <4 x i32> [[T3]], <4 x i32> [[T4]]
+; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[T2]], <4 x float> [[T0]], <4 x float> [[T1]]
+; CHECK-NEXT: [[T5:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32>
; CHECK-NEXT: ret <4 x i32> [[T5]]
;
%t0 = bitcast <2 x i64> %a to <4 x float>
; CHECK-NEXT: [[T0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
; CHECK-NEXT: [[T1:%.*]] = bitcast <2 x i64> %b to <4 x i32>
; CHECK-NEXT: [[T2:%.*]] = icmp slt <4 x i32> [[T1]], [[T0]]
-; CHECK-NEXT: [[T3:%.*]] = bitcast <2 x i64> %a to <4 x float>
-; CHECK-NEXT: [[T4:%.*]] = bitcast <2 x i64> %b to <4 x float>
-; CHECK-NEXT: [[T5:%.*]] = select <4 x i1> [[T2]], <4 x float> [[T3]], <4 x float> [[T4]]
+; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[T2]], <4 x i32> [[T0]], <4 x i32> [[T1]]
+; CHECK-NEXT: [[T5:%.*]] = bitcast <4 x i32> [[TMP1]] to <4 x float>
; CHECK-NEXT: ret <4 x float> [[T5]]
;
%t0 = bitcast <2 x i64> %a to <4 x i32>