1; This tests a switch statement, including multiple branches to the 2; same label which also results in phi instructions with multiple 3; entries for the same incoming edge. 4 5; For x86 see adv-switch-opt.ll 6 7; TODO(jvoung): Update to -02 once the phi assignments is done for ARM 8; RUN: %if --need=target_ARM32 \ 9; RUN: --command %p2i --filetype=obj --disassemble \ 10; RUN: --target arm32 -i %s --args -Om1 \ 11; RUN: | %if --need=target_ARM32 \ 12; RUN: --command FileCheck --check-prefix ARM32 %s 13 14; RUN: %if --need=target_MIPS32 --need=allow_dump \ 15; RUN: --command %p2i --filetype=asm --assemble --disassemble \ 16; RUN: --target mips32 -i %s --args -Om1 \ 17; RUN: -allow-externally-defined-symbols \ 18; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 19; RUN: --command FileCheck --check-prefix MIPS32 %s 20 21define internal i32 @testSwitch(i32 %a) { 22entry: 23 switch i32 %a, label %sw.default [ 24 i32 1, label %sw.epilog 25 i32 2, label %sw.epilog 26 i32 3, label %sw.epilog 27 i32 7, label %sw.bb1 28 i32 8, label %sw.bb1 29 i32 15, label %sw.bb2 30 i32 14, label %sw.bb2 31 ] 32 33sw.default: ; preds = %entry 34 %add = add i32 %a, 27 35 br label %sw.epilog 36 37sw.bb1: ; preds = %entry, %entry 38 %phitmp = sub i32 21, %a 39 br label %sw.bb2 40 41sw.bb2: ; preds = %sw.bb1, %entry, %entry 42 %result.0 = phi i32 [ 1, %entry ], [ 1, %entry ], [ %phitmp, %sw.bb1 ] 43 br label %sw.epilog 44 45sw.epilog: ; preds = %sw.bb2, %sw.default, %entry, %entry, %entry 46 %result.1 = phi i32 [ %add, %sw.default ], [ %result.0, %sw.bb2 ], [ 17, %entry ], [ 17, %entry ], [ 17, %entry ] 47 ret i32 %result.1 48} 49 50; MIPS32-LABEL: testSwitch 51; MIPS32: li {{.*}},1 52; MIPS32: li {{.*}},17 53; MIPS32: li {{.*}},1 54; MIPS32: beq {{.*}},{{.*}},{{.*}} <[[SW_EPILOG:.*]]> 55; MIPS32: li {{.*}},2 56; MIPS32: beq {{.*}},{{.*}},{{.*}} <[[SW_EPILOG]]> 57; MIPS32: li {{.*}},3 58; MIPS32: beq {{.*}},{{.*}},{{.*}} <[[SW_EPILOG]]> 59; MIPS32: li {{.*}},7 60; MIPS32: beq {{.*}},{{.*}},{{.*}} <[[SW_BB1:.*]]> 61; MIPS32: li {{.*}},8 62; MIPS32: beq {{.*}},{{.*}},{{.*}} <[[SW_BB1]]> 63; MIPS32: li {{.*}},15 64; MIPS32: beq {{.*}},{{.*}},{{.*}} <[[SW_BB2:.*]]> 65; MIPS32: li {{.*}},14 66; MIPS32: beq {{.*}},{{.*}},{{.*}} <[[SW_BB2]]> 67; MIPS32: b {{.*}} <[[SW_DEFAULT:.*]]> 68; MIPS32: <[[SW_DEFAULT]]> 69; MIPS32: addiu {{.*}},27 70; MIPS32: b {{.*}} <[[SW_EPILOG]]> 71; MIPS32: <[[SW_BB1]]> 72; MIPS32: li {{.*}},21 73; MIPS32: b {{.*}} <[[SW_BB2]]> 74; MIPS32: <[[SW_BB2]]> 75; MIPS32: b {{.*}} <[[SW_EPILOG]]> 76; MIPS32: <[[SW_EPILOG]]> 77; MIPS32: jr ra 78 79; Check for a valid addressing mode when the switch operand is an 80; immediate. It's important that there is exactly one case, because 81; for two or more cases the source operand is legalized into a 82; register. 83define internal i32 @testSwitchImm() { 84entry: 85 switch i32 10, label %sw.default [ 86 i32 1, label %sw.default 87 ] 88 89sw.default: 90 ret i32 20 91} 92; ARM32-LABEL: testSwitchImm 93; ARM32: cmp {{r[0-9]+}}, #1 94; ARM32-NEXT: beq 95; ARM32-NEXT: b 96 97; MIPS32-LABEL: testSwitchImm 98; MIPS32: li {{.*}},10 99; MIPS32: li {{.*}},1 100; MIPS32: beq {{.*}},{{.*}},{{.*}} <.LtestSwitchImm$sw.default> 101; MIPS32: .LtestSwitchImm$sw.default 102; MIPS32: li v0,20 103; MIPS32: jr ra 104 105; Test for correct 64-bit lowering. 106define internal i32 @testSwitch64(i64 %a) { 107entry: 108 switch i64 %a, label %sw.default [ 109 i64 123, label %return 110 i64 234, label %sw.bb1 111 i64 345, label %sw.bb2 112 i64 78187493520, label %sw.bb3 113 ] 114 115sw.bb1: ; preds = %entry 116 br label %return 117 118sw.bb2: ; preds = %entry 119 br label %return 120 121sw.bb3: ; preds = %entry 122 br label %return 123 124sw.default: ; preds = %entry 125 br label %return 126 127return: ; preds = %sw.default, %sw.bb3, %sw.bb2, %sw.bb1, %entry 128 %retval.0 = phi i32 [ 5, %sw.default ], [ 4, %sw.bb3 ], [ 3, %sw.bb2 ], [ 2, %sw.bb1 ], [ 1, %entry ] 129 ret i32 %retval.0 130} 131; ARM32-LABEL: testSwitch64 132; ARM32: cmp {{r[0-9]+}}, #123 133; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0 134; ARM32-NEXT: beq 135; ARM32: cmp {{r[0-9]+}}, #234 136; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0 137; ARM32-NEXT: beq 138; ARM32: movw [[REG:r[0-9]+]], #345 139; ARM32-NEXT: cmp {{r[0-9]+}}, [[REG]] 140; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0 141; ARM32-NEXT: beq 142; ARM32: movw [[REG:r[0-9]+]], #30864 143; ARM32-NEXT: movt [[REG]], #13398 144; ARM32-NEXT: cmp {{r[0-9]+}}, [[REG]] 145; ARM32-NEXT: cmpeq {{r[0-9]+}}, #18 146; ARM32-NEXT: beq 147; ARM32-NEXT: b 148 149; MIPS32-LABEL: testSwitch64 150; MIPS32: bne {{.*}},{{.*}},{{.*}} <.LtestSwitch64$local$__0> 151; MIPS32: li {{.*}},123 152; MIPS32: beq {{.*}},{{.*}},{{.*}} <.LtestSwitch64$return> 153; MIPS32: .LtestSwitch64$local$__0 154; MIPS32: li {{.*}},0 155; MIPS32: bne {{.*}},{{.*}},{{.*}} <.LtestSwitch64$local$__1> 156; MIPS32: li {{.*}},234 157; MIPS32: beq {{.*}},{{.*}},{{.*}} <.LtestSwitch64$sw.bb1> 158; MIPS32: .LtestSwitch64$local$__1 159; MIPS32: li {{.*}},0 160; MIPS32: bne {{.*}},{{.*}},{{.*}} <.LtestSwitch64$local$__2> 161; MIPS32: li {{.*}},345 162; MIPS32: beq {{.*}},{{.*}},{{.*}} <.LtestSwitch64$sw.bb2> 163; MIPS32: .LtestSwitch64$local$__2 164; MIPS32: li {{.*}},18 165; MIPS32: bne {{.*}},{{.*}},{{.*}} <.LtestSwitch64$local$__3> 166; MIPS32: lui {{.*}},0x3456 167; MIPS32: ori {{.*}},{{.*}},0x7890 168; MIPS32: beq {{.*}},{{.*}},{{.*}} <.LtestSwitch64$sw.bb3> 169; MIPS32: .LtestSwitch64$local$__3 170; MIPS32: b {{.*}} <.LtestSwitch64$sw.default> 171; MIPS32: .LtestSwitch64$sw.bb1 172; MIPS32: li {{.*}},2 173; MIPS32: b {{.*}} <.LtestSwitch64$return> 174; MIPS32: .LtestSwitch64$sw.bb2 175; MIPS32: li {{.*}},3 176; MIPS32: b {{.*}} <.LtestSwitch64$return> 177; MIPS32: .LtestSwitch64$sw.bb3 178; MIPS32: li {{.*}},4 179; MIPS32: b {{.*}} <.LtestSwitch64$return> 180; MIPS32: .LtestSwitch64$sw.default 181; MIPS32: li {{.*}},5 182; MIPS32: b {{.*}} <.LtestSwitch64$return> 183; MIPS32: .LtestSwitch64$return 184; MIPS32: jr ra 185 186; Similar to testSwitchImm, make sure proper addressing modes are 187; used. In reality, this is tested by running the output through the 188; assembler. 189define internal i32 @testSwitchImm64() { 190entry: 191 switch i64 10, label %sw.default [ 192 i64 1, label %sw.default 193 ] 194 195sw.default: 196 ret i32 20 197} 198; ARM32-LABEL: testSwitchImm64 199; ARM32: cmp {{r[0-9]+}}, #1 200; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0 201; ARM32-NEXT: beq [[ADDR:[0-9a-f]+]] 202; ARM32-NEXT: b [[ADDR]] 203 204; MIPS32-LABEL: testSwitchImm64 205; MIPS32: li {{.*}},10 206; MIPS32: li {{.*}},0 207; MIPS32: li {{.*}},0 208; MIPS32: bne {{.*}},{{.*}},{{.*}} <.LtestSwitchImm64$local$__0> 209; MIPS32: li {{.*}},1 210; MIPS32: beq {{.*}},{{.*}},{{.*}} <.LtestSwitchImm64$sw.default> 211; MIPS32: .LtestSwitchImm64$local$__0 212; MIPS32: b {{.*}} <.LtestSwitchImm64$sw.default> 213; MIPS32: .LtestSwitchImm64$sw.default 214; MIPS32: li {{.*}},20 215; MIPS32: jr ra 216 217define internal i32 @testSwitchUndef64() { 218entry: 219 switch i64 undef, label %sw.default [ 220 i64 1, label %sw.default 221 ] 222 223sw.default: 224 ret i32 20 225} 226; ARM32-LABEL: testSwitchUndef64 227; ARM32: mov {{.*}}, #0 228; ARM32: mov {{.*}}, #0 229 230; MIPS32-LABEL: testSwitchUndef64 231; MIPS32: li {{.*}},0 232; MIPS32: li {{.*}},0 233; MIPS32: li {{.*}},0 234; MIPS32: bne {{.*}},{{.*}},{{.*}} <.LtestSwitchUndef64$local$__0> 235; MIPS32: li {{.*}},1 236; MIPS32: beq {{.*}},{{.*}},{{.*}} <.LtestSwitchUndef64$sw.default> 237; MIPS32: .LtestSwitchUndef64$local$__0 238; MIPS32: b {{.*}} <.LtestSwitchUndef64$sw.default> 239; MIPS32: .LtestSwitchUndef64$sw.default 240; MIPS32: li {{.*}},20 241; MIPS32: jr ra 242