Value *Cond;
Value *NotB;
if (match(A, m_SExt(m_Value(Cond))) &&
- Cond->getType()->isIntOrIntVectorTy(1) &&
- match(B, m_OneUse(m_Not(m_Value(NotB))))) {
- NotB = peekThroughBitcast(NotB, true);
- if (match(NotB, m_SExt(m_Specific(Cond))))
+ Cond->getType()->isIntOrIntVectorTy(1)) {
+ // A = sext i1 Cond; B = sext (not (i1 Cond))
+ if (match(B, m_SExt(m_Not(m_Specific(Cond)))))
return Cond;
+
+ // A = sext i1 Cond; B = not ({bitcast} (sext (i1 Cond)))
+ // TODO: The one-use checks are unnecessary or misplaced. If the caller
+ // checked for uses on logic ops/casts, that should be enough to
+ // make this transform worthwhile.
+ if (match(B, m_OneUse(m_Not(m_Value(NotB))))) {
+ NotB = peekThroughBitcast(NotB, true);
+ if (match(NotB, m_SExt(m_Specific(Cond))))
+ return Cond;
+ }
}
// All scalar (and most vector) possibilities should be handled now.
ret i64 %r
}
-; TODO:
; Peek through bitcasts and sexts to find negated bool condition.
define <1 x i6> @bitcast_sext_cond(<2 x i1> %cmp, <1 x i6> %a, <1 x i6> %b) {
; CHECK-LABEL: @bitcast_sext_cond(
-; CHECK-NEXT: [[SEXT:%.*]] = sext <2 x i1> [[CMP:%.*]] to <2 x i3>
-; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i3> [[SEXT]] to <1 x i6>
-; CHECK-NEXT: [[NEG:%.*]] = xor <2 x i1> [[CMP]], <i1 true, i1 true>
-; CHECK-NEXT: [[SEXT2:%.*]] = sext <2 x i1> [[NEG]] to <2 x i3>
-; CHECK-NEXT: [[BC2:%.*]] = bitcast <2 x i3> [[SEXT2]] to <1 x i6>
-; CHECK-NEXT: [[AND1:%.*]] = and <1 x i6> [[BC1]], [[A:%.*]]
-; CHECK-NEXT: [[AND2:%.*]] = and <1 x i6> [[BC2]], [[B:%.*]]
-; CHECK-NEXT: [[OR:%.*]] = or <1 x i6> [[AND1]], [[AND2]]
-; CHECK-NEXT: ret <1 x i6> [[OR]]
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast <1 x i6> [[A:%.*]] to <2 x i3>
+; CHECK-NEXT: [[TMP2:%.*]] = bitcast <1 x i6> [[B:%.*]] to <2 x i3>
+; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[CMP:%.*]], <2 x i3> [[TMP1]], <2 x i3> [[TMP2]]
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast <2 x i3> [[TMP3]] to <1 x i6>
+; CHECK-NEXT: ret <1 x i6> [[TMP4]]
;
%sext = sext <2 x i1> %cmp to <2 x i3>
%bc1 = bitcast <2 x i3> %sext to <1 x i6>
ret <1 x i6> %or
}
-; TODO:
; Extra uses may prevent other transforms from creating the canonical patterns.
define i8 @sext_cond_extra_uses(i1 %cmp, i8 %a, i8 %b) {
; CHECK-NEXT: call void @use(i8 [[SEXT1]])
; CHECK-NEXT: [[SEXT2:%.*]] = sext i1 [[NEG]] to i8
; CHECK-NEXT: call void @use(i8 [[SEXT2]])
-; CHECK-NEXT: [[AND1:%.*]] = and i8 [[SEXT1]], [[A:%.*]]
-; CHECK-NEXT: [[AND2:%.*]] = and i8 [[SEXT2]], [[B:%.*]]
-; CHECK-NEXT: [[OR:%.*]] = or i8 [[AND1]], [[AND2]]
-; CHECK-NEXT: ret i8 [[OR]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[CMP]], i8 [[A:%.*]], i8 [[B:%.*]]
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%neg = xor i1 %cmp, -1
%sext1 = sext i1 %cmp to i8