mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[InstCombine] canonicalize* LE/GE vector integer comparisons to LT/GT (PR26701, PR26819)
*We don't currently handle the edge case constants (min/max values), so it's not a complete canonicalization. To fully solve the motivating bugs, we need to enhance this to recognize a zero vector too because that's a ConstantAggregateZero which is a ConstantData, not a ConstantVector or a ConstantDataVector. Differential Revision: http://reviews.llvm.org/D17859 llvm-svn: 269426
This commit is contained in:
parent
e327d609fa
commit
2c688c8b52
@ -3125,11 +3125,64 @@ static ICmpInst *canonicalizeCmpWithConstant(ICmpInst &I,
|
||||
assert(!Op1C->isMinValue(true)); // A >=s MIN -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_SGT, Op0, Builder.getInt(Op1Val - 1));
|
||||
default:
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Handle vectors.
|
||||
// The usual vector types are ConstantDataVector. Exotic vector types are
|
||||
// ConstantVector. They both derive from Constant.
|
||||
if (isa<ConstantDataVector>(Op1) || isa<ConstantVector>(Op1)) {
|
||||
Constant *Op1C = cast<Constant>(Op1);
|
||||
Type *Op1Type = Op1->getType();
|
||||
unsigned NumElts = Op1Type->getVectorNumElements();
|
||||
|
||||
// Set the new comparison predicate and splat a vector of 1 or -1 to
|
||||
// increment or decrement the vector constants. But first, check that no
|
||||
// elements of the constant vector would overflow/underflow when we
|
||||
// increment/decrement the constants.
|
||||
//
|
||||
// TODO? If the edge cases for vectors were guaranteed to be handled as they
|
||||
// are for scalar, we could remove the min/max checks here. However, to do
|
||||
// that, we would have to use insertelement/shufflevector to replace edge
|
||||
// values.
|
||||
|
||||
CmpInst::Predicate NewPred;
|
||||
Constant *OneOrNegOne = nullptr;
|
||||
switch (I.getPredicate()) {
|
||||
case ICmpInst::ICMP_ULE:
|
||||
for (unsigned i = 0; i != NumElts; ++i)
|
||||
if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMaxValue(false))
|
||||
return nullptr;
|
||||
NewPred = ICmpInst::ICMP_ULT;
|
||||
OneOrNegOne = ConstantInt::get(Op1Type, 1);
|
||||
break;
|
||||
case ICmpInst::ICMP_SLE:
|
||||
for (unsigned i = 0; i != NumElts; ++i)
|
||||
if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMaxValue(true))
|
||||
return nullptr;
|
||||
NewPred = ICmpInst::ICMP_SLT;
|
||||
OneOrNegOne = ConstantInt::get(Op1Type, 1);
|
||||
break;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
for (unsigned i = 0; i != NumElts; ++i)
|
||||
if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMinValue(false))
|
||||
return nullptr;
|
||||
NewPred = ICmpInst::ICMP_UGT;
|
||||
OneOrNegOne = ConstantInt::get(Op1Type, -1);
|
||||
break;
|
||||
case ICmpInst::ICMP_SGE:
|
||||
for (unsigned i = 0; i != NumElts; ++i)
|
||||
if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMinValue(true))
|
||||
return nullptr;
|
||||
NewPred = ICmpInst::ICMP_SGT;
|
||||
OneOrNegOne = ConstantInt::get(Op1Type, -1);
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new ICmpInst(NewPred, Op0, ConstantExpr::getAdd(Op1C, OneOrNegOne));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
124
test/Transforms/InstCombine/icmp-vec.ll
Normal file
124
test/Transforms/InstCombine/icmp-vec.ll
Normal file
@ -0,0 +1,124 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
|
||||
; Canonicalize vector ge/le comparisons with constants to gt/lt.
|
||||
|
||||
; Normal types are ConstantDataVectors. Test the constant values adjacent to the
|
||||
; min/max values that we're not allowed to transform.
|
||||
|
||||
define <2 x i1> @sge(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @sge(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> %x, <i8 -128, i8 126>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp sge <2 x i8> %x, <i8 -127, i8 -129>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
||||
define <2 x i1> @uge(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @uge(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> %x, <i8 -2, i8 0>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp uge <2 x i8> %x, <i8 -1, i8 1>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
||||
define <2 x i1> @sle(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @sle(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> %x, <i8 127, i8 -127>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp sle <2 x i8> %x, <i8 126, i8 128>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
||||
define <2 x i1> @ule(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @ule(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> %x, <i8 -1, i8 1>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp ule <2 x i8> %x, <i8 254, i8 0>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
||||
; Weird types are ConstantVectors, not ConstantDataVectors. For an i3 type:
|
||||
; Signed min = -4
|
||||
; Unsigned min = 0
|
||||
; Signed max = 3
|
||||
; Unsigned max = 7
|
||||
|
||||
define <3 x i1> @sge_weird(<3 x i3> %x) {
|
||||
; CHECK-LABEL: @sge_weird(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i3> %x, <i3 -4, i3 2, i3 -1>
|
||||
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp sge <3 x i3> %x, <i3 -3, i3 -5, i3 0>
|
||||
ret <3 x i1> %cmp
|
||||
}
|
||||
|
||||
define <3 x i1> @uge_weird(<3 x i3> %x) {
|
||||
; CHECK-LABEL: @uge_weird(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <3 x i3> %x, <i3 -2, i3 0, i3 1>
|
||||
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp uge <3 x i3> %x, <i3 -1, i3 1, i3 2>
|
||||
ret <3 x i1> %cmp
|
||||
}
|
||||
|
||||
define <3 x i1> @sle_weird(<3 x i3> %x) {
|
||||
; CHECK-LABEL: @sle_weird(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i3> %x, <i3 3, i3 -3, i3 1>
|
||||
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp sle <3 x i3> %x, <i3 2, i3 4, i3 0>
|
||||
ret <3 x i1> %cmp
|
||||
}
|
||||
|
||||
define <3 x i1> @ule_weird(<3 x i3> %x) {
|
||||
; CHECK-LABEL: @ule_weird(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <3 x i3> %x, <i3 -1, i3 1, i3 2>
|
||||
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp ule <3 x i3> %x, <i3 6, i3 0, i3 1>
|
||||
ret <3 x i1> %cmp
|
||||
}
|
||||
|
||||
; We can't do the transform if any constants are already at the limits.
|
||||
|
||||
define <2 x i1> @sge_min(<2 x i3> %x) {
|
||||
; CHECK-LABEL: @sge_min(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i3> %x, <i3 -4, i3 1>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp sge <2 x i3> %x, <i3 -4, i3 1>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
||||
define <2 x i1> @uge_min(<2 x i3> %x) {
|
||||
; CHECK-LABEL: @uge_min(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp uge <2 x i3> %x, <i3 1, i3 0>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp uge <2 x i3> %x, <i3 1, i3 0>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
||||
define <2 x i1> @sle_max(<2 x i3> %x) {
|
||||
; CHECK-LABEL: @sle_max(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i3> %x, <i3 1, i3 3>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp sle <2 x i3> %x, <i3 1, i3 3>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
||||
define <2 x i1> @ule_max(<2 x i3> %x) {
|
||||
; CHECK-LABEL: @ule_max(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ule <2 x i3> %x, <i3 -1, i3 1>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%cmp = icmp ule <2 x i3> %x, <i3 7, i3 1>
|
||||
ret <2 x i1> %cmp
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ for.end:
|
||||
;CHECK-LABEL: @reduction_func(
|
||||
;CHECK: load <4 x i32>
|
||||
;CHECK: add <4 x i32>
|
||||
;CHECK: icmp sle <4 x i32>
|
||||
;CHECK: icmp slt <4 x i32>
|
||||
;CHECK: select <4 x i1>
|
||||
;CHECK: ret i32
|
||||
define i32 @reduction_func(i32* nocapture %A, i32 %n) nounwind uwtable readonly ssp {
|
||||
|
Loading…
Reference in New Issue
Block a user