| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -mtriple=aarch64-none-linux-gnu < %s -o -| FileCheck %s |
| |
| define i64 @umull(i64 %x0, i64 %x1) { |
| ; CHECK-LABEL: umull: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: umull x0, w1, w0 |
| ; CHECK-NEXT: ret |
| entry: |
| %and = and i64 %x0, 4294967295 |
| %and1 = and i64 %x1, 4294967295 |
| %mul = mul nuw i64 %and1, %and |
| ret i64 %mul |
| } |
| |
| define i64 @umull2(i64 %x, i32 %y) { |
| ; CHECK-LABEL: umull2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: umull x0, w0, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %and = and i64 %x, 4294967295 |
| %conv = zext i32 %y to i64 |
| %mul = mul nuw nsw i64 %and, %conv |
| ret i64 %mul |
| } |
| |
| define i64 @umull2_commuted(i64 %x, i32 %y) { |
| ; CHECK-LABEL: umull2_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: umull x0, w0, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %and = and i64 %x, 4294967295 |
| %conv = zext i32 %y to i64 |
| %mul = mul nuw nsw i64 %conv, %and |
| ret i64 %mul |
| } |
| |
| define i64 @smull(i64 %x0, i64 %x1) { |
| ; CHECK-LABEL: smull: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: smull x0, w1, w0 |
| ; CHECK-NEXT: ret |
| entry: |
| %sext = shl i64 %x0, 32 |
| %conv1 = ashr exact i64 %sext, 32 |
| %sext4 = shl i64 %x1, 32 |
| %conv3 = ashr exact i64 %sext4, 32 |
| %mul = mul nsw i64 %conv3, %conv1 |
| ret i64 %mul |
| } |
| |
| define i64 @smull2(i64 %x, i32 %y) { |
| ; CHECK-LABEL: smull2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: smull x0, w0, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %shl = shl i64 %x, 32 |
| %shr = ashr exact i64 %shl, 32 |
| %conv = sext i32 %y to i64 |
| %mul = mul nsw i64 %shr, %conv |
| ret i64 %mul |
| } |
| |
| define i64 @smull2_commuted(i64 %x, i32 %y) { |
| ; CHECK-LABEL: smull2_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: smull x0, w0, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %shl = shl i64 %x, 32 |
| %shr = ashr exact i64 %shl, 32 |
| %conv = sext i32 %y to i64 |
| %mul = mul nsw i64 %conv, %shr |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsb_b(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smull_ldrsb_b: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsb_b_commuted(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smull_ldrsb_b_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smull x0, w9, w8 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsb_h(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: smull_ldrsb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsb_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: smull_ldrsb_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: smull x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsh_b(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smull_ldrsh_b: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsh_h(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: smull_ldrsh_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsh_h_commuted(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: smull_ldrsh_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smull x0, w9, w8 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsh_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: smull_ldrsh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: smull x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_b(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_b: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext4 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_h(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: smull x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_w_commuted(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_w_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: smull x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| ret i64 %mul |
| } |
| |
| define i64 @smull_sext_bb(i8 %x0, i8 %x1) { |
| ; CHECK-LABEL: smull_sext_bb: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 |
| ; CHECK-NEXT: sxtb x8, w0 |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %sext = sext i8 %x0 to i64 |
| %sext4 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_shift(ptr %x0, i64 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_shift: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtw x9, w1 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %shl = shl i64 %x1, 32 |
| %shr = ashr exact i64 %shl, 32 |
| %mul = mul i64 %sext, %shr |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsh_zextw(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: smull_ldrsh_zextw: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: mov w9, w1 |
| ; CHECK-NEXT: mul x0, x8, x9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %zext = zext i32 %x1 to i64 |
| %mul = mul i64 %sext, %zext |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_zexth(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_zexth: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %zext = zext i16 %x1 to i64 |
| %mul = mul i64 %sext, %zext |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_zextb(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_zextb: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %zext = zext i8 %x1 to i64 |
| %mul = mul i64 %sext, %zext |
| ret i64 %mul |
| } |
| |
| define i64 @smull_ldrsw_zextb_commuted(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smull_ldrsw_zextb_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: smull x0, w9, w8 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %zext = zext i8 %x1 to i64 |
| %mul = mul i64 %zext, %sext |
| ret i64 %mul |
| } |
| |
| define i64 @smaddl_ldrsb_h(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsb_h_commuted(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsb_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smaddl x0, w9, w8, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsh_w(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: smaddl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsh_w_commuted(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsh_w_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: smaddl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsw_b(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsw_b: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsw_b_commuted(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsw_b_commuted: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smaddl x0, w9, w8, x2 |
| ; CHECK-NEXT: ret |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext2, %sext |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsw_ldrsw(ptr %x0, ptr %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsw_ldrsw: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: ldrsw x9, [x1] |
| ; CHECK-NEXT: smaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %ext64_2 = load i32, ptr %x1 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i32 %ext64_2 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_sext_hh(i16 %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_sext_hh: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 |
| ; CHECK-NEXT: sxth x8, w0 |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %sext = sext i16 %x0 to i64 |
| %sext2 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsw_shift(ptr %x0, i64 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsw_shift: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtw x9, w1 |
| ; CHECK-NEXT: smaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %shl = shl i64 %x1, 32 |
| %shr = ashr exact i64 %shl, 32 |
| %mul = mul i64 %sext, %shr |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smaddl_ldrsw_zextb(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: smaddl_ldrsw_zextb: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: smaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %zext = zext i8 %x1 to i64 |
| %mul = mul i64 %sext, %zext |
| %add = add i64 %x2, %mul |
| ret i64 %add |
| } |
| |
| define i64 @smnegl_ldrsb_h(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsb_h_commuted(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsb_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smnegl x0, w9, w8 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsh_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: smnegl x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsh_w_commuted(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsh_w_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: smnegl x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsw_b(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsw_b: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsw_b_commuted(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsw_b_commuted: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smnegl x0, w9, w8 |
| ; CHECK-NEXT: ret |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext2, %sext |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsw_ldrsw(ptr %x0, ptr %x1) { |
| ; CHECK-LABEL: smnegl_ldrsw_ldrsw: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: ldrsw x9, [x1] |
| ; CHECK-NEXT: smnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %ext64_2 = load i32, ptr %x1 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i32 %ext64_2 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_sext_hh(i16 %x0, i16 %x1) { |
| ; CHECK-LABEL: smnegl_sext_hh: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 |
| ; CHECK-NEXT: sxth x8, w0 |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %sext = sext i16 %x0 to i64 |
| %sext2 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsw_shift(ptr %x0, i64 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsw_shift: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtw x9, w1 |
| ; CHECK-NEXT: smnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %shl = shl i64 %x1, 32 |
| %shr = ashr exact i64 %shl, 32 |
| %mul = mul i64 %sext, %shr |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smnegl_ldrsw_zextb(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: smnegl_ldrsw_zextb: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: smnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %zext = zext i8 %x1 to i64 |
| %mul = mul i64 %sext, %zext |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsb_h(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsb_h_commuted(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsb_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsb x8, [x0] |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smsubl x0, w9, w8, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %sext = sext i8 %ext64 to i64 |
| %sext4 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsh_w(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: smsubl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext, %sext4 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsh_w_commuted(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsh_w_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsh x8, [x0] |
| ; CHECK-NEXT: smsubl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %sext = sext i16 %ext64 to i64 |
| %sext4 = sext i32 %x1 to i64 |
| %mul = mul i64 %sext4, %sext |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsw_b(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsw_b: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsw_b_commuted(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsw_b_commuted: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtb x9, w1 |
| ; CHECK-NEXT: smsubl x0, w9, w8, x2 |
| ; CHECK-NEXT: ret |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i8 %x1 to i64 |
| %mul = mul i64 %sext2, %sext |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsw_ldrsw(ptr %x0, ptr %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsw_ldrsw: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: ldrsw x9, [x1] |
| ; CHECK-NEXT: smsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %ext64_2 = load i32, ptr %x1 |
| %sext = sext i32 %ext64 to i64 |
| %sext2 = sext i32 %ext64_2 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_sext_hh(i16 %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_sext_hh: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 |
| ; CHECK-NEXT: sxth x8, w0 |
| ; CHECK-NEXT: sxth x9, w1 |
| ; CHECK-NEXT: smsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %sext = sext i16 %x0 to i64 |
| %sext2 = sext i16 %x1 to i64 |
| %mul = mul i64 %sext, %sext2 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsw_shift(ptr %x0, i64 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsw_shift: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: sxtw x9, w1 |
| ; CHECK-NEXT: smsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %shl = shl i64 %x1, 32 |
| %shr = ashr exact i64 %shl, 32 |
| %mul = mul i64 %sext, %shr |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smsubl_ldrsw_zextb(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: smsubl_ldrsw_zextb: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrsw x8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: smsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %sext = sext i32 %ext64 to i64 |
| %zext = zext i8 %x1 to i64 |
| %mul = mul i64 %sext, %zext |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @smull_sext_ashr31(i32 %a, i64 %b) nounwind { |
| ; CHECK-LABEL: smull_sext_ashr31: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 |
| ; CHECK-NEXT: sxtw x8, w0 |
| ; CHECK-NEXT: asr x9, x1, #31 |
| ; CHECK-NEXT: mul x0, x8, x9 |
| ; CHECK-NEXT: ret |
| entry: |
| %tmp1 = sext i32 %a to i64 |
| %c = ashr i64 %b, 31 |
| %tmp3 = mul i64 %tmp1, %c |
| ret i64 %tmp3 |
| } |
| |
| define i64 @smull_sext_ashr32(i32 %a, i64 %b) nounwind { |
| ; CHECK-LABEL: smull_sext_ashr32: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: asr x8, x1, #32 |
| ; CHECK-NEXT: smull x0, w8, w0 |
| ; CHECK-NEXT: ret |
| entry: |
| %tmp1 = sext i32 %a to i64 |
| %c = ashr i64 %b, 32 |
| %tmp3 = mul i64 %tmp1, %c |
| ret i64 %tmp3 |
| } |
| |
| |
| define i64 @smull_ashr31_both(i64 %a, i64 %b) nounwind { |
| ; CHECK-LABEL: smull_ashr31_both: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: asr x8, x0, #31 |
| ; CHECK-NEXT: asr x9, x1, #31 |
| ; CHECK-NEXT: mul x0, x8, x9 |
| ; CHECK-NEXT: ret |
| entry: |
| %tmp1 = ashr i64 %a, 31 |
| %c = ashr i64 %b, 31 |
| %tmp3 = mul i64 %tmp1, %c |
| ret i64 %tmp3 |
| } |
| |
| define i64 @smull_ashr32_both(i64 %a, i64 %b) nounwind { |
| ; CHECK-LABEL: smull_ashr32_both: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: asr x8, x0, #32 |
| ; CHECK-NEXT: asr x9, x1, #32 |
| ; CHECK-NEXT: smull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %tmp1 = ashr i64 %a, 32 |
| %c = ashr i64 %b, 32 |
| %tmp3 = mul i64 %tmp1, %c |
| ret i64 %tmp3 |
| } |
| |
| define i64 @umull_ldrb_h(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: umull_ldrb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| ret i64 %mul |
| } |
| |
| define i64 @umull_ldrb_h_commuted(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: umull_ldrb_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umull x0, w9, w8 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext4, %zext |
| ret i64 %mul |
| } |
| |
| define i64 @umull_ldrh_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: umull_ldrh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrh w8, [x0] |
| ; CHECK-NEXT: umull x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %zext = zext i16 %ext64 to i64 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| ret i64 %mul |
| } |
| |
| define i64 @umull_ldr_b(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: umull_ldr_b: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: umull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %zext = zext i32 %ext64 to i64 |
| %zext4 = zext i8 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| ret i64 %mul |
| } |
| |
| define i64 @umull_ldr2_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: umull_ldr2_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: umull x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %and, %zext4 |
| ret i64 %mul |
| } |
| |
| define i64 @umull_ldr2_ldr2(ptr %x0, ptr %x1) { |
| ; CHECK-LABEL: umull_ldr2_ldr2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: ldr w9, [x1] |
| ; CHECK-NEXT: umull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %ext64_2 = load i64, ptr %x1 |
| %and2 = and i64 %ext64_2, 4294967295 |
| %mul = mul i64 %and, %and2 |
| ret i64 %mul |
| } |
| |
| define i64 @umull_ldr2_d(ptr %x0, i64 %x1) { |
| ; CHECK-LABEL: umull_ldr2_d: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: and x9, x1, #0xffffffff |
| ; CHECK-NEXT: umull x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %and2 = and i64 %x1, 4294967295 |
| %mul = mul i64 %and, %and2 |
| ret i64 %mul |
| } |
| |
| define i64 @umaddl_ldrb_h(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: umaddl_ldrb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %add = add i64 %mul, %x2 |
| ret i64 %add |
| } |
| |
| define i64 @umaddl_ldrb_h_commuted(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: umaddl_ldrb_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umaddl x0, w9, w8, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext4, %zext |
| %add = add i64 %mul, %x2 |
| ret i64 %add |
| } |
| |
| define i64 @umaddl_ldrh_w(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: umaddl_ldrh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrh w8, [x0] |
| ; CHECK-NEXT: umaddl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %zext = zext i16 %ext64 to i64 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %add = add i64 %mul, %x2 |
| ret i64 %add |
| } |
| |
| define i64 @umaddl_ldr_b(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: umaddl_ldr_b: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: umaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %zext = zext i32 %ext64 to i64 |
| %zext4 = zext i8 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %add = add i64 %mul, %x2 |
| ret i64 %add |
| } |
| |
| define i64 @umaddl_ldr2_w(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: umaddl_ldr2_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: umaddl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %and, %zext4 |
| %add = add i64 %mul, %x2 |
| ret i64 %add |
| } |
| |
| define i64 @umaddl_ldr2_ldr2(ptr %x0, ptr %x1, i64 %x2) { |
| ; CHECK-LABEL: umaddl_ldr2_ldr2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: ldr w9, [x1] |
| ; CHECK-NEXT: umaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %ext64_2 = load i64, ptr %x1 |
| %and2 = and i64 %ext64_2, 4294967295 |
| %mul = mul i64 %and, %and2 |
| %add = add i64 %mul, %x2 |
| ret i64 %add |
| } |
| |
| define i64 @umaddl_ldr2_d(ptr %x0, i64 %x1, i64 %x2) { |
| ; CHECK-LABEL: umaddl_ldr2_d: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: and x9, x1, #0xffffffff |
| ; CHECK-NEXT: umaddl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %and2 = and i64 %x1, 4294967295 |
| %mul = mul i64 %and, %and2 |
| %add = add i64 %mul, %x2 |
| ret i64 %add |
| } |
| |
| define i64 @umnegl_ldrb_h(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: umnegl_ldrb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umnegl_ldrb_h_commuted(ptr %x0, i16 %x1) { |
| ; CHECK-LABEL: umnegl_ldrb_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umnegl x0, w9, w8 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext4, %zext |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umnegl_ldrh_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: umnegl_ldrh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrh w8, [x0] |
| ; CHECK-NEXT: umnegl x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %zext = zext i16 %ext64 to i64 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umnegl_ldr_b(ptr %x0, i8 %x1) { |
| ; CHECK-LABEL: umnegl_ldr_b: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: umnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %zext = zext i32 %ext64 to i64 |
| %zext4 = zext i8 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umnegl_ldr2_w(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: umnegl_ldr2_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: umnegl x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %and, %zext4 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umnegl_ldr2_ldr2(ptr %x0, ptr %x1) { |
| ; CHECK-LABEL: umnegl_ldr2_ldr2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: ldr w9, [x1] |
| ; CHECK-NEXT: umnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %ext64_2 = load i64, ptr %x1 |
| %and2 = and i64 %ext64_2, 4294967295 |
| %mul = mul i64 %and, %and2 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umnegl_ldr2_d(ptr %x0, i64 %x1) { |
| ; CHECK-LABEL: umnegl_ldr2_d: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: and x9, x1, #0xffffffff |
| ; CHECK-NEXT: umnegl x0, w8, w9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %and2 = and i64 %x1, 4294967295 |
| %mul = mul i64 %and, %and2 |
| %sub = sub i64 0, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umsubl_ldrb_h(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: umsubl_ldrb_h: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umsubl_ldrb_h_commuted(ptr %x0, i16 %x1, i64 %x2) { |
| ; CHECK-LABEL: umsubl_ldrb_h_commuted: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrb w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xffff |
| ; CHECK-NEXT: umsubl x0, w9, w8, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i8, ptr %x0 |
| %zext = zext i8 %ext64 to i64 |
| %zext4 = zext i16 %x1 to i64 |
| %mul = mul i64 %zext4, %zext |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umsubl_ldrh_w(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: umsubl_ldrh_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldrh w8, [x0] |
| ; CHECK-NEXT: umsubl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i16, ptr %x0 |
| %zext = zext i16 %ext64 to i64 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umsubl_ldr_b(ptr %x0, i8 %x1, i64 %x2) { |
| ; CHECK-LABEL: umsubl_ldr_b: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 |
| ; CHECK-NEXT: and x9, x1, #0xff |
| ; CHECK-NEXT: umsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i32, ptr %x0 |
| %zext = zext i32 %ext64 to i64 |
| %zext4 = zext i8 %x1 to i64 |
| %mul = mul i64 %zext, %zext4 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umsubl_ldr2_w(ptr %x0, i32 %x1, i64 %x2) { |
| ; CHECK-LABEL: umsubl_ldr2_w: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: umsubl x0, w8, w1, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %and, %zext4 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umsubl_ldr2_ldr2(ptr %x0, ptr %x1, i64 %x2) { |
| ; CHECK-LABEL: umsubl_ldr2_ldr2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: ldr w9, [x1] |
| ; CHECK-NEXT: umsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %ext64_2 = load i64, ptr %x1 |
| %and2 = and i64 %ext64_2, 4294967295 |
| %mul = mul i64 %and, %and2 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umsubl_ldr2_d(ptr %x0, i64 %x1, i64 %x2) { |
| ; CHECK-LABEL: umsubl_ldr2_d: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr w8, [x0] |
| ; CHECK-NEXT: and x9, x1, #0xffffffff |
| ; CHECK-NEXT: umsubl x0, w8, w9, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 4294967295 |
| %and2 = and i64 %x1, 4294967295 |
| %mul = mul i64 %and, %and2 |
| %sub = sub i64 %x2, %mul |
| ret i64 %sub |
| } |
| |
| define i64 @umull_ldr2_w_cc1(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: umull_ldr2_w_cc1: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr x8, [x0] |
| ; CHECK-NEXT: and x8, x8, #0x7fffffff |
| ; CHECK-NEXT: umull x0, w8, w1 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 2147483647 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %and, %zext4 |
| ret i64 %mul |
| } |
| |
| define i64 @umull_ldr2_w_cc2(ptr %x0, i32 %x1) { |
| ; CHECK-LABEL: umull_ldr2_w_cc2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr x8, [x0] |
| ; CHECK-NEXT: mov w9, w1 |
| ; CHECK-NEXT: and x8, x8, #0x1ffffffff |
| ; CHECK-NEXT: mul x0, x8, x9 |
| ; CHECK-NEXT: ret |
| entry: |
| %ext64 = load i64, ptr %x0 |
| %and = and i64 %ext64, 8589934591 |
| %zext4 = zext i32 %x1 to i64 |
| %mul = mul i64 %and, %zext4 |
| ret i64 %mul |
| } |
| |
| define i64 @regression_umsubl(i64 %a, i32 %b, i64 %c) { |
| ; CHECK-LABEL: regression_umsubl: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: mov w8, w1 |
| ; CHECK-NEXT: udiv x9, x0, x8 |
| ; CHECK-NEXT: msub x0, x9, x8, x2 |
| ; CHECK-NEXT: ret |
| entry: |
| %zext1 = zext i32 %b to i64 |
| %res = udiv i64 %a, %zext1 |
| %mul = mul i64 %res, %zext1 |
| %sub = sub i64 %c, %mul |
| ret i64 %sub |
| } |