[llvm] r335622 - [InstCombine] fold urem with sext bool divisor
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 26 09:30:00 PDT 2018
Author: spatel
Date: Tue Jun 26 09:30:00 2018
New Revision: 335622
URL: http://llvm.org/viewvc/llvm-project?rev=335622&view=rev
Log:
[InstCombine] fold urem with sext bool divisor
Similar to other patches in this series:
https://reviews.llvm.org/rL335512
https://reviews.llvm.org/rL335527
https://reviews.llvm.org/rL335597
https://reviews.llvm.org/rL335616
...this is filling a gap in analysis that is exposed by an unrelated select-of-constants transform.
I didn't see a way to unify the sext cases because each div/rem opcode results in a different fold.
Note that in this case, the backend might want to convert the select into math:
Name: sext urem
%e = sext i1 %x to i32
%r = urem i32 %y, %e
=>
%c = icmp eq i32 %y, -1
%z = zext i1 %c to i32
%r = add i32 %z, %y
Modified:
llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
llvm/trunk/test/Transforms/InstCombine/rem.ll
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=335622&r1=335621&r2=335622&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Tue Jun 26 09:30:00 2018
@@ -1295,8 +1295,9 @@ Instruction *InstCombiner::visitURem(Bin
// X urem Y -> X and Y-1, where Y is a power of 2,
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+ Type *Ty = I.getType();
if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
- Constant *N1 = Constant::getAllOnesValue(I.getType());
+ Constant *N1 = Constant::getAllOnesValue(Ty);
Value *Add = Builder.CreateAdd(Op1, N1);
return BinaryOperator::CreateAnd(Op0, Add);
}
@@ -1304,7 +1305,7 @@ Instruction *InstCombiner::visitURem(Bin
// 1 urem X -> zext(X != 1)
if (match(Op0, m_One())) {
Value *Cmp = Builder.CreateICmpNE(Op1, Op0);
- Value *Ext = Builder.CreateZExt(Cmp, I.getType());
+ Value *Ext = Builder.CreateZExt(Cmp, Ty);
return replaceInstUsesWith(I, Ext);
}
@@ -1315,6 +1316,16 @@ Instruction *InstCombiner::visitURem(Bin
return SelectInst::Create(Cmp, Op0, Sub);
}
+ // If the divisor is a sext of a boolean, then the divisor must be max
+ // unsigned value (-1). Therefore, the remainder is Op0 unless Op0 is also
+ // max unsigned value. In that case, the remainder is 0:
+ // urem Op0, (sext i1 X) --> (Op0 == -1) ? 0 : Op0
+ Value *X;
+ if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
+ Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::getAllOnesValue(Ty));
+ return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Op0);
+ }
+
return nullptr;
}
Modified: llvm/trunk/test/Transforms/InstCombine/rem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/rem.ll?rev=335622&r1=335621&r2=335622&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/rem.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/rem.ll Tue Jun 26 09:30:00 2018
@@ -60,8 +60,8 @@ define i5 @biggest_divisor(i5 %x) {
define i8 @urem_with_sext_bool_divisor(i1 %x, i8 %y) {
; CHECK-LABEL: @urem_with_sext_bool_divisor(
-; CHECK-NEXT: [[S:%.*]] = sext i1 [[X:%.*]] to i8
-; CHECK-NEXT: [[REM:%.*]] = urem i8 [[Y:%.*]], [[S]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], -1
+; CHECK-NEXT: [[REM:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y]]
; CHECK-NEXT: ret i8 [[REM]]
;
%s = sext i1 %x to i8
@@ -71,8 +71,8 @@ define i8 @urem_with_sext_bool_divisor(i
define <2 x i8> @urem_with_sext_bool_divisor_vec(<2 x i1> %x, <2 x i8> %y) {
; CHECK-LABEL: @urem_with_sext_bool_divisor_vec(
-; CHECK-NEXT: [[S:%.*]] = sext <2 x i1> [[X:%.*]] to <2 x i8>
-; CHECK-NEXT: [[REM:%.*]] = urem <2 x i8> [[Y:%.*]], [[S]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[Y:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> zeroinitializer, <2 x i8> [[Y]]
; CHECK-NEXT: ret <2 x i8> [[REM]]
;
%s = sext <2 x i1> %x to <2 x i8>
More information about the llvm-commits
mailing list