| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -mtriple=riscv64 -mattr=+d,+zbb,+zfh -verify-machineinstrs -mcpu=sifive-u74 \ |
| ; RUN: -O1 -riscv-enable-machine-combiner=true -riscv-force-machine-combiner-strategy=local < %s | \ |
| ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK_LOCAL |
| |
| ; RUN: llc -mtriple=riscv64 -mattr=+d,+zbb,+zfh -verify-machineinstrs -mcpu=sifive-u74 \ |
| ; RUN: -O1 -riscv-enable-machine-combiner=true -riscv-force-machine-combiner-strategy=min-instr < %s | \ |
| ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK_GLOBAL |
| |
| define double @test_reassoc_fadd1(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fadd1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fadd.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %t0, %a2 |
| %t2 = fadd nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fadd2(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fadd2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fadd.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %a2, %t0 |
| %t2 = fadd nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fadd3(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fadd3: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fadd.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %t0, %a2 |
| %t2 = fadd nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fadd4(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fadd4: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fadd.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %a2, %t0 |
| %t2 = fadd nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fmul1(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fmul1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmul.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmul.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fmul.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = fmul nsz reassoc double %a0, %a1 |
| %t1 = fmul nsz reassoc double %t0, %a2 |
| %t2 = fmul nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fmul2(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fmul2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmul.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmul.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fmul.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fmul nsz reassoc double %a0, %a1 |
| %t1 = fmul nsz reassoc double %a2, %t0 |
| %t2 = fmul nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fmul3(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fmul3: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmul.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmul.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fmul.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fmul nsz reassoc double %a0, %a1 |
| %t1 = fmul nsz reassoc double %t0, %a2 |
| %t2 = fmul nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fmul4(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fmul4: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmul.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmul.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fmul.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fmul nsz reassoc double %a0, %a1 |
| %t1 = fmul nsz reassoc double %a2, %t0 |
| %t2 = fmul nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_big1(double %a0, double %a1, double %a2, double %a3, double %a4, double %a5, double %a6) { |
| ; CHECK-LABEL: test_reassoc_big1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa1, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa3, fa2, fa3 |
| ; CHECK-NEXT: fadd.d fa5, fa4, fa5 |
| ; CHECK-NEXT: fadd.d fa4, fa1, fa3 |
| ; CHECK-NEXT: fadd.d fa5, fa5, fa6 |
| ; CHECK-NEXT: fadd.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %t0, %a2 |
| %t2 = fadd nsz reassoc double %t1, %a3 |
| %t3 = fadd nsz reassoc double %t2, %a4 |
| %t4 = fadd nsz reassoc double %t3, %a5 |
| %t5 = fadd nsz reassoc double %t4, %a6 |
| ret double %t5 |
| } |
| |
| define double @test_reassoc_big2(double %a0, double %a1, i32 %a2, double %a3, i32 %a4, double %a5) { |
| ; CHECK-LABEL: test_reassoc_big2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fadd.d fa3, fa2, fa1 |
| ; CHECK-NEXT: fcvt.d.w ft0, a0 |
| ; CHECK-NEXT: fcvt.d.w ft1, a1 |
| ; CHECK-NEXT: fmul.d fa2, fa2, ft0 |
| ; CHECK-NEXT: fmul.d fa1, ft1, fa1 |
| ; CHECK-NEXT: fsub.d fa5, fa4, fa5 |
| ; CHECK-NEXT: fmul.d fa4, fa0, fa3 |
| ; CHECK-NEXT: fmul.d fa3, fa1, fa2 |
| ; CHECK-NEXT: fmul.d fa5, fa5, fa4 |
| ; CHECK-NEXT: fmul.d fa0, fa5, fa3 |
| ; CHECK-NEXT: ret |
| %cvt1 = sitofp i32 %a2 to double |
| %cvt2 = sitofp i32 %a4 to double |
| %t5 = fmul nsz reassoc double %a3, %cvt1 |
| %t9 = fmul nsz reassoc double %cvt2, %t5 |
| %t4 = fmul nsz reassoc double %t9, %a1 |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %a3, %t0 |
| %t3 = fadd nsz reassoc double %a3, %a1 |
| %t6 = fmul nsz reassoc double %t4, %a0 |
| %t2 = fsub nsz reassoc double %a5, %t1 |
| %t7 = fmul nsz reassoc double %t6, %t3 |
| %t8 = fmul nsz reassoc double %t2, %t7 |
| ret double %t8 |
| } |
| |
| ; Negative test |
| define double @test_reassoc_fadd_flags_1(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fadd_flags_1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa5, fa5, fa2 |
| ; CHECK-NEXT: fadd.d fa0, fa5, fa3 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd double %t0, %a2 |
| %t2 = fadd nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| ; Negative test |
| define double @test_reassoc_fadd_flags_2(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fadd_flags_2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa5, fa5, fa2 |
| ; CHECK-NEXT: fadd.d fa0, fa5, fa3 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %t0, %a2 |
| %t2 = fadd double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_fmadd1(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_fmadd1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmadd.d fa5, fa0, fa1, fa2 |
| ; CHECK-NEXT: fmadd.d fa4, fa0, fa1, fa3 |
| ; CHECK-NEXT: fadd.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = fmul contract double %a0, %a1 |
| %t1 = fadd contract double %t0, %a2 |
| %t2 = fadd contract double %a3, %t0 |
| %t3 = fadd double %t1, %t2 |
| ret double %t3 |
| } |
| |
| define double @test_fmadd2(double %a0, double %a1, double %a2) { |
| ; CHECK-LABEL: test_fmadd2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmul.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmadd.d fa4, fa0, fa1, fa2 |
| ; CHECK-NEXT: fdiv.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fmul contract double %a0, %a1 |
| %t1 = fadd contract double %t0, %a2 |
| %t2 = fdiv double %t1, %t0 |
| ret double %t2 |
| } |
| |
| define double @test_fmsub(double %a0, double %a1, double %a2) { |
| ; CHECK-LABEL: test_fmsub: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmul.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmsub.d fa4, fa0, fa1, fa2 |
| ; CHECK-NEXT: fdiv.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fmul contract double %a0, %a1 |
| %t1 = fsub contract double %t0, %a2 |
| %t2 = fdiv double %t1, %t0 |
| ret double %t2 |
| } |
| |
| define double @test_fnmsub(double %a0, double %a1, double %a2) { |
| ; CHECK-LABEL: test_fnmsub: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmul.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fnmsub.d fa4, fa0, fa1, fa2 |
| ; CHECK-NEXT: fdiv.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fmul contract double %a0, %a1 |
| %t1 = fsub contract double %a2, %t0 |
| %t2 = fdiv double %t1, %t0 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub1(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fadd.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %t0, %a2 |
| %t2 = fsub nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub2(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fsub.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %t0, %a2 |
| %t2 = fadd nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub3(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub3: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fsub.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %t0, %a2 |
| %t2 = fsub nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub4(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub4: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fadd.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %a2, %t0 |
| %t2 = fsub nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub5(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub5: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fsub.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %a2, %t0 |
| %t2 = fadd nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub6(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub6: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fsub.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %a2, %t0 |
| %t2 = fsub nsz reassoc double %t1, %a3 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub7(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub7: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fsub.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %t0, %a2 |
| %t2 = fsub nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub8(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fadd.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %t0, %a2 |
| %t2 = fadd nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub9(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub9: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fsub.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %t0, %a2 |
| %t2 = fsub nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub10(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub10: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fsub.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fadd nsz reassoc double %a2, %t0 |
| %t2 = fsub nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub11(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub11: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fadd.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fsub.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %a2, %t0 |
| %t2 = fadd nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define double @test_reassoc_fsub12(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_reassoc_fsub12: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fadd.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fsub.d fa4, fa3, fa2 |
| ; CHECK-NEXT: fadd.d fa0, fa4, fa5 |
| ; CHECK-NEXT: ret |
| %t0 = fadd nsz reassoc double %a0, %a1 |
| %t1 = fsub nsz reassoc double %a2, %t0 |
| %t2 = fsub nsz reassoc double %a3, %t1 |
| ret double %t2 |
| } |
| |
| define i8 @test_reassoc_add_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: add a2, a2, a3 |
| ; CHECK-NEXT: add a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i8 %a0, %a1 |
| %t1 = add i8 %t0, %a2 |
| %t2 = add i8 %t1, %a3 |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_add_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: add a2, a2, a3 |
| ; CHECK-NEXT: add a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i16 %a0, %a1 |
| %t1 = add i16 %t0, %a2 |
| %t2 = add i16 %t1, %a3 |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_add_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: add a2, a2, a3 |
| ; CHECK-NEXT: addw a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i32 %a0, %a1 |
| %t1 = add i32 %t0, %a2 |
| %t2 = add i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_add_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: add a2, a2, a3 |
| ; CHECK-NEXT: add a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i64 %a0, %a1 |
| %t1 = add i64 %t0, %a2 |
| %t2 = add i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i32 @test_reassoc_add_sub_i32_1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_sub_i32_1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: subw a2, a2, a3 |
| ; CHECK-NEXT: subw a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i32 %a0, %a1 |
| %t1 = sub i32 %t0, %a2 |
| %t2 = add i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i32 @test_reassoc_add_sub_i32_2(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_sub_i32_2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: subw a2, a2, a3 |
| ; CHECK-NEXT: addw a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i32 %a0, %a1 |
| %t1 = add i32 %t0, %a2 |
| %t2 = sub i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i32 @test_reassoc_add_sub_i32_3(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_sub_i32_3: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: add a2, a2, a3 |
| ; CHECK-NEXT: subw a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i32 %a0, %a1 |
| %t1 = sub i32 %t0, %a2 |
| %t2 = sub i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_add_sub_i64_1(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_sub_i64_1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: sub a2, a2, a3 |
| ; CHECK-NEXT: sub a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i64 %a0, %a1 |
| %t1 = sub i64 %t0, %a2 |
| %t2 = add i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i64 @test_reassoc_add_sub_i64_2(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_sub_i64_2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: sub a2, a2, a3 |
| ; CHECK-NEXT: add a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i64 %a0, %a1 |
| %t1 = add i64 %t0, %a2 |
| %t2 = sub i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i64 @test_reassoc_add_sub_i64_3(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_add_sub_i64_3: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: add a0, a0, a1 |
| ; CHECK-NEXT: add a2, a2, a3 |
| ; CHECK-NEXT: sub a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = add i64 %a0, %a1 |
| %t1 = sub i64 %t0, %a2 |
| %t2 = sub i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_and_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_and_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: and a0, a0, a1 |
| ; CHECK-NEXT: and a2, a2, a3 |
| ; CHECK-NEXT: and a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = and i8 %a0, %a1 |
| %t1 = and i8 %t0, %a2 |
| %t2 = and i8 %t1, %a3 |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_and_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_and_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: and a0, a0, a1 |
| ; CHECK-NEXT: and a2, a2, a3 |
| ; CHECK-NEXT: and a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = and i16 %a0, %a1 |
| %t1 = and i16 %t0, %a2 |
| %t2 = and i16 %t1, %a3 |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_and_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_and_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: and a0, a0, a1 |
| ; CHECK-NEXT: and a2, a2, a3 |
| ; CHECK-NEXT: and a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = and i32 %a0, %a1 |
| %t1 = and i32 %t0, %a2 |
| %t2 = and i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_and_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_and_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: and a0, a0, a1 |
| ; CHECK-NEXT: and a2, a2, a3 |
| ; CHECK-NEXT: and a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = and i64 %a0, %a1 |
| %t1 = and i64 %t0, %a2 |
| %t2 = and i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_or_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_or_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: or a0, a0, a1 |
| ; CHECK-NEXT: or a2, a2, a3 |
| ; CHECK-NEXT: or a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = or i8 %a0, %a1 |
| %t1 = or i8 %t0, %a2 |
| %t2 = or i8 %t1, %a3 |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_or_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_or_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: or a0, a0, a1 |
| ; CHECK-NEXT: or a2, a2, a3 |
| ; CHECK-NEXT: or a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = or i16 %a0, %a1 |
| %t1 = or i16 %t0, %a2 |
| %t2 = or i16 %t1, %a3 |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_or_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_or_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: or a0, a0, a1 |
| ; CHECK-NEXT: or a2, a2, a3 |
| ; CHECK-NEXT: or a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = or i32 %a0, %a1 |
| %t1 = or i32 %t0, %a2 |
| %t2 = or i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_or_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_or_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: or a0, a0, a1 |
| ; CHECK-NEXT: or a2, a2, a3 |
| ; CHECK-NEXT: or a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = or i64 %a0, %a1 |
| %t1 = or i64 %t0, %a2 |
| %t2 = or i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_xor_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_xor_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: xor a0, a0, a1 |
| ; CHECK-NEXT: xor a2, a2, a3 |
| ; CHECK-NEXT: xor a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = xor i8 %a0, %a1 |
| %t1 = xor i8 %t0, %a2 |
| %t2 = xor i8 %t1, %a3 |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_xor_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_xor_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: xor a0, a0, a1 |
| ; CHECK-NEXT: xor a2, a2, a3 |
| ; CHECK-NEXT: xor a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = xor i16 %a0, %a1 |
| %t1 = xor i16 %t0, %a2 |
| %t2 = xor i16 %t1, %a3 |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_xor_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_xor_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: xor a0, a0, a1 |
| ; CHECK-NEXT: xor a2, a2, a3 |
| ; CHECK-NEXT: xor a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = xor i32 %a0, %a1 |
| %t1 = xor i32 %t0, %a2 |
| %t2 = xor i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_xor_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_xor_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: xor a0, a0, a1 |
| ; CHECK-NEXT: xor a2, a2, a3 |
| ; CHECK-NEXT: xor a0, a0, a2 |
| ; CHECK-NEXT: ret |
| %t0 = xor i64 %a0, %a1 |
| %t1 = xor i64 %t0, %a2 |
| %t2 = xor i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_mul_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_mul_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: mul a0, a0, a1 |
| ; CHECK-NEXT: mul a1, a2, a3 |
| ; CHECK-NEXT: mul a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = mul i8 %a0, %a1 |
| %t1 = mul i8 %t0, %a2 |
| %t2 = mul i8 %t1, %a3 |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_mul_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_mul_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: mul a0, a0, a1 |
| ; CHECK-NEXT: mul a1, a2, a3 |
| ; CHECK-NEXT: mul a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = mul i16 %a0, %a1 |
| %t1 = mul i16 %t0, %a2 |
| %t2 = mul i16 %t1, %a3 |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_mul_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_mul_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: mul a0, a0, a1 |
| ; CHECK-NEXT: mul a1, a2, a3 |
| ; CHECK-NEXT: mulw a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = mul i32 %a0, %a1 |
| %t1 = mul i32 %t0, %a2 |
| %t2 = mul i32 %t1, %a3 |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_mul_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_mul_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: mul a0, a0, a1 |
| ; CHECK-NEXT: mul a1, a2, a3 |
| ; CHECK-NEXT: mul a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = mul i64 %a0, %a1 |
| %t1 = mul i64 %t0, %a2 |
| %t2 = mul i64 %t1, %a3 |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_minu_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_minu_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: andi a3, a3, 255 |
| ; CHECK-NEXT: andi a2, a2, 255 |
| ; CHECK-NEXT: andi a1, a1, 255 |
| ; CHECK-NEXT: andi a0, a0, 255 |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: minu a1, a2, a3 |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i8 @llvm.umin.i8(i8 %a0, i8 %a1) |
| %t1 = call i8 @llvm.umin.i8(i8 %t0, i8 %a2) |
| %t2 = call i8 @llvm.umin.i8(i8 %t1, i8 %a3) |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_minu_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_minu_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: zext.h a3, a3 |
| ; CHECK-NEXT: zext.h a2, a2 |
| ; CHECK-NEXT: zext.h a1, a1 |
| ; CHECK-NEXT: zext.h a0, a0 |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: minu a1, a2, a3 |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i16 @llvm.umin.i16(i16 %a0, i16 %a1) |
| %t1 = call i16 @llvm.umin.i16(i16 %t0, i16 %a2) |
| %t2 = call i16 @llvm.umin.i16(i16 %t1, i16 %a3) |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_minu_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_minu_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.w a3, a3 |
| ; CHECK-NEXT: sext.w a2, a2 |
| ; CHECK-NEXT: sext.w a1, a1 |
| ; CHECK-NEXT: sext.w a0, a0 |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: minu a1, a2, a3 |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i32 @llvm.umin.i32(i32 %a0, i32 %a1) |
| %t1 = call i32 @llvm.umin.i32(i32 %t0, i32 %a2) |
| %t2 = call i32 @llvm.umin.i32(i32 %t1, i32 %a3) |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_minu_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_minu_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: minu a1, a2, a3 |
| ; CHECK-NEXT: minu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i64 @llvm.umin.i64(i64 %a0, i64 %a1) |
| %t1 = call i64 @llvm.umin.i64(i64 %t0, i64 %a2) |
| %t2 = call i64 @llvm.umin.i64(i64 %t1, i64 %a3) |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_min_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_min_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.b a3, a3 |
| ; CHECK-NEXT: sext.b a2, a2 |
| ; CHECK-NEXT: sext.b a1, a1 |
| ; CHECK-NEXT: sext.b a0, a0 |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: min a1, a2, a3 |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i8 @llvm.smin.i8(i8 %a0, i8 %a1) |
| %t1 = call i8 @llvm.smin.i8(i8 %t0, i8 %a2) |
| %t2 = call i8 @llvm.smin.i8(i8 %t1, i8 %a3) |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_min_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_min_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.h a3, a3 |
| ; CHECK-NEXT: sext.h a2, a2 |
| ; CHECK-NEXT: sext.h a1, a1 |
| ; CHECK-NEXT: sext.h a0, a0 |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: min a1, a2, a3 |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i16 @llvm.smin.i16(i16 %a0, i16 %a1) |
| %t1 = call i16 @llvm.smin.i16(i16 %t0, i16 %a2) |
| %t2 = call i16 @llvm.smin.i16(i16 %t1, i16 %a3) |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_min_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_min_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.w a3, a3 |
| ; CHECK-NEXT: sext.w a2, a2 |
| ; CHECK-NEXT: sext.w a1, a1 |
| ; CHECK-NEXT: sext.w a0, a0 |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: min a1, a2, a3 |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i32 @llvm.smin.i32(i32 %a0, i32 %a1) |
| %t1 = call i32 @llvm.smin.i32(i32 %t0, i32 %a2) |
| %t2 = call i32 @llvm.smin.i32(i32 %t1, i32 %a3) |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_min_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_min_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: min a1, a2, a3 |
| ; CHECK-NEXT: min a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i64 @llvm.smin.i64(i64 %a0, i64 %a1) |
| %t1 = call i64 @llvm.smin.i64(i64 %t0, i64 %a2) |
| %t2 = call i64 @llvm.smin.i64(i64 %t1, i64 %a3) |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_maxu_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_maxu_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: andi a3, a3, 255 |
| ; CHECK-NEXT: andi a2, a2, 255 |
| ; CHECK-NEXT: andi a1, a1, 255 |
| ; CHECK-NEXT: andi a0, a0, 255 |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: maxu a1, a2, a3 |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i8 @llvm.umax.i8(i8 %a0, i8 %a1) |
| %t1 = call i8 @llvm.umax.i8(i8 %t0, i8 %a2) |
| %t2 = call i8 @llvm.umax.i8(i8 %t1, i8 %a3) |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_maxu_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_maxu_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: zext.h a3, a3 |
| ; CHECK-NEXT: zext.h a2, a2 |
| ; CHECK-NEXT: zext.h a1, a1 |
| ; CHECK-NEXT: zext.h a0, a0 |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: maxu a1, a2, a3 |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i16 @llvm.umax.i16(i16 %a0, i16 %a1) |
| %t1 = call i16 @llvm.umax.i16(i16 %t0, i16 %a2) |
| %t2 = call i16 @llvm.umax.i16(i16 %t1, i16 %a3) |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_maxu_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_maxu_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.w a3, a3 |
| ; CHECK-NEXT: sext.w a2, a2 |
| ; CHECK-NEXT: sext.w a1, a1 |
| ; CHECK-NEXT: sext.w a0, a0 |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: maxu a1, a2, a3 |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i32 @llvm.umax.i32(i32 %a0, i32 %a1) |
| %t1 = call i32 @llvm.umax.i32(i32 %t0, i32 %a2) |
| %t2 = call i32 @llvm.umax.i32(i32 %t1, i32 %a3) |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_maxu_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_maxu_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: maxu a1, a2, a3 |
| ; CHECK-NEXT: maxu a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i64 @llvm.umax.i64(i64 %a0, i64 %a1) |
| %t1 = call i64 @llvm.umax.i64(i64 %t0, i64 %a2) |
| %t2 = call i64 @llvm.umax.i64(i64 %t1, i64 %a3) |
| ret i64 %t2 |
| } |
| |
| define i8 @test_reassoc_max_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { |
| ; CHECK-LABEL: test_reassoc_max_i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.b a3, a3 |
| ; CHECK-NEXT: sext.b a2, a2 |
| ; CHECK-NEXT: sext.b a1, a1 |
| ; CHECK-NEXT: sext.b a0, a0 |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: max a1, a2, a3 |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i8 @llvm.smax.i8(i8 %a0, i8 %a1) |
| %t1 = call i8 @llvm.smax.i8(i8 %t0, i8 %a2) |
| %t2 = call i8 @llvm.smax.i8(i8 %t1, i8 %a3) |
| ret i8 %t2 |
| } |
| |
| define i16 @test_reassoc_max_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { |
| ; CHECK-LABEL: test_reassoc_max_i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.h a3, a3 |
| ; CHECK-NEXT: sext.h a2, a2 |
| ; CHECK-NEXT: sext.h a1, a1 |
| ; CHECK-NEXT: sext.h a0, a0 |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: max a1, a2, a3 |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i16 @llvm.smax.i16(i16 %a0, i16 %a1) |
| %t1 = call i16 @llvm.smax.i16(i16 %t0, i16 %a2) |
| %t2 = call i16 @llvm.smax.i16(i16 %t1, i16 %a3) |
| ret i16 %t2 |
| } |
| |
| define i32 @test_reassoc_max_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { |
| ; CHECK-LABEL: test_reassoc_max_i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: sext.w a3, a3 |
| ; CHECK-NEXT: sext.w a2, a2 |
| ; CHECK-NEXT: sext.w a1, a1 |
| ; CHECK-NEXT: sext.w a0, a0 |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: max a1, a2, a3 |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i32 @llvm.smax.i32(i32 %a0, i32 %a1) |
| %t1 = call i32 @llvm.smax.i32(i32 %t0, i32 %a2) |
| %t2 = call i32 @llvm.smax.i32(i32 %t1, i32 %a3) |
| ret i32 %t2 |
| } |
| |
| define i64 @test_reassoc_max_i64(i64 %a0, i64 %a1, i64 %a2, i64 %a3) { |
| ; CHECK-LABEL: test_reassoc_max_i64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: max a1, a2, a3 |
| ; CHECK-NEXT: max a0, a0, a1 |
| ; CHECK-NEXT: ret |
| %t0 = call i64 @llvm.smax.i64(i64 %a0, i64 %a1) |
| %t1 = call i64 @llvm.smax.i64(i64 %t0, i64 %a2) |
| %t2 = call i64 @llvm.smax.i64(i64 %t1, i64 %a3) |
| ret i64 %t2 |
| } |
| |
| define half @test_fmin_f16(half %a0, half %a1, half %a2, half %a3) { |
| ; CHECK-LABEL: test_fmin_f16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmin.h fa5, fa0, fa1 |
| ; CHECK-NEXT: fmin.h fa4, fa2, fa3 |
| ; CHECK-NEXT: fmin.h fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = call half @llvm.minnum.f16(half %a0, half %a1) |
| %t1 = call half @llvm.minnum.f16(half %t0, half %a2) |
| %t2 = call half @llvm.minnum.f16(half %t1, half %a3) |
| ret half %t2 |
| } |
| |
| define float @test_fmin_f32(float %a0, float %a1, float %a2, float %a3) { |
| ; CHECK-LABEL: test_fmin_f32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmin.s fa5, fa0, fa1 |
| ; CHECK-NEXT: fmin.s fa4, fa2, fa3 |
| ; CHECK-NEXT: fmin.s fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = call float @llvm.minnum.f32(float %a0, float %a1) |
| %t1 = call float @llvm.minnum.f32(float %t0, float %a2) |
| %t2 = call float @llvm.minnum.f32(float %t1, float %a3) |
| ret float %t2 |
| } |
| |
| define double @test_fmin_f64(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_fmin_f64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmin.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmin.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fmin.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = call double @llvm.minnum.f64(double %a0, double %a1) |
| %t1 = call double @llvm.minnum.f64(double %t0, double %a2) |
| %t2 = call double @llvm.minnum.f64(double %t1, double %a3) |
| ret double %t2 |
| } |
| |
| define half @test_fmax_f16(half %a0, half %a1, half %a2, half %a3) { |
| ; CHECK-LABEL: test_fmax_f16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmax.h fa5, fa0, fa1 |
| ; CHECK-NEXT: fmax.h fa4, fa2, fa3 |
| ; CHECK-NEXT: fmax.h fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = call half @llvm.maxnum.f16(half %a0, half %a1) |
| %t1 = call half @llvm.maxnum.f16(half %t0, half %a2) |
| %t2 = call half @llvm.maxnum.f16(half %t1, half %a3) |
| ret half %t2 |
| } |
| |
| define float @test_fmax_f32(float %a0, float %a1, float %a2, float %a3) { |
| ; CHECK-LABEL: test_fmax_f32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmax.s fa5, fa0, fa1 |
| ; CHECK-NEXT: fmax.s fa4, fa2, fa3 |
| ; CHECK-NEXT: fmax.s fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = call float @llvm.maxnum.f32(float %a0, float %a1) |
| %t1 = call float @llvm.maxnum.f32(float %t0, float %a2) |
| %t2 = call float @llvm.maxnum.f32(float %t1, float %a3) |
| ret float %t2 |
| } |
| |
| define double @test_fmax_f64(double %a0, double %a1, double %a2, double %a3) { |
| ; CHECK-LABEL: test_fmax_f64: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: fmax.d fa5, fa0, fa1 |
| ; CHECK-NEXT: fmax.d fa4, fa2, fa3 |
| ; CHECK-NEXT: fmax.d fa0, fa5, fa4 |
| ; CHECK-NEXT: ret |
| %t0 = call double @llvm.maxnum.f64(double %a0, double %a1) |
| %t1 = call double @llvm.maxnum.f64(double %t0, double %a2) |
| %t2 = call double @llvm.maxnum.f64(double %t1, double %a3) |
| ret double %t2 |
| } |
| |
| declare i8 @llvm.umin.i8(i8 %a, i8 %b) |
| declare i16 @llvm.umin.i16(i16 %a, i16 %b) |
| declare i32 @llvm.umin.i32(i32 %a, i32 %b) |
| declare i64 @llvm.umin.i64(i64 %a, i64 %b) |
| declare i8 @llvm.smin.i8(i8 %a, i8 %b) |
| declare i16 @llvm.smin.i16(i16 %a, i16 %b) |
| declare i32 @llvm.smin.i32(i32 %a, i32 %b) |
| declare i64 @llvm.smin.i64(i64 %a, i64 %b) |
| declare i8 @llvm.umax.i8(i8 %a, i8 %b) |
| declare i16 @llvm.umax.i16(i16 %a, i16 %b) |
| declare i32 @llvm.umax.i32(i32 %a, i32 %b) |
| declare i64 @llvm.umax.i64(i64 %a, i64 %b) |
| declare i8 @llvm.smax.i8(i8 %a, i8 %b) |
| declare i16 @llvm.smax.i16(i16 %a, i16 %b) |
| declare i32 @llvm.smax.i32(i32 %a, i32 %b) |
| declare i64 @llvm.smax.i64(i64 %a, i64 %b) |
| declare half @llvm.minnum.f16(half, half) |
| declare float @llvm.minnum.f32(float, float) |
| declare double @llvm.minnum.f64(double, double) |
| declare half @llvm.maxnum.f16(half, half) |
| declare float @llvm.maxnum.f32(float, float) |
| declare double @llvm.maxnum.f64(double, double) |
| |
| define double @test_fmadd_strategy(double %a0, double %a1, double %a2, double %a3, i64 %flag) { |
| ; CHECK_LOCAL-LABEL: test_fmadd_strategy: |
| ; CHECK_LOCAL: # %bb.0: # %entry |
| ; CHECK_LOCAL-NEXT: fmv.d fa5, fa0 |
| ; CHECK_LOCAL-NEXT: fsub.d fa4, fa0, fa1 |
| ; CHECK_LOCAL-NEXT: fmul.d fa0, fa4, fa2 |
| ; CHECK_LOCAL-NEXT: andi a0, a0, 1 |
| ; CHECK_LOCAL-NEXT: beqz a0, .LBB76_2 |
| ; CHECK_LOCAL-NEXT: # %bb.1: # %entry |
| ; CHECK_LOCAL-NEXT: fmul.d fa4, fa5, fa1 |
| ; CHECK_LOCAL-NEXT: fmadd.d fa5, fa5, fa1, fa0 |
| ; CHECK_LOCAL-NEXT: fsub.d fa0, fa5, fa4 |
| ; CHECK_LOCAL-NEXT: .LBB76_2: # %entry |
| ; CHECK_LOCAL-NEXT: ret |
| ; |
| ; CHECK_GLOBAL-LABEL: test_fmadd_strategy: |
| ; CHECK_GLOBAL: # %bb.0: # %entry |
| ; CHECK_GLOBAL-NEXT: fmv.d fa5, fa0 |
| ; CHECK_GLOBAL-NEXT: fsub.d fa4, fa0, fa1 |
| ; CHECK_GLOBAL-NEXT: fmul.d fa0, fa4, fa2 |
| ; CHECK_GLOBAL-NEXT: andi a0, a0, 1 |
| ; CHECK_GLOBAL-NEXT: beqz a0, .LBB76_2 |
| ; CHECK_GLOBAL-NEXT: # %bb.1: # %entry |
| ; CHECK_GLOBAL-NEXT: fmul.d fa5, fa5, fa1 |
| ; CHECK_GLOBAL-NEXT: fadd.d fa4, fa5, fa0 |
| ; CHECK_GLOBAL-NEXT: fsub.d fa0, fa4, fa5 |
| ; CHECK_GLOBAL-NEXT: .LBB76_2: # %entry |
| ; CHECK_GLOBAL-NEXT: ret |
| entry: |
| %sub = fsub contract double %a0, %a1 |
| %mul = fmul contract double %sub, %a2 |
| %and = and i64 %flag, 1 |
| %tobool.not = icmp eq i64 %and, 0 |
| %mul2 = fmul contract double %a0, %a1 |
| %add = fadd contract double %mul2, %mul |
| %sub3 = fsub contract double %add, %mul2 |
| %retval.0 = select i1 %tobool.not, double %mul, double %sub3 |
| ret double %retval.0 |
| } |