1 ; RUN: opt < %s -S -early-cse | FileCheck %s 2 ; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s 3 4 define void @test1(float %A, float %B, float* %PA, float* %PB) { 5 ; CHECK-LABEL: @test1( 6 ; CHECK-NEXT: [[C:%.*]] = fadd float %A, %B 7 ; CHECK-NEXT: store float [[C]], float* %PA 8 ; CHECK-NEXT: store float [[C]], float* %PB 9 ; CHECK-NEXT: ret void 10 ; 11 %C = fadd float %A, %B 12 store float %C, float* %PA 13 %D = fadd float %B, %A 14 store float %D, float* %PB 15 ret void 16 } 17 18 define void @test2(float %A, float %B, i1* %PA, i1* %PB) { 19 ; CHECK-LABEL: @test2( 20 ; CHECK-NEXT: [[C:%.*]] = fcmp oeq float %A, %B 21 ; CHECK-NEXT: store i1 [[C]], i1* %PA 22 ; CHECK-NEXT: store i1 [[C]], i1* %PB 23 ; CHECK-NEXT: ret void 24 ; 25 %C = fcmp oeq float %A, %B 26 store i1 %C, i1* %PA 27 %D = fcmp oeq float %B, %A 28 store i1 %D, i1* %PB 29 ret void 30 } 31 32 define void @test3(float %A, float %B, i1* %PA, i1* %PB) { 33 ; CHECK-LABEL: @test3( 34 ; CHECK-NEXT: [[C:%.*]] = fcmp uge float %A, %B 35 ; CHECK-NEXT: store i1 [[C]], i1* %PA 36 ; CHECK-NEXT: store i1 [[C]], i1* %PB 37 ; CHECK-NEXT: ret void 38 ; 39 %C = fcmp uge float %A, %B 40 store i1 %C, i1* %PA 41 %D = fcmp ule float %B, %A 42 store i1 %D, i1* %PB 43 ret void 44 } 45 46 define void @test4(i32 %A, i32 %B, i1* %PA, i1* %PB) { 47 ; CHECK-LABEL: @test4( 48 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 %A, %B 49 ; CHECK-NEXT: store i1 [[C]], i1* %PA 50 ; CHECK-NEXT: store i1 [[C]], i1* %PB 51 ; CHECK-NEXT: ret void 52 ; 53 %C = icmp eq i32 %A, %B 54 store i1 %C, i1* %PA 55 %D = icmp eq i32 %B, %A 56 store i1 %D, i1* %PB 57 ret void 58 } 59 60 define void @test5(i32 %A, i32 %B, i1* %PA, i1* %PB) { 61 ; CHECK-LABEL: @test5( 62 ; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 %A, %B 63 ; CHECK-NEXT: store i1 [[C]], i1* %PA 64 ; CHECK-NEXT: store i1 [[C]], i1* %PB 65 ; CHECK-NEXT: ret void 66 ; 67 %C = icmp sgt i32 %A, %B 68 store i1 %C, i1* %PA 69 %D = icmp slt i32 %B, %A 70 store i1 %D, i1* %PB 71 ret void 72 } 73 74 ; Min/max operands may be commuted in the compare and select. 75 76 define i8 @smin_commute(i8 %a, i8 %b) { 77 ; CHECK-LABEL: @smin_commute( 78 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, %b 79 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 %b, %a 80 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b 81 ; CHECK-NEXT: [[R:%.*]] = mul i8 [[M1]], [[M1]] 82 ; CHECK-NEXT: ret i8 [[R]] 83 ; 84 %cmp1 = icmp slt i8 %a, %b 85 %cmp2 = icmp slt i8 %b, %a 86 %m1 = select i1 %cmp1, i8 %a, i8 %b 87 %m2 = select i1 %cmp2, i8 %b, i8 %a 88 %r = mul i8 %m1, %m2 89 ret i8 %r 90 } 91 92 ; Min/max can also have a swapped predicate and select operands. 93 94 define i1 @smin_swapped(i8 %a, i8 %b) { 95 ; CHECK-LABEL: @smin_swapped( 96 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 %a, %b 97 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 %a, %b 98 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a 99 ; CHECK-NEXT: ret i1 true 100 ; 101 %cmp1 = icmp sgt i8 %a, %b 102 %cmp2 = icmp slt i8 %a, %b 103 %m1 = select i1 %cmp1, i8 %b, i8 %a 104 %m2 = select i1 %cmp2, i8 %a, i8 %b 105 %r = icmp eq i8 %m2, %m1 106 ret i1 %r 107 } 108 109 define i8 @smax_commute(i8 %a, i8 %b) { 110 ; CHECK-LABEL: @smax_commute( 111 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 %a, %b 112 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 %b, %a 113 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b 114 ; CHECK-NEXT: ret i8 0 115 ; 116 %cmp1 = icmp sgt i8 %a, %b 117 %cmp2 = icmp sgt i8 %b, %a 118 %m1 = select i1 %cmp1, i8 %a, i8 %b 119 %m2 = select i1 %cmp2, i8 %b, i8 %a 120 %r = urem i8 %m2, %m1 121 ret i8 %r 122 } 123 124 define i8 @smax_swapped(i8 %a, i8 %b) { 125 ; CHECK-LABEL: @smax_swapped( 126 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, %b 127 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 %a, %b 128 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a 129 ; CHECK-NEXT: ret i8 1 130 ; 131 %cmp1 = icmp slt i8 %a, %b 132 %cmp2 = icmp sgt i8 %a, %b 133 %m1 = select i1 %cmp1, i8 %b, i8 %a 134 %m2 = select i1 %cmp2, i8 %a, i8 %b 135 %r = sdiv i8 %m1, %m2 136 ret i8 %r 137 } 138 139 define i8 @umin_commute(i8 %a, i8 %b) { 140 ; CHECK-LABEL: @umin_commute( 141 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 %a, %b 142 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 %b, %a 143 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b 144 ; CHECK-NEXT: ret i8 0 145 ; 146 %cmp1 = icmp ult i8 %a, %b 147 %cmp2 = icmp ult i8 %b, %a 148 %m1 = select i1 %cmp1, i8 %a, i8 %b 149 %m2 = select i1 %cmp2, i8 %b, i8 %a 150 %r = sub i8 %m2, %m1 151 ret i8 %r 152 } 153 154 ; Choose a vector type just to show that works. 155 156 define <2 x i8> @umin_swapped(<2 x i8> %a, <2 x i8> %b) { 157 ; CHECK-LABEL: @umin_swapped( 158 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i8> %a, %b 159 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i8> %a, %b 160 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> %b, <2 x i8> %a 161 ; CHECK-NEXT: ret <2 x i8> zeroinitializer 162 ; 163 %cmp1 = icmp ugt <2 x i8> %a, %b 164 %cmp2 = icmp ult <2 x i8> %a, %b 165 %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a 166 %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b 167 %r = sub <2 x i8> %m2, %m1 168 ret <2 x i8> %r 169 } 170 171 define i8 @umax_commute(i8 %a, i8 %b) { 172 ; CHECK-LABEL: @umax_commute( 173 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 %a, %b 174 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 %b, %a 175 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b 176 ; CHECK-NEXT: ret i8 1 177 ; 178 %cmp1 = icmp ugt i8 %a, %b 179 %cmp2 = icmp ugt i8 %b, %a 180 %m1 = select i1 %cmp1, i8 %a, i8 %b 181 %m2 = select i1 %cmp2, i8 %b, i8 %a 182 %r = udiv i8 %m1, %m2 183 ret i8 %r 184 } 185 186 define i8 @umax_swapped(i8 %a, i8 %b) { 187 ; CHECK-LABEL: @umax_swapped( 188 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 %a, %b 189 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 %a, %b 190 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a 191 ; CHECK-NEXT: [[R:%.*]] = add i8 [[M1]], [[M1]] 192 ; CHECK-NEXT: ret i8 [[R]] 193 ; 194 %cmp1 = icmp ult i8 %a, %b 195 %cmp2 = icmp ugt i8 %a, %b 196 %m1 = select i1 %cmp1, i8 %b, i8 %a 197 %m2 = select i1 %cmp2, i8 %a, i8 %b 198 %r = add i8 %m2, %m1 199 ret i8 %r 200 } 201 202 ; Min/max may exist with non-canonical operands. Value tracking can match those. 203 204 define i8 @smax_nsw(i8 %a, i8 %b) { 205 ; CHECK-LABEL: @smax_nsw( 206 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 %a, %b 207 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, %b 208 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0 209 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]] 210 ; CHECK-NEXT: ret i8 0 211 ; 212 %sub = sub nsw i8 %a, %b 213 %cmp1 = icmp slt i8 %a, %b 214 %cmp2 = icmp sgt i8 %sub, 0 215 %m1 = select i1 %cmp1, i8 0, i8 %sub 216 %m2 = select i1 %cmp2, i8 %sub, i8 0 217 %r = sub i8 %m2, %m1 218 ret i8 %r 219 } 220 221 define i8 @abs_swapped(i8 %a) { 222 ; CHECK-LABEL: @abs_swapped( 223 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, %a 224 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 %a, 0 225 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 %a, 0 226 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]] 227 ; CHECK-NEXT: ret i8 [[M1]] 228 ; 229 %neg = sub i8 0, %a 230 %cmp1 = icmp sgt i8 %a, 0 231 %cmp2 = icmp slt i8 %a, 0 232 %m1 = select i1 %cmp1, i8 %a, i8 %neg 233 %m2 = select i1 %cmp2, i8 %neg, i8 %a 234 %r = or i8 %m2, %m1 235 ret i8 %r 236 } 237 238 define i8 @nabs_swapped(i8 %a) { 239 ; CHECK-LABEL: @nabs_swapped( 240 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, %a 241 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, 0 242 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 %a, 0 243 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]] 244 ; CHECK-NEXT: ret i8 0 245 ; 246 %neg = sub i8 0, %a 247 %cmp1 = icmp slt i8 %a, 0 248 %cmp2 = icmp sgt i8 %a, 0 249 %m1 = select i1 %cmp1, i8 %a, i8 %neg 250 %m2 = select i1 %cmp2, i8 %neg, i8 %a 251 %r = xor i8 %m2, %m1 252 ret i8 %r 253 } 254 255 ; These two tests make sure we still consider it a match when the RHS of the 256 ; compares are different. 257 define i8 @abs_different_constants(i8 %a) { 258 ; CHECK-LABEL: @abs_different_constants( 259 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, %a 260 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 %a, -1 261 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 %a, 0 262 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]] 263 ; CHECK-NEXT: ret i8 [[M1]] 264 ; 265 %neg = sub i8 0, %a 266 %cmp1 = icmp sgt i8 %a, -1 267 %cmp2 = icmp slt i8 %a, 0 268 %m1 = select i1 %cmp1, i8 %a, i8 %neg 269 %m2 = select i1 %cmp2, i8 %neg, i8 %a 270 %r = or i8 %m2, %m1 271 ret i8 %r 272 } 273 274 define i8 @nabs_different_constants(i8 %a) { 275 ; CHECK-LABEL: @nabs_different_constants( 276 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, %a 277 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, 0 278 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 %a, -1 279 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]] 280 ; CHECK-NEXT: ret i8 0 281 ; 282 %neg = sub i8 0, %a 283 %cmp1 = icmp slt i8 %a, 0 284 %cmp2 = icmp sgt i8 %a, -1 285 %m1 = select i1 %cmp1, i8 %a, i8 %neg 286 %m2 = select i1 %cmp2, i8 %neg, i8 %a 287 %r = xor i8 %m2, %m1 288 ret i8 %r 289 } 290 291