forked from OSchip/llvm-project
Generalize the and-icmp-select instcombine further by allowing selects of the form
(x & 2^n) ? 2^m+C : C we can offset both arms by C to get the "(x & 2^n) ? 2^m : 0" form, optimize the select to a shift and apply the offset afterwards. llvm-svn: 121609
This commit is contained in:
parent
c8b035d006
commit
c4169cebe3
|
@ -1055,18 +1055,6 @@ Should also combine to x | 8. Currently not optimized with "clang
|
|||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
int a(int x) {return (x & 8) == 0 ? -1 : -9;}
|
||||
Should combine to (x | -9) ^ 8. Currently not optimized with "clang
|
||||
-emit-llvm-bc | opt -std-compile-opts".
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
int a(int x) {return (x & 8) == 0 ? -9 : -1;}
|
||||
Should combine to x | -9. Currently not optimized with "clang
|
||||
-emit-llvm-bc | opt -std-compile-opts".
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
int a(int x) {return ((x | -9) ^ 8) & x;}
|
||||
Should combine to x & -9. Currently not optimized with "clang
|
||||
-emit-llvm-bc | opt -std-compile-opts".
|
||||
|
|
|
@ -457,10 +457,6 @@ static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal,
|
|||
if (!IC || !IC->isEquality())
|
||||
return 0;
|
||||
|
||||
// One of the select arms must be zero.
|
||||
if (!TrueVal->isZero() && !FalseVal->isZero())
|
||||
return 0;
|
||||
|
||||
if (ConstantInt *C = dyn_cast<ConstantInt>(IC->getOperand(1)))
|
||||
if (!C->isZero())
|
||||
return 0;
|
||||
|
@ -471,6 +467,24 @@ static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal,
|
|||
!match(LHS, m_And(m_Value(), m_ConstantInt(AndRHS))))
|
||||
return 0;
|
||||
|
||||
// If both select arms are non-zero see if we have a select of the form
|
||||
// 'x ? 2^n + C : C'. Then we can offset both arms by C, use the logic
|
||||
// for 'x ? 2^n : 0' and fix the thing up at the end.
|
||||
ConstantInt *Offset = 0;
|
||||
if (!TrueVal->isZero() && !FalseVal->isZero()) {
|
||||
if ((TrueVal->getValue() - FalseVal->getValue()).isPowerOf2())
|
||||
Offset = FalseVal;
|
||||
else if ((FalseVal->getValue() - TrueVal->getValue()).isPowerOf2())
|
||||
Offset = TrueVal;
|
||||
else
|
||||
return 0;
|
||||
|
||||
// Adjust TrueVal and FalseVal to the offset.
|
||||
TrueVal = ConstantInt::get(Builder->getContext(),
|
||||
TrueVal->getValue() - Offset->getValue());
|
||||
FalseVal = ConstantInt::get(Builder->getContext(),
|
||||
FalseVal->getValue() - Offset->getValue());
|
||||
}
|
||||
|
||||
// Make sure the mask in the 'and' and one of the select arms is a power of 2.
|
||||
if (!AndRHS->getValue().isPowerOf2() ||
|
||||
|
@ -496,6 +510,10 @@ static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal,
|
|||
ShouldNotVal ^= IC->getPredicate() == ICmpInst::ICMP_NE;
|
||||
if (ShouldNotVal)
|
||||
V = Builder->CreateXor(V, ValC);
|
||||
|
||||
// Apply an offset if needed.
|
||||
if (Offset)
|
||||
V = Builder->CreateAdd(V, Offset);
|
||||
return V;
|
||||
}
|
||||
|
||||
|
|
|
@ -248,6 +248,56 @@ define i32 @test15f(i32 %X) {
|
|||
; CHECK: ret i32
|
||||
}
|
||||
|
||||
;; (a & 8) ? -1 : -9
|
||||
define i32 @test15g(i32 %X) {
|
||||
%t1 = and i32 %X, 8
|
||||
%t2 = icmp ne i32 %t1, 0
|
||||
%t3 = select i1 %t2, i32 -1, i32 -9
|
||||
ret i32 %t3
|
||||
; CHECK: @test15g
|
||||
; CHECK-NEXT: %1 = or i32 %X, -9
|
||||
; CHECK-NEXT: ret i32 %1
|
||||
}
|
||||
|
||||
;; (a & 8) ? -9 : -1
|
||||
define i32 @test15h(i32 %X) {
|
||||
%t1 = and i32 %X, 8
|
||||
%t2 = icmp ne i32 %t1, 0
|
||||
%t3 = select i1 %t2, i32 -9, i32 -1
|
||||
ret i32 %t3
|
||||
; CHECK: @test15h
|
||||
; CHECK-NEXT: %1 = or i32 %X, -9
|
||||
; CHECK-NEXT: %2 = xor i32 %1, 8
|
||||
; CHECK-NEXT: ret i32 %2
|
||||
}
|
||||
|
||||
;; (a & 2) ? 577 : 1089
|
||||
define i32 @test15i(i32 %X) {
|
||||
%t1 = and i32 %X, 2
|
||||
%t2 = icmp ne i32 %t1, 0
|
||||
%t3 = select i1 %t2, i32 577, i32 1089
|
||||
ret i32 %t3
|
||||
; CHECK: @test15i
|
||||
; CHECK-NEXT: %t1 = shl i32 %X, 8
|
||||
; CHECK-NEXT: %1 = and i32 %t1, 512
|
||||
; CHECK-NEXT: %2 = xor i32 %1, 512
|
||||
; CHECK-NEXT: %3 = add i32 %2, 577
|
||||
; CHECK-NEXT: ret i32 %3
|
||||
}
|
||||
|
||||
;; (a & 2) ? 1089 : 577
|
||||
define i32 @test15j(i32 %X) {
|
||||
%t1 = and i32 %X, 2
|
||||
%t2 = icmp ne i32 %t1, 0
|
||||
%t3 = select i1 %t2, i32 1089, i32 577
|
||||
ret i32 %t3
|
||||
; CHECK: @test15j
|
||||
; CHECK-NEXT: %t1 = shl i32 %X, 8
|
||||
; CHECK-NEXT: %1 = and i32 %t1, 512
|
||||
; CHECK-NEXT: %2 = add i32 %1, 577
|
||||
; CHECK-NEXT: ret i32 %2
|
||||
}
|
||||
|
||||
define i32 @test16(i1 %C, i32* %P) {
|
||||
%P2 = select i1 %C, i32* %P, i32* null
|
||||
%V = load i32* %P2
|
||||
|
|
Loading…
Reference in New Issue