mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[InstCombine] X | C == C --> (X & ~C) == 0
We should canonicalize to one of these forms, and compare-with-zero could be more conducive to follow-on transforms. This also leads to generally better codegen as shown in PR40611: https://bugs.llvm.org/show_bug.cgi?id=40611 llvm-svn: 353313
This commit is contained in:
parent
7f07204e39
commit
a5f5cd5eca
@ -1771,13 +1771,22 @@ Instruction *InstCombiner::foldICmpOrConstant(ICmpInst &Cmp, BinaryOperator *Or,
|
|||||||
ConstantInt::get(V->getType(), 1));
|
ConstantInt::get(V->getType(), 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value *OrOp0 = Or->getOperand(0), *OrOp1 = Or->getOperand(1);
|
||||||
|
if (Cmp.isEquality() && Cmp.getOperand(1) == OrOp1) {
|
||||||
// X | C == C --> X <=u C
|
// X | C == C --> X <=u C
|
||||||
// X | C != C --> X >u C
|
// X | C != C --> X >u C
|
||||||
// iff C+1 is a power of 2 (C is a bitmask of the low bits)
|
// iff C+1 is a power of 2 (C is a bitmask of the low bits)
|
||||||
if (Cmp.isEquality() && Cmp.getOperand(1) == Or->getOperand(1) &&
|
if ((C + 1).isPowerOf2()) {
|
||||||
(C + 1).isPowerOf2()) {
|
|
||||||
Pred = (Pred == CmpInst::ICMP_EQ) ? CmpInst::ICMP_ULE : CmpInst::ICMP_UGT;
|
Pred = (Pred == CmpInst::ICMP_EQ) ? CmpInst::ICMP_ULE : CmpInst::ICMP_UGT;
|
||||||
return new ICmpInst(Pred, Or->getOperand(0), Or->getOperand(1));
|
return new ICmpInst(Pred, OrOp0, OrOp1);
|
||||||
|
}
|
||||||
|
// More general: are all bits outside of a mask constant set or not set?
|
||||||
|
// X | C == C --> (X & ~C) == 0
|
||||||
|
// X | C != C --> (X & ~C) != 0
|
||||||
|
if (Or->hasOneUse()) {
|
||||||
|
Value *A = Builder.CreateAnd(OrOp0, ~C);
|
||||||
|
return new ICmpInst(Pred, A, ConstantInt::getNullValue(OrOp0->getType()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Cmp.isEquality() || !C.isNullValue() || !Or->hasOneUse())
|
if (!Cmp.isEquality() || !C.isNullValue() || !Or->hasOneUse())
|
||||||
@ -1798,8 +1807,8 @@ Instruction *InstCombiner::foldICmpOrConstant(ICmpInst &Cmp, BinaryOperator *Or,
|
|||||||
// Are we using xors to bitwise check for a pair of (in)equalities? Convert to
|
// Are we using xors to bitwise check for a pair of (in)equalities? Convert to
|
||||||
// a shorter form that has more potential to be folded even further.
|
// a shorter form that has more potential to be folded even further.
|
||||||
Value *X1, *X2, *X3, *X4;
|
Value *X1, *X2, *X3, *X4;
|
||||||
if (match(Or->getOperand(0), m_OneUse(m_Xor(m_Value(X1), m_Value(X2)))) &&
|
if (match(OrOp0, m_OneUse(m_Xor(m_Value(X1), m_Value(X2)))) &&
|
||||||
match(Or->getOperand(1), m_OneUse(m_Xor(m_Value(X3), m_Value(X4))))) {
|
match(OrOp1, m_OneUse(m_Xor(m_Value(X3), m_Value(X4))))) {
|
||||||
// ((X1 ^ X2) || (X3 ^ X4)) == 0 --> (X1 == X2) && (X3 == X4)
|
// ((X1 ^ X2) || (X3 ^ X4)) == 0 --> (X1 == X2) && (X3 == X4)
|
||||||
// ((X1 ^ X2) || (X3 ^ X4)) != 0 --> (X1 != X2) || (X3 != X4)
|
// ((X1 ^ X2) || (X3 ^ X4)) != 0 --> (X1 != X2) || (X3 != X4)
|
||||||
Value *Cmp12 = Builder.CreateICmp(Pred, X1, X2);
|
Value *Cmp12 = Builder.CreateICmp(Pred, X1, X2);
|
||||||
|
@ -2169,8 +2169,8 @@ define <2 x i1> @or63_ne63_vec(<2 x i8> %x) {
|
|||||||
|
|
||||||
define i1 @orC_eqC(i32 %x) {
|
define i1 @orC_eqC(i32 %x) {
|
||||||
; CHECK-LABEL: @orC_eqC(
|
; CHECK-LABEL: @orC_eqC(
|
||||||
; CHECK-NEXT: [[T0:%.*]] = or i32 [[X:%.*]], 42
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -43
|
||||||
; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[T0]], 42
|
; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[TMP1]], 0
|
||||||
; CHECK-NEXT: ret i1 [[T1]]
|
; CHECK-NEXT: ret i1 [[T1]]
|
||||||
;
|
;
|
||||||
%t0 = or i32 %x, 42
|
%t0 = or i32 %x, 42
|
||||||
@ -2182,8 +2182,8 @@ define i1 @orC_eqC(i32 %x) {
|
|||||||
|
|
||||||
define <2 x i1> @orC_eqC_vec(<2 x i8> %x) {
|
define <2 x i1> @orC_eqC_vec(<2 x i8> %x) {
|
||||||
; CHECK-LABEL: @orC_eqC_vec(
|
; CHECK-LABEL: @orC_eqC_vec(
|
||||||
; CHECK-NEXT: [[T0:%.*]] = or <2 x i8> [[X:%.*]], <i8 43, i8 43>
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -44, i8 -44>
|
||||||
; CHECK-NEXT: [[T1:%.*]] = icmp eq <2 x i8> [[T0]], <i8 43, i8 43>
|
; CHECK-NEXT: [[T1:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer
|
||||||
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
||||||
;
|
;
|
||||||
%t0 = or <2 x i8> %x, <i8 43, i8 43>
|
%t0 = or <2 x i8> %x, <i8 43, i8 43>
|
||||||
@ -2195,8 +2195,8 @@ define <2 x i1> @orC_eqC_vec(<2 x i8> %x) {
|
|||||||
|
|
||||||
define i1 @orC_neC(i32 %x) {
|
define i1 @orC_neC(i32 %x) {
|
||||||
; CHECK-LABEL: @orC_neC(
|
; CHECK-LABEL: @orC_neC(
|
||||||
; CHECK-NEXT: [[T0:%.*]] = or i32 [[X:%.*]], -42
|
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 41
|
||||||
; CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], -42
|
; CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[TMP1]], 0
|
||||||
; CHECK-NEXT: ret i1 [[T1]]
|
; CHECK-NEXT: ret i1 [[T1]]
|
||||||
;
|
;
|
||||||
%t0 = or i32 %x, -42
|
%t0 = or i32 %x, -42
|
||||||
@ -2208,8 +2208,8 @@ define i1 @orC_neC(i32 %x) {
|
|||||||
|
|
||||||
define <2 x i1> @orC_neC_vec(<2 x i8> %x) {
|
define <2 x i1> @orC_neC_vec(<2 x i8> %x) {
|
||||||
; CHECK-LABEL: @orC_neC_vec(
|
; CHECK-LABEL: @orC_neC_vec(
|
||||||
; CHECK-NEXT: [[T0:%.*]] = or <2 x i8> [[X:%.*]], <i8 -43, i8 -43>
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 42, i8 42>
|
||||||
; CHECK-NEXT: [[T1:%.*]] = icmp ne <2 x i8> [[T0]], <i8 -43, i8 -43>
|
; CHECK-NEXT: [[T1:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer
|
||||||
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
; CHECK-NEXT: ret <2 x i1> [[T1]]
|
||||||
;
|
;
|
||||||
%t0 = or <2 x i8> %x, <i8 -43, i8 -43>
|
%t0 = or <2 x i8> %x, <i8 -43, i8 -43>
|
||||||
|
Loading…
Reference in New Issue
Block a user