Compiler projects using llvm
# RUN: llc -verify-machineinstrs -run-pass arm-cp-islands %s -o - | FileCheck %s
--- |
  target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
  target triple = "thumbv8.1m.main-arm-unknown-eabi"

  ; Tests adjustments to jump tables, made by the ARM Constant Islands pass
  ; int g(int), h(int);
  ; void g0(int), g1(int), g2(int);
  ; void h0(int), h1(int), h2(int);
  ;
  ; void f(int x) {
  ;   for (;;) {
  ;   up:
  ;     x = g(x);
  ;     switch (x) {
  ;     case 0:
  ;       g0(x);
  ;       break;
  ;     case 1:
  ;       g1(x);
  ;       break;
  ;     case 2:
  ;       g2(x);
  ;       break;
  ;     case 3:
  ;       break;
  ;     case 4:
  ;       for (;;) {
  ;         x = h(x);
  ;         switch (x) {
  ;         case 0:
  ;           h0(x);
  ;           break;
  ;         case 1:
  ;           h1(x);
  ;           break;
  ;         case 2:
  ;           h2(x);
  ;           break;
  ;         case 3:
  ;           goto up;
  ;         case 4:
  ;           return;
  ;         }
  ;       }
  ;     }
  ;   }
  ; }

  define hidden void @f(i32 %x) local_unnamed_addr #0 {
  entry:
    br label %up

  up:                                               ; preds = %up, %sw.bb, %sw.bb1, %sw.bb2, %up.backedge.loopexit, %entry
    %x.addr.1 = phi i32 [ %x, %entry ], [ %call, %up ], [ %call, %sw.bb2 ], [ %call, %sw.bb1 ], [ %call, %sw.bb ], [ %call5, %up.backedge.loopexit ]
    %call = tail call i32 @g(i32 %x.addr.1)
    switch i32 %call, label %up [
      i32 0, label %sw.bb
      i32 1, label %sw.bb1
      i32 2, label %sw.bb2
      i32 4, label %for.cond4.preheader
    ]

  for.cond4.preheader:                              ; preds = %up
    br label %for.cond4

  up.backedge.loopexit:                             ; preds = %for.cond4
    br label %up

  sw.bb:                                            ; preds = %up
    tail call void @g0(i32 0)
    br label %up

  sw.bb1:                                           ; preds = %up
    tail call void @g1(i32 1)
    br label %up

  sw.bb2:                                           ; preds = %up
    tail call void @g2(i32 2)
    br label %up

  for.cond4:                                        ; preds = %for.cond4, %sw.bb6, %sw.bb7, %sw.bb8, %for.cond4.preheader
    %x.addr.2 = phi i32 [ %call, %for.cond4.preheader ], [ %call5, %sw.bb8 ], [ %call5, %sw.bb7 ], [ %call5, %sw.bb6 ], [ %call5, %for.cond4 ]
    %call5 = tail call i32 @h(i32 %x.addr.2)
    switch i32 %call5, label %for.cond4 [
      i32 0, label %sw.bb6
      i32 1, label %sw.bb7
      i32 2, label %sw.bb8
      i32 3, label %up.backedge.loopexit
      i32 4, label %sw.bb10
    ]

  sw.bb6:                                           ; preds = %for.cond4
    tail call void @h0(i32 0)
    br label %for.cond4

  sw.bb7:                                           ; preds = %for.cond4
    tail call void @h1(i32 1)
    br label %for.cond4

  sw.bb8:                                           ; preds = %for.cond4
    tail call void @h2(i32 2)
    br label %for.cond4

  sw.bb10:                                          ; preds = %for.cond4
    ret void
  }

  declare dso_local i32 @g(i32)

  declare dso_local void @g0(i32)

  declare dso_local void @g1(i32)

  declare dso_local void @g2(i32)

  declare dso_local i32 @h(i32)

  declare dso_local void @h0(i32)

  declare dso_local void @h1(i32)

  declare dso_local void @h2(i32)

  attributes #0 = { nounwind "disable-tail-calls"="false" "frame-pointer"="none" "no-jump-tables"="false" "target-cpu"="generic" "target-features"="+armv8.1-m.main,+fp-armv8d16sp,+fp16,+fullfp16,+hwdiv,+lob,+ras,+thumb-mode,+vfp2sp,+vfp3d16sp,+vfp4d16sp" }

  !llvm.module.flags = !{!0}

  !0 = !{i32 8, !"branch-target-enforcement", i32 1}

...
---
name:            f
alignment:       4
exposesReturnsTwice: false
legalized:       false
regBankSelected: false
selected:        false
failedISel:      false
tracksRegLiveness: true
hasWinCFI:       false
registers:       []
liveins:
  - { reg: '$r0', virtual-reg: '' }
frameInfo:
  isFrameAddressTaken: false
  isReturnAddressTaken: false
  hasStackMap:     false
  hasPatchPoint:   false
  stackSize:       8
  offsetAdjustment: 0
  maxAlignment:    4
  adjustsStack:    true
  hasCalls:        true
  stackProtector:  ''
  maxCallFrameSize: 0
  cvBytesOfCalleeSavedRegisters: 0
  hasOpaqueSPAdjustment: false
  hasVAStart:      false
  hasMustTailInVarArgFunc: false
  localFrameSize:  0
  savePoint:       ''
  restorePoint:    ''
