1; RUN: opt < %s -instsimplify -S | FileCheck %s 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) 5declare {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b) 6declare {i8, i1} @llvm.ssub.with.overflow.i8(i8 %a, i8 %b) 7declare {i8, i1} @llvm.umul.with.overflow.i8(i8 %a, i8 %b) 8 9define i1 @test_uadd1() { 10; CHECK-LABEL: @test_uadd1( 11 %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 3) 12 %overflow = extractvalue {i8, i1} %x, 1 13 ret i1 %overflow 14; CHECK-NEXT: ret i1 true 15} 16 17define i8 @test_uadd2() { 18; CHECK-LABEL: @test_uadd2( 19 %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 44) 20 %result = extractvalue {i8, i1} %x, 0 21 ret i8 %result 22; CHECK-NEXT: ret i8 42 23} 24 25define {i8, i1} @test_usub1(i8 %V) { 26; CHECK-LABEL: @test_usub1( 27 %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 %V) 28 ret {i8, i1} %x 29; CHECK-NEXT: ret { i8, i1 } zeroinitializer 30} 31 32define {i8, i1} @test_ssub1(i8 %V) { 33; CHECK-LABEL: @test_ssub1( 34 %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 %V) 35 ret {i8, i1} %x 36; CHECK-NEXT: ret { i8, i1 } zeroinitializer 37} 38 39define {i8, i1} @test_umul1(i8 %V) { 40; CHECK-LABEL: @test_umul1( 41 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %V, i8 0) 42 ret {i8, i1} %x 43; CHECK-NEXT: ret { i8, i1 } zeroinitializer 44} 45 46declare i256 @llvm.cttz.i256(i256 %src, i1 %is_zero_undef) 47 48define i256 @test_cttz() { 49; CHECK-LABEL: @test_cttz( 50 %x = call i256 @llvm.cttz.i256(i256 10, i1 false) 51 ret i256 %x 52; CHECK-NEXT: ret i256 1 53} 54 55declare i256 @llvm.ctpop.i256(i256 %src) 56 57define i256 @test_ctpop() { 58; CHECK-LABEL: @test_ctpop( 59 %x = call i256 @llvm.ctpop.i256(i256 10) 60 ret i256 %x 61; CHECK-NEXT: ret i256 2 62} 63 64; Test a non-intrinsic that we know about as a library call. 65declare float @fabs(float %x) 66 67define float @test_fabs_libcall() { 68; CHECK-LABEL: @test_fabs_libcall( 69 70 %x = call float @fabs(float -42.0) 71; This is still a real function call, so instsimplify won't nuke it -- other 72; passes have to do that. 73; CHECK-NEXT: call float @fabs 74 75 ret float %x 76; CHECK-NEXT: ret float 4.2{{0+}}e+01 77} 78 79 80declare float @llvm.fabs.f32(float) nounwind readnone 81declare float @llvm.floor.f32(float) nounwind readnone 82declare float @llvm.ceil.f32(float) nounwind readnone 83declare float @llvm.trunc.f32(float) nounwind readnone 84declare float @llvm.rint.f32(float) nounwind readnone 85declare float @llvm.nearbyint.f32(float) nounwind readnone 86 87; Test idempotent intrinsics 88define float @test_idempotence(float %a) { 89; CHECK-LABEL: @test_idempotence( 90 91; CHECK: fabs 92; CHECK-NOT: fabs 93 %a0 = call float @llvm.fabs.f32(float %a) 94 %a1 = call float @llvm.fabs.f32(float %a0) 95 96; CHECK: floor 97; CHECK-NOT: floor 98 %b0 = call float @llvm.floor.f32(float %a) 99 %b1 = call float @llvm.floor.f32(float %b0) 100 101; CHECK: ceil 102; CHECK-NOT: ceil 103 %c0 = call float @llvm.ceil.f32(float %a) 104 %c1 = call float @llvm.ceil.f32(float %c0) 105 106; CHECK: trunc 107; CHECK-NOT: trunc 108 %d0 = call float @llvm.trunc.f32(float %a) 109 %d1 = call float @llvm.trunc.f32(float %d0) 110 111; CHECK: rint 112; CHECK-NOT: rint 113 %e0 = call float @llvm.rint.f32(float %a) 114 %e1 = call float @llvm.rint.f32(float %e0) 115 116; CHECK: nearbyint 117; CHECK-NOT: nearbyint 118 %f0 = call float @llvm.nearbyint.f32(float %a) 119 %f1 = call float @llvm.nearbyint.f32(float %f0) 120 121 %r0 = fadd float %a1, %b1 122 %r1 = fadd float %r0, %c1 123 %r2 = fadd float %r1, %d1 124 %r3 = fadd float %r2, %e1 125 %r4 = fadd float %r3, %f1 126 127 ret float %r4 128} 129 130define i8* @operator_new() { 131entry: 132 %call = tail call noalias i8* @_Znwm(i64 8) 133 %cmp = icmp eq i8* %call, null 134 br i1 %cmp, label %cast.end, label %cast.notnull 135 136cast.notnull: ; preds = %entry 137 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 138 br label %cast.end 139 140cast.end: ; preds = %cast.notnull, %entry 141 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 142 ret i8* %cast.result 143 144; CHECK-LABEL: @operator_new 145; CHECK: br i1 false, label %cast.end, label %cast.notnull 146} 147 148declare nonnull noalias i8* @_Znwm(i64) 149 150%"struct.std::nothrow_t" = type { i8 } 151@_ZSt7nothrow = external global %"struct.std::nothrow_t" 152 153define i8* @operator_new_nothrow_t() { 154entry: 155 %call = tail call noalias i8* @_ZnamRKSt9nothrow_t(i64 8, %"struct.std::nothrow_t"* @_ZSt7nothrow) 156 %cmp = icmp eq i8* %call, null 157 br i1 %cmp, label %cast.end, label %cast.notnull 158 159cast.notnull: ; preds = %entry 160 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 161 br label %cast.end 162 163cast.end: ; preds = %cast.notnull, %entry 164 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 165 ret i8* %cast.result 166 167; CHECK-LABEL: @operator_new_nothrow_t 168; CHECK: br i1 %cmp, label %cast.end, label %cast.notnull 169} 170 171declare i8* @_ZnamRKSt9nothrow_t(i64, %"struct.std::nothrow_t"*) nounwind 172 173define i8* @malloc_can_return_null() { 174entry: 175 %call = tail call noalias i8* @malloc(i64 8) 176 %cmp = icmp eq i8* %call, null 177 br i1 %cmp, label %cast.end, label %cast.notnull 178 179cast.notnull: ; preds = %entry 180 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 181 br label %cast.end 182 183cast.end: ; preds = %cast.notnull, %entry 184 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 185 ret i8* %cast.result 186 187; CHECK-LABEL: @malloc_can_return_null 188; CHECK: br i1 %cmp, label %cast.end, label %cast.notnull 189} 190 191define i32 @call_null() { 192entry: 193 %call = call i32 null() 194 ret i32 %call 195} 196; CHECK-LABEL: define i32 @call_null( 197; CHECK: ret i32 undef 198 199define i32 @call_undef() { 200entry: 201 %call = call i32 undef() 202 ret i32 %call 203} 204; CHECK-LABEL: define i32 @call_undef( 205; CHECK: ret i32 undef 206 207@GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49] 208 209define <8 x i32> @partial_masked_load() { 210; CHECK-LABEL: @partial_masked_load( 211; CHECK: ret <8 x i32> <i32 undef, i32 undef, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47> 212 %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -2) to <8 x i32>*), i32 4, <8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef) 213 ret <8 x i32> %masked.load 214} 215 216define <8 x i32> @masked_load_undef_mask(<8 x i32>* %V) { 217; CHECK-LABEL: @masked_load_undef_mask( 218; CHECK: ret <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0> 219 %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %V, i32 4, <8 x i1> undef, <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0>) 220 ret <8 x i32> %masked.load 221} 222 223declare noalias i8* @malloc(i64) 224 225declare <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>*, i32, <8 x i1>, <8 x i32>) 226