1 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s 2 3 @var32 = global i32 0 4 @var64 = global i64 0 5 6 define void @test_csel(i32 %lhs32, i32 %rhs32, i64 %lhs64) { 7 ; CHECK-LABEL: test_csel: 8 9 %tst1 = icmp ugt i32 %lhs32, %rhs32 10 %val1 = select i1 %tst1, i32 42, i32 52 11 store i32 %val1, i32* @var32 12 ; CHECK: movz [[W52:w[0-9]+]], #52 13 ; CHECK: movz [[W42:w[0-9]+]], #42 14 ; CHECK: csel {{w[0-9]+}}, [[W42]], [[W52]], hi 15 16 %rhs64 = sext i32 %rhs32 to i64 17 %tst2 = icmp sle i64 %lhs64, %rhs64 18 %val2 = select i1 %tst2, i64 %lhs64, i64 %rhs64 19 store i64 %val2, i64* @var64 20 ; CHECK: cmp [[LHS:x[0-9]+]], [[RHS:w[0-9]+]], sxtw 21 ; CHECK: sxtw [[EXT_RHS:x[0-9]+]], [[RHS]] 22 ; CHECK: csel {{x[0-9]+}}, [[LHS]], [[EXT_RHS]], le 23 24 ret void 25 ; CHECK: ret 26 } 27 28 define void @test_floatcsel(float %lhs32, float %rhs32, double %lhs64, double %rhs64) { 29 ; CHECK-LABEL: test_floatcsel: 30 31 %tst1 = fcmp one float %lhs32, %rhs32 32 ; CHECK: fcmp {{s[0-9]+}}, {{s[0-9]+}} 33 %val1 = select i1 %tst1, i32 42, i32 52 34 store i32 %val1, i32* @var32 35 ; CHECK: movz [[W52:w[0-9]+]], #52 36 ; CHECK: movz [[W42:w[0-9]+]], #42 37 ; CHECK: csel [[MAYBETRUE:w[0-9]+]], [[W42]], [[W52]], mi 38 ; CHECK: csel {{w[0-9]+}}, [[W42]], [[MAYBETRUE]], gt 39 40 41 %tst2 = fcmp ueq double %lhs64, %rhs64 42 ; CHECK: fcmp {{d[0-9]+}}, {{d[0-9]+}} 43 %val2 = select i1 %tst2, i64 9, i64 15 44 store i64 %val2, i64* @var64 45 ; CHECK: movz [[CONST15:x[0-9]+]], #15 46 ; CHECK: movz [[CONST9:x[0-9]+]], #9 47 ; CHECK: csel [[MAYBETRUE:x[0-9]+]], [[CONST9]], [[CONST15]], eq 48 ; CHECK: csel {{x[0-9]+}}, [[CONST9]], [[MAYBETRUE]], vs 49 50 ret void 51 ; CHECK: ret 52 } 53 54 55 define void @test_csinc(i32 %lhs32, i32 %rhs32, i64 %lhs64) { 56 ; CHECK-LABEL: test_csinc: 57 58 ; Note that commuting rhs and lhs in the select changes ugt to ule (i.e. hi to ls). 59 %tst1 = icmp ugt i32 %lhs32, %rhs32 60 %inc1 = add i32 %rhs32, 1 61 %val1 = select i1 %tst1, i32 %inc1, i32 %lhs32 62 store volatile i32 %val1, i32* @var32 63 ; CHECK: cmp [[LHS:w[0-9]+]], [[RHS:w[0-9]+]] 64 ; CHECK: csinc {{w[0-9]+}}, [[LHS]], [[RHS]], ls 65 66 %rhs2 = add i32 %rhs32, 42 67 %tst2 = icmp sle i32 %lhs32, %rhs2 68 %inc2 = add i32 %rhs32, 1 69 %val2 = select i1 %tst2, i32 %lhs32, i32 %inc2 70 store volatile i32 %val2, i32* @var32 71 ; CHECK: cmp [[LHS:w[0-9]+]], {{w[0-9]+}} 72 ; CHECK: csinc {{w[0-9]+}}, [[LHS]], {{w[0-9]+}}, le 73 74 ; Note that commuting rhs and lhs in the select changes ugt to ule (i.e. hi to ls). 75 %rhs3 = sext i32 %rhs32 to i64 76 %tst3 = icmp ugt i64 %lhs64, %rhs3 77 %inc3 = add i64 %rhs3, 1 78 %val3 = select i1 %tst3, i64 %inc3, i64 %lhs64 79 store volatile i64 %val3, i64* @var64 80 ; CHECK: cmp [[LHS:x[0-9]+]], {{w[0-9]+}} 81 ; CHECK: csinc {{x[0-9]+}}, [[LHS]], {{x[0-9]+}}, ls 82 83 %rhs4 = zext i32 %rhs32 to i64 84 %tst4 = icmp sle i64 %lhs64, %rhs4 85 %inc4 = add i64 %rhs4, 1 86 %val4 = select i1 %tst4, i64 %lhs64, i64 %inc4 87 store volatile i64 %val4, i64* @var64 88 ; CHECK: cmp [[LHS:x[0-9]+]], {{w[0-9]+}} 89 ; CHECK: csinc {{x[0-9]+}}, [[LHS]], {{x[0-9]+}}, le 90 91 ret void 92 ; CHECK: ret 93 } 94 95 define void @test_csinv(i32 %lhs32, i32 %rhs32, i64 %lhs64) { 96 ; CHECK-LABEL: test_csinv: 97 98 ; Note that commuting rhs and lhs in the select changes ugt to ule (i.e. hi to ls). 99 %tst1 = icmp ugt i32 %lhs32, %rhs32 100 %inc1 = xor i32 -1, %rhs32 101 %val1 = select i1 %tst1, i32 %inc1, i32 %lhs32 102 store volatile i32 %val1, i32* @var32 103 ; CHECK: cmp [[LHS:w[0-9]+]], [[RHS:w[0-9]+]] 104 ; CHECK: csinv {{w[0-9]+}}, [[LHS]], [[RHS]], ls 105 106 %rhs2 = add i32 %rhs32, 42 107 %tst2 = icmp sle i32 %lhs32, %rhs2 108 %inc2 = xor i32 -1, %rhs32 109 %val2 = select i1 %tst2, i32 %lhs32, i32 %inc2 110 store volatile i32 %val2, i32* @var32 111 ; CHECK: cmp [[LHS:w[0-9]+]], {{w[0-9]+}} 112 ; CHECK: csinv {{w[0-9]+}}, [[LHS]], {{w[0-9]+}}, le 113 114 ; Note that commuting rhs and lhs in the select changes ugt to ule (i.e. hi to ls). 115 %rhs3 = sext i32 %rhs32 to i64 116 %tst3 = icmp ugt i64 %lhs64, %rhs3 117 %inc3 = xor i64 -1, %rhs3 118 %val3 = select i1 %tst3, i64 %inc3, i64 %lhs64 119 store volatile i64 %val3, i64* @var64 120 ; CHECK: cmp [[LHS:x[0-9]+]], {{w[0-9]+}} 121 ; CHECK: csinv {{x[0-9]+}}, [[LHS]], {{x[0-9]+}}, ls 122 123 %rhs4 = zext i32 %rhs32 to i64 124 %tst4 = icmp sle i64 %lhs64, %rhs4 125 %inc4 = xor i64 -1, %rhs4 126 %val4 = select i1 %tst4, i64 %lhs64, i64 %inc4 127 store volatile i64 %val4, i64* @var64 128 ; CHECK: cmp [[LHS:x[0-9]+]], {{w[0-9]+}} 129 ; CHECK: csinv {{x[0-9]+}}, [[LHS]], {{x[0-9]+}}, le 130 131 ret void 132 ; CHECK: ret 133 } 134 135 define void @test_csneg(i32 %lhs32, i32 %rhs32, i64 %lhs64) { 136 ; CHECK-LABEL: test_csneg: 137 138 ; Note that commuting rhs and lhs in the select changes ugt to ule (i.e. hi to ls). 139 %tst1 = icmp ugt i32 %lhs32, %rhs32 140 %inc1 = sub i32 0, %rhs32 141 %val1 = select i1 %tst1, i32 %inc1, i32 %lhs32 142 store volatile i32 %val1, i32* @var32 143 ; CHECK: cmp [[LHS:w[0-9]+]], [[RHS:w[0-9]+]] 144 ; CHECK: csneg {{w[0-9]+}}, [[LHS]], [[RHS]], ls 145 146 %rhs2 = add i32 %rhs32, 42 147 %tst2 = icmp sle i32 %lhs32, %rhs2 148 %inc2 = sub i32 0, %rhs32 149 %val2 = select i1 %tst2, i32 %lhs32, i32 %inc2 150 store volatile i32 %val2, i32* @var32 151 ; CHECK: cmp [[LHS:w[0-9]+]], {{w[0-9]+}} 152 ; CHECK: csneg {{w[0-9]+}}, [[LHS]], {{w[0-9]+}}, le 153 154 ; Note that commuting rhs and lhs in the select changes ugt to ule (i.e. hi to ls). 155 %rhs3 = sext i32 %rhs32 to i64 156 %tst3 = icmp ugt i64 %lhs64, %rhs3 157 %inc3 = sub i64 0, %rhs3 158 %val3 = select i1 %tst3, i64 %inc3, i64 %lhs64 159 store volatile i64 %val3, i64* @var64 160 ; CHECK: cmp [[LHS:x[0-9]+]], {{w[0-9]+}} 161 ; CHECK: csneg {{x[0-9]+}}, [[LHS]], {{x[0-9]+}}, ls 162 163 %rhs4 = zext i32 %rhs32 to i64 164 %tst4 = icmp sle i64 %lhs64, %rhs4 165 %inc4 = sub i64 0, %rhs4 166 %val4 = select i1 %tst4, i64 %lhs64, i64 %inc4 167 store volatile i64 %val4, i64* @var64 168 ; CHECK: cmp [[LHS:x[0-9]+]], {{w[0-9]+}} 169 ; CHECK: csneg {{x[0-9]+}}, [[LHS]], {{x[0-9]+}}, le 170 171 ret void 172 ; CHECK: ret 173 } 174 175 define void @test_cset(i32 %lhs, i32 %rhs, i64 %lhs64) { 176 ; CHECK-LABEL: test_cset: 177 178 ; N.b. code is not optimal here (32-bit csinc would be better) but 179 ; incoming DAG is too complex 180 %tst1 = icmp eq i32 %lhs, %rhs 181 %val1 = zext i1 %tst1 to i32 182 store i32 %val1, i32* @var32 183 ; CHECK: cmp {{w[0-9]+}}, {{w[0-9]+}} 184 ; CHECK: csinc {{w[0-9]+}}, wzr, wzr, ne 185 186 %rhs64 = sext i32 %rhs to i64 187 %tst2 = icmp ule i64 %lhs64, %rhs64 188 %val2 = zext i1 %tst2 to i64 189 store i64 %val2, i64* @var64 190 ; CHECK: csinc {{w[0-9]+}}, wzr, wzr, hi 191 192 ret void 193 ; CHECK: ret 194 } 195 196 define void @test_csetm(i32 %lhs, i32 %rhs, i64 %lhs64) { 197 ; CHECK-LABEL: test_csetm: 198 199 %tst1 = icmp eq i32 %lhs, %rhs 200 %val1 = sext i1 %tst1 to i32 201 store i32 %val1, i32* @var32 202 ; CHECK: cmp {{w[0-9]+}}, {{w[0-9]+}} 203 ; CHECK: csinv {{w[0-9]+}}, wzr, wzr, ne 204 205 %rhs64 = sext i32 %rhs to i64 206 %tst2 = icmp ule i64 %lhs64, %rhs64 207 %val2 = sext i1 %tst2 to i64 208 store i64 %val2, i64* @var64 209 ; CHECK: csinv {{x[0-9]+}}, xzr, xzr, hi 210 211 ret void 212 ; CHECK: ret 213 } 214