fixedStack:      []
stack:
  - { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
      stack-id: default, callee-saved-register: '$lr', callee-saved-restored: false,
      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
  - { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
      stack-id: default, callee-saved-register: '$r4', callee-saved-restored: true,
      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
callSites:       []
debugValueSubstitutions: []
constants:       []
machineFunctionInfo: {}
jumpTable:
  kind:            inline
  entries:
    - id:              0
      blocks:          [ '%bb.3', '%bb.4', '%bb.5', '%bb.1', '%bb.7' ]
    - id:              1
      blocks:          [ '%bb.6', '%bb.9', '%bb.10', '%bb.1', '%bb.11' ]

# %bb.4 and %bb.10 redirect to %bb1, the rest are just renumbered
# CHECK-LABEL: jumpTable:
# CHECK-NEXT:  kind:            inline
# CHECK-NEXT:  entries:
# CHECK-NEXT:    - id:              0
# CHECK-NEXT:      blocks:          [ '%bb.6', '%bb.14', '%bb.5', '%bb.4', '%bb.7' ]
# CHECK-NEXT:    - id:              1
# CHECK-NEXT:      blocks:          [ '%bb.11', '%bb.12', '%bb.13', '%bb.10', '%bb.15' ]

# %bb.1 loses the BTI
# CHECK-LABEL: bb.1.up (align 4):
# CHECK-NOT:   t2BTI
# CHECK-LABEL: bb.2.up:

# CHECK-LABEL: bb.4.up:
# CHECK:       t2BTI
# CHECK:       tB %bb.1

# CHECK-LABEL: bb.10.for.cond4:
# CHECK:     t2BTI
# CHECK:     tB %bb.1
body:             |
  bb.0.entry:
    successors: %bb.1(0x80000000)
    liveins: $r0, $r4, $lr

    t2BTI
    frame-setup tPUSH 14 /* CC::al */, $noreg, killed $r4, killed $lr, implicit-def $sp, implicit $sp
    frame-setup CFI_INSTRUCTION def_cfa_offset 8
    frame-setup CFI_INSTRUCTION offset $lr, -4
    frame-setup CFI_INSTRUCTION offset $r4, -8
    $r4 = tMOVr killed $r0, 14 /* CC::al */, $noreg
    t2B %bb.1, 14 /* CC::al */, $noreg

  bb.5.sw.bb2:
    successors: %bb.1(0x80000000)
    liveins: $r4

    t2BTI
    $r0, dead $cpsr = tMOVi8 2, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @g2, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp

  bb.1.up (align 4):
    successors: %bb.1(0x20000000), %bb.2(0x60000000)
    liveins: $r4

    t2BTI
    $r0 = tMOVr killed $r4, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @g, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp, implicit-def $r0
    $r4 = tMOVr $r0, 14 /* CC::al */, $noreg
    tCMPi8 killed $r0, 4, 14 /* CC::al */, $noreg, implicit-def $cpsr
    t2Bcc %bb.1, 8 /* CC::hi */, killed $cpsr
  bb.2.up:
    successors: %bb.3(0x15555555), %bb.4(0x15555555), %bb.5(0x15555555), %bb.1(0x2aaaaaab), %bb.7(0x15555555)
    liveins: $r4

    renamable $r0 = t2LEApcrelJT %jump-table.0, 14 /* CC::al */, $noreg
    renamable $r0 = t2ADDrs killed renamable $r0, renamable $r4, 18, 14 /* CC::al */, $noreg, $noreg
    t2BR_JT killed renamable $r0, renamable $r4, %jump-table.0

  bb.3.sw.bb:
    successors: %bb.1(0x80000000)
    liveins: $r4

    t2BTI
    $r0, dead $cpsr = tMOVi8 0, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @g0, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp
    t2B %bb.1, 14 /* CC::al */, $noreg

  bb.6.sw.bb6:
    successors: %bb.7(0x80000000)
    liveins: $r4

    t2BTI
    $r0, dead $cpsr = tMOVi8 0, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @h0, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp

  bb.7.for.cond4 (align 4):
    successors: %bb.7(0x3efbefc0), %bb.8(0x41041040)
    liveins: $r4

    t2BTI
    $r0 = tMOVr killed $r4, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @h, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp, implicit-def $r0
    $r4 = tMOVr $r0, 14 /* CC::al */, $noreg
    tCMPi8 killed $r0, 4, 14 /* CC::al */, $noreg, implicit-def $cpsr
    t2Bcc %bb.7, 8 /* CC::hi */, killed $cpsr

  bb.8.for.cond4:
    successors: %bb.6(0x29555555), %bb.9(0x29555555), %bb.10(0x29555555), %bb.1(0x02000000), %bb.11(0x02000000)
    liveins: $r4

    renamable $r0 = t2LEApcrelJT %jump-table.1, 14 /* CC::al */, $noreg
    renamable $r0 = t2ADDrs killed renamable $r0, renamable $r4, 18, 14 /* CC::al */, $noreg, $noreg
    t2BR_JT killed renamable $r0, renamable $r4, %jump-table.1

  bb.9.sw.bb7:
    successors: %bb.7(0x80000000)
    liveins: $r4

    t2BTI
    $r0, dead $cpsr = tMOVi8 1, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @h1, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp
    t2B %bb.7, 14 /* CC::al */, $noreg

  bb.10.sw.bb8:
    successors: %bb.7(0x80000000)
    liveins: $r4

    t2BTI
    $r0, dead $cpsr = tMOVi8 2, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @h2, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp
    t2B %bb.7, 14 /* CC::al */, $noreg

  bb.4.sw.bb1:
    successors: %bb.1(0x80000000)
    liveins: $r4

    t2BTI
    $r0, dead $cpsr = tMOVi8 1, 14 /* CC::al */, $noreg
    tBL 14 /* CC::al */, $noreg, @g1, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $r0, implicit-def $sp
    t2B %bb.1, 14 /* CC::al */, $noreg

  bb.11.sw.bb10:
    t2BTI
    frame-destroy tPOP_RET 14 /* CC::al */, $noreg, def $r4, def $pc

...