| # 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 |
| |
| ... |