[llvm] r354746 - [CGP] add special-cases to form unsigned add with overflow (PR40486)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 24 07:31:28 PST 2019


Author: spatel
Date: Sun Feb 24 07:31:27 2019
New Revision: 354746

URL: http://llvm.org/viewvc/llvm-project?rev=354746&view=rev
Log:
[CGP] add special-cases to form unsigned add with overflow (PR40486)

There's likely a missed IR canonicalization for at least 1 of these
patterns. Otherwise, we wouldn't have needed the pattern-matching
enhancement in D57516.

Note that -- unlike usubo added with D57789 -- the TLI hook for
this transform defaults to 'on'. So if there's any perf fallout
from this, targets should look at how they're lowering the uaddo
node in SDAG and/or override that hook.

The x86 diffs suggest that there's some missing pattern-matching
for forming inc/dec.

This should fix the remaining known problems in:
https://bugs.llvm.org/show_bug.cgi?id=40486
https://bugs.llvm.org/show_bug.cgi?id=31754

Modified:
    llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
    llvm/trunk/test/CodeGen/AArch64/uaddo.ll
    llvm/trunk/test/CodeGen/X86/codegen-prepare-uaddo.ll
    llvm/trunk/test/CodeGen/X86/rd-mod-wr-eflags.ll
    llvm/trunk/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll

Modified: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp?rev=354746&r1=354745&r2=354746&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp Sun Feb 24 07:31:27 2019
@@ -1197,6 +1197,31 @@ static bool replaceMathCmpWithIntrinsic(
   return true;
 }
 
