Skip to content

Commit 7a1a476

Browse files
authored
[InstCombine] Fold (X & C1) | C2 into X & (C1 | C2) iff (X & C2) == C2 (#76470)
Alive2: https://alive2.llvm.org/ce/z/VKJYaS
1 parent 8c6172b commit 7a1a476

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3872,6 +3872,14 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
38723872
}
38733873
}
38743874

3875+
// (X & C1) | C2 -> X & (C1 | C2) iff (X & C2) == C2
3876+
if (match(Op0, m_OneUse(m_And(m_Value(X), m_APInt(C1)))) &&
3877+
match(Op1, m_APInt(C2))) {
3878+
KnownBits KnownX = computeKnownBits(X, /*Depth*/ 0, &I);
3879+
if ((KnownX.One & *C2) == *C2)
3880+
return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, *C1 | *C2));
3881+
}
3882+
38753883
return nullptr;
38763884
}
38773885

llvm/test/Transforms/InstCombine/or.ll

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,3 +1636,98 @@ define i32 @assoc_cast_assoc_disjoint(i16 %x) {
16361636
%c = or disjoint i32 %b, 65536
16371637
ret i32 %c
16381638
}
1639+
1640+
; (X & C1) | C2 -> X & (C1 | C2) iff (X & C2) == C2
1641+
define i32 @test_or_and_disjoint(i32 %a) {
1642+
; CHECK-LABEL: @test_or_and_disjoint(
1643+
; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 24
1644+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 8
1645+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1646+
; CHECK: if.then:
1647+
; CHECK-NEXT: [[A2:%.*]] = and i32 [[A]], 15
1648+
; CHECK-NEXT: ret i32 [[A2]]
1649+
; CHECK: if.else:
1650+
; CHECK-NEXT: ret i32 0
1651+
;
1652+
%a0 = and i32 %a, 24
1653+
%cmp = icmp eq i32 %a0, 8
1654+
br i1 %cmp, label %if.then, label %if.else
1655+
if.then:
1656+
%a1 = and i32 %a, 7
1657+
%a2 = or i32 %a1, 8
1658+
ret i32 %a2
1659+
if.else:
1660+
ret i32 0
1661+
}
1662+
1663+
define i32 @test_or_and_mixed(i32 %a) {
1664+
; CHECK-LABEL: @test_or_and_mixed(
1665+
; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 27
1666+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 11
1667+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1668+
; CHECK: if.then:
1669+
; CHECK-NEXT: [[A2:%.*]] = and i32 [[A]], 15
1670+
; CHECK-NEXT: ret i32 [[A2]]
1671+
; CHECK: if.else:
1672+
; CHECK-NEXT: ret i32 0
1673+
;
1674+
%a0 = and i32 %a, 27
1675+
%cmp = icmp eq i32 %a0, 11
1676+
br i1 %cmp, label %if.then, label %if.else
1677+
if.then:
1678+
%a1 = and i32 %a, 7
1679+
%a2 = or i32 %a1, 11
1680+
ret i32 %a2
1681+
if.else:
1682+
ret i32 0
1683+
}
1684+
1685+
; Negative tests
1686+
1687+
define i32 @test_or_and_disjoint_fail(i32 %a) {
1688+
; CHECK-LABEL: @test_or_and_disjoint_fail(
1689+
; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 24
1690+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 16
1691+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1692+
; CHECK: if.then:
1693+
; CHECK-NEXT: [[A1:%.*]] = and i32 [[A]], 7
1694+
; CHECK-NEXT: [[A2:%.*]] = or disjoint i32 [[A1]], 8
1695+
; CHECK-NEXT: ret i32 [[A2]]
1696+
; CHECK: if.else:
1697+
; CHECK-NEXT: ret i32 0
1698+
;
1699+
%a0 = and i32 %a, 24
1700+
%cmp = icmp eq i32 %a0, 16
1701+
br i1 %cmp, label %if.then, label %if.else
1702+
if.then:
1703+
%a1 = and i32 %a, 7
1704+
%a2 = or i32 %a1, 8
1705+
ret i32 %a2
1706+
if.else:
1707+
ret i32 0
1708+
}
1709+
1710+
define i32 @test_or_and_disjoint_multiuse(i32 %a) {
1711+
; CHECK-LABEL: @test_or_and_disjoint_multiuse(
1712+
; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 24
1713+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 8
1714+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1715+
; CHECK: if.then:
1716+
; CHECK-NEXT: [[A1:%.*]] = and i32 [[A]], 7
1717+
; CHECK-NEXT: call void @use(i32 [[A1]])
1718+
; CHECK-NEXT: [[A2:%.*]] = or disjoint i32 [[A1]], 8
1719+
; CHECK-NEXT: ret i32 [[A2]]
1720+
; CHECK: if.else:
1721+
; CHECK-NEXT: ret i32 0
1722+
;
1723+
%a0 = and i32 %a, 24
1724+
%cmp = icmp eq i32 %a0, 8
1725+
br i1 %cmp, label %if.then, label %if.else
1726+
if.then:
1727+
%a1 = and i32 %a, 7
1728+
call void @use(i32 %a1)
1729+
%a2 = or i32 %a1, 8
1730+
ret i32 %a2
1731+
if.else:
1732+
ret i32 0
1733+
}

0 commit comments

Comments
 (0)