1; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 2; RUN: llc -mtriple aarch64 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s 3 4declare i32 @bar(...) 5define void @or_cond(i32 %X, i32 %Y, i32 %Z) nounwind { 6 ; CHECK-LABEL: name: or_cond 7 ; CHECK: bb.1.entry: 8 ; CHECK: successors: %bb.2(0x20000000), %bb.4(0x60000000) 9 ; CHECK: liveins: $w0, $w1, $w2 10 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 11 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 12 ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 13 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 14 ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 15 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 16 ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]] 17 ; CHECK: [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]] 18 ; CHECK: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]] 19 ; CHECK: G_BRCOND [[ICMP2]](s1), %bb.2 20 ; CHECK: G_BR %bb.4 21 ; CHECK: bb.4.entry: 22 ; CHECK: successors: %bb.2(0x2aaaaaab), %bb.3(0x55555555) 23 ; CHECK: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 24 ; CHECK: G_BRCOND [[ICMP3]](s1), %bb.2 25 ; CHECK: G_BR %bb.3 26 ; CHECK: bb.2.cond_true: 27 ; CHECK: TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp 28 ; CHECK: bb.3.UnifiedReturnBlock: 29 ; CHECK: RET_ReallyLR 30entry: 31 %tmp1 = icmp eq i32 %X, 0 32 %tmp3 = icmp slt i32 %Y, 5 33 %tmp4 = or i1 %tmp3, %tmp1 34 br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock 35 36cond_true: 37 %tmp5 = tail call i32 (...) @bar( ) 38 ret void 39 40UnifiedReturnBlock: 41 ret void 42} 43 44define void @and_cond(i32 %X, i32 %Y, i32 %Z) nounwind { 45 ; CHECK-LABEL: name: and_cond 46 ; CHECK: bb.1.entry: 47 ; CHECK: successors: %bb.4(0x60000000), %bb.3(0x20000000) 48 ; CHECK: liveins: $w0, $w1, $w2 49 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 50 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 51 ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 52 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 53 ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 54 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 55 ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]] 56 ; CHECK: [[AND:%[0-9]+]]:_(s1) = G_AND [[ICMP1]], [[ICMP]] 57 ; CHECK: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]] 58 ; CHECK: G_BRCOND [[ICMP2]](s1), %bb.4 59 ; CHECK: G_BR %bb.3 60 ; CHECK: bb.4.entry: 61 ; CHECK: successors: %bb.2(0x55555555), %bb.3(0x2aaaaaab) 62 ; CHECK: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 63 ; CHECK: G_BRCOND [[ICMP3]](s1), %bb.2 64 ; CHECK: G_BR %bb.3 65 ; CHECK: bb.2.cond_true: 66 ; CHECK: TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp 67 ; CHECK: bb.3.UnifiedReturnBlock: 68 ; CHECK: RET_ReallyLR 69entry: 70 %tmp1 = icmp eq i32 %X, 0 71 %tmp3 = icmp slt i32 %Y, 5 72 %tmp4 = and i1 %tmp3, %tmp1 73 br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock 74 75cond_true: 76 %tmp5 = tail call i32 (...) @bar( ) 77 ret void 78 79UnifiedReturnBlock: 80 ret void 81} 82 83; Don't emit two branches for same operands. 84define void @or_cond_same_values_cmp(i32 %X, i32 %Y, i32 %Z) nounwind { 85 ; CHECK-LABEL: name: or_cond_same_values_cmp 86 ; CHECK: bb.1.entry: 87 ; CHECK: successors: %bb.2(0x40000000), %bb.3(0x40000000) 88 ; CHECK: liveins: $w0, $w1, $w2 89 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 90 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 91 ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 92 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 93 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 94 ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY]](s32), [[C]] 95 ; CHECK: [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]] 96 ; CHECK: G_BRCOND [[OR]](s1), %bb.2 97 ; CHECK: G_BR %bb.3 98 ; CHECK: bb.2.cond_true: 99 ; CHECK: TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp 100 ; CHECK: bb.3.UnifiedReturnBlock: 101 ; CHECK: RET_ReallyLR 102entry: 103 %tmp1 = icmp eq i32 %X, 5 104 %tmp3 = icmp slt i32 %X, 5 105 %tmp4 = or i1 %tmp3, %tmp1 106 br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock 107 108cond_true: 109 %tmp5 = tail call i32 (...) @bar( ) 110 ret void 111 112UnifiedReturnBlock: 113 ret void 114} 115 116; Emit multiple branches for more than 2 cases. 117define void @or_cond_multiple_cases(i32 %X, i32 %Y, i32 %Z) nounwind { 118 ; CHECK-LABEL: name: or_cond_multiple_cases 119 ; CHECK: bb.1.entry: 120 ; CHECK: successors: %bb.2(0x10000000), %bb.5(0x70000000) 121 ; CHECK: liveins: $w0, $w1, $w2 122 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 123 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 124 ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 125 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 126 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 127 ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY]](s32), [[C]] 128 ; CHECK: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]] 129 ; CHECK: [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]] 130 ; CHECK: [[OR1:%[0-9]+]]:_(s1) = G_OR [[OR]], [[ICMP2]] 131 ; CHECK: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY]](s32), [[C]] 132 ; CHECK: G_BRCOND [[ICMP3]](s1), %bb.2 133 ; CHECK: G_BR %bb.5 134 ; CHECK: bb.5.entry: 135 ; CHECK: successors: %bb.2(0x12492492), %bb.4(0x6db6db6e) 136 ; CHECK: [[ICMP4:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 137 ; CHECK: G_BRCOND [[ICMP4]](s1), %bb.2 138 ; CHECK: G_BR %bb.4 139 ; CHECK: bb.4.entry: 140 ; CHECK: successors: %bb.2(0x2aaaaaab), %bb.3(0x55555555) 141 ; CHECK: [[ICMP5:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]] 142 ; CHECK: G_BRCOND [[ICMP5]](s1), %bb.2 143 ; CHECK: G_BR %bb.3 144 ; CHECK: bb.2.cond_true: 145 ; CHECK: TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp 146 ; CHECK: bb.3.UnifiedReturnBlock: 147 ; CHECK: RET_ReallyLR 148entry: 149 %tmp1 = icmp eq i32 %X, 5 150 %tmp3 = icmp slt i32 %X, 5 151 %tmpZ = icmp eq i32 %Z, 5 152 %tmp4 = or i1 %tmp3, %tmp1 153 %final = or i1 %tmp4, %tmpZ 154 br i1 %final, label %cond_true, label %UnifiedReturnBlock 155 156cond_true: 157 %tmp5 = tail call i32 (...) @bar( ) 158 ret void 159 160UnifiedReturnBlock: 161 ret void 162} 163 164; (X != null) | (Y != null) --> (X|Y) != 0 165; Don't emit two branches. 166define void @or_cond_ne_null(i32 %X, i32 %Y, i32 %Z) nounwind { 167 ; CHECK-LABEL: name: or_cond_ne_null 168 ; CHECK: bb.1.entry: 169 ; CHECK: successors: %bb.2(0x40000000), %bb.3(0x40000000) 170 ; CHECK: liveins: $w0, $w1, $w2 171 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 172 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 173 ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 174 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 175 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[COPY]](s32), [[C]] 176 ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[COPY1]](s32), [[C]] 177 ; CHECK: [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]] 178 ; CHECK: G_BRCOND [[OR]](s1), %bb.2 179 ; CHECK: G_BR %bb.3 180 ; CHECK: bb.2.cond_true: 181 ; CHECK: TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp 182 ; CHECK: bb.3.UnifiedReturnBlock: 183 ; CHECK: RET_ReallyLR 184entry: 185 %tmp1 = icmp ne i32 %X, 0 186 %tmp3 = icmp ne i32 %Y, 0 187 %tmp4 = or i1 %tmp3, %tmp1 188 br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock 189 190cond_true: 191 %tmp5 = tail call i32 (...) @bar( ) 192 ret void 193 194UnifiedReturnBlock: 195 ret void 196} 197 198; If the branch is unpredictable, don't add another branch 199; regardless of whether they are expensive or not. 200 201define void @unpredictable(i32 %X, i32 %Y, i32 %Z) nounwind { 202 ; CHECK-LABEL: name: unpredictable 203 ; CHECK: bb.1.entry: 204 ; CHECK: successors: %bb.2(0x40000000), %bb.3(0x40000000) 205 ; CHECK: liveins: $w0, $w1, $w2 206 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 207 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 208 ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 209 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 210 ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 211 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] 212 ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]] 213 ; CHECK: [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]] 214 ; CHECK: G_BRCOND [[OR]](s1), %bb.2 215 ; CHECK: G_BR %bb.3 216 ; CHECK: bb.2.cond_true: 217 ; CHECK: TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp 218 ; CHECK: bb.3.UnifiedReturnBlock: 219 ; CHECK: RET_ReallyLR 220entry: 221 %tmp1 = icmp eq i32 %X, 0 222 %tmp3 = icmp slt i32 %Y, 5 223 %tmp4 = or i1 %tmp3, %tmp1 224 br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock, !unpredictable !0 225 226cond_true: 227 %tmp5 = tail call i32 (...) @bar( ) 228 ret void 229 230UnifiedReturnBlock: 231 ret void 232} 233 234!0 = !{} 235