brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.1 KiB · 75ee539 Raw
456 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S < %s -passes=instcombine | FileCheck %s3 4target 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"5target triple = "x86_64-apple-macosx10.7.0"6 7; Check transforms involving atomic operations8 9define i32 @test1(ptr %p) {10; CHECK-LABEL: @test1(11; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 412; CHECK-NEXT:    [[Z:%.*]] = shl i32 [[X]], 113; CHECK-NEXT:    ret i32 [[Z]]14;15  %x = load atomic i32, ptr %p seq_cst, align 416  %y = load i32, ptr %p, align 417  %z = add i32 %x, %y18  ret i32 %z19}20 21define i32 @test2(ptr %p) {22; CHECK-LABEL: @test2(23; CHECK-NEXT:    [[X:%.*]] = load volatile i32, ptr [[P:%.*]], align 424; CHECK-NEXT:    [[Y:%.*]] = load volatile i32, ptr [[P]], align 425; CHECK-NEXT:    [[Z:%.*]] = add i32 [[X]], [[Y]]26; CHECK-NEXT:    ret i32 [[Z]]27;28  %x = load volatile i32, ptr %p, align 429  %y = load volatile i32, ptr %p, align 430  %z = add i32 %x, %y31  ret i32 %z32}33 34; The exact semantics of mixing volatile and non-volatile on the same35; memory location are a bit unclear, but conservatively, we know we don't36; want to remove the volatile.37define i32 @test3(ptr %p) {38; CHECK-LABEL: @test3(39; CHECK-NEXT:    [[X:%.*]] = load volatile i32, ptr [[P:%.*]], align 440; CHECK-NEXT:    [[Z:%.*]] = shl i32 [[X]], 141; CHECK-NEXT:    ret i32 [[Z]]42;43  %x = load volatile i32, ptr %p, align 444  %y = load i32, ptr %p, align 445  %z = add i32 %x, %y46  ret i32 %z47}48 49; Forwarding from a stronger ordered atomic is fine50define i32 @test4(ptr %p) {51; CHECK-LABEL: @test4(52; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 453; CHECK-NEXT:    [[Z:%.*]] = shl i32 [[X]], 154; CHECK-NEXT:    ret i32 [[Z]]55;56  %x = load atomic i32, ptr %p seq_cst, align 457  %y = load atomic i32, ptr %p unordered, align 458  %z = add i32 %x, %y59  ret i32 %z60}61 62; Forwarding from a non-atomic is not.  (The earlier load63; could in priciple be promoted to atomic and then forwarded,64; but we can't just  drop the atomic from the load.)65define i32 @test5(ptr %p) {66; CHECK-LABEL: @test5(67; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[P:%.*]] unordered, align 468; CHECK-NEXT:    [[Z:%.*]] = shl i32 [[X]], 169; CHECK-NEXT:    ret i32 [[Z]]70;71  %x = load atomic i32, ptr %p unordered, align 472  %y = load i32, ptr %p, align 473  %z = add i32 %x, %y74  ret i32 %z75}76 77; Forwarding atomic to atomic is fine78define i32 @test6(ptr %p) {79; CHECK-LABEL: @test6(80; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[P:%.*]] unordered, align 481; CHECK-NEXT:    [[Z:%.*]] = shl i32 [[X]], 182; CHECK-NEXT:    ret i32 [[Z]]83;84  %x = load atomic i32, ptr %p unordered, align 485  %y = load atomic i32, ptr %p unordered, align 486  %z = add i32 %x, %y87  ret i32 %z88}89 90; FIXME: we currently don't do anything for monotonic91define i32 @test7(ptr %p) {92; CHECK-LABEL: @test7(93; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 494; CHECK-NEXT:    [[Y:%.*]] = load atomic i32, ptr [[P]] monotonic, align 495; CHECK-NEXT:    [[Z:%.*]] = add i32 [[X]], [[Y]]96; CHECK-NEXT:    ret i32 [[Z]]97;98  %x = load atomic i32, ptr %p seq_cst, align 499  %y = load atomic i32, ptr %p monotonic, align 4100  %z = add i32 %x, %y101  ret i32 %z102}103 104; FIXME: We could forward in racy code105define i32 @test8(ptr %p) {106; CHECK-LABEL: @test8(107; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 4108; CHECK-NEXT:    [[Y:%.*]] = load atomic i32, ptr [[P]] acquire, align 4109; CHECK-NEXT:    [[Z:%.*]] = add i32 [[X]], [[Y]]110; CHECK-NEXT:    ret i32 [[Z]]111;112  %x = load atomic i32, ptr %p seq_cst, align 4113  %y = load atomic i32, ptr %p acquire, align 4114  %z = add i32 %x, %y115  ret i32 %z116}117 118; An unordered access to null is still unreachable.  There's no119; ordering imposed.120define i32 @test9() {121; CHECK-LABEL: @test9(122; CHECK-NEXT:    store i1 true, ptr poison, align 1123; CHECK-NEXT:    ret i32 poison124;125  %x = load atomic i32, ptr null unordered, align 4126  ret i32 %x127}128 129define i32 @test9_no_null_opt() #0 {130; CHECK-LABEL: @test9_no_null_opt(131; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr null unordered, align 4132; CHECK-NEXT:    ret i32 [[X]]133;134  %x = load atomic i32, ptr null unordered, align 4135  ret i32 %x136}137 138; FIXME: Could also fold139define i32 @test10() {140; CHECK-LABEL: @test10(141; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr null monotonic, align 4142; CHECK-NEXT:    ret i32 [[X]]143;144  %x = load atomic i32, ptr null monotonic, align 4145  ret i32 %x146}147 148define i32 @test10_no_null_opt() #0 {149; CHECK-LABEL: @test10_no_null_opt(150; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr null monotonic, align 4151; CHECK-NEXT:    ret i32 [[X]]152;153  %x = load atomic i32, ptr null monotonic, align 4154  ret i32 %x155}156 157; Would this be legal to fold?  Probably?158define i32 @test11() {159; CHECK-LABEL: @test11(160; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr null seq_cst, align 4161; CHECK-NEXT:    ret i32 [[X]]162;163  %x = load atomic i32, ptr null seq_cst, align 4164  ret i32 %x165}166 167define i32 @test11_no_null_opt() #0 {168; CHECK-LABEL: @test11_no_null_opt(169; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr null seq_cst, align 4170; CHECK-NEXT:    ret i32 [[X]]171;172  %x = load atomic i32, ptr null seq_cst, align 4173  ret i32 %x174}175 176; An unordered access to null is still unreachable.  There's no177; ordering imposed.178define i32 @test12() {179; CHECK-LABEL: @test12(180; CHECK-NEXT:    store atomic i32 poison, ptr null unordered, align 4181; CHECK-NEXT:    ret i32 0182;183  store atomic i32 0, ptr null unordered, align 4184  ret i32 0185}186 187define i32 @test12_no_null_opt() #0 {188; CHECK-LABEL: @test12_no_null_opt(189; CHECK-NEXT:    store atomic i32 0, ptr null unordered, align 4190; CHECK-NEXT:    ret i32 0191;192  store atomic i32 0, ptr null unordered, align 4193  ret i32 0194}195 196; FIXME: Could also fold197define i32 @test13() {198; CHECK-LABEL: @test13(199; CHECK-NEXT:    store atomic i32 0, ptr null monotonic, align 4200; CHECK-NEXT:    ret i32 0201;202  store atomic i32 0, ptr null monotonic, align 4203  ret i32 0204}205 206define i32 @test13_no_null_opt() #0 {207; CHECK-LABEL: @test13_no_null_opt(208; CHECK-NEXT:    store atomic i32 0, ptr null monotonic, align 4209; CHECK-NEXT:    ret i32 0210;211  store atomic i32 0, ptr null monotonic, align 4212  ret i32 0213}214 215; Would this be legal to fold?  Probably?216define i32 @test14() {217; CHECK-LABEL: @test14(218; CHECK-NEXT:    store atomic i32 0, ptr null seq_cst, align 4219; CHECK-NEXT:    ret i32 0220;221  store atomic i32 0, ptr null seq_cst, align 4222  ret i32 0223}224 225define i32 @test14_no_null_opt() #0 {226; CHECK-LABEL: @test14_no_null_opt(227; CHECK-NEXT:    store atomic i32 0, ptr null seq_cst, align 4228; CHECK-NEXT:    ret i32 0229;230  store atomic i32 0, ptr null seq_cst, align 4231  ret i32 0232}233 234@a = external global i32235@b = external global i32236 237define i32 @test15(i1 %cnd) {238; CHECK-LABEL: @test15(239; CHECK-NEXT:    [[A_VAL:%.*]] = load atomic i32, ptr @a unordered, align 4240; CHECK-NEXT:    [[B_VAL:%.*]] = load atomic i32, ptr @b unordered, align 4241; CHECK-NEXT:    [[X:%.*]] = select i1 [[CND:%.*]], i32 [[A_VAL]], i32 [[B_VAL]]242; CHECK-NEXT:    ret i32 [[X]]243;244  %addr = select i1 %cnd, ptr @a, ptr @b245  %x = load atomic i32, ptr %addr unordered, align 4246  ret i32 %x247}248 249; FIXME: This would be legal to transform250define i32 @test16(i1 %cnd) {251; CHECK-LABEL: @test16(252; CHECK-NEXT:    [[ADDR:%.*]] = select i1 [[CND:%.*]], ptr @a, ptr @b253; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[ADDR]] monotonic, align 4254; CHECK-NEXT:    ret i32 [[X]]255;256  %addr = select i1 %cnd, ptr @a, ptr @b257  %x = load atomic i32, ptr %addr monotonic, align 4258  ret i32 %x259}260 261; FIXME: This would be legal to transform262define i32 @test17(i1 %cnd) {263; CHECK-LABEL: @test17(264; CHECK-NEXT:    [[ADDR:%.*]] = select i1 [[CND:%.*]], ptr @a, ptr @b265; CHECK-NEXT:    [[X:%.*]] = load atomic i32, ptr [[ADDR]] seq_cst, align 4266; CHECK-NEXT:    ret i32 [[X]]267;268  %addr = select i1 %cnd, ptr @a, ptr @b269  %x = load atomic i32, ptr %addr seq_cst, align 4270  ret i32 %x271}272 273define i32 @test22(i1 %cnd) {274; CHECK-LABEL: @test22(275; CHECK-NEXT:    br i1 [[CND:%.*]], label [[BLOCK1:%.*]], label [[BLOCK2:%.*]]276; CHECK:       block1:277; CHECK-NEXT:    br label [[MERGE:%.*]]278; CHECK:       block2:279; CHECK-NEXT:    br label [[MERGE]]280; CHECK:       merge:281; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 2, [[BLOCK2]] ], [ 1, [[BLOCK1]] ]282; CHECK-NEXT:    store atomic i32 [[STOREMERGE]], ptr @a unordered, align 4283; CHECK-NEXT:    ret i32 0284;285  br i1 %cnd, label %block1, label %block2286 287block1:288  store atomic i32 1, ptr @a unordered, align 4289  br label %merge290block2:291  store atomic i32 2, ptr @a unordered, align 4292  br label %merge293 294merge:295  ret i32 0296}297 298; TODO: probably also legal here299define i32 @test23(i1 %cnd) {300; CHECK-LABEL: @test23(301; CHECK-NEXT:    br i1 [[CND:%.*]], label [[BLOCK1:%.*]], label [[BLOCK2:%.*]]302; CHECK:       block1:303; CHECK-NEXT:    store atomic i32 1, ptr @a monotonic, align 4304; CHECK-NEXT:    br label [[MERGE:%.*]]305; CHECK:       block2:306; CHECK-NEXT:    store atomic i32 2, ptr @a monotonic, align 4307; CHECK-NEXT:    br label [[MERGE]]308; CHECK:       merge:309; CHECK-NEXT:    ret i32 0310;311  br i1 %cnd, label %block1, label %block2312 313block1:314  store atomic i32 1, ptr @a monotonic, align 4315  br label %merge316block2:317  store atomic i32 2, ptr @a monotonic, align 4318  br label %merge319 320merge:321  ret i32 0322}323 324declare void @clobber()325 326define i32 @test18(ptr %p) {327; CHECK-LABEL: @test18(328; CHECK-NEXT:    [[X:%.*]] = load atomic float, ptr [[P:%.*]] unordered, align 4329; CHECK-NEXT:    call void @clobber()330; CHECK-NEXT:    store atomic float [[X]], ptr [[P]] unordered, align 4331; CHECK-NEXT:    ret i32 0332;333  %x = load atomic float, ptr %p unordered, align 4334  call void @clobber() ;; keep the load around335  store atomic float %x, ptr %p unordered, align 4336  ret i32 0337}338 339; TODO: probably also legal in this case340define i32 @test19(ptr %p) {341; CHECK-LABEL: @test19(342; CHECK-NEXT:    [[X:%.*]] = load atomic float, ptr [[P:%.*]] seq_cst, align 4343; CHECK-NEXT:    call void @clobber()344; CHECK-NEXT:    store atomic float [[X]], ptr [[P]] seq_cst, align 4345; CHECK-NEXT:    ret i32 0346;347  %x = load atomic float, ptr %p seq_cst, align 4348  call void @clobber() ;; keep the load around349  store atomic float %x, ptr %p seq_cst, align 4350  ret i32 0351}352 353define i32 @test20(ptr %p, ptr %v) {354; CHECK-LABEL: @test20(355; CHECK-NEXT:    store atomic ptr [[V:%.*]], ptr [[P:%.*]] unordered, align 4356; CHECK-NEXT:    ret i32 0357;358  store atomic ptr %v, ptr %p unordered, align 4359  ret i32 0360}361 362define i32 @test21(ptr %p, ptr %v) {363; CHECK-LABEL: @test21(364; CHECK-NEXT:    store atomic ptr [[V:%.*]], ptr [[P:%.*]] monotonic, align 4365; CHECK-NEXT:    ret i32 0366;367  store atomic ptr %v, ptr %p monotonic, align 4368  ret i32 0369}370 371define void @pr27490a(ptr %p1, ptr %p2) {372; CHECK-LABEL: @pr27490a(373; CHECK-NEXT:    [[L:%.*]] = load ptr, ptr [[P1:%.*]], align 8374; CHECK-NEXT:    store volatile ptr [[L]], ptr [[P2:%.*]], align 8375; CHECK-NEXT:    ret void376;377  %l = load ptr, ptr %p1378  store volatile ptr %l, ptr %p2379  ret void380}381 382define void @pr27490b(ptr %p1, ptr %p2) {383; CHECK-LABEL: @pr27490b(384; CHECK-NEXT:    [[L:%.*]] = load ptr, ptr [[P1:%.*]], align 8385; CHECK-NEXT:    store atomic ptr [[L]], ptr [[P2:%.*]] seq_cst, align 8386; CHECK-NEXT:    ret void387;388  %l = load ptr, ptr %p1389  store atomic ptr %l, ptr %p2 seq_cst, align 8390  ret void391}392 393;; At the moment, we can't form atomic vectors by folding since these are394;; not representable in the IR.  This was pr29121.  The right long term395;; solution is to extend the IR to handle this case.396define <2 x float> @no_atomic_vector_load(ptr %p) {397; CHECK-LABEL: @no_atomic_vector_load(398; CHECK-NEXT:    [[LOAD:%.*]] = load atomic i64, ptr [[P:%.*]] unordered, align 8399; CHECK-NEXT:    [[DOTCAST:%.*]] = bitcast i64 [[LOAD]] to <2 x float>400; CHECK-NEXT:    ret <2 x float> [[DOTCAST]]401;402  %load = load atomic i64, ptr %p unordered, align 8403  %.cast = bitcast i64 %load to <2 x float>404  ret <2 x float> %.cast405}406 407define void @no_atomic_vector_store(<2 x float> %p, ptr %p2) {408; CHECK-LABEL: @no_atomic_vector_store(409; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[P:%.*]] to i64410; CHECK-NEXT:    store atomic i64 [[TMP1]], ptr [[P2:%.*]] unordered, align 8411; CHECK-NEXT:    ret void412;413  %1 = bitcast <2 x float> %p to i64414  store atomic i64 %1, ptr %p2 unordered, align 8415  ret void416}417 418@c = constant i32 42419@g = global i32 42420 421define i32 @atomic_load_from_constant_global() {422; CHECK-LABEL: @atomic_load_from_constant_global(423; CHECK-NEXT:    ret i32 42424;425  %v = load atomic i32, ptr @c seq_cst, align 4426  ret i32 %v427}428 429define i8 @atomic_load_from_constant_global_bitcast() {430; CHECK-LABEL: @atomic_load_from_constant_global_bitcast(431; CHECK-NEXT:    ret i8 42432;433  %v = load atomic i8, ptr @c seq_cst, align 1434  ret i8 %v435}436 437define void @atomic_load_from_non_constant_global() {438; CHECK-LABEL: @atomic_load_from_non_constant_global(439; CHECK-NEXT:    [[TMP1:%.*]] = load atomic i32, ptr @g seq_cst, align 4440; CHECK-NEXT:    ret void441;442  load atomic i32, ptr @g seq_cst, align 4443  ret void444}445 446define void @volatile_load_from_constant_global() {447; CHECK-LABEL: @volatile_load_from_constant_global(448; CHECK-NEXT:    [[TMP1:%.*]] = load volatile i32, ptr @c, align 4449; CHECK-NEXT:    ret void450;451  load volatile i32, ptr @c, align 4452  ret void453}454 455attributes #0 = { null_pointer_is_valid }456