llvm.org GIT mirror llvm / 91e37ef
InstCombine: Add a bunch of combines of the form x | (y ^ z). We usually catch this kind of optimization through InstSimplify's distributive magic, but or doesn't distribute over xor in general. "A | ~(A | B) -> A | ~B" hits 24 times on gcc.c. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126081 91177308-0d34-0410-b5e6-96231b3b80d8 Benjamin Kramer 8 years ago
2 changed file(s) with 135 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
18961896 return BinaryOperator::CreateNot(And);
18971897 }
18981898
1899 // Canonicalize xor to the RHS.
1900 if (match(Op0, m_Xor(m_Value(), m_Value())))
1901 std::swap(Op0, Op1);
1902
1903 // A | ( A ^ B) -> A | B
1904 // A | (~A ^ B) -> A | ~B
1905 if (match(Op1, m_Xor(m_Value(A), m_Value(B)))) {
1906 if (Op0 == A || Op0 == B)
1907 return BinaryOperator::CreateOr(A, B);
1908
1909 if (Op1->hasOneUse() && match(A, m_Not(m_Specific(Op0)))) {
1910 Value *Not = Builder->CreateNot(B, B->getName()+".not");
1911 return BinaryOperator::CreateOr(Not, Op0);
1912 }
1913 if (Op1->hasOneUse() && match(B, m_Not(m_Specific(Op0)))) {
1914 Value *Not = Builder->CreateNot(A, A->getName()+".not");
1915 return BinaryOperator::CreateOr(Not, Op0);
1916 }
1917 }
1918
1919 // A | ~(A | B) -> A | ~B
1920 // A | ~(A ^ B) -> A | ~B
1921 // A | ~(A & B) -> -1
1922 if (match(Op1, m_Not(m_Value(A))))
1923 if (BinaryOperator *B = dyn_cast(A))
1924 if (Op0 == B->getOperand(0) || Op0 == B->getOperand(1))
1925 switch (B->getOpcode()) {
1926 default: break;
1927 case Instruction::Or:
1928 case Instruction::Xor:
1929 if (Op1->hasOneUse()) {
1930 Value *NotOp = Op0 == B->getOperand(0) ? B->getOperand(1) :
1931 B->getOperand(0);
1932 Value *Not = Builder->CreateNot(NotOp, NotOp->getName()+".not");
1933 return BinaryOperator::CreateOr(Not, Op0);
1934 }
1935 break;
1936 case Instruction::And:
1937 return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
1938 }
1939
18991940 if (ICmpInst *RHS = dyn_cast(I.getOperand(1)))
19001941 if (ICmpInst *LHS = dyn_cast(I.getOperand(0)))
19011942 if (Value *Res = FoldOrOfICmps(LHS, RHS))
0 ; RUN: opt -S -instcombine < %s | FileCheck %s
1
2 define i32 @test1(i32 %x, i32 %y) nounwind {
3 %or = or i32 %x, %y
4 %not = xor i32 %or, -1
5 %z = or i32 %x, %not
6 ret i32 %z
7 ; CHECK: @test1
8 ; CHECK-NEXT: %y.not = xor i32 %y, -1
9 ; CHECK-NEXT: %z = or i32 %y.not, %x
10 ; CHECK-NEXT: ret i32 %z
11 }
12
13 define i32 @test2(i32 %x, i32 %y) nounwind {
14 %or = or i32 %x, %y
15 %not = xor i32 %or, -1
16 %z = or i32 %y, %not
17 ret i32 %z
18 ; CHECK: @test2
19 ; CHECK-NEXT: %x.not = xor i32 %x, -1
20 ; CHECK-NEXT: %z = or i32 %x.not, %y
21 ; CHECK-NEXT: ret i32 %z
22 }
23
24 define i32 @test3(i32 %x, i32 %y) nounwind {
25 %xor = xor i32 %x, %y
26 %not = xor i32 %xor, -1
27 %z = or i32 %x, %not
28 ret i32 %z
29 ; CHECK: @test3
30 ; CHECK-NEXT: %y.not = xor i32 %y, -1
31 ; CHECK-NEXT: %z = or i32 %y.not, %x
32 ; CHECK-NEXT: ret i32 %z
33 }
34
35 define i32 @test4(i32 %x, i32 %y) nounwind {
36 %xor = xor i32 %x, %y
37 %not = xor i32 %xor, -1
38 %z = or i32 %y, %not
39 ret i32 %z
40 ; CHECK: @test4
41 ; CHECK-NEXT: %x.not = xor i32 %x, -1
42 ; CHECK-NEXT: %z = or i32 %x.not, %y
43 ; CHECK-NEXT: ret i32 %z
44 }
45
46 define i32 @test5(i32 %x, i32 %y) nounwind {
47 %and = and i32 %x, %y
48 %not = xor i32 %and, -1
49 %z = or i32 %x, %not
50 ret i32 %z
51 ; CHECK: @test5
52 ; CHECK-NEXT: ret i32 -1
53 }
54
55 define i32 @test6(i32 %x, i32 %y) nounwind {
56 %and = and i32 %x, %y
57 %not = xor i32 %and, -1
58 %z = or i32 %y, %not
59 ret i32 %z
60 ; CHECK: @test6
61 ; CHECK-NEXT: ret i32 -1
62 }
63
64 define i32 @test7(i32 %x, i32 %y) nounwind {
65 %xor = xor i32 %x, %y
66 %z = or i32 %y, %xor
67 ret i32 %z
68 ; CHECK: @test7
69 ; CHECK-NEXT: %z = or i32 %x, %y
70 ; CHECK-NEXT: ret i32 %z
71 }
72
73 define i32 @test8(i32 %x, i32 %y) nounwind {
74 %not = xor i32 %y, -1
75 %xor = xor i32 %x, %not
76 %z = or i32 %y, %xor
77 ret i32 %z
78 ; CHECK: @test8
79 ; CHECK-NEXT: %x.not = xor i32 %x, -1
80 ; CHECK-NEXT: %z = or i32 %x.not, %y
81 ; CHECK-NEXT: ret i32 %z
82 }
83
84 define i32 @test9(i32 %x, i32 %y) nounwind {
85 %not = xor i32 %x, -1
86 %xor = xor i32 %not, %y
87 %z = or i32 %x, %xor
88 ret i32 %z
89 ; CHECK: @test9
90 ; CHECK-NEXT: %y.not = xor i32 %y, -1
91 ; CHECK-NEXT: %z = or i32 %y.not, %x
92 ; CHECK-NEXT: ret i32 %z
93 }