Skip to content

Commit 12d1cb1

Browse files
authored
[InstCombine] Preserve disjoint or after folding casted bitwise logic (llvm#136815)
Optimize `or disjoint (zext/sext a) (zext/sext b))` to `(zext/sext (or disjoint a, b))` without losing disjoint. Confirmed here: https://alive2.llvm.org/ce/z/kQ5fJv.
1 parent ab405fb commit 12d1cb1

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,10 @@ Instruction *InstCombinerImpl::foldCastedBitwiseLogic(BinaryOperator &I) {
18691869

18701870
// Do the logic op in the intermediate width, then widen more.
18711871
Value *NarrowLogic = Builder.CreateBinOp(LogicOpc, X, Y, I.getName());
1872+
auto *Disjoint = dyn_cast<PossiblyDisjointInst>(&I);
1873+
auto *NewDisjoint = dyn_cast<PossiblyDisjointInst>(NarrowLogic);
1874+
if (Disjoint && NewDisjoint)
1875+
NewDisjoint->setIsDisjoint(Disjoint->isDisjoint());
18721876
return CastInst::Create(CastOpcode, NarrowLogic, DestTy);
18731877
}
18741878

llvm/test/Transforms/InstCombine/and-xor-or.ll

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4334,6 +4334,33 @@ define i16 @or_zext_zext_2_use1(i8 %x, i8 %y) {
43344334
ret i16 %r
43354335
}
43364336

4337+
define i16 @or_disjoint_zext_zext(i8 %x, i4 %y) {
4338+
; CHECK-LABEL: define {{[^@]+}}@or_disjoint_zext_zext
4339+
; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {
4340+
; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y]] to i8
4341+
; CHECK-NEXT: [[R1:%.*]] = or disjoint i8 [[X]], [[TMP1]]
4342+
; CHECK-NEXT: [[R:%.*]] = zext i8 [[R1]] to i16
4343+
; CHECK-NEXT: ret i16 [[R]]
4344+
;
4345+
%zx = zext i8 %x to i16
4346+
%zy = zext i4 %y to i16
4347+
%r = or disjoint i16 %zy, %zx
4348+
ret i16 %r
4349+
}
4350+
4351+
define i16 @or_disjoint_zext_zext_2(i8 %x, i8 %y) {
4352+
; CHECK-LABEL: define {{[^@]+}}@or_disjoint_zext_zext_2
4353+
; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
4354+
; CHECK-NEXT: [[R1:%.*]] = or disjoint i8 [[Y]], [[X]]
4355+
; CHECK-NEXT: [[R:%.*]] = zext i8 [[R1]] to i16
4356+
; CHECK-NEXT: ret i16 [[R]]
4357+
;
4358+
%zx = zext i8 %x to i16
4359+
%zy = zext i8 %y to i16
4360+
%r = or disjoint i16 %zy, %zx
4361+
ret i16 %r
4362+
}
4363+
43374364
define <2 x i16> @xor_zext_zext(<2 x i8> %x, <2 x i4> %y) {
43384365
; CHECK-LABEL: define {{[^@]+}}@xor_zext_zext
43394366
; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i4> [[Y:%.*]]) {
@@ -4463,6 +4490,33 @@ define i16 @or_sext_sext_2_use1(i8 %x, i8 %y) {
44634490
ret i16 %r
44644491
}
44654492

4493+
define i16 @or_disjoint_sext_sext(i8 %x, i4 %y) {
4494+
; CHECK-LABEL: define {{[^@]+}}@or_disjoint_sext_sext
4495+
; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {
4496+
; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y]] to i8
4497+
; CHECK-NEXT: [[R1:%.*]] = or disjoint i8 [[X]], [[TMP1]]
4498+
; CHECK-NEXT: [[R:%.*]] = sext i8 [[R1]] to i16
4499+
; CHECK-NEXT: ret i16 [[R]]
4500+
;
4501+
%sx = sext i8 %x to i16
4502+
%sy = sext i4 %y to i16
4503+
%r = or disjoint i16 %sx, %sy
4504+
ret i16 %r
4505+
}
4506+
4507+
define i16 @or_disjoint_sext_sext_2(i8 %x, i8 %y) {
4508+
; CHECK-LABEL: define {{[^@]+}}@or_disjoint_sext_sext_2
4509+
; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
4510+
; CHECK-NEXT: [[R1:%.*]] = or disjoint i8 [[X]], [[Y]]
4511+
; CHECK-NEXT: [[R:%.*]] = sext i8 [[R1]] to i16
4512+
; CHECK-NEXT: ret i16 [[R]]
4513+
;
4514+
%sx = sext i8 %x to i16
4515+
%sy = sext i8 %y to i16
4516+
%r = or disjoint i16 %sx, %sy
4517+
ret i16 %r
4518+
}
4519+
44664520
define i16 @xor_sext_sext(i8 %x, i4 %y) {
44674521
; CHECK-LABEL: define {{[^@]+}}@xor_sext_sext
44684522
; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {

0 commit comments

Comments
 (0)