1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S --mtriple=loongarch64 --passes=atomic-expand --mattr=+d %s | FileCheck %s 3 4define float @atomicrmw_fadd_float(ptr %ptr, float %value) { 5; CHECK-LABEL: @atomicrmw_fadd_float( 6; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 7; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 8; CHECK: atomicrmw.start: 9; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] 10; CHECK-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] 11; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 12; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 13; CHECK-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 14; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 15; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 16; CHECK-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float 17; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 18; CHECK: atomicrmw.end: 19; CHECK-NEXT: ret float [[TMP5]] 20; 21 %res = atomicrmw fadd ptr %ptr, float %value seq_cst 22 ret float %res 23} 24 25define float @atomicrmw_fsub_float(ptr %ptr, float %value) { 26; CHECK-LABEL: @atomicrmw_fsub_float( 27; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 28; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 29; CHECK: atomicrmw.start: 30; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] 31; CHECK-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]] 32; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 33; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 34; CHECK-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 35; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 36; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 37; CHECK-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float 38; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 39; CHECK: atomicrmw.end: 40; CHECK-NEXT: ret float [[TMP5]] 41; 42 %res = atomicrmw fsub ptr %ptr, float %value seq_cst 43 ret float %res 44} 45 46define float @atomicrmw_fmin_float(ptr %ptr, float %value) { 47; CHECK-LABEL: @atomicrmw_fmin_float( 48; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 49; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 50; CHECK: atomicrmw.start: 51; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] 52; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE:%.*]]) 53; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 54; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 55; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 56; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 57; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 58; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float 59; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 60; CHECK: atomicrmw.end: 61; CHECK-NEXT: ret float [[TMP6]] 62; 63 %res = atomicrmw fmin ptr %ptr, float %value seq_cst 64 ret float %res 65} 66 67define float @atomicrmw_fmax_float(ptr %ptr, float %value) { 68; CHECK-LABEL: @atomicrmw_fmax_float( 69; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 70; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 71; CHECK: atomicrmw.start: 72; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] 73; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE:%.*]]) 74; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 75; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 76; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 77; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 78; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 79; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float 80; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 81; CHECK: atomicrmw.end: 82; CHECK-NEXT: ret float [[TMP6]] 83; 84 %res = atomicrmw fmax ptr %ptr, float %value seq_cst 85 ret float %res 86} 87 88define double @atomicrmw_fadd_double(ptr %ptr, double %value) { 89; CHECK-LABEL: @atomicrmw_fadd_double( 90; CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 91; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 92; CHECK: atomicrmw.start: 93; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] 94; CHECK-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] 95; CHECK-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 96; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 97; CHECK-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 98; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 99; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 100; CHECK-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double 101; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 102; CHECK: atomicrmw.end: 103; CHECK-NEXT: ret double [[TMP5]] 104; 105 %res = atomicrmw fadd ptr %ptr, double %value seq_cst 106 ret double %res 107} 108 109define double @atomicrmw_fsub_double(ptr %ptr, double %value) { 110; CHECK-LABEL: @atomicrmw_fsub_double( 111; CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 112; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 113; CHECK: atomicrmw.start: 114; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] 115; CHECK-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE:%.*]] 116; CHECK-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 117; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 118; CHECK-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 119; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 120; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 121; CHECK-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double 122; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 123; CHECK: atomicrmw.end: 124; CHECK-NEXT: ret double [[TMP5]] 125; 126 %res = atomicrmw fsub ptr %ptr, double %value seq_cst 127 ret double %res 128} 129 130define double @atomicrmw_fmin_double(ptr %ptr, double %value) { 131; CHECK-LABEL: @atomicrmw_fmin_double( 132; CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 133; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 134; CHECK: atomicrmw.start: 135; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] 136; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE:%.*]]) 137; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 138; CHECK-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 139; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 140; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 141; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 142; CHECK-NEXT: [[TMP6]] = bitcast i64 [[NEWLOADED]] to double 143; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 144; CHECK: atomicrmw.end: 145; CHECK-NEXT: ret double [[TMP6]] 146; 147 %res = atomicrmw fmin ptr %ptr, double %value seq_cst 148 ret double %res 149} 150 151define double @atomicrmw_fmax_double(ptr %ptr, double %value) { 152; CHECK-LABEL: @atomicrmw_fmax_double( 153; CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 154; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]] 155; CHECK: atomicrmw.start: 156; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] 157; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE:%.*]]) 158; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 159; CHECK-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 160; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 161; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 162; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 163; CHECK-NEXT: [[TMP6]] = bitcast i64 [[NEWLOADED]] to double 164; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] 165; CHECK: atomicrmw.end: 166; CHECK-NEXT: ret double [[TMP6]] 167; 168 %res = atomicrmw fmax ptr %ptr, double %value seq_cst 169 ret double %res 170} 171