| # RUN: llc -mtriple=aarch64-linux-gnu -run-pass machine-combiner -o - %s | FileCheck %s |
| |
| # The test cases in this file check following transformation if the right form |
| # can reduce latency. |
| # A - (B + C) ==> (A - B) - C |
| |
| --- |
| # 32 bit. |
| |
| # CHECK-LABEL: name: test1 |
| # CHECK: [[TMP:%[0-9]+]]:gpr32common = SUBWrr killed %3, %4 |
| # CHECK-NEXT: %7:gpr32 = SUBWrr killed [[TMP]], %5 |
| |
| name: test1 |
| registers: |
| - { id: 0, class: gpr32common } |
| - { id: 1, class: gpr32 } |
| - { id: 2, class: gpr32 } |
| - { id: 3, class: gpr32common } |
| - { id: 4, class: gpr32common } |
| - { id: 5, class: gpr32 } |
| - { id: 6, class: gpr32 } |
| - { id: 7, class: gpr32 } |
| - { id: 8, class: gpr32 } |
| body: | |
| bb.0: |
| %2:gpr32 = COPY $w2 |
| %1:gpr32 = COPY $w1 |
| %0:gpr32common = COPY $w0 |
| %3:gpr32common = ORRWri %2:gpr32, 1600 |
| %4:gpr32common = ADDWri %0:gpr32common, 100, 0 |
| %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8 |
| %6:gpr32 = ADDWrr %5:gpr32, %4:gpr32common |
| %7:gpr32 = SUBWrr killed %3:gpr32common, killed %6:gpr32 |
| %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141 |
| $w0 = COPY %8:gpr32 |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| # 64 bit. |
| |
| # CHECK-LABEL: name: test2 |
| # CHECK: [[TMP:%[0-9]+]]:gpr64common = SUBXrr killed %3, %4 |
| # CHECK-NEXT: %7:gpr64 = SUBXrr killed [[TMP]], %5 |
| |
| name: test2 |
| registers: |
| - { id: 0, class: gpr64common } |
| - { id: 1, class: gpr64 } |
| - { id: 2, class: gpr64 } |
| - { id: 3, class: gpr64common } |
| - { id: 4, class: gpr64common } |
| - { id: 5, class: gpr64 } |
| - { id: 6, class: gpr64 } |
| - { id: 7, class: gpr64 } |
| - { id: 8, class: gpr64 } |
| body: | |
| bb.0: |
| %2:gpr64 = COPY $x2 |
| %1:gpr64 = COPY $x1 |
| %0:gpr64common = COPY $x0 |
| %3:gpr64common = ORRXri %2:gpr64, 1600 |
| %4:gpr64common = ADDXri %0:gpr64common, 100, 0 |
| %5:gpr64 = EORXrs %1:gpr64, %4:gpr64common, 8 |
| %6:gpr64 = ADDXrr %5:gpr64, %4:gpr64common |
| %7:gpr64 = SUBXrr killed %3:gpr64common, killed %6:gpr64 |
| %8:gpr64 = EORXrs killed %7:gpr64, %5:gpr64, 141 |
| $x0 = COPY %8:gpr64 |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| # Negative test. The right form can't reduce latency. |
| |
| # CHECK-LABEL: name: test3 |
| # CHECK: %6:gpr32 = ADDWrr killed %3, %4 |
| # CHECK-NEXT: %7:gpr32 = SUBWrr %5, killed %6 |
| |
| name: test3 |
| registers: |
| - { id: 0, class: gpr32common } |
| - { id: 1, class: gpr32 } |
| - { id: 2, class: gpr32 } |
| - { id: 3, class: gpr32common } |
| - { id: 4, class: gpr32common } |
| - { id: 5, class: gpr32 } |
| - { id: 6, class: gpr32 } |
| - { id: 7, class: gpr32 } |
| - { id: 8, class: gpr32 } |
| body: | |
| bb.0: |
| %2:gpr32 = COPY $w2 |
| %1:gpr32 = COPY $w1 |
| %0:gpr32common = COPY $w0 |
| %3:gpr32common = ORRWri %2:gpr32, 1600 |
| %4:gpr32common = ADDWri %0:gpr32common, 100, 0 |
| %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8 |
| %6:gpr32 = ADDWrr killed %3:gpr32common, %4:gpr32common |
| %7:gpr32 = SUBWrr %5:gpr32, killed %6:gpr32 |
| %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141 |
| $w0 = COPY %8:gpr32 |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| # Dead define of flag registers should not block transformation. |
| |
| # CHECK-LABEL: name: test4 |
| # CHECK: [[TMP:%[0-9]+]]:gpr64common = SUBXrr killed %3, %4 |
| # CHECK-NEXT: %7:gpr64 = SUBXrr killed [[TMP]], %5 |
| |
| name: test4 |
| registers: |
| - { id: 0, class: gpr64common } |
| - { id: 1, class: gpr64 } |
| - { id: 2, class: gpr64 } |
| - { id: 3, class: gpr64common } |
| - { id: 4, class: gpr64common } |
| - { id: 5, class: gpr64 } |
| - { id: 6, class: gpr64 } |
| - { id: 7, class: gpr64 } |
| - { id: 8, class: gpr64 } |
| body: | |
| bb.0: |
| %2:gpr64 = COPY $x2 |
| %1:gpr64 = COPY $x1 |
| %0:gpr64common = COPY $x0 |
| %3:gpr64common = ORRXri %2:gpr64, 1600 |
| %4:gpr64common = ADDXri %0:gpr64common, 100, 0 |
| %5:gpr64 = EORXrs %1:gpr64, %4:gpr64common, 8 |
| %6:gpr64 = ADDSXrr %5:gpr64, %4:gpr64common, implicit-def dead $nzcv |
| %7:gpr64 = SUBSXrr killed %3:gpr64common, killed %6:gpr64, implicit-def dead $nzcv |
| %8:gpr64 = EORXrs killed %7:gpr64, %5:gpr64, 141 |
| $x0 = COPY %8:gpr64 |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| # Non dead define of flag register in SUB can block the transformation. |
| |
| # CHECK-LABEL: name: test5 |
| # CHECK: %6:gpr32 = ADDWrr %5, %4 |
| # CHECK-NEXT: %7:gpr32 = SUBSWrr killed %3, killed %6, implicit-def $nzcv |
| |
| name: test5 |
| registers: |
| - { id: 0, class: gpr32common } |
| - { id: 1, class: gpr32 } |
| - { id: 2, class: gpr32 } |
| - { id: 3, class: gpr32common } |
| - { id: 4, class: gpr32common } |
| - { id: 5, class: gpr32 } |
| - { id: 6, class: gpr32 } |
| - { id: 7, class: gpr32 } |
| - { id: 8, class: gpr32 } |
| body: | |
| bb.0: |
| %2:gpr32 = COPY $w2 |
| %1:gpr32 = COPY $w1 |
| %0:gpr32common = COPY $w0 |
| %3:gpr32common = ORRWri %2:gpr32, 1600 |
| %4:gpr32common = ADDWri %0:gpr32common, 100, 0 |
| %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8 |
| %6:gpr32 = ADDWrr %5:gpr32, %4:gpr32common |
| %7:gpr32 = SUBSWrr killed %3:gpr32common, killed %6:gpr32, implicit-def $nzcv |
| %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141 |
| $w0 = COPY %8:gpr32 |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| # Non dead define of flag register in ADD can block the transformation. |
| |
| # CHECK-LABEL: name: test6 |
| # CHECK: %6:gpr64 = ADDSXrr %5, %4, implicit-def $nzcv |
| # CHECK-NEXT: %7:gpr64 = SUBXrr killed %3, killed %6 |
| |
| name: test6 |
| registers: |
| - { id: 0, class: gpr64common } |
| - { id: 1, class: gpr64 } |
| - { id: 2, class: gpr64 } |
| - { id: 3, class: gpr64common } |
| - { id: 4, class: gpr64common } |
| - { id: 5, class: gpr64 } |
| - { id: 6, class: gpr64 } |
| - { id: 7, class: gpr64 } |
| - { id: 8, class: gpr64 } |
| body: | |
| bb.0: |
| %2:gpr64 = COPY $x2 |
| %1:gpr64 = COPY $x1 |
| %0:gpr64common = COPY $x0 |
| %3:gpr64common = ORRXri %2:gpr64, 1600 |
| %4:gpr64common = ADDXri %0:gpr64common, 100, 0 |
| %5:gpr64 = EORXrs %1:gpr64, %4:gpr64common, 8 |
| %6:gpr64 = ADDSXrr %5:gpr64, %4:gpr64common, implicit-def $nzcv |
| %7:gpr64 = SUBXrr killed %3:gpr64common, killed %6:gpr64 |
| %8:gpr64 = EORXrs killed %7:gpr64, %5:gpr64, 141 |
| $x0 = COPY %8:gpr64 |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| # ADD has multiple uses, so it is always required, we should not transform it. |
| |
| # CHECK-LABEL: name: test7 |
| # CHECK: %6:gpr32 = ADDWrr %5, %4 |
| # CHECK-NEXT: %7:gpr32 = SUBWrr killed %3, %6 |
| |
| name: test7 |
| registers: |
| - { id: 0, class: gpr32common } |
| - { id: 1, class: gpr32 } |
| - { id: 2, class: gpr32 } |
| - { id: 3, class: gpr32common } |
| - { id: 4, class: gpr32common } |
| - { id: 5, class: gpr32 } |
| - { id: 6, class: gpr32 } |
| - { id: 7, class: gpr32 } |
| - { id: 8, class: gpr32 } |
| - { id: 9, class: gpr32 } |
| body: | |
| bb.0: |
| %2:gpr32 = COPY $w2 |
| %1:gpr32 = COPY $w1 |
| %0:gpr32common = COPY $w0 |
| %3:gpr32common = ORRWri %2:gpr32, 1600 |
| %4:gpr32common = ADDWri %0:gpr32common, 100, 0 |
| %5:gpr32 = EORWrs %1:gpr32, %4:gpr32common, 8 |
| %6:gpr32 = ADDWrr %5:gpr32, %4:gpr32common |
| %7:gpr32 = SUBWrr killed %3:gpr32common, %6:gpr32 |
| %8:gpr32 = EORWrs killed %7:gpr32, %5:gpr32, 141 |
| %9:gpr32 = ADDWrr %8:gpr32, %6:gpr32 |
| $w0 = COPY %9:gpr32 |
| RET_ReallyLR implicit $w0 |
| |
| ... |