mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-13 23:18:51 +00:00
Teaching SimplifyCFG to recognize the Or-Mask trick that InstCombine uses to
reduce the number of comparisons. Specifically, InstCombine can turn: (i == 5334 || i == 5335) into: ((i | 1) == 5335) SimplifyCFG was already able to detect the pattern: (i == 5334 || i == 5335) to: ((i & -2) == 5334) This patch supersedes D21315 and resolves PR27555 (https://llvm.org/bugs/show_bug.cgi?id=27555). Thanks to David and Chandler for the suggestions! Author: Thomas Jablin (tjablin) Reviewers: majnemer chandlerc halfdan cycheng http://reviews.llvm.org/D21397 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273639 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1d084dfa7b
commit
fa7c6a0a04
@ -461,6 +461,9 @@ private:
|
||||
QUERY( (y & ~mask = y) =>
|
||||
((x & ~mask = y) <=> (x = y OR x = (y | mask)))
|
||||
);
|
||||
QUERY( (y | mask = y) =>
|
||||
((x | mask = y) <=> (x = y OR x = (y & ~mask)))
|
||||
);
|
||||
*/
|
||||
|
||||
// Please note that each pattern must be a dual implication (<--> or
|
||||
@ -503,6 +506,28 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Pattern match a special case:
|
||||
/*
|
||||
QUERY( (y | mask = y) =>
|
||||
((x | mask = y) <=> (x = y OR x = (y & ~mask)))
|
||||
);
|
||||
*/
|
||||
if (match(ICI->getOperand(0),
|
||||
m_Or(m_Value(RHSVal), m_APInt(RHSC)))) {
|
||||
APInt Mask = *RHSC;
|
||||
if (Mask.isPowerOf2() && (C->getValue() | Mask) == C->getValue()) {
|
||||
// If we already have a value for the switch, it has to match!
|
||||
if (!setValueOnce(RHSVal))
|
||||
return false;
|
||||
|
||||
Vals.push_back(C);
|
||||
Vals.push_back(ConstantInt::get(C->getContext(),
|
||||
C->getValue() & ~Mask));
|
||||
UsedICmps++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we already have a value for the switch, it has to match!
|
||||
if (!setValueOnce(ICI->getOperand(0)))
|
||||
return false;
|
||||
|
@ -616,6 +616,45 @@ if:
|
||||
call void @foo1()
|
||||
ret void
|
||||
|
||||
else:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Form a switch when or'ing a power of two
|
||||
; CHECK-LABEL: define void @test21
|
||||
; CHECK: i32 32, label %else
|
||||
; CHECK: i32 13, label %else
|
||||
; CHECK: i32 12, label %else
|
||||
define void @test21(i32 %arg) {
|
||||
%and = or i32 %arg, 1
|
||||
%cmp1 = icmp ne i32 %and, 13
|
||||
%cmp2 = icmp ne i32 %arg, 32
|
||||
%pred = and i1 %cmp1, %cmp2
|
||||
br i1 %pred, label %if, label %else
|
||||
|
||||
if:
|
||||
call void @foo1()
|
||||
ret void
|
||||
|
||||
else:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Since %cmp1 is always false, a switch is never formed
|
||||
; CHECK-LABEL: define void @test22
|
||||
; CHECK-NOT: switch
|
||||
; CHECK: ret void
|
||||
define void @test22(i32 %arg) {
|
||||
%and = or i32 %arg, 1
|
||||
%cmp1 = icmp ne i32 %and, 12
|
||||
%cmp2 = icmp ne i32 %arg, 32
|
||||
%pred = and i1 %cmp1, %cmp2
|
||||
br i1 %pred, label %if, label %else
|
||||
|
||||
if:
|
||||
call void @foo1()
|
||||
ret void
|
||||
|
||||
else:
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue
Block a user