llvm/llvm/test/CodeGen/AArch64/aarch64-mull-masks.ll

; 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:    smull x0, w8, w1
; 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:    smaddl x0, w8, w1, 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:    smnegl x0, w8, w1
; 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:    smsubl x0, w8, w1, 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:    umull x0, w8, w1
; 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:    umaddl x0, w8, w1, 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:    umnegl x0, w8, w1
; 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:    umsubl x0, w8, w1, 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
}

define i64 @umull_and_lshr(i64 %x) {
; CHECK-LABEL: umull_and_lshr:
; CHECK:       // %bb.0:
; CHECK-NEXT:    lsr x8, x0, #32
; CHECK-NEXT:    umull x0, w0, w8
; CHECK-NEXT:    ret
    %lo = and i64 %x, u0xffffffff
    %hi = lshr i64 %x, 32
    %mul = mul i64 %lo, %hi
    ret i64 %mul
}

define i64 @umull_and_and(i64 %x, i64 %y) {
; CHECK-LABEL: umull_and_and:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umull x0, w0, w1
; CHECK-NEXT:    ret
    %lo = and i64 %x, u0xffffffff
    %hi = and i64 %y, u0xffffffff
    %mul = mul i64 %lo, %hi
    ret i64 %mul
}

define i64 @umaddl_and_lshr(i64 %x, i64 %a) {
; CHECK-LABEL: umaddl_and_lshr:
; CHECK:       // %bb.0:
; CHECK-NEXT:    lsr x8, x0, #32
; CHECK-NEXT:    umaddl x0, w0, w8, x1
; CHECK-NEXT:    ret
    %lo = and i64 %x, u0xffffffff
    %hi = lshr i64 %x, 32
    %mul = mul i64 %lo, %hi
    %add = add i64 %a, %mul
    ret i64 %add
}

define i64 @umaddl_and_and(i64 %x, i64 %y, i64 %a) {
; CHECK-LABEL: umaddl_and_and:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umaddl x0, w0, w1, x2
; CHECK-NEXT:    ret
    %lo = and i64 %x, u0xffffffff
    %hi = and i64 %y, u0xffffffff
    %mul = mul i64 %lo, %hi
    %add = add i64 %a, %mul
    ret i64 %add
}

; Check which can contain multiple copies that should all be removed.
define i32 @f(i32 %0) {
entry:
  %1 = sext i32 %0 to i64
  br label %A

A:
  %2 = trunc i64 %1 to i32
  %a69.us = sub i32 0, %2
  %a69.us.fr = freeze i32 %a69.us
  %3 = zext i32 %a69.us.fr to i64
  br label %B

B:
  %t = icmp eq i64 0, %3
  br i1 %t, label %A, label %B
}