diff --git a/lib/Target/X86/README.txt b/lib/Target/X86/README.txt index a305ae6ec55..181c1bd4a9a 100644 --- a/lib/Target/X86/README.txt +++ b/lib/Target/X86/README.txt @@ -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 properly. diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 2cbb810fc15..6f0da3eb64a 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -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(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(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) { Value *CondVal = SI.getCondition(); @@ -509,32 +560,9 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { Value *NotCond = Builder->CreateNot(CondVal, "not."+CondVal->getName()); return new SExtInst(NotCond, SI.getType()); } - - if (ICmpInst *IC = dyn_cast(SI.getCondition())) { - // 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, eliminate this whole mess. This corresponds to - // cases like this: ((X & 27) ? 27 : 0) - if (TrueValC->isZero() || FalseValC->isZero()) - if (IC->isEquality() && isa(IC->getOperand(1)) && - cast(IC->getOperand(1))->isNullValue()) - if (Instruction *ICA = dyn_cast(IC->getOperand(0))) - if (ICA->getOpcode() == Instruction::And && - isa(ICA->getOperand(1)) && - (ICA->getOperand(1) == TrueValC || - ICA->getOperand(1) == FalseValC) && - cast(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); - } - } + + if (Value *V = foldSelectICmpAnd(SI, TrueValC, FalseValC, Builder)) + return ReplaceInstUsesWith(SI, V); } // See if we are selecting two values based on a comparison of the two values. diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 120d158aa66..e9efa74e1a2 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -223,6 +223,31 @@ define i32 @test15d(i32 %X) { ; 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) { %P2 = select i1 %C, i32* %P, i32* null %V = load i32* %P2