Skip to content

Commit f84ad45

Browse files
[LLVM][InstCombine] not (bitcast (cmp A, B) --> bitcast (!cmp A, B) (llvm#167693)
1 parent 876114f commit f84ad45

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5096,9 +5096,17 @@ Instruction *InstCombinerImpl::foldNot(BinaryOperator &I) {
50965096
return &I;
50975097
}
50985098

5099+
// not (bitcast (cmp A, B) --> bitcast (!cmp A, B)
5100+
if (match(NotOp, m_OneUse(m_BitCast(m_Value(X)))) &&
5101+
match(X, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
5102+
cast<CmpInst>(X)->setPredicate(CmpInst::getInversePredicate(Pred));
5103+
return new BitCastInst(X, Ty);
5104+
}
5105+
50995106
// Move a 'not' ahead of casts of a bool to enable logic reduction:
51005107
// not (bitcast (sext i1 X)) --> bitcast (sext (not i1 X))
5101-
if (match(NotOp, m_OneUse(m_BitCast(m_OneUse(m_SExt(m_Value(X)))))) && X->getType()->isIntOrIntVectorTy(1)) {
5108+
if (match(NotOp, m_OneUse(m_BitCast(m_OneUse(m_SExt(m_Value(X)))))) &&
5109+
X->getType()->isIntOrIntVectorTy(1)) {
51025110
Type *SextTy = cast<BitCastOperator>(NotOp)->getSrcTy();
51035111
Value *NotX = Builder.CreateNot(X);
51045112
Value *Sext = Builder.CreateSExt(NotX, SextTy);

llvm/test/Transforms/InstCombine/not.ll

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,3 +1061,81 @@ if.else:
10611061
call void @f2()
10621062
unreachable
10631063
}
1064+
1065+
define i8 @invert_bitcasted_icmp(<8 x i32> %a, <8 x i32> %b) {
1066+
; CHECK-LABEL: @invert_bitcasted_icmp(
1067+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <8 x i32> [[A:%.*]], [[B:%.*]]
1068+
; CHECK-NEXT: [[MASK_AS_INT:%.*]] = bitcast <8 x i1> [[CMP]] to i8
1069+
; CHECK-NEXT: ret i8 [[MASK_AS_INT]]
1070+
;
1071+
%cmp = icmp sle <8 x i32> %a, %b
1072+
%mask.as.int = bitcast <8 x i1> %cmp to i8
1073+
%not = xor i8 %mask.as.int, 255
1074+
ret i8 %not
1075+
}
1076+
1077+
define i8 @invert_bitcasted_icmp_samesign(<8 x i32> %a, <8 x i32> %b) {
1078+
; CHECK-LABEL: @invert_bitcasted_icmp_samesign(
1079+
; CHECK-NEXT: [[CMP:%.*]] = icmp samesign sgt <8 x i32> [[A:%.*]], [[B:%.*]]
1080+
; CHECK-NEXT: [[MASK_AS_INT:%.*]] = bitcast <8 x i1> [[CMP]] to i8
1081+
; CHECK-NEXT: ret i8 [[MASK_AS_INT]]
1082+
;
1083+
%cmp = icmp samesign sle <8 x i32> %a, %b
1084+
%mask.as.int = bitcast <8 x i1> %cmp to i8
1085+
%not = xor i8 %mask.as.int, 255
1086+
ret i8 %not
1087+
}
1088+
1089+
define i8 @invert_bitcasted_icmp_multi_use_1(<8 x i32> %a, <8 x i32> %b) {
1090+
; CHECK-LABEL: @invert_bitcasted_icmp_multi_use_1(
1091+
; CHECK-NEXT: [[CMP:%.*]] = icmp sle <8 x i32> [[A:%.*]], [[B:%.*]]
1092+
; CHECK-NEXT: call void (...) @llvm.fake.use(<8 x i1> [[CMP]])
1093+
; CHECK-NEXT: [[MASK_AS_INT:%.*]] = bitcast <8 x i1> [[CMP]] to i8
1094+
; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[MASK_AS_INT]], -1
1095+
; CHECK-NEXT: ret i8 [[NOT]]
1096+
;
1097+
%cmp = icmp sle <8 x i32> %a, %b
1098+
call void (...) @llvm.fake.use(<8 x i1> %cmp)
1099+
%mask.as.int = bitcast <8 x i1> %cmp to i8
1100+
%not = xor i8 %mask.as.int, -1
1101+
ret i8 %not
1102+
}
1103+
1104+
define i8 @invert_bitcasted_icmp_multi_use_2(<8 x i32> %a, <8 x i32> %b) {
1105+
; CHECK-LABEL: @invert_bitcasted_icmp_multi_use_2(
1106+
; CHECK-NEXT: [[CMP:%.*]] = icmp sle <8 x i32> [[A:%.*]], [[B:%.*]]
1107+
; CHECK-NEXT: [[MASK_AS_INT:%.*]] = bitcast <8 x i1> [[CMP]] to i8
1108+
; CHECK-NEXT: call void (...) @llvm.fake.use(i8 [[MASK_AS_INT]])
1109+
; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[MASK_AS_INT]], -1
1110+
; CHECK-NEXT: ret i8 [[NOT]]
1111+
;
1112+
%cmp = icmp sle <8 x i32> %a, %b
1113+
%mask.as.int = bitcast <8 x i1> %cmp to i8
1114+
call void (...) @llvm.fake.use(i8 %mask.as.int)
1115+
%not = xor i8 %mask.as.int, -1
1116+
ret i8 %not
1117+
}
1118+
1119+
define i8 @invert_bitcasted_fcmp(<8 x float> %a, <8 x float> %b) {
1120+
; CHECK-LABEL: @invert_bitcasted_fcmp(
1121+
; CHECK-NEXT: [[CMP:%.*]] = fcmp uge <8 x float> [[A:%.*]], [[B:%.*]]
1122+
; CHECK-NEXT: [[MASK_AS_INT:%.*]] = bitcast <8 x i1> [[CMP]] to i8
1123+
; CHECK-NEXT: ret i8 [[MASK_AS_INT]]
1124+
;
1125+
%cmp = fcmp olt <8 x float> %a, %b
1126+
%mask.as.int = bitcast <8 x i1> %cmp to i8
1127+
%not = xor i8 %mask.as.int, 255
1128+
ret i8 %not
1129+
}
1130+
1131+
define i8 @invert_bitcasted_fcmp_fast(<8 x float> %a, <8 x float> %b) {
1132+
; CHECK-LABEL: @invert_bitcasted_fcmp_fast(
1133+
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast uge <8 x float> [[A:%.*]], [[B:%.*]]
1134+
; CHECK-NEXT: [[MASK_AS_INT:%.*]] = bitcast <8 x i1> [[CMP]] to i8
1135+
; CHECK-NEXT: ret i8 [[MASK_AS_INT]]
1136+
;
1137+
%cmp = fcmp fast olt <8 x float> %a, %b
1138+
%mask.as.int = bitcast <8 x i1> %cmp to i8
1139+
%not = xor i8 %mask.as.int, 255
1140+
ret i8 %not
1141+
}

0 commit comments

Comments
 (0)