diff options
| author | Sanjay Patel <spatel@rotateright.com> | 2016-03-01 23:55:18 +0000 |
|---|---|---|
| committer | Sanjay Patel <spatel@rotateright.com> | 2016-03-01 23:55:18 +0000 |
| commit | 147e9279570a5afa297f9b1a7f5ff0b26a05758d (patch) | |
| tree | bc8153ff050c6bf9026fb5965ecfc48c23a55569 | |
| parent | 947648f5023cb23644cd0071bc958783f74994e4 (diff) | |
| download | bcm5719-llvm-147e9279570a5afa297f9b1a7f5ff0b26a05758d.tar.gz bcm5719-llvm-147e9279570a5afa297f9b1a7f5ff0b26a05758d.zip | |
[InstCombine] convert 'isPositive' and 'isNegative' vector comparisons to shifts (PR26701)
As noted in the code comment, I don't think we can do the same transform that we do for
*scalar* integers comparisons to *vector* integers comparisons because it might pessimize
the general case.
Exhibit A for an incomplete integer comparison ISA remains x86 SSE/AVX: it only has EQ and GT
for integer vectors.
But we should now recognize all the variants of this construct and produce the optimal code
for the cases shown in:
https://llvm.org/bugs/show_bug.cgi?id=26701
llvm-svn: 262424
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 22 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/vec_sext.ll | 28 |
2 files changed, 45 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 6d0e8821e8f..3cf38c33853 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -976,16 +976,28 @@ Instruction *InstCombiner::transformSExtICmp(ICmpInst *ICI, Instruction &CI) { // (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if negative // (x >s -1) ? -1 : 0 -> not (ashr x, 31) -> all ones if positive if ((Pred == ICmpInst::ICMP_SLT && Op1C->isNullValue()) || - (Pred == ICmpInst::ICMP_SGT && Op1C->isAllOnesValue())) { + (Pred == ICmpInst::ICMP_SGT && Op1C->isAllOnesValue()) || + // The following patterns should only be present for vectors. + // For scalar integers, the comparison should be canonicalized to one of + // the above forms. We don't do that for vectors because vector ISAs may + // not have a full range of comparison operators. This transform, + // however, will simplify the IR, so we always do it. + // + // (x <=s -1) ? -1 : 0 -> ashr x, 31 -> all ones if negative + // (x >=s 0) ? -1 : 0 -> not (ashr x, 31) -> all ones if positive + (Pred == ICmpInst::ICMP_SLE && Op1C->isAllOnesValue()) || + (Pred == ICmpInst::ICMP_SGE && Op1C->isNullValue())) { Value *Sh = ConstantInt::get(Op0->getType(), - Op0->getType()->getScalarSizeInBits()-1); - Value *In = Builder->CreateAShr(Op0, Sh, Op0->getName()+".lobit"); + Op0->getType()->getScalarSizeInBits() - 1); + Value *In = Builder->CreateAShr(Op0, Sh, Op0->getName() + ".lobit"); if (In->getType() != CI.getType()) In = Builder->CreateIntCast(In, CI.getType(), true/*SExt*/); - if (Pred == ICmpInst::ICMP_SGT) - In = Builder->CreateNot(In, In->getName()+".not"); + // Invert the sign bit if the comparison was checking for 'is positive'. + if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) + In = Builder->CreateNot(In, In->getName() + ".not"); + return replaceInstUsesWith(CI, In); } } diff --git a/llvm/test/Transforms/InstCombine/vec_sext.ll b/llvm/test/Transforms/InstCombine/vec_sext.ll index 6f0d21476e3..670789af050 100644 --- a/llvm/test/Transforms/InstCombine/vec_sext.ll +++ b/llvm/test/Transforms/InstCombine/vec_sext.ll @@ -43,3 +43,31 @@ entry: ; CHECK: and <4 x i32> %b.lobit.not, %sub ; CHECK: or <4 x i32> %0, %1 } + +;;; PR26701: https://llvm.org/bugs/show_bug.cgi?id=26701 + +; Signed-less-than-or-equal to -1 is the same operation as above: smear the sign bit. + +define <2 x i32> @is_negative(<2 x i32> %a) { + %cmp = icmp sle <2 x i32> %a, <i32 -1, i32 -1> + %sext = sext <2 x i1> %cmp to <2 x i32> + ret <2 x i32> %sext + +; CHECK-LABEL: @is_negative( +; CHECK-NEXT: ashr <2 x i32> %a, <i32 31, i32 31> +; CHECK-NEXT: ret <2 x i32> +} + +; Signed-greater-than-or-equal to 0 is 'not' of the same operation as above. + +define <2 x i32> @is_positive(<2 x i32> %a) { + %cmp = icmp sge <2 x i32> %a, zeroinitializer + %sext = sext <2 x i1> %cmp to <2 x i32> + ret <2 x i32> %sext + +; CHECK-LABEL: @is_positive( +; CHECK-NEXT: [[SHIFT:%[a-zA-Z0-9.]+]] = ashr <2 x i32> %a, <i32 31, i32 31> +; CHECK-NEXT: xor <2 x i32> [[SHIFT]], <i32 -1, i32 -1> +; CHECK-NEXT: ret <2 x i32> +} + |

