diff options
author | Matthias Braun <matthiasb@fb.com> | 2021-09-27 17:57:22 -0700 |
---|---|---|
committer | Matthias Braun <matze@braunis.de> | 2022-01-11 09:07:29 -0800 |
commit | ad25f8a556d239d8b7d17383cf1a0771359521fd (patch) | |
tree | 93eb034f7cbf67f9f4a294b10f8955c077c2eff7 /llvm/test/CodeGen/X86/peep-test-5.ll | |
parent | be1cc64cc13cb24bcd9ed097925a140d74beaa45 (diff) | |
download | llvm-optimize_compinstr_fix.tar.gz |
X86InstrInfo: Support immediates that are +1/-1 different in optimizeCompareInstroptimize_compinstr_fix
This is a re-commit of e2c7ee0743592e39274e28dbe0d0c213ba342317 which
was reverted in a2a58d91e82db38fbdf88cc317dcb3753d79d492 and
ea81cea8163a1a0e54df42103ee1c657bbf03791. This includes a fix to
consistently check for EFLAGS being live-out. See phabricator
review.
Original Summary:
This extends `optimizeCompareInstr` to re-use previous comparison
results if the previous comparison was with an immediate that was 1
bigger or smaller. Example:
CMP x, 13
...
CMP x, 12 ; can be removed if we change the SETg
SETg ... ; x > 12 changed to `SETge` (x >= 13) removing CMP
Motivation: This often happens because SelectionDAG canonicalization
tends to add/subtract 1 often when optimizing for fallthrough blocks.
Example for `x > C` the fallthrough optimization switches true/false
blocks with `!(x > C)` --> `x <= C` and canonicalization turns this into
`x < C + 1`.
Differential Revision: https://reviews.llvm.org/D110867
Diffstat (limited to 'llvm/test/CodeGen/X86/peep-test-5.ll')
-rw-r--r-- | llvm/test/CodeGen/X86/peep-test-5.ll | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/llvm/test/CodeGen/X86/peep-test-5.ll b/llvm/test/CodeGen/X86/peep-test-5.ll new file mode 100644 index 000000000000..2530cf6576b8 --- /dev/null +++ b/llvm/test/CodeGen/X86/peep-test-5.ll @@ -0,0 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -o - %s -mtriple=x86_64-- | FileCheck %s +; Example of a decref operation with "immortal" objects. +; void decref(long* refcount) { +; long count = *refcount; +; if (count == 1) { free_object() } +; else if (count > 1) { *refcount = count - 1; } +; else { /* immortal */ } +; } +; Resulting assembly should share flags from single CMP instruction for both +; conditions! +define void @decref(i32* %p) { +; CHECK-LABEL: decref: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movl (%rdi), %eax +; CHECK-NEXT: cmpl $1, %eax +; CHECK-NEXT: jne .LBB0_2 +; CHECK-NEXT: # %bb.1: # %bb_free +; CHECK-NEXT: callq free_object@PLT +; CHECK-NEXT: .LBB0_4: # %end +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB0_2: # %bb2 +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: jle .LBB0_4 +; CHECK-NEXT: # %bb.3: # %bb_dec +; CHECK-NEXT: decl %eax +; CHECK-NEXT: movl %eax, (%rdi) +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq + %count = load i32, i32* %p, align 4 + %cmp0 = icmp eq i32 %count, 1 + br i1 %cmp0, label %bb_free, label %bb2 + +bb2: + %cmp1 = icmp sgt i32 %count, 1 + br i1 %cmp1, label %bb_dec, label %end + +bb_dec: + %dec = add nsw i32 %count, -1 + store i32 %dec, i32* %p, align 4 + br label %end + +bb_free: + call void @free_object() + br label %end + +end: + ret void +} + +declare void @free_object() |