Home | History | Annotate | Download | only in GlobalISel
      1 # RUN: llc -O0 -run-pass=regbankselect -global-isel %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
      2 # RUN: llc -O0 -run-pass=regbankselect -global-isel %s -regbankselect-greedy -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY
      3 # REQUIRES: global-isel
      4 
      5 --- |
      6   ; ModuleID = 'generic-virtual-registers-type-error.mir'
      7   target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
      8   target triple = "aarch64-apple-ios"
      9   define void @defaultMapping() {
     10   entry:
     11     ret void
     12   }
     13   define void @defaultMappingVector() {
     14   entry:
     15     ret void
     16   }
     17   define void @defaultMapping1Repair() {
     18   entry:
     19     ret void
     20   }
     21   define void @defaultMapping2Repairs() {
     22   entry:
     23     ret void
     24   }
     25   define void @defaultMappingDefRepair() {
     26   entry:
     27     ret void
     28   }
     29   define void @phiPropagation(i32* %src, i32* %dst, i1 %cond) {
     30   entry:
     31     %srcVal = load i32, i32* %src
     32     br i1 %cond, label %end, label %then
     33   then:
     34     %res = add i32 %srcVal, 36
     35     br label %end
     36   end:
     37     %toStore = phi i32 [ %srcVal, %entry ], [ %res, %then ]
     38     store i32 %toStore, i32* %dst
     39     ret void
     40   }
     41   define void @defaultMappingUseRepairPhysReg() {
     42   entry:
     43     ret void
     44   }
     45   define void @defaultMappingDefRepairPhysReg() {
     46   entry:
     47     ret void
     48   }
     49   define void @greedyMappingOr() {
     50   entry:
     51     ret void
     52   }
     53   define void @greedyMappingOrWithConstraints() {
     54   entry:
     55     ret void
     56   }
     57 ...
     58 
     59 ---
     60 # Check that we assign a relevant register bank for %0.
     61 # Based on the type i32, this should be gpr.
     62 name:            defaultMapping
     63 isSSA:           true
     64 # CHECK:      registers:
     65 # CHECK-NEXT:   - { id: 0, class: gpr }
     66 registers:
     67   - { id: 0, class: _ }
     68 body: |
     69   bb.0.entry:
     70     liveins: %x0
     71     ; CHECK:      %0(32) = G_ADD i32 %x0
     72     %0(32) = G_ADD i32 %x0, %x0
     73 ...
     74 
     75 ---
     76 # Check that we assign a relevant register bank for %0.
     77 # Based on the type <2 x i32>, this should be fpr.
     78 # FPR is used for both floating point and vector registers.
     79 name:            defaultMappingVector
     80 isSSA:           true
     81 # CHECK:      registers:
     82 # CHECK-NEXT:   - { id: 0, class: fpr }
     83 registers:
     84   - { id: 0, class: _ }
     85 body: |
     86   bb.0.entry:
     87     liveins: %d0
     88     ; CHECK:      %0(32) = G_ADD <2 x i32> %d0
     89     %0(32) = G_ADD <2 x i32> %d0, %d0
     90 ...
     91 
     92 ---
     93 # Check that we repair the assignment for %0.
     94 # Indeed based on the source of the copy it should live
     95 # in FPR, but at the use, it should be GPR.
     96 name:            defaultMapping1Repair
     97 isSSA:           true
     98 # CHECK:      registers:
     99 # CHECK-NEXT:   - { id: 0, class: fpr }
    100 # CHECK-NEXT:   - { id: 1, class: gpr }
    101 # CHECK-NEXT:   - { id: 2, class: gpr }
    102 registers:
    103   - { id: 0, class: _ }
    104   - { id: 1, class: _ }
    105 body: |
    106   bb.0.entry:
    107     liveins: %s0, %x0
    108     ; CHECK:           %0(32) = COPY %s0
    109     ; CHECK-NEXT:      %2(32) = COPY %0
    110     ; CHECK-NEXT:      %1(32) = G_ADD i32 %2, %x0
    111     %0(32) = COPY %s0
    112     %1(32) = G_ADD i32 %0, %x0
    113 ...
    114 
    115 # Check that we repair the assignment for %0 differently for both uses.
    116 name:            defaultMapping2Repairs
    117 isSSA:           true
    118 # CHECK:      registers:
    119 # CHECK-NEXT:   - { id: 0, class: fpr }
    120 # CHECK-NEXT:   - { id: 1, class: gpr }
    121 # CHECK-NEXT:   - { id: 2, class: gpr }
    122 # CHECK-NEXT:   - { id: 3, class: gpr }
    123 registers:
    124   - { id: 0, class: _ }
    125   - { id: 1, class: _ }
    126 body: |
    127   bb.0.entry:
    128     liveins: %s0, %x0
    129     ; CHECK:           %0(32) = COPY %s0
    130     ; CHECK-NEXT:      %2(32) = COPY %0
    131     ; CHECK-NEXT:      %3(32) = COPY %0
    132     ; CHECK-NEXT:      %1(32) = G_ADD i32 %2, %3
    133     %0(32) = COPY %s0
    134     %1(32) = G_ADD i32 %0, %0
    135 ...
    136 
    137 ---
    138 # Check that we repair the definition of %1.
    139 # %1 is forced to be into FPR, but its definition actually
    140 # requires that it lives in GPR. Make sure regbankselect
    141 # fixes that.
    142 name:            defaultMappingDefRepair
    143 isSSA:           true
    144 # CHECK:      registers:
    145 # CHECK-NEXT:   - { id: 0, class: gpr }
    146 # CHECK-NEXT:   - { id: 1, class: fpr }
    147 # CHECK-NEXT:   - { id: 2, class: gpr }
    148 registers:
    149   - { id: 0, class: _ }
    150   - { id: 1, class: fpr }
    151 body: |
    152   bb.0.entry:
    153     liveins: %w0
    154     ; CHECK:           %0(32) = COPY %w0
    155     ; CHECK-NEXT:      %2(32) = G_ADD i32 %0, %w0
    156     ; CHECK-NEXT:      %1(32) = COPY %2
    157     %0(32) = COPY %w0
    158     %1(32) = G_ADD i32 %0, %w0
    159 ...
    160 
    161 ---
    162 # Check that we are able to propagate register banks from phis.
    163 name:            phiPropagation
    164 isSSA:           true
    165 tracksRegLiveness:   true
    166 # CHECK:      registers:
    167 # CHECK-NEXT:   - { id: 0, class: gpr32 }
    168 # CHECK-NEXT:   - { id: 1, class: gpr64sp }
    169 # CHECK-NEXT:   - { id: 2, class: gpr32 }
    170 # CHECK-NEXT:   - { id: 3, class: gpr }
    171 # CHECK-NEXT:   - { id: 4, class: gpr }
    172 registers:
    173   - { id: 0, class: gpr32 }
    174   - { id: 1, class: gpr64sp }
    175   - { id: 2, class: gpr32 }
    176   - { id: 3, class: _ }
    177   - { id: 4, class: _ }
    178 body: |
    179   bb.0.entry:
    180     successors: %bb.2.end, %bb.1.then
    181     liveins: %x0, %x1, %w2
    182   
    183     %0 = LDRWui killed %x0, 0 :: (load 4 from %ir.src)
    184     %1 = COPY %x1
    185     %2 = COPY %w2
    186     TBNZW killed %2, 0, %bb.2.end
    187   
    188   bb.1.then:
    189     successors: %bb.2.end
    190     %3(32) = G_ADD i32 %0, %0
    191   
    192   bb.2.end:
    193     %4(32) = PHI %0, %bb.0.entry, %3, %bb.1.then
    194     STRWui killed %4, killed %1, 0 :: (store 4 into %ir.dst)
    195     RET_ReallyLR
    196 ...
    197 
    198 ---
    199 # Make sure we can repair physical register uses as well.
    200 name:            defaultMappingUseRepairPhysReg
    201 isSSA:           true
    202 # CHECK:      registers:
    203 # CHECK-NEXT:   - { id: 0, class: gpr }
    204 # CHECK-NEXT:   - { id: 1, class: gpr }
    205 # CHECK-NEXT:   - { id: 2, class: gpr }
    206 registers:
    207   - { id: 0, class: _ }
    208   - { id: 1, class: _ }
    209 body: |
    210   bb.0.entry:
    211     liveins: %w0, %s0
    212     ; CHECK:           %0(32) = COPY %w0
    213     ; CHECK-NEXT:      %2(32) = COPY %s0
    214     ; CHECK-NEXT:      %1(32) = G_ADD i32 %0, %2
    215     %0(32) = COPY %w0
    216     %1(32) = G_ADD i32 %0, %s0
    217 ...
    218 
    219 ---
    220 # Make sure we can repair physical register defs.
    221 name:            defaultMappingDefRepairPhysReg
    222 isSSA:           true
    223 # CHECK:      registers:
    224 # CHECK-NEXT:   - { id: 0, class: gpr }
    225 # CHECK-NEXT:   - { id: 1, class: gpr }
    226 registers:
    227   - { id: 0, class: _ }
    228 body: |
    229   bb.0.entry:
    230     liveins: %w0
    231     ; CHECK:           %0(32) = COPY %w0
    232     ; CHECK-NEXT:      %1(32) = G_ADD i32 %0, %0
    233     ; CHECK-NEXT:      %s0 = COPY %1
    234     %0(32) = COPY %w0
    235     %s0 = G_ADD i32 %0, %0
    236 ...
    237 
    238 ---
    239 # Check that the greedy mode is able to switch the
    240 # G_OR instruction from fpr to gpr.
    241 name:            greedyMappingOr
    242 isSSA:           true
    243 # CHECK:      registers:
    244 # CHECK-NEXT:  - { id: 0, class: gpr }
    245 # CHECK-NEXT:  - { id: 1, class: gpr }
    246 
    247 # Fast mode maps vector instruction on FPR.
    248 # FAST-NEXT:  - { id: 2, class: fpr }
    249 # Fast mode needs two extra copies.
    250 # FAST-NEXT:  - { id: 3, class: fpr }
    251 # FAST-NEXT:  - { id: 4, class: fpr }
    252 
    253 # Greedy mode coalesce the computation on the GPR register
    254 # because it is the cheapest.
    255 # GREEDY-NEXT:  - { id: 2, class: gpr }
    256 
    257 registers:
    258   - { id: 0, class: _ }
    259   - { id: 1, class: _ }
    260   - { id: 2, class: _ }
    261 body: |
    262   bb.0.entry:
    263     liveins: %x0, %x1
    264     ; CHECK: %0(64) = COPY %x0
    265     ; CHECK-NEXT: %1(64) = COPY %x1
    266 
    267 
    268     ; Fast mode tries to reuse the source of the copy for the destination.
    269     ; Now, the default mapping says that %0 and %1 need to be in FPR.
    270     ; The repairing code insert two copies to materialize that.
    271     ; FAST-NEXT: %3(64) = COPY %0
    272     ; FAST-NEXT: %4(64) = COPY %1
    273     ; The mapping of G_OR is on FPR.
    274     ; FAST-NEXT: %2(64) = G_OR <2 x i32> %3, %4
    275 
    276     ; Greedy mode remapped the instruction on the GPR bank.
    277     ; GREEDY-NEXT: %2(64) = G_OR <2 x i32> %0, %1
    278     %0(64) = COPY %x0
    279     %1(64) = COPY %x1
    280     %2(64) = G_OR <2 x i32> %0, %1
    281 ...
    282 
    283 ---
    284 # Check that the greedy mode is able to switch the
    285 # G_OR instruction from fpr to gpr, while still honoring
    286 # %2 constraint.
    287 name:            greedyMappingOrWithConstraints
    288 isSSA:           true
    289 # CHECK:      registers:
    290 # CHECK-NEXT:  - { id: 0, class: gpr }
    291 # CHECK-NEXT:  - { id: 1, class: gpr }
    292 # CHECK-NEXT:  - { id: 2, class: fpr }
    293 
    294 # Fast mode maps vector instruction on FPR.
    295 # Fast mode needs two extra copies.
    296 # FAST-NEXT:  - { id: 3, class: fpr }
    297 # FAST-NEXT:  - { id: 4, class: fpr }
    298 
    299 # Greedy mode coalesce the computation on the GPR register because it
    300 # is the cheapest, but will need one extra copy to materialize %2 into a FPR.
    301 # GREEDY-NEXT:  - { id: 3, class: gpr }
    302 
    303 registers:
    304   - { id: 0, class: _ }
    305   - { id: 1, class: _ }
    306   - { id: 2, class: fpr }
    307 body: |
    308   bb.0.entry:
    309     liveins: %x0, %x1
    310     ; CHECK: %0(64) = COPY %x0
    311     ; CHECK-NEXT: %1(64) = COPY %x1
    312 
    313 
    314     ; Fast mode tries to reuse the source of the copy for the destination.
    315     ; Now, the default mapping says that %0 and %1 need to be in FPR.
    316     ; The repairing code insert two copies to materialize that.
    317     ; FAST-NEXT: %3(64) = COPY %0
    318     ; FAST-NEXT: %4(64) = COPY %1
    319     ; The mapping of G_OR is on FPR.
    320     ; FAST-NEXT: %2(64) = G_OR <2 x i32> %3, %4
    321 
    322     ; Greedy mode remapped the instruction on the GPR bank.
    323     ; GREEDY-NEXT: %3(64) = G_OR <2 x i32> %0, %1
    324     ; We need to keep %2 into FPR because we do not know anything about it.
    325     ; GREEDY-NEXT: %2(64) = COPY %3
    326     %0(64) = COPY %x0
    327     %1(64) = COPY %x1
    328     %2(64) = G_OR <2 x i32> %0, %1
    329 ...
    330