+/// Match special-case patterns that check for unsigned add overflow.
+static bool matchUAddWithOverflowConstantEdgeCases(CmpInst *Cmp,
+                                                   BinaryOperator *&Add) {
+  // Add = add A, 1; Cmp = icmp eq A,-1 (overflow if A is max val)
+  // Add = add A,-1; Cmp = icmp ne A, 0 (overflow if A is non-zero)
+  Value *A = Cmp->getOperand(0), *B = Cmp->getOperand(1);
+  ICmpInst::Predicate Pred = Cmp->getPredicate();
+  if (Pred == ICmpInst::ICMP_EQ && match(B, m_AllOnes()))
+    B = ConstantInt::get(B->getType(), 1);
+  else if (Pred == ICmpInst::ICMP_NE && match(B, m_ZeroInt()))
+    B = ConstantInt::get(B->getType(), -1);
+  else
+    return false;
+
+  // Check the users of the variable operand of the compare looking for an add
+  // with the adjusted constant.
+  for (User *U : A->users()) {
+    if (match(U, m_Add(m_Specific(A), m_Specific(B)))) {
+      Add = cast<BinaryOperator>(U);
+      return true;
+    }
+  }
+  return false;
+}
+
 /// Try to combine the compare into a call to the llvm.uadd.with.overflow
 /// intrinsic. Return true if any changes were made.
 static bool combineToUAddWithOverflow(CmpInst *Cmp, const TargetLowering &TLI,
@@ -1204,7 +1229,8 @@ static bool combineToUAddWithOverflow(Cm
   Value *A, *B;
   BinaryOperator *Add;
   if (!match(Cmp, m_UAddWithOverflow(m_Value(A), m_Value(B), m_BinOp(Add))))
-    return false;
+    if (!matchUAddWithOverflowConstantEdgeCases(Cmp, Add))
+      return false;
 
   if (!TLI.shouldFormOverflowOp(ISD::UADDO,
                                 TLI.getValueType(DL, Add->getType())))
@@ -1216,13 +1242,6 @@ static bool combineToUAddWithOverflow(Cm
   if (Add->getParent() != Cmp->getParent() && !Add->hasOneUse())
     return false;
 
-#ifndef NDEBUG
-  // Someday m_UAddWithOverflow may get smarter, but this is a safe assumption
-  // for now:
-  if (Add->hasOneUse())
-    assert(*Add->user_begin() == Cmp && "expected!");
-#endif
-
   if (!replaceMathCmpWithIntrinsic(Add, Cmp, Intrinsic::uadd_with_overflow))
     return false;
 

Modified: llvm/trunk/test/CodeGen/AArch64/uaddo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/uaddo.ll?rev=354746&r1=354745&r2=354746&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/uaddo.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/uaddo.ll Sun Feb 24 07:31:27 2019
@@ -8,9 +8,8 @@
 define i1 @uaddo_i64_increment_alt(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_increment_alt:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #1 // =1
-; CHECK-NEXT:    add x8, x0, #1 // =1
-; CHECK-NEXT:    cset w0, eq
+; CHECK-NEXT:    adds x8, x0, #1 // =1
+; CHECK-NEXT:    cset w0, hs
 ; CHECK-NEXT:    str x8, [x1]
 ; CHECK-NEXT:    ret
   %a = add i64 %x, 1
@@ -24,11 +23,9 @@ define i1 @uaddo_i64_increment_alt(i64 %
 define i1 @uaddo_i64_increment_alt_dom(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_increment_alt_dom:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #1 // =1
-; CHECK-NEXT:    cset w8, eq
-; CHECK-NEXT:    add x9, x0, #1 // =1
-; CHECK-NEXT:    mov w0, w8
-; CHECK-NEXT:    str x9, [x1]
+; CHECK-NEXT:    adds x8, x0, #1 // =1
+; CHECK-NEXT:    cset w0, hs
+; CHECK-NEXT:    str x8, [x1]
 ; CHECK-NEXT:    ret
   %ov = icmp eq i64 %x, -1
   %a = add i64 %x, 1
@@ -41,9 +38,8 @@ define i1 @uaddo_i64_increment_alt_dom(i
 define i1 @uaddo_i64_decrement_alt(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_decrement_alt:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmp x0, #0 // =0
-; CHECK-NEXT:    sub x8, x0, #1 // =1
-; CHECK-NEXT:    cset w0, ne
+; CHECK-NEXT:    subs x8, x0, #1 // =1
+; CHECK-NEXT:    cset w0, hs
 ; CHECK-NEXT:    str x8, [x1]
 ; CHECK-NEXT:    ret
   %a = add i64 %x, -1
@@ -57,11 +53,9 @@ define i1 @uaddo_i64_decrement_alt(i64 %
 define i1 @uaddo_i64_decrement_alt_dom(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_decrement_alt_dom:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmp x0, #0 // =0
-; CHECK-NEXT:    cset w8, ne
-; CHECK-NEXT:    sub x9, x0, #1 // =1
-; CHECK-NEXT:    mov w0, w8
-; CHECK-NEXT:    str x9, [x1]
+; CHECK-NEXT:    subs x8, x0, #1 // =1
+; CHECK-NEXT:    cset w0, hs
+; CHECK-NEXT:    str x8, [x1]
 ; CHECK-NEXT:    ret
   %ov = icmp ne i64 %x, 0
   %a = add i64 %x, -1

Modified: llvm/trunk/test/CodeGen/X86/codegen-prepare-uaddo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/codegen-prepare-uaddo.ll?rev=354746&r1=354745&r2=354746&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/codegen-prepare-uaddo.ll (original)
+++ llvm/trunk/test/CodeGen/X86/codegen-prepare-uaddo.ll Sun Feb 24 07:31:27 2019
@@ -229,12 +229,7 @@ define void @test_18446744073709551614(i
 define void @test_18446744073709551615(i64*, i64*) {
 ; CHECK-LABEL: test_18446744073709551615:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq (%rdi), %rax
-; CHECK-NEXT:    leaq -1(%rax), %rcx
-; CHECK-NEXT:    movq %rcx, (%rdi)
-; CHECK-NEXT:    testq %rax, %rax
-; CHECK-NEXT:    setne %al
-; CHECK-NEXT:    addb $-1, %al
+; CHECK-NEXT:    addq $-1, (%rdi)
 ; CHECK-NEXT:    adcq $0, (%rsi)
 ; CHECK-NEXT:    retq
   %3 = load i64, i64* %0, align 8
@@ -272,10 +267,9 @@ define i1 @illegal_type(i17 %x, i17* %p)
 define i1 @uaddo_i64_increment_alt(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_increment_alt:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    leaq 1(%rdi), %rax
-; CHECK-NEXT:    movq %rax, (%rsi)
-; CHECK-NEXT:    cmpq $-1, %rdi
+; CHECK-NEXT:    incq %rdi
 ; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rdi, (%rsi)
 ; CHECK-NEXT:    retq
   %a = add i64 %x, 1
   store i64 %a, i64* %p
@@ -288,9 +282,8 @@ define i1 @uaddo_i64_increment_alt(i64 %
 define i1 @uaddo_i64_increment_alt_dom(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_increment_alt_dom:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    cmpq $-1, %rdi
-; CHECK-NEXT:    sete %al
 ; CHECK-NEXT:    incq %rdi
+; CHECK-NEXT:    sete %al
 ; CHECK-NEXT:    movq %rdi, (%rsi)
 ; CHECK-NEXT:    retq
   %ov = icmp eq i64 %x, -1
@@ -304,10 +297,9 @@ define i1 @uaddo_i64_increment_alt_dom(i
 define i1 @uaddo_i64_decrement_alt(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_decrement_alt:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    leaq -1(%rdi), %rax
-; CHECK-NEXT:    movq %rax, (%rsi)
-; CHECK-NEXT:    testq %rdi, %rdi
-; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    addq $-1, %rdi
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    movq %rdi, (%rsi)
 ; CHECK-NEXT:    retq
   %a = add i64 %x, -1
   store i64 %a, i64* %p
@@ -320,9 +312,8 @@ define i1 @uaddo_i64_decrement_alt(i64 %
 define i1 @uaddo_i64_decrement_alt_dom(i64 %x, i64* %p) {
 ; CHECK-LABEL: uaddo_i64_decrement_alt_dom:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    testq %rdi, %rdi
-; CHECK-NEXT:    setne %al
-; CHECK-NEXT:    decq %rdi
+; CHECK-NEXT:    addq $-1, %rdi
+; CHECK-NEXT:    setb %al
 ; CHECK-NEXT:    movq %rdi, (%rsi)
 ; CHECK-NEXT:    retq
   %ov = icmp ne i64 %x, 0

Modified: llvm/trunk/test/CodeGen/X86/rd-mod-wr-eflags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/rd-mod-wr-eflags.ll?rev=354746&r1=354745&r2=354746&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/rd-mod-wr-eflags.ll (original)
+++ llvm/trunk/test/CodeGen/X86/rd-mod-wr-eflags.ll Sun Feb 24 07:31:27 2019
@@ -68,13 +68,12 @@ define i32 @test2() nounwind uwtable ssp
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    pushq %rax
 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
-; CHECK-NEXT:    movq {{.*}}(%rip), %rax
-; CHECK-NEXT:    leaq -1(%rax), %rsi
+; CHECK-NEXT:    movq {{.*}}(%rip), %rsi
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    addq $-1, %rsi
+; CHECK-NEXT:    setb %al
 ; CHECK-NEXT:    movq %rsi, {{.*}}(%rip)
-; CHECK-NEXT:    xorl %ecx, %ecx
-; CHECK-NEXT:    testq %rax, %rax
-; CHECK-NEXT:    setne %cl
-; CHECK-NEXT:    movl %ecx, {{.*}}(%rip)
+; CHECK-NEXT:    movl %eax, {{.*}}(%rip)
 ; CHECK-NEXT:    movl $.L.str, %edi
 ; CHECK-NEXT:    xorl %eax, %eax
 ; CHECK-NEXT:    callq printf

Modified: llvm/trunk/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll?rev=354746&r1=354745&r2=354746&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll (original)
+++ llvm/trunk/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll Sun Feb 24 07:31:27 2019
@@ -162,10 +162,11 @@ define i1 @uaddo_i16_increment_noncanoni
 
 define i1 @uaddo_i64_increment_alt(i64 %x, i64* %p) {
 ; CHECK-LABEL: @uaddo_i64_increment_alt(
-; CHECK-NEXT:    [[A:%.*]] = add i64 [[X:%.*]], 1
-; CHECK-NEXT:    store i64 [[A]], i64* [[P:%.*]]
-; CHECK-NEXT:    [[OV:%.*]] = icmp eq i64 [[X]], -1
-; CHECK-NEXT:    ret i1 [[OV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
+; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
+; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
+; CHECK-NEXT:    store i64 [[MATH]], i64* [[P:%.*]]
+; CHECK-NEXT:    ret i1 [[OV1]]
 ;
   %a = add i64 %x, 1
   store i64 %a, i64* %p
@@ -177,10 +178,11 @@ define i1 @uaddo_i64_increment_alt(i64 %
 
 define i1 @uaddo_i64_increment_alt_dom(i64 %x, i64* %p) {
 ; CHECK-LABEL: @uaddo_i64_increment_alt_dom(
-; CHECK-NEXT:    [[OV:%.*]] = icmp eq i64 [[X:%.*]], -1
-; CHECK-NEXT:    [[A:%.*]] = add i64 [[X]], 1
-; CHECK-NEXT:    store i64 [[A]], i64* [[P:%.*]]
-; CHECK-NEXT:    ret i1 [[OV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
+; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
+; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
+; CHECK-NEXT:    store i64 [[MATH]], i64* [[P:%.*]]
+; CHECK-NEXT:    ret i1 [[OV1]]
 ;
   %ov = icmp eq i64 %x, -1
   %a = add i64 %x, 1
@@ -192,10 +194,11 @@ define i1 @uaddo_i64_increment_alt_dom(i
 
 define i1 @uaddo_i64_decrement_alt(i64 %x, i64* %p) {
 ; CHECK-LABEL: @uaddo_i64_decrement_alt(
-; CHECK-NEXT:    [[A:%.*]] = add i64 [[X:%.*]], -1
-; CHECK-NEXT:    store i64 [[A]], i64* [[P:%.*]]
-; CHECK-NEXT:    [[OV:%.*]] = icmp ne i64 [[X]], 0
-; CHECK-NEXT:    ret i1 [[OV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 -1)
+; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
+; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
+; CHECK-NEXT:    store i64 [[MATH]], i64* [[P:%.*]]
+; CHECK-NEXT:    ret i1 [[OV1]]
 ;
   %a = add i64 %x, -1
   store i64 %a, i64* %p
@@ -207,10 +210,11 @@ define i1 @uaddo_i64_decrement_alt(i64 %
 
 define i1 @uaddo_i64_decrement_alt_dom(i64 %x, i64* %p) {
 ; CHECK-LABEL: @uaddo_i64_decrement_alt_dom(
-; CHECK-NEXT:    [[OV:%.*]] = icmp ne i64 [[X:%.*]], 0
-; CHECK-NEXT:    [[A:%.*]] = add i64 [[X]], -1
-; CHECK-NEXT:    store i64 [[A]], i64* [[P:%.*]]
-; CHECK-NEXT:    ret i1 [[OV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 -1)
+; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
+; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
+; CHECK-NEXT:    store i64 [[MATH]], i64* [[P:%.*]]
+; CHECK-NEXT:    ret i1 [[OV1]]
 ;
   %ov = icmp ne i64 %x, 0
   %a = add i64 %x, -1




More information about the llvm-commits mailing list