mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
Factor the (x & 2^n) ? 2^m : 0 instcombine into its own method and generalize it
to catch cases where n != m with a shift. llvm-svn: 121608
This commit is contained in:
parent
b6773d7e1f
commit
5a1721f4ac
@ -1736,46 +1736,6 @@ Ideal output:
|
|||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
Testcase:
|
|
||||||
int x(int a) { return (a & 0x80) ? 0x100 : 0; }
|
|
||||||
int y(int a) { return (a & 0x80) *2; }
|
|
||||||
|
|
||||||
Current:
|
|
||||||
testl $128, 4(%esp)
|
|
||||||
setne %al
|
|
||||||
movzbl %al, %eax
|
|
||||||
shll $8, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
Better:
|
|
||||||
movl 4(%esp), %eax
|
|
||||||
addl %eax, %eax
|
|
||||||
andl $256, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
This is another general instcombine transformation that is profitable on all
|
|
||||||
targets. In LLVM IR, these functions look like this:
|
|
||||||
|
|
||||||
define i32 @x(i32 %a) nounwind readnone {
|
|
||||||
entry:
|
|
||||||
%0 = and i32 %a, 128
|
|
||||||
%1 = icmp eq i32 %0, 0
|
|
||||||
%iftmp.0.0 = select i1 %1, i32 0, i32 256
|
|
||||||
ret i32 %iftmp.0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
define i32 @y(i32 %a) nounwind readnone {
|
|
||||||
entry:
|
|
||||||
%0 = shl i32 %a, 1
|
|
||||||
%1 = and i32 %0, 256
|
|
||||||
ret i32 %1
|
|
||||||
}
|
|
||||||
|
|
||||||
Replacing an icmp+select with a shift should always be considered profitable in
|
|
||||||
instcombine.
|
|
||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
Re-implement atomic builtins __sync_add_and_fetch() and __sync_sub_and_fetch
|
Re-implement atomic builtins __sync_add_and_fetch() and __sync_sub_and_fetch
|
||||||
properly.
|
properly.
|
||||||
|
|
||||||
|
@ -446,7 +446,58 @@ Instruction *InstCombiner::FoldSPFofSPF(Instruction *Inner,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// foldSelectICmpAnd - If one of the constants is zero (we know they can't
|
||||||
|
/// both be) and we have an icmp instruction with zero, and we have an 'and'
|
||||||
|
/// with the non-constant value and a power of two we can turn the select
|
||||||
|
/// into a shift on the result of the 'and'.
|
||||||
|
static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal,
|
||||||
|
ConstantInt *FalseVal,
|
||||||
|
InstCombiner::BuilderTy *Builder) {
|
||||||
|
const ICmpInst *IC = dyn_cast<ICmpInst>(SI.getCondition());
|
||||||
|
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;
|
||||||
|
|
||||||
|
ConstantInt *AndRHS;
|
||||||
|
Value *LHS = IC->getOperand(0);
|
||||||
|
if (LHS->getType() != SI.getType() ||
|
||||||
|
!match(LHS, m_And(m_Value(), m_ConstantInt(AndRHS))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Make sure the mask in the 'and' and one of the select arms is a power of 2.
|
||||||
|
if (!AndRHS->getValue().isPowerOf2() ||
|
||||||
|
(!TrueVal->getValue().isPowerOf2() &&
|
||||||
|
!FalseVal->getValue().isPowerOf2()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Determine which shift is needed to transform result of the 'and' into the
|
||||||
|
// desired result.
|
||||||
|
ConstantInt *ValC = !TrueVal->isZero() ? TrueVal : FalseVal;
|
||||||
|
unsigned ValZeros = ValC->getValue().logBase2();
|
||||||
|
unsigned AndZeros = AndRHS->getValue().logBase2();
|
||||||
|
|
||||||
|
Value *V = LHS;
|
||||||
|
if (ValZeros > AndZeros)
|
||||||
|
V = Builder->CreateShl(V, ValZeros - AndZeros);
|
||||||
|
else if (ValZeros < AndZeros)
|
||||||
|
V = Builder->CreateLShr(V, AndZeros - ValZeros);
|
||||||
|
|
||||||
|
// Okay, now we know that everything is set up, we just don't know whether we
|
||||||
|
// have a icmp_ne or icmp_eq and whether the true or false val is the zero.
|
||||||
|
bool ShouldNotVal = !TrueVal->isZero();
|
||||||
|
ShouldNotVal ^= IC->getPredicate() == ICmpInst::ICMP_NE;
|
||||||
|
if (ShouldNotVal)
|
||||||
|
V = Builder->CreateXor(V, ValC);
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
||||||
Value *CondVal = SI.getCondition();
|
Value *CondVal = SI.getCondition();
|
||||||
@ -509,32 +560,9 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
|||||||
Value *NotCond = Builder->CreateNot(CondVal, "not."+CondVal->getName());
|
Value *NotCond = Builder->CreateNot(CondVal, "not."+CondVal->getName());
|
||||||
return new SExtInst(NotCond, SI.getType());
|
return new SExtInst(NotCond, SI.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ICmpInst *IC = dyn_cast<ICmpInst>(SI.getCondition())) {
|
if (Value *V = foldSelectICmpAnd(SI, TrueValC, FalseValC, Builder))
|
||||||
// If one of the constants is zero (we know they can't both be) and we
|
return ReplaceInstUsesWith(SI, V);
|
||||||
// have an icmp instruction with zero, and we have an 'and' with the
|
|
||||||
// non-constant value, eliminate this whole mess. This corresponds to
|
|
||||||
// cases like this: ((X & 27) ? 27 : 0)
|
|
||||||
if (TrueValC->isZero() || FalseValC->isZero())
|
|
||||||
if (IC->isEquality() && isa<ConstantInt>(IC->getOperand(1)) &&
|
|
||||||
cast<Constant>(IC->getOperand(1))->isNullValue())
|
|
||||||
if (Instruction *ICA = dyn_cast<Instruction>(IC->getOperand(0)))
|
|
||||||
if (ICA->getOpcode() == Instruction::And &&
|
|
||||||
isa<ConstantInt>(ICA->getOperand(1)) &&
|
|
||||||
(ICA->getOperand(1) == TrueValC ||
|
|
||||||
ICA->getOperand(1) == FalseValC) &&
|
|
||||||
cast<ConstantInt>(ICA->getOperand(1))->getValue().isPowerOf2()) {
|
|
||||||
// Okay, now we know that everything is set up, we just don't
|
|
||||||
// know whether we have a icmp_ne or icmp_eq and whether the
|
|
||||||
// true or false val is the zero.
|
|
||||||
bool ShouldNotVal = !TrueValC->isZero();
|
|
||||||
ShouldNotVal ^= IC->getPredicate() == ICmpInst::ICMP_NE;
|
|
||||||
Value *V = ICA;
|
|
||||||
if (ShouldNotVal)
|
|
||||||
V = Builder->CreateXor(V, ICA->getOperand(1));
|
|
||||||
return ReplaceInstUsesWith(SI, V);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we are selecting two values based on a comparison of the two values.
|
// See if we are selecting two values based on a comparison of the two values.
|
||||||
|
@ -223,6 +223,31 @@ define i32 @test15d(i32 %X) {
|
|||||||
; CHECK: ret i32 %t1
|
; CHECK: ret i32 %t1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
;; (a & 128) ? 256 : 0
|
||||||
|
define i32 @test15e(i32 %X) {
|
||||||
|
%t1 = and i32 %X, 128
|
||||||
|
%t2 = icmp ne i32 %t1, 0
|
||||||
|
%t3 = select i1 %t2, i32 256, i32 0
|
||||||
|
ret i32 %t3
|
||||||
|
; CHECK: @test15e
|
||||||
|
; CHECK: %t1 = shl i32 %X, 1
|
||||||
|
; CHECK: and i32 %t1, 256
|
||||||
|
; CHECK: ret i32
|
||||||
|
}
|
||||||
|
|
||||||
|
;; (a & 128) ? 0 : 256
|
||||||
|
define i32 @test15f(i32 %X) {
|
||||||
|
%t1 = and i32 %X, 128
|
||||||
|
%t2 = icmp ne i32 %t1, 0
|
||||||
|
%t3 = select i1 %t2, i32 0, i32 256
|
||||||
|
ret i32 %t3
|
||||||
|
; CHECK: @test15f
|
||||||
|
; CHECK: %t1 = shl i32 %X, 1
|
||||||
|
; CHECK: and i32 %t1, 256
|
||||||
|
; CHECK: xor i32 %{{.*}}, 256
|
||||||
|
; CHECK: ret i32
|
||||||
|
}
|
||||||
|
|
||||||
define i32 @test16(i1 %C, i32* %P) {
|
define i32 @test16(i1 %C, i32* %P) {
|
||||||
%P2 = select i1 %C, i32* %P, i32* null
|
%P2 = select i1 %C, i32* %P, i32* null
|
||||||
%V = load i32* %P2
|
%V = load i32* %P2
|
||||||
|
Loading…
Reference in New Issue
Block a user