Commit c0886dd5 authored by Juergen Ributzka's avatar Juergen Ributzka
Browse files

[FastISel][AArch64] Factor out ADDS/SUBS instruction emission and add support...

[FastISel][AArch64] Factor out ADDS/SUBS instruction emission and add support for extensions and shift folding.

Factor out the ADDS/SUBS instruction emission code into helper functions and
make the helper functions more clever to support most of the different ADDS/SUBS
instructions the architecture support. This includes better immedediate support,
shift folding, and sign-/zero-extend folding.

This fixes <rdar://problem/17913111>.

llvm-svn: 216033
parent a3c8f042
Loading
Loading
Loading
Loading
+397 −224

File changed.

Preview size limit exceeded, changes collapsed.

+72 −76
Original line number Diff line number Diff line
; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
; RUN: llc -O0 -fast-isel-abort -mtriple=arm64-apple-darwin < %s | FileCheck %s

define i32 @icmp_eq_imm(i32 %a) nounwind ssp {
entry:
; CHECK: icmp_eq_imm
; CHECK-LABEL: icmp_eq_imm
; CHECK:       cmp w0, #31
; CHECK: cset w0, eq
; CHECK-NEXT:  cset w0, eq
  %cmp = icmp eq i32 %a, 31
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -12,19 +12,19 @@ entry:

define i32 @icmp_eq_neg_imm(i32 %a) nounwind ssp {
entry:
; CHECK: icmp_eq_neg_imm
; CHECK-LABEL: icmp_eq_neg_imm
; CHECK:       cmn w0, #7
; CHECK: cset w0, eq
; CHECK-NEXT:  cset w0, eq
  %cmp = icmp eq i32 %a, -7
  %conv = zext i1 %cmp to i32
  ret i32 %conv
}

define i32 @icmp_eq(i32 %a, i32 %b) nounwind ssp {
define i32 @icmp_eq_i32(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_eq
; CHECK-LABEL: icmp_eq_i32
; CHECK:       cmp w0, w1
; CHECK: cset w0, eq
; CHECK-NEXT:  cset w0, eq
  %cmp = icmp eq i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -32,9 +32,9 @@ entry:

define i32 @icmp_ne(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_ne
; CHECK-LABEL: icmp_ne
; CHECK:       cmp w0, w1
; CHECK: cset w0, ne
; CHECK-NEXT:  cset w0, ne
  %cmp = icmp ne i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -42,9 +42,9 @@ entry:

define i32 @icmp_ugt(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_ugt
; CHECK-LABEL: icmp_ugt
; CHECK:       cmp w0, w1
; CHECK: cset w0, hi
; CHECK-NEXT:  cset w0, hi
  %cmp = icmp ugt i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -52,9 +52,9 @@ entry:

define i32 @icmp_uge(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_uge
; CHECK-LABEL: icmp_uge
; CHECK:       cmp w0, w1
; CHECK: cset w0, hs
; CHECK-NEXT:  cset w0, hs
  %cmp = icmp uge i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -62,9 +62,9 @@ entry:

define i32 @icmp_ult(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_ult
; CHECK-LABEL: icmp_ult
; CHECK:       cmp w0, w1
; CHECK: cset w0, lo
; CHECK-NEXT:  cset w0, lo
  %cmp = icmp ult i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -72,9 +72,9 @@ entry:

define i32 @icmp_ule(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_ule
; CHECK-LABEL: icmp_ule
; CHECK:       cmp w0, w1
; CHECK: cset w0, ls
; CHECK-NEXT:  cset w0, ls
  %cmp = icmp ule i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -82,9 +82,9 @@ entry:

define i32 @icmp_sgt(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_sgt
; CHECK-LABEL: icmp_sgt
; CHECK:       cmp w0, w1
; CHECK: cset w0, gt
; CHECK-NEXT:  cset w0, gt
  %cmp = icmp sgt i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -92,9 +92,9 @@ entry:

define i32 @icmp_sge(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_sge
; CHECK-LABEL: icmp_sge
; CHECK:       cmp w0, w1
; CHECK: cset w0, ge
; CHECK-NEXT:  cset w0, ge
  %cmp = icmp sge i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -102,9 +102,9 @@ entry:

define i32 @icmp_slt(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_slt
; CHECK-LABEL: icmp_slt
; CHECK:       cmp w0, w1
; CHECK: cset w0, lt
; CHECK-NEXT:  cset w0, lt
  %cmp = icmp slt i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -112,9 +112,9 @@ entry:

define i32 @icmp_sle(i32 %a, i32 %b) nounwind ssp {
entry:
; CHECK: icmp_sle
; CHECK-LABEL: icmp_sle
; CHECK:       cmp w0, w1
; CHECK: cset w0, le
; CHECK-NEXT:  cset w0, le
  %cmp = icmp sle i32 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -122,9 +122,9 @@ entry:

define i32 @icmp_i64(i64 %a, i64 %b) nounwind ssp {
entry:
; CHECK: icmp_i64
; CHECK-LABEL: icmp_i64
; CHECK:       cmp  x0, x1
; CHECK: cset w{{[0-9]+}}, le
; CHECK-NEXT:  cset w{{[0-9]+}}, le
  %cmp = icmp sle i64 %a, %b
  %conv = zext i1 %cmp to i32
  ret i32 %conv
@@ -132,33 +132,30 @@ entry:

define zeroext i1 @icmp_eq_i16(i16 %a, i16 %b) nounwind ssp {
entry:
; CHECK: icmp_eq_i16
; CHECK-LABEL: icmp_eq_i16
; CHECK:       sxth w0, w0
; CHECK: sxth w1, w1
; CHECK: cmp  w0, w1
; CHECK: cset w0, eq
; CHECK:       cmp w0, w1, sxth
; CHECK-NEXT:  cset w0, eq
  %cmp = icmp eq i16 %a, %b
  ret i1 %cmp
}

define zeroext i1 @icmp_eq_i8(i8 %a, i8 %b) nounwind ssp {
entry:
; CHECK: icmp_eq_i8
; CHECK-LABEL: icmp_eq_i8
; CHECK:       sxtb w0, w0
; CHECK: sxtb w1, w1
; CHECK: cmp  w0, w1
; CHECK: cset w0, eq
; CHECK-NEXT:  cmp w0, w1, sxtb
; CHECK-NEXT:  cset w0, eq
  %cmp = icmp eq i8 %a, %b
  ret i1 %cmp
}

define i32 @icmp_i16_unsigned(i16 %a, i16 %b) nounwind {
entry:
; CHECK: icmp_i16_unsigned
; CHECK-LABEL: icmp_i16_unsigned
; CHECK:       uxth w0, w0
; CHECK: uxth w1, w1
; CHECK: cmp  w0, w1
; CHECK: cset w0, lo
; CHECK-NEXT:  cmp w0, w1, uxth
; CHECK-NEXT:  cset w0, lo
  %cmp = icmp ult i16 %a, %b
  %conv2 = zext i1 %cmp to i32
  ret i32 %conv2
@@ -166,11 +163,10 @@ entry:

define i32 @icmp_i8_signed(i8 %a, i8 %b) nounwind {
entry:
; CHECK: @icmp_i8_signed
; CHECK-LABEL: icmp_i8_signed
; CHECK:       sxtb w0, w0
; CHECK: sxtb w1, w1
; CHECK: cmp  w0, w1
; CHECK: cset w0, gt
; CHECK-NEXT:  cmp w0, w1, sxtb
; CHECK-NEXT:  cset w0, gt
  %cmp = icmp sgt i8 %a, %b
  %conv2 = zext i1 %cmp to i32
  ret i32 %conv2
@@ -179,11 +175,11 @@ entry:

define i32 @icmp_i16_signed_const(i16 %a) nounwind {
entry:
; CHECK: icmp_i16_signed_const
; CHECK-LABEL: icmp_i16_signed_const
; CHECK:       sxth w0, w0
; CHECK: cmn  w0, #233
; CHECK: cset w0, lt
; CHECK: and w0, w0, #0x1
; CHECK-NEXT:  cmn w0, #233
; CHECK-NEXT:  cset w0, lt
; CHECK-NEXT:  and w0, w0, #0x1
  %cmp = icmp slt i16 %a, -233
  %conv2 = zext i1 %cmp to i32
  ret i32 %conv2
@@ -191,11 +187,11 @@ entry:

define i32 @icmp_i8_signed_const(i8 %a) nounwind {
entry:
; CHECK: icmp_i8_signed_const
; CHECK-LABEL: icmp_i8_signed_const
; CHECK:       sxtb w0, w0
; CHECK: cmp  w0, #124
; CHECK: cset w0, gt
; CHECK: and w0, w0, #0x1
; CHECK-NEXT:  cmp w0, #124
; CHECK-NEXT:  cset w0, gt
; CHECK-NEXT:  and w0, w0, #0x1
  %cmp = icmp sgt i8 %a, 124
  %conv2 = zext i1 %cmp to i32
  ret i32 %conv2
@@ -203,11 +199,11 @@ entry:

define i32 @icmp_i1_unsigned_const(i1 %a) nounwind {
entry:
; CHECK: icmp_i1_unsigned_const
; CHECK: and w0, w0, #0x1
; CHECK: cmp  w0, #0
; CHECK: cset w0, lo
; CHECK-LABEL: icmp_i1_unsigned_const
; CHECK:       and w0, w0, #0x1
; CHECK-NEXT:  cmp w0, #0
; CHECK-NEXT:  cset w0, lo
; CHECK-NEXT:  and w0, w0, #0x1
  %cmp = icmp ult i1 %a, 0
  %conv2 = zext i1 %cmp to i32
  ret i32 %conv2
+14 −0
Original line number Diff line number Diff line
@@ -55,6 +55,20 @@ entry:
  ret i1 %obit
}

; Test shift folding.
define zeroext i1 @saddo5.i32(i32 %v1, i32 %v2, i32* %res) {
entry:
; CHECK-LABEL:  saddo5.i32
; CHECK:        adds {{w[0-9]+}}, w0, w1
; CHECK-NEXT:   cset {{w[0-9]+}}, vs
  %lsl = shl i32 %v2, 16
  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %lsl)
  %val = extractvalue {i32, i1} %t, 0
  %obit = extractvalue {i32, i1} %t, 1
  store i32 %val, i32* %res
  ret i1 %obit
}

define zeroext i1 @saddo1.i64(i64 %v1, i64 %v2, i64* %res) {
entry:
; CHECK-LABEL:  saddo1.i64