1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use16(i16) 5declare void @use32(i32) 6declare void @use64(i64) 7 8define i32 @t0(i64 %data, i32 %nbits) { 9; CHECK-LABEL: @t0( 10; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 11; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 12; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 13; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 14; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 15; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 16; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 17; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 18; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 19; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 20; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]] 21; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32 22; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 23; 24 %skip_high = sub i32 64, %nbits 25 call void @use32(i32 %skip_high) 26 %skip_high_wide = zext i32 %skip_high to i64 27 call void @use64(i64 %skip_high_wide) 28 %extracted = lshr i64 %data, %skip_high_wide 29 call void @use64(i64 %extracted) 30 %extracted_narrow = trunc i64 %extracted to i32 31 call void @use32(i32 %extracted_narrow) 32 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 33 call void @use32(i32 %num_high_bits_to_smear_narrow) 34 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 35 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 36 ret i32 %signextended 37} 38define i32 @t0_zext_of_nbits(i64 %data, i8 %nbits_narrow) { 39; CHECK-LABEL: @t0_zext_of_nbits( 40; CHECK-NEXT: [[NBITS:%.*]] = zext i8 [[NBITS_NARROW:%.*]] to i16 41; CHECK-NEXT: call void @use16(i16 [[NBITS]]) 42; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub nsw i16 64, [[NBITS]] 43; CHECK-NEXT: call void @use16(i16 [[SKIP_HIGH]]) 44; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i16 [[SKIP_HIGH]] to i64 45; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 46; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 47; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 48; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 49; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 50; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW_NARROW:%.*]] = sub nsw i16 32, [[NBITS]] 51; CHECK-NEXT: call void @use16(i16 [[NUM_HIGH_BITS_TO_SMEAR_NARROW_NARROW]]) 52; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = zext i16 [[NUM_HIGH_BITS_TO_SMEAR_NARROW_NARROW]] to i32 53; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 54; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]] 55; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32 56; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 57; 58 %nbits = zext i8 %nbits_narrow to i16 59 call void @use16(i16 %nbits) 60 %skip_high = sub i16 64, %nbits 61 call void @use16(i16 %skip_high) 62 %skip_high_wide = zext i16 %skip_high to i64 63 call void @use64(i64 %skip_high_wide) 64 %extracted = lshr i64 %data, %skip_high_wide 65 call void @use64(i64 %extracted) 66 %extracted_narrow = trunc i64 %extracted to i32 67 call void @use32(i32 %extracted_narrow) 68 %num_high_bits_to_smear_narrow_narrow = sub i16 32, %nbits 69 call void @use16(i16 %num_high_bits_to_smear_narrow_narrow) 70 %num_high_bits_to_smear_narrow = zext i16 %num_high_bits_to_smear_narrow_narrow to i32 71 call void @use32(i32 %num_high_bits_to_smear_narrow) 72 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 73 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 74 ret i32 %signextended 75} 76define i32 @t0_exact(i64 %data, i32 %nbits) { 77; CHECK-LABEL: @t0_exact( 78; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 79; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 80; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 81; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 82; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr exact i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 83; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 84; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 85; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 86; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 87; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 88; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i64 [[DATA]], [[SKIP_HIGH_WIDE]] 89; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32 90; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 91; 92 %skip_high = sub i32 64, %nbits 93 call void @use32(i32 %skip_high) 94 %skip_high_wide = zext i32 %skip_high to i64 95 call void @use64(i64 %skip_high_wide) 96 %extracted = lshr exact i64 %data, %skip_high_wide ; We can preserve `exact`-ness of the original shift. 97 call void @use64(i64 %extracted) 98 %extracted_narrow = trunc i64 %extracted to i32 99 call void @use32(i32 %extracted_narrow) 100 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 101 call void @use32(i32 %num_high_bits_to_smear_narrow) 102 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 103 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 104 ret i32 %signextended 105} 106 107define i32 @t1_redundant_sext(i64 %data, i32 %nbits) { 108; CHECK-LABEL: @t1_redundant_sext( 109; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 110; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 111; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 112; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 113; CHECK-NEXT: [[EXTRACTED_WITH_SIGNEXTENSION:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 114; CHECK-NEXT: call void @use64(i64 [[EXTRACTED_WITH_SIGNEXTENSION]]) 115; CHECK-NEXT: [[EXTRACTED_WITH_SIGNEXTENSION_NARROW:%.*]] = trunc i64 [[EXTRACTED_WITH_SIGNEXTENSION]] to i32 116; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_WITH_SIGNEXTENSION_NARROW]]) 117; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 118; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 119; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_WITH_SIGNEXTENSION_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 120; CHECK-NEXT: call void @use32(i32 [[SIGNBIT_POSITIONED]]) 121; CHECK-NEXT: ret i32 [[EXTRACTED_WITH_SIGNEXTENSION_NARROW]] 122; 123 %skip_high = sub i32 64, %nbits 124 call void @use32(i32 %skip_high) 125 %skip_high_wide = zext i32 %skip_high to i64 126 call void @use64(i64 %skip_high_wide) 127 %extracted_with_signextension = ashr i64 %data, %skip_high_wide 128 call void @use64(i64 %extracted_with_signextension) 129 %extracted_with_signextension_narrow = trunc i64 %extracted_with_signextension to i32 ; this is already the answer. 130 call void @use32(i32 %extracted_with_signextension_narrow) 131 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 132 call void @use32(i32 %num_high_bits_to_smear_narrow) 133 %signbit_positioned = shl i32 %extracted_with_signextension_narrow, %num_high_bits_to_smear_narrow 134 call void @use32(i32 %signbit_positioned) 135 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 136 ret i32 %signextended 137} 138 139define i64 @t2_notrunc(i64 %data, i64 %nbits) { 140; CHECK-LABEL: @t2_notrunc( 141; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i64 64, [[NBITS:%.*]] 142; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH]]) 143; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH]] 144; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 145; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR:%.*]] = sub i64 64, [[NBITS]] 146; CHECK-NEXT: call void @use64(i64 [[NUM_HIGH_BITS_TO_SMEAR]]) 147; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i64 [[EXTRACTED]], [[NUM_HIGH_BITS_TO_SMEAR]] 148; CHECK-NEXT: call void @use64(i64 [[SIGNBIT_POSITIONED]]) 149; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH]] 150; CHECK-NEXT: ret i64 [[SIGNEXTENDED]] 151; 152 %skip_high = sub i64 64, %nbits 153 call void @use64(i64 %skip_high) 154 %extracted = lshr i64 %data, %skip_high 155 call void @use64(i64 %extracted) 156 %num_high_bits_to_smear = sub i64 64, %nbits 157 call void @use64(i64 %num_high_bits_to_smear) 158 %signbit_positioned = shl i64 %extracted, %num_high_bits_to_smear ; 159 call void @use64(i64 %signbit_positioned) 160 %signextended = ashr i64 %signbit_positioned, %num_high_bits_to_smear ; can just shift %data itself. 161 ret i64 %signextended 162} 163 164define i64 @t3_notrunc_redundant_sext(i64 %data, i64 %nbits) { 165; CHECK-LABEL: @t3_notrunc_redundant_sext( 166; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i64 64, [[NBITS:%.*]] 167; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH]]) 168; CHECK-NEXT: [[EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH]] 169; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 170; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR:%.*]] = sub i64 64, [[NBITS]] 171; CHECK-NEXT: call void @use64(i64 [[NUM_HIGH_BITS_TO_SMEAR]]) 172; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i64 [[EXTRACTED]], [[NUM_HIGH_BITS_TO_SMEAR]] 173; CHECK-NEXT: call void @use64(i64 [[SIGNBIT_POSITIONED]]) 174; CHECK-NEXT: ret i64 [[EXTRACTED]] 175; 176 %skip_high = sub i64 64, %nbits 177 call void @use64(i64 %skip_high) 178 %extracted = ashr i64 %data, %skip_high ; this is already the answer. 179 call void @use64(i64 %extracted) 180 %num_high_bits_to_smear = sub i64 64, %nbits 181 call void @use64(i64 %num_high_bits_to_smear) 182 %signbit_positioned = shl i64 %extracted, %num_high_bits_to_smear 183 call void @use64(i64 %signbit_positioned) 184 %signextended = ashr i64 %signbit_positioned, %num_high_bits_to_smear 185 ret i64 %signextended 186} 187 188define <2 x i32> @t4_vec(<2 x i64> %data, <2 x i32> %nbits) { 189; CHECK-LABEL: @t4_vec( 190; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub <2 x i32> splat (i32 64), [[NBITS:%.*]] 191; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext nneg <2 x i32> [[SKIP_HIGH]] to <2 x i64> 192; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i64> [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 193; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32> 194; CHECK-NEXT: ret <2 x i32> [[SIGNEXTENDED]] 195; 196 %skip_high = sub <2 x i32> <i32 64, i32 64>, %nbits 197 %skip_high_wide = zext <2 x i32> %skip_high to <2 x i64> 198 %extracted = lshr <2 x i64> %data, %skip_high_wide 199 %extracted_narrow = trunc <2 x i64> %extracted to <2 x i32> 200 %num_high_bits_to_smear_narrow = sub <2 x i32> <i32 32, i32 32>, %nbits 201 %signbit_positioned = shl <2 x i32> %extracted_narrow, %num_high_bits_to_smear_narrow 202 %signextended = ashr <2 x i32> %signbit_positioned, %num_high_bits_to_smear_narrow 203 ret <2 x i32> %signextended 204} 205 206define <3 x i32> @t5_vec_poison(<3 x i64> %data, <3 x i32> %nbits) { 207; CHECK-LABEL: @t5_vec_poison( 208; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub <3 x i32> <i32 64, i32 64, i32 poison>, [[NBITS:%.*]] 209; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext nneg <3 x i32> [[SKIP_HIGH]] to <3 x i64> 210; CHECK-NEXT: [[TMP1:%.*]] = ashr <3 x i64> [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 211; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc <3 x i64> [[TMP1]] to <3 x i32> 212; CHECK-NEXT: ret <3 x i32> [[SIGNEXTENDED]] 213; 214 %skip_high = sub <3 x i32> <i32 64, i32 64, i32 poison>, %nbits 215 %skip_high_wide = zext <3 x i32> %skip_high to <3 x i64> 216 %extracted = lshr <3 x i64> %data, %skip_high_wide 217 %extracted_narrow = trunc <3 x i64> %extracted to <3 x i32> 218 %num_high_bits_to_smear_narrow0 = sub <3 x i32> <i32 32, i32 32, i32 poison>, %nbits 219 %num_high_bits_to_smear_narrow1 = sub <3 x i32> <i32 poison, i32 32, i32 32>, %nbits 220 %signbit_positioned = shl <3 x i32> %extracted_narrow, %num_high_bits_to_smear_narrow0 221 %signextended = ashr <3 x i32> %signbit_positioned, %num_high_bits_to_smear_narrow1 222 ret <3 x i32> %signextended 223} 224 225; Extra-uses 226define i32 @t6_extrause_good0(i64 %data, i32 %nbits) { 227; CHECK-LABEL: @t6_extrause_good0( 228; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 229; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 230; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 231; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 232; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 233; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 234; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 235; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 236; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 237; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 238; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]] 239; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32 240; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 241; 242 %skip_high = sub i32 64, %nbits 243 call void @use32(i32 %skip_high) 244 %skip_high_wide = zext i32 %skip_high to i64 245 call void @use64(i64 %skip_high_wide) 246 %extracted = lshr i64 %data, %skip_high_wide 247 call void @use64(i64 %extracted) 248 %extracted_narrow = trunc i64 %extracted to i32 249 call void @use32(i32 %extracted_narrow) 250 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 251 call void @use32(i32 %num_high_bits_to_smear_narrow) 252 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow ; will go away 253 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 254 ret i32 %signextended 255} 256define i32 @t7_extrause_good1(i64 %data, i32 %nbits) { 257; CHECK-LABEL: @t7_extrause_good1( 258; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 259; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 260; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 261; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 262; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 263; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 264; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 265; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 266; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW0:%.*]] = sub i32 32, [[NBITS]] 267; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW0]]) 268; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW0]] 269; CHECK-NEXT: call void @use32(i32 [[SIGNBIT_POSITIONED]]) 270; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]] 271; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32 272; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 273; 274 %skip_high = sub i32 64, %nbits 275 call void @use32(i32 %skip_high) 276 %skip_high_wide = zext i32 %skip_high to i64 277 call void @use64(i64 %skip_high_wide) 278 %extracted = lshr i64 %data, %skip_high_wide 279 call void @use64(i64 %extracted) 280 %extracted_narrow = trunc i64 %extracted to i32 281 call void @use32(i32 %extracted_narrow) 282 %num_high_bits_to_smear_narrow0 = sub i32 32, %nbits 283 call void @use32(i32 %num_high_bits_to_smear_narrow0) 284 %num_high_bits_to_smear_narrow1 = sub i32 32, %nbits ; will go away. 285 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow0 286 call void @use32(i32 %signbit_positioned) 287 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow1 288 ret i32 %signextended 289} 290define i32 @n8_extrause_bad(i64 %data, i32 %nbits) { 291; CHECK-LABEL: @n8_extrause_bad( 292; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 293; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 294; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 295; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 296; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 297; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 298; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 299; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 300; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 301; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 302; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 303; CHECK-NEXT: call void @use32(i32 [[SIGNBIT_POSITIONED]]) 304; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 305; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 306; 307 %skip_high = sub i32 64, %nbits 308 call void @use32(i32 %skip_high) 309 %skip_high_wide = zext i32 %skip_high to i64 310 call void @use64(i64 %skip_high_wide) 311 %extracted = lshr i64 %data, %skip_high_wide 312 call void @use64(i64 %extracted) 313 %extracted_narrow = trunc i64 %extracted to i32 314 call void @use32(i32 %extracted_narrow) 315 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 316 call void @use32(i32 %num_high_bits_to_smear_narrow) 317 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 318 call void @use32(i32 %signbit_positioned) 319 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow ; neither of operands will go away. 320 ret i32 %signextended 321} 322 323; Negative tests 324define i32 @n9(i64 %data, i32 %nbits) { 325; CHECK-LABEL: @n9( 326; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 63, [[NBITS:%.*]] 327; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 328; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 329; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 330; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 331; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 332; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 333; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 334; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 335; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 336; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 337; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 338; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 339; 340 %skip_high = sub i32 63, %nbits ; not 64 341 call void @use32(i32 %skip_high) 342 %skip_high_wide = zext i32 %skip_high to i64 343 call void @use64(i64 %skip_high_wide) 344 %extracted = lshr i64 %data, %skip_high_wide 345 call void @use64(i64 %extracted) 346 %extracted_narrow = trunc i64 %extracted to i32 347 call void @use32(i32 %extracted_narrow) 348 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 349 call void @use32(i32 %num_high_bits_to_smear_narrow) 350 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 351 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 352 ret i32 %signextended 353} 354 355define i32 @n10(i64 %data, i32 %nbits) { 356; CHECK-LABEL: @n10( 357; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 358; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 359; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 360; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 361; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 362; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 363; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 364; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 365; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 31, [[NBITS]] 366; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 367; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 368; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 369; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 370; 371 %skip_high = sub i32 64, %nbits 372 call void @use32(i32 %skip_high) 373 %skip_high_wide = zext i32 %skip_high to i64 374 call void @use64(i64 %skip_high_wide) 375 %extracted = lshr i64 %data, %skip_high_wide 376 call void @use64(i64 %extracted) 377 %extracted_narrow = trunc i64 %extracted to i32 378 call void @use32(i32 %extracted_narrow) 379 %num_high_bits_to_smear_narrow = sub i32 31, %nbits ; not 32 380 call void @use32(i32 %num_high_bits_to_smear_narrow) 381 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 382 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 383 ret i32 %signextended 384} 385 386define i32 @n11(i64 %data, i32 %nbits1, i32 %nbits2) { 387; CHECK-LABEL: @n11( 388; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS1:%.*]] 389; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 390; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 391; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 392; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 393; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 394; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 395; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 396; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS2:%.*]] 397; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 398; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 399; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 400; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 401; 402 %skip_high = sub i32 64, %nbits1 ; not %nbits2 403 call void @use32(i32 %skip_high) 404 %skip_high_wide = zext i32 %skip_high to i64 405 call void @use64(i64 %skip_high_wide) 406 %extracted = lshr i64 %data, %skip_high_wide 407 call void @use64(i64 %extracted) 408 %extracted_narrow = trunc i64 %extracted to i32 409 call void @use32(i32 %extracted_narrow) 410 %num_high_bits_to_smear_narrow = sub i32 32, %nbits2 ; not %nbits1 411 call void @use32(i32 %num_high_bits_to_smear_narrow) 412 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 413 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow 414 ret i32 %signextended 415} 416 417define i32 @n12(i64 %data, i32 %nbits1, i32 %nbits2) { 418; CHECK-LABEL: @n12( 419; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS1:%.*]] 420; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 421; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 422; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 423; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 424; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 425; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 426; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 427; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW1:%.*]] = sub i32 32, [[NBITS1]] 428; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW2:%.*]] = sub i32 32, [[NBITS2:%.*]] 429; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW1]]) 430; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW2]]) 431; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW1]] 432; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW2]] 433; CHECK-NEXT: ret i32 [[SIGNEXTENDED]] 434; 435 %skip_high = sub i32 64, %nbits1 436 call void @use32(i32 %skip_high) 437 %skip_high_wide = zext i32 %skip_high to i64 438 call void @use64(i64 %skip_high_wide) 439 %extracted = lshr i64 %data, %skip_high_wide 440 call void @use64(i64 %extracted) 441 %extracted_narrow = trunc i64 %extracted to i32 442 call void @use32(i32 %extracted_narrow) 443 %num_high_bits_to_smear_narrow1 = sub i32 32, %nbits1 ; not %nbits2 444 %num_high_bits_to_smear_narrow2 = sub i32 32, %nbits2 ; not %nbits1 445 call void @use32(i32 %num_high_bits_to_smear_narrow1) 446 call void @use32(i32 %num_high_bits_to_smear_narrow2) 447 %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow1 448 %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow2 449 ret i32 %signextended 450} 451 452define i32 @n13(i64 %data, i32 %nbits) { 453; CHECK-LABEL: @n13( 454; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 455; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 456; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 457; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 458; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 459; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 460; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 461; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 462; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 463; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 464; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 -1, [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 465; CHECK-NEXT: [[RES:%.*]] = and i32 [[TMP1]], [[EXTRACTED_NARROW]] 466; CHECK-NEXT: ret i32 [[RES]] 467; 468 %skip_high = sub i32 64, %nbits 469 call void @use32(i32 %skip_high) 470 %skip_high_wide = zext i32 %skip_high to i64 471 call void @use64(i64 %skip_high_wide) 472 %extracted = lshr i64 %data, %skip_high_wide 473 call void @use64(i64 %extracted) 474 %extracted_narrow = trunc i64 %extracted to i32 475 call void @use32(i32 %extracted_narrow) 476 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 477 call void @use32(i32 %num_high_bits_to_smear_narrow) 478 %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 479 %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr 480 ret i32 %res 481} 482define i32 @n13_extrause(i64 %data, i32 %nbits) { 483; CHECK-LABEL: @n13_extrause( 484; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 485; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 486; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 487; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 488; CHECK-NEXT: [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 489; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 490; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 491; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 492; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 493; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 494; CHECK-NEXT: [[HIGHBITS_CLEANED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 495; CHECK-NEXT: call void @use32(i32 [[HIGHBITS_CLEANED]]) 496; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 497; CHECK-NEXT: ret i32 [[RES]] 498; 499 %skip_high = sub i32 64, %nbits 500 call void @use32(i32 %skip_high) 501 %skip_high_wide = zext i32 %skip_high to i64 502 call void @use64(i64 %skip_high_wide) 503 %extracted = lshr i64 %data, %skip_high_wide 504 call void @use64(i64 %extracted) 505 %extracted_narrow = trunc i64 %extracted to i32 506 call void @use32(i32 %extracted_narrow) 507 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 508 call void @use32(i32 %num_high_bits_to_smear_narrow) 509 %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 510 call void @use32(i32 %highbits_cleaned) 511 %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr 512 ret i32 %res 513} 514define i32 @n14(i64 %data, i32 %nbits) { 515; CHECK-LABEL: @n14( 516; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 517; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 518; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 519; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 520; CHECK-NEXT: [[EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 521; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 522; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 523; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 524; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 525; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 526; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 -1, [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 527; CHECK-NEXT: [[RES:%.*]] = and i32 [[TMP1]], [[EXTRACTED_NARROW]] 528; CHECK-NEXT: ret i32 [[RES]] 529; 530 %skip_high = sub i32 64, %nbits 531 call void @use32(i32 %skip_high) 532 %skip_high_wide = zext i32 %skip_high to i64 533 call void @use64(i64 %skip_high_wide) 534 %extracted = ashr i64 %data, %skip_high_wide 535 call void @use64(i64 %extracted) 536 %extracted_narrow = trunc i64 %extracted to i32 537 call void @use32(i32 %extracted_narrow) 538 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 539 call void @use32(i32 %num_high_bits_to_smear_narrow) 540 %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 541 %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr 542 ret i32 %res 543} 544define i32 @n14_extrause(i64 %data, i32 %nbits) { 545; CHECK-LABEL: @n14_extrause( 546; CHECK-NEXT: [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]] 547; CHECK-NEXT: call void @use32(i32 [[SKIP_HIGH]]) 548; CHECK-NEXT: [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64 549; CHECK-NEXT: call void @use64(i64 [[SKIP_HIGH_WIDE]]) 550; CHECK-NEXT: [[EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]] 551; CHECK-NEXT: call void @use64(i64 [[EXTRACTED]]) 552; CHECK-NEXT: [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32 553; CHECK-NEXT: call void @use32(i32 [[EXTRACTED_NARROW]]) 554; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]] 555; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]) 556; CHECK-NEXT: [[HIGHBITS_CLEANED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 557; CHECK-NEXT: call void @use32(i32 [[HIGHBITS_CLEANED]]) 558; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]] 559; CHECK-NEXT: ret i32 [[RES]] 560; 561 %skip_high = sub i32 64, %nbits 562 call void @use32(i32 %skip_high) 563 %skip_high_wide = zext i32 %skip_high to i64 564 call void @use64(i64 %skip_high_wide) 565 %extracted = ashr i64 %data, %skip_high_wide 566 call void @use64(i64 %extracted) 567 %extracted_narrow = trunc i64 %extracted to i32 568 call void @use32(i32 %extracted_narrow) 569 %num_high_bits_to_smear_narrow = sub i32 32, %nbits 570 call void @use32(i32 %num_high_bits_to_smear_narrow) 571 %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow 572 call void @use32(i32 %highbits_cleaned) 573 %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr 574 ret i32 %res 575} 576