1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=aarch64-linux-gnuabi -O2 | FileCheck %s 3 4; The following cases are for i16 5 6%struct.s_signed_i16 = type { i16, i16, i16 } 7%struct.s_unsigned_i16 = type { i16, i16, i16 } 8 9@cost_s_i8_i16 = common global %struct.s_signed_i16 zeroinitializer, align 2 10@cost_u_i16 = common global %struct.s_unsigned_i16 zeroinitializer, align 2 11 12define void @test_i16_2cmp_signed_1() { 13; CHECK-LABEL: test_i16_2cmp_signed_1: 14; CHECK: // %bb.0: // %entry 15; CHECK-NEXT: adrp x8, :got:cost_s_i8_i16 16; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s_i8_i16] 17; CHECK-NEXT: ldrsh w9, [x8, #2] 18; CHECK-NEXT: ldrsh w10, [x8, #4] 19; CHECK-NEXT: cmp w9, w10 20; CHECK-NEXT: b.lt .LBB0_2 21; CHECK-NEXT: // %bb.1: // %if.end8.sink.split 22; CHECK-NEXT: strh w9, [x8] 23; CHECK-NEXT: .LBB0_2: // %if.end8 24; CHECK-NEXT: ret 25entry: 26 %0 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 1), align 2 27 %1 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 2), align 2 28 %cmp = icmp sgt i16 %0, %1 29 br i1 %cmp, label %if.then, label %if.else 30 31if.then: ; preds = %entry 32 store i16 %0, ptr @cost_s_i8_i16, align 2 33 br label %if.end8 34 35if.else: ; preds = %entry 36 %cmp5 = icmp eq i16 %0, %1 37 br i1 %cmp5, label %if.then7, label %if.end8 38 39if.then7: ; preds = %if.else 40 store i16 %0, ptr @cost_s_i8_i16, align 2 41 br label %if.end8 42 43if.end8: ; preds = %if.else, %if.then7, %if.then 44 ret void 45} 46 47define void @test_i16_2cmp_signed_2() { 48; CHECK-LABEL: test_i16_2cmp_signed_2: 49; CHECK: // %bb.0: // %entry 50; CHECK-NEXT: adrp x8, :got:cost_s_i8_i16 51; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s_i8_i16] 52; CHECK-NEXT: ldrsh w9, [x8, #2] 53; CHECK-NEXT: ldrsh w10, [x8, #4] 54; CHECK-NEXT: cmp w9, w10 55; CHECK-NEXT: b.gt .LBB1_2 56; CHECK-NEXT: // %bb.1: // %if.else 57; CHECK-NEXT: mov w9, w10 58; CHECK-NEXT: b.ge .LBB1_3 59; CHECK-NEXT: .LBB1_2: // %if.end8.sink.split 60; CHECK-NEXT: strh w9, [x8] 61; CHECK-NEXT: .LBB1_3: // %if.end8 62; CHECK-NEXT: ret 63entry: 64 %0 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 1), align 2 65 %1 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 2), align 2 66 %cmp = icmp sgt i16 %0, %1 67 br i1 %cmp, label %if.then, label %if.else 68 69if.then: ; preds = %entry 70 store i16 %0, ptr @cost_s_i8_i16, align 2 71 br label %if.end8 72 73if.else: ; preds = %entry 74 %cmp5 = icmp slt i16 %0, %1 75 br i1 %cmp5, label %if.then7, label %if.end8 76 77if.then7: ; preds = %if.else 78 store i16 %1, ptr @cost_s_i8_i16, align 2 79 br label %if.end8 80 81if.end8: ; preds = %if.else, %if.then7, %if.then 82 ret void 83} 84 85define void @test_i16_2cmp_unsigned_1() { 86; CHECK-LABEL: test_i16_2cmp_unsigned_1: 87; CHECK: // %bb.0: // %entry 88; CHECK-NEXT: adrp x8, :got:cost_u_i16 89; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i16] 90; CHECK-NEXT: ldrh w9, [x8, #2] 91; CHECK-NEXT: ldrh w10, [x8, #4] 92; CHECK-NEXT: cmp w9, w10 93; CHECK-NEXT: b.lo .LBB2_2 94; CHECK-NEXT: // %bb.1: // %if.end8.sink.split 95; CHECK-NEXT: strh w9, [x8] 96; CHECK-NEXT: .LBB2_2: // %if.end8 97; CHECK-NEXT: ret 98entry: 99 %0 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 1), align 2 100 %1 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 2), align 2 101 %cmp = icmp ugt i16 %0, %1 102 br i1 %cmp, label %if.then, label %if.else 103 104if.then: ; preds = %entry 105 store i16 %0, ptr @cost_u_i16, align 2 106 br label %if.end8 107 108if.else: ; preds = %entry 109 %cmp5 = icmp eq i16 %0, %1 110 br i1 %cmp5, label %if.then7, label %if.end8 111 112if.then7: ; preds = %if.else 113 store i16 %0, ptr @cost_u_i16, align 2 114 br label %if.end8 115 116if.end8: ; preds = %if.else, %if.then7, %if.then 117 ret void 118} 119 120define void @test_i16_2cmp_unsigned_2() { 121; CHECK-LABEL: test_i16_2cmp_unsigned_2: 122; CHECK: // %bb.0: // %entry 123; CHECK-NEXT: adrp x8, :got:cost_u_i16 124; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i16] 125; CHECK-NEXT: ldrh w9, [x8, #2] 126; CHECK-NEXT: ldrh w10, [x8, #4] 127; CHECK-NEXT: cmp w9, w10 128; CHECK-NEXT: b.hi .LBB3_2 129; CHECK-NEXT: // %bb.1: // %if.else 130; CHECK-NEXT: mov w9, w10 131; CHECK-NEXT: b.hs .LBB3_3 132; CHECK-NEXT: .LBB3_2: // %if.end8.sink.split 133; CHECK-NEXT: strh w9, [x8] 134; CHECK-NEXT: .LBB3_3: // %if.end8 135; CHECK-NEXT: ret 136entry: 137 %0 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 1), align 2 138 %1 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 2), align 2 139 %cmp = icmp ugt i16 %0, %1 140 br i1 %cmp, label %if.then, label %if.else 141 142if.then: ; preds = %entry 143 store i16 %0, ptr @cost_u_i16, align 2 144 br label %if.end8 145 146if.else: ; preds = %entry 147 %cmp5 = icmp ult i16 %0, %1 148 br i1 %cmp5, label %if.then7, label %if.end8 149 150if.then7: ; preds = %if.else 151 store i16 %1, ptr @cost_u_i16, align 2 152 br label %if.end8 153 154if.end8: ; preds = %if.else, %if.then7, %if.then 155 ret void 156} 157 158; The following cases are for i8 159 160%struct.s_signed_i8 = type { i8, i8, i8 } 161%struct.s_unsigned_i8 = type { i8, i8, i8 } 162 163@cost_s = common global %struct.s_signed_i8 zeroinitializer, align 2 164@cost_u_i8 = common global %struct.s_unsigned_i8 zeroinitializer, align 2 165 166 167define void @test_i8_2cmp_signed_1() { 168; CHECK-LABEL: test_i8_2cmp_signed_1: 169; CHECK: // %bb.0: // %entry 170; CHECK-NEXT: adrp x8, :got:cost_s 171; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s] 172; CHECK-NEXT: ldrsb w9, [x8, #1] 173; CHECK-NEXT: ldrsb w10, [x8, #2] 174; CHECK-NEXT: cmp w9, w10 175; CHECK-NEXT: b.lt .LBB4_2 176; CHECK-NEXT: // %bb.1: // %if.end8.sink.split 177; CHECK-NEXT: strb w9, [x8] 178; CHECK-NEXT: .LBB4_2: // %if.end8 179; CHECK-NEXT: ret 180entry: 181 %0 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 1), align 2 182 %1 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 2), align 2 183 %cmp = icmp sgt i8 %0, %1 184 br i1 %cmp, label %if.then, label %if.else 185 186if.then: ; preds = %entry 187 store i8 %0, ptr @cost_s, align 2 188 br label %if.end8 189 190if.else: ; preds = %entry 191 %cmp5 = icmp eq i8 %0, %1 192 br i1 %cmp5, label %if.then7, label %if.end8 193 194if.then7: ; preds = %if.else 195 store i8 %0, ptr @cost_s, align 2 196 br label %if.end8 197 198if.end8: ; preds = %if.else, %if.then7, %if.then 199 ret void 200} 201 202define void @test_i8_2cmp_signed_2() { 203; CHECK-LABEL: test_i8_2cmp_signed_2: 204; CHECK: // %bb.0: // %entry 205; CHECK-NEXT: adrp x8, :got:cost_s 206; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s] 207; CHECK-NEXT: ldrsb w9, [x8, #1] 208; CHECK-NEXT: ldrsb w10, [x8, #2] 209; CHECK-NEXT: cmp w9, w10 210; CHECK-NEXT: b.gt .LBB5_2 211; CHECK-NEXT: // %bb.1: // %if.else 212; CHECK-NEXT: mov w9, w10 213; CHECK-NEXT: b.ge .LBB5_3 214; CHECK-NEXT: .LBB5_2: // %if.end8.sink.split 215; CHECK-NEXT: strb w9, [x8] 216; CHECK-NEXT: .LBB5_3: // %if.end8 217; CHECK-NEXT: ret 218entry: 219 %0 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 1), align 2 220 %1 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 2), align 2 221 %cmp = icmp sgt i8 %0, %1 222 br i1 %cmp, label %if.then, label %if.else 223 224if.then: ; preds = %entry 225 store i8 %0, ptr @cost_s, align 2 226 br label %if.end8 227 228if.else: ; preds = %entry 229 %cmp5 = icmp slt i8 %0, %1 230 br i1 %cmp5, label %if.then7, label %if.end8 231 232if.then7: ; preds = %if.else 233 store i8 %1, ptr @cost_s, align 2 234 br label %if.end8 235 236if.end8: ; preds = %if.else, %if.then7, %if.then 237 ret void 238} 239 240define void @test_i8_2cmp_unsigned_1() { 241; CHECK-LABEL: test_i8_2cmp_unsigned_1: 242; CHECK: // %bb.0: // %entry 243; CHECK-NEXT: adrp x8, :got:cost_u_i8 244; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i8] 245; CHECK-NEXT: ldrb w9, [x8, #1] 246; CHECK-NEXT: ldrb w10, [x8, #2] 247; CHECK-NEXT: cmp w9, w10 248; CHECK-NEXT: b.lo .LBB6_2 249; CHECK-NEXT: // %bb.1: // %if.end8.sink.split 250; CHECK-NEXT: strb w9, [x8] 251; CHECK-NEXT: .LBB6_2: // %if.end8 252; CHECK-NEXT: ret 253entry: 254 %0 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 1), align 2 255 %1 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 2), align 2 256 %cmp = icmp ugt i8 %0, %1 257 br i1 %cmp, label %if.then, label %if.else 258 259if.then: ; preds = %entry 260 store i8 %0, ptr @cost_u_i8, align 2 261 br label %if.end8 262 263if.else: ; preds = %entry 264 %cmp5 = icmp eq i8 %0, %1 265 br i1 %cmp5, label %if.then7, label %if.end8 266 267if.then7: ; preds = %if.else 268 store i8 %0, ptr @cost_u_i8, align 2 269 br label %if.end8 270 271if.end8: ; preds = %if.else, %if.then7, %if.then 272 ret void 273} 274 275define void @test_i8_2cmp_unsigned_2() { 276; CHECK-LABEL: test_i8_2cmp_unsigned_2: 277; CHECK: // %bb.0: // %entry 278; CHECK-NEXT: adrp x8, :got:cost_u_i8 279; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i8] 280; CHECK-NEXT: ldrb w9, [x8, #1] 281; CHECK-NEXT: ldrb w10, [x8, #2] 282; CHECK-NEXT: cmp w9, w10 283; CHECK-NEXT: b.hi .LBB7_2 284; CHECK-NEXT: // %bb.1: // %if.else 285; CHECK-NEXT: mov w9, w10 286; CHECK-NEXT: b.hs .LBB7_3 287; CHECK-NEXT: .LBB7_2: // %if.end8.sink.split 288; CHECK-NEXT: strb w9, [x8] 289; CHECK-NEXT: .LBB7_3: // %if.end8 290; CHECK-NEXT: ret 291entry: 292 %0 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 1), align 2 293 %1 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 2), align 2 294 %cmp = icmp ugt i8 %0, %1 295 br i1 %cmp, label %if.then, label %if.else 296 297if.then: ; preds = %entry 298 store i8 %0, ptr @cost_u_i8, align 2 299 br label %if.end8 300 301if.else: ; preds = %entry 302 %cmp5 = icmp ult i8 %0, %1 303 br i1 %cmp5, label %if.then7, label %if.end8 304 305if.then7: ; preds = %if.else 306 store i8 %1, ptr @cost_u_i8, align 2 307 br label %if.end8 308 309if.end8: ; preds = %if.else, %if.then7, %if.then 310 ret void 311} 312 313; Make sure the case below won't crash. 314 315; The optimization of ZERO_EXTEND and SIGN_EXTEND in type legalization stage can't assert 316; the operand of a set_cc is always a TRUNCATE. 317 318define i1 @foo(float %inl, float %inr) { 319; CHECK-LABEL: foo: 320; CHECK: // %bb.0: 321; CHECK-NEXT: fcvtzs w8, s0 322; CHECK-NEXT: fcvtzs w9, s1 323; CHECK-NEXT: cmp w8, w9 324; CHECK-NEXT: cset w0, eq 325; CHECK-NEXT: ret 326 %lval = fptosi float %inl to i8 327 %rval = fptosi float %inr to i8 328 %sum = icmp eq i8 %lval, %rval 329 ret i1 %sum 330} 331