1; RUN: opt < %s -instcombine -S | FileCheck %s 2target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 3 4; Instcombine should be able to eliminate all of these ext casts. 5 6declare void @use(i32) 7 8define i64 @test1(i64 %a) { 9 %b = trunc i64 %a to i32 10 %c = and i32 %b, 15 11 %d = zext i32 %c to i64 12 call void @use(i32 %b) 13 ret i64 %d 14; CHECK-LABEL: @test1( 15; CHECK-NOT: ext 16; CHECK: ret 17} 18define i64 @test2(i64 %a) { 19 %b = trunc i64 %a to i32 20 %c = shl i32 %b, 4 21 %q = ashr i32 %c, 4 22 %d = sext i32 %q to i64 23 call void @use(i32 %b) 24 ret i64 %d 25; CHECK-LABEL: @test2( 26; CHECK: shl i64 %a, 36 27; CHECK: %d = ashr exact i64 {{.*}}, 36 28; CHECK: ret i64 %d 29} 30define i64 @test3(i64 %a) { 31 %b = trunc i64 %a to i32 32 %c = and i32 %b, 8 33 %d = zext i32 %c to i64 34 call void @use(i32 %b) 35 ret i64 %d 36; CHECK-LABEL: @test3( 37; CHECK-NOT: ext 38; CHECK: ret 39} 40define i64 @test4(i64 %a) { 41 %b = trunc i64 %a to i32 42 %c = and i32 %b, 8 43 %x = xor i32 %c, 8 44 %d = zext i32 %x to i64 45 call void @use(i32 %b) 46 ret i64 %d 47; CHECK-LABEL: @test4( 48; CHECK: = and i64 %a, 8 49; CHECK: = xor i64 {{.*}}, 8 50; CHECK-NOT: ext 51; CHECK: ret 52} 53 54define i32 @test5(i32 %A) { 55 %B = zext i32 %A to i128 56 %C = lshr i128 %B, 16 57 %D = trunc i128 %C to i32 58 ret i32 %D 59; CHECK-LABEL: @test5( 60; CHECK: %C = lshr i32 %A, 16 61; CHECK: ret i32 %C 62} 63 64define i32 @test6(i64 %A) { 65 %B = zext i64 %A to i128 66 %C = lshr i128 %B, 32 67 %D = trunc i128 %C to i32 68 ret i32 %D 69; CHECK-LABEL: @test6( 70; CHECK: %C = lshr i64 %A, 32 71; CHECK: %D = trunc i64 %C to i32 72; CHECK: ret i32 %D 73} 74 75define i92 @test7(i64 %A) { 76 %B = zext i64 %A to i128 77 %C = lshr i128 %B, 32 78 %D = trunc i128 %C to i92 79 ret i92 %D 80; CHECK-LABEL: @test7( 81; CHECK: %B = zext i64 %A to i92 82; CHECK: %C = lshr i92 %B, 32 83; CHECK: ret i92 %C 84} 85 86define i64 @test8(i32 %A, i32 %B) { 87 %tmp38 = zext i32 %A to i128 88 %tmp32 = zext i32 %B to i128 89 %tmp33 = shl i128 %tmp32, 32 90 %ins35 = or i128 %tmp33, %tmp38 91 %tmp42 = trunc i128 %ins35 to i64 92 ret i64 %tmp42 93; CHECK-LABEL: @test8( 94; CHECK: %tmp38 = zext i32 %A to i64 95; CHECK: %tmp32 = zext i32 %B to i64 96; CHECK: %tmp33 = shl nuw i64 %tmp32, 32 97; CHECK: %ins35 = or i64 %tmp33, %tmp38 98; CHECK: ret i64 %ins35 99} 100 101define i8 @test9(i32 %X) { 102 %Y = and i32 %X, 42 103 %Z = trunc i32 %Y to i8 104 ret i8 %Z 105; CHECK-LABEL: @test9( 106; CHECK: trunc 107; CHECK: and 108; CHECK: ret 109} 110 111; rdar://8808586 112define i8 @test10(i32 %X) { 113 %Y = trunc i32 %X to i8 114 %Z = and i8 %Y, 42 115 ret i8 %Z 116; CHECK-LABEL: @test10( 117; CHECK: trunc 118; CHECK: and 119; CHECK: ret 120} 121 122; PR25543 123; https://llvm.org/bugs/show_bug.cgi?id=25543 124; This is an extractelement. 125 126define i32 @trunc_bitcast1(<4 x i32> %v) { 127 %bc = bitcast <4 x i32> %v to i128 128 %shr = lshr i128 %bc, 32 129 %ext = trunc i128 %shr to i32 130 ret i32 %ext 131 132; CHECK-LABEL: @trunc_bitcast1( 133; CHECK-NEXT: %ext = extractelement <4 x i32> %v, i32 1 134; CHECK-NEXT: ret i32 %ext 135} 136 137; A bitcast may still be required. 138 139define i32 @trunc_bitcast2(<2 x i64> %v) { 140 %bc = bitcast <2 x i64> %v to i128 141 %shr = lshr i128 %bc, 64 142 %ext = trunc i128 %shr to i32 143 ret i32 %ext 144 145; CHECK-LABEL: @trunc_bitcast2( 146; CHECK-NEXT: %bc1 = bitcast <2 x i64> %v to <4 x i32> 147; CHECK-NEXT: %ext = extractelement <4 x i32> %bc1, i32 2 148; CHECK-NEXT: ret i32 %ext 149} 150 151; The right shift is optional. 152 153define i32 @trunc_bitcast3(<4 x i32> %v) { 154 %bc = bitcast <4 x i32> %v to i128 155 %ext = trunc i128 %bc to i32 156 ret i32 %ext 157 158; CHECK-LABEL: @trunc_bitcast3( 159; CHECK-NEXT: %ext = extractelement <4 x i32> %v, i32 0 160; CHECK-NEXT: ret i32 %ext 161} 162 163; CHECK-LABEL: @trunc_shl_infloop( 164; CHECK: %tmp = lshr i64 %arg, 1 165; CHECK: %tmp21 = shl i64 %tmp, 2 166; CHECK: %tmp2 = trunc i64 %tmp21 to i32 167; CHECK: icmp sgt i32 %tmp2, 0 168define void @trunc_shl_infloop(i64 %arg) { 169bb: 170 %tmp = lshr i64 %arg, 1 171 %tmp1 = trunc i64 %tmp to i32 172 %tmp2 = shl i32 %tmp1, 2 173 %tmp3 = icmp sgt i32 %tmp2, 0 174 br i1 %tmp3, label %bb2, label %bb1 175 176bb1: 177 %tmp5 = sub i32 0, %tmp1 178 %tmp6 = sub i32 %tmp5, 1 179 unreachable 180 181bb2: 182 unreachable 183} 184