[PATCH] D69245: [InstCombine] Canonicalize uadd.with.overflow to uadd.sat
Dave Green via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 21 02:42:38 PDT 2019
dmgreen created this revision.
dmgreen added reviewers: nikic, lebedev.ri, spatel.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.
This adds some patterns to transform uadd.with.overflow to uadd.sat (with usub.with.overflow to usub.sat too). The patterns selects from UINTMAX (or 0 for subs) depending on whether the operation overflowed.
Signed patterns are a little more involved (they can wrap in two directions), but can be added here in a followup patch too.
https://reviews.llvm.org/D69245
Files:
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
llvm/test/Transforms/InstCombine/overflow_to_sat.ll
Index: llvm/test/Transforms/InstCombine/overflow_to_sat.ll
===================================================================
--- llvm/test/Transforms/InstCombine/overflow_to_sat.ll
+++ llvm/test/Transforms/InstCombine/overflow_to_sat.ll
@@ -3,10 +3,7 @@
define i32 @uadd(i32 %x, i32 %y) {
; CHECK-LABEL: @uadd(
-; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
-; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1
-; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0
-; CHECK-NEXT: [[S:%.*]] = select i1 [[O]], i32 -1, i32 [[A]]
+; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
; CHECK-NEXT: ret i32 [[S]]
;
%ao = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
@@ -18,10 +15,7 @@
define i32 @usub(i32 %x, i32 %y) {
; CHECK-LABEL: @usub(
-; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
-; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1
-; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0
-; CHECK-NEXT: [[S:%.*]] = select i1 [[O]], i32 0, i32 [[A]]
+; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
; CHECK-NEXT: ret i32 [[S]]
;
%ao = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y)
Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1733,6 +1733,44 @@
return nullptr;
}
+/// Turn A, O = uadd.with.overflow X, Y; O ? -1 : A --> uadd_sat X, Y
+/// And A, O = usub.with.overflow X, Y; O ? 0 : A --> usub_sat X, Y
+static Instruction *
+foldOverflowingAddSubSelect(SelectInst &SI, InstCombiner::BuilderTy &Builder) {
+ auto *CondVal = dyn_cast<ExtractValueInst>(SI.getCondition());
+ Value *TrueVal = SI.getTrueValue();
+ auto *FalseVal = dyn_cast<ExtractValueInst>(SI.getFalseValue());
+ if (!CondVal || !FalseVal)
+ return nullptr;
+
+ // Check the extracts point to the same instruction
+ if (CondVal->getNumIndices() != 1 || CondVal->getIndices()[0] != 1)
+ return nullptr;
+ if (FalseVal->getNumIndices() != 1 || FalseVal->getIndices()[0] != 0)
+ return nullptr;
+ if (CondVal->getAggregateOperand() != FalseVal->getAggregateOperand())
+ return nullptr;
+ auto *II = dyn_cast<IntrinsicInst>(CondVal->getAggregateOperand());
+ if (!II)
+ return nullptr;
+
+ Intrinsic::ID NewIntrinsicID;
+ if (II->getIntrinsicID() == Intrinsic::uadd_with_overflow &&
+ match(TrueVal, m_AllOnes()))
+ // A, O = uadd.with.overflow X, Y; O ? -1 : A --> uadd_sat X, Y
+ NewIntrinsicID = Intrinsic::uadd_sat;
+ else if (II->getIntrinsicID() == Intrinsic::usub_with_overflow &&
+ match(TrueVal, m_Zero()))
+ // A, O = usub.with.overflow X, Y; O ? 0 : A --> usub_sat X, Y
+ NewIntrinsicID = Intrinsic::usub_sat;
+ else
+ return nullptr;
+
+ Function *F =
+ Intrinsic::getDeclaration(SI.getModule(), NewIntrinsicID, SI.getType());
+ return CallInst::Create(F, {II->getArgOperand(0), II->getArgOperand(1)});
+}
+
Instruction *InstCombiner::foldSelectExtConst(SelectInst &Sel) {
Constant *C;
if (!match(Sel.getTrueValue(), m_Constant(C)) &&
@@ -2399,6 +2437,8 @@
if (Instruction *Add = foldAddSubSelect(SI, Builder))
return Add;
+ if (Instruction *Add = foldOverflowingAddSubSelect(SI, Builder))
+ return Add;
// Turn (select C, (op X, Y), (op X, Z)) -> (op X, (select C, Y, Z))
auto *TI = dyn_cast<Instruction>(TrueVal);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69245.225841.patch
Type: text/x-patch
Size: 3721 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191021/a2fdab29/attachment.bin>
More information about the llvm-commits
mailing list