1 // RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple | \ 2 // RUN: FileCheck %s \ 3 // RUN: '-DWE="class.std::__1::weak_equality"' \ 4 // RUN: '-DSO="class.std::__1::strong_ordering"' \ 5 // RUN: '-DSE="class.std::__1::strong_equality"' \ 6 // RUN: '-DPO="class.std::__1::partial_ordering"' \ 7 // RUN: -DEQ=0 -DLT=-1 -DGT=1 -DUNORD=-127 -DNE=1 8 9 #include "Inputs/std-compare.h" 10 11 // Ensure we don't emit definitions for the global variables 12 // since the builtins shouldn't ODR use them. 13 // CHECK-NOT: constant %[[SO]] 14 // CHECK-NOT: constant %[[SE]] 15 // CHECK-NOT: constant %[[WE]] 16 // CHECK-NOT: constant %[[PO]] 17 18 // CHECK-LABEL: @_Z11test_signedii 19 auto test_signed(int x, int y) { 20 // CHECK: %[[DEST:retval|agg.result]] 21 // CHECK: %cmp.lt = icmp slt i32 %{{.+}}, %{{.+}} 22 // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]] 23 // CHECK: %cmp.eq = icmp eq i32 %{{.+}}, %{{.+}} 24 // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt 25 // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] 26 // CHECK: store i8 %sel.eq, i8* %__value_, align 1 27 // CHECK: ret 28 return x <=> y; 29 } 30 31 // CHECK-LABEL: @_Z13test_unsignedjj 32 auto test_unsigned(unsigned x, unsigned y) { 33 // CHECK: %[[DEST:retval|agg.result]] 34 // CHECK: %cmp.lt = icmp ult i32 %{{.+}}, %{{.+}} 35 // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]] 36 // CHECK: %cmp.eq = icmp eq i32 %{{.+}}, %{{.+}} 37 // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt 38 // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] 39 // CHECK: store i8 %sel.eq, i8* %__value_ 40 // CHECK: ret 41 return x <=> y; 42 } 43 44 // CHECK-LABEL: @_Z10float_testdd 45 auto float_test(double x, double y) { 46 // CHECK: %[[DEST:retval|agg.result]] 47 // CHECK: %cmp.eq = fcmp oeq double %{{.+}}, %{{.+}} 48 // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 [[UNORD]] 49 // CHECK: %cmp.gt = fcmp ogt double %{{.+}}, %{{.+}} 50 // CHECK: %sel.gt = select i1 %cmp.gt, i8 [[GT]], i8 %sel.eq 51 // CHECK: %cmp.lt = fcmp olt double %{{.+}}, %{{.+}} 52 // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 %sel.gt 53 // CHECK: %__value_ = getelementptr inbounds %[[PO]], %[[PO]]* %[[DEST]] 54 // CHECK: store i8 %sel.lt, i8* %__value_ 55 // CHECK: ret 56 return x <=> y; 57 } 58 59 // CHECK-LABEL: @_Z8ptr_testPiS_ 60 auto ptr_test(int *x, int *y) { 61 // CHECK: %[[DEST:retval|agg.result]] 62 // CHECK: %cmp.lt = icmp ult i32* %{{.+}}, %{{.+}} 63 // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]] 64 // CHECK: %cmp.eq = icmp eq i32* %{{.+}}, %{{.+}} 65 // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt 66 // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] 67 // CHECK: store i8 %sel.eq, i8* %__value_, align 1 68 // CHECK: ret 69 return x <=> y; 70 } 71 72 struct MemPtr {}; 73 using MemPtrT = void (MemPtr::*)(); 74 using MemDataT = int(MemPtr::*); 75 76 // CHECK-LABEL: @_Z12mem_ptr_testM6MemPtrFvvES1_ 77 auto mem_ptr_test(MemPtrT x, MemPtrT y) { 78 // CHECK: %[[DEST:retval|agg.result]] 79 // CHECK: %cmp.ptr = icmp eq [[TY:i[0-9]+]] %lhs.memptr.ptr, %rhs.memptr.ptr 80 // CHECK: %cmp.ptr.null = icmp eq [[TY]] %lhs.memptr.ptr, 0 81 // CHECK: %cmp.adj = icmp eq [[TY]] %lhs.memptr.adj, %rhs.memptr.adj 82 // CHECK: %[[OR:.*]] = or i1 83 // CHECK-SAME: %cmp.adj 84 // CHECK: %memptr.eq = and i1 %cmp.ptr, %[[OR]] 85 // CHECK: %sel.eq = select i1 %memptr.eq, i8 [[EQ]], i8 [[NE]] 86 // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] 87 // CHECK: store i8 %sel.eq, i8* %__value_, align 1 88 // CHECK: ret 89 return x <=> y; 90 } 91 92 // CHECK-LABEL: @_Z13mem_data_testM6MemPtriS0_ 93 auto mem_data_test(MemDataT x, MemDataT y) { 94 // CHECK: %[[DEST:retval|agg.result]] 95 // CHECK: %[[CMP:.*]] = icmp eq i{{[0-9]+}} %{{.+}}, %{{.+}} 96 // CHECK: %sel.eq = select i1 %[[CMP]], i8 [[EQ]], i8 [[NE]] 97 // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] 98 // CHECK: store i8 %sel.eq, i8* %__value_, align 1 99 return x <=> y; 100 } 101 102 // CHECK-LABEL: @_Z13test_constantv 103 auto test_constant() { 104 // CHECK: %[[DEST:retval|agg.result]] 105 // CHECK-NOT: icmp 106 // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] 107 // CHECK-NEXT: store i8 -1, i8* %__value_ 108 // CHECK: ret 109 const int x = 42; 110 const int y = 101; 111 return x <=> y; 112 } 113 114 // CHECK-LABEL: @_Z16test_nullptr_objPiDn 115 auto test_nullptr_obj(int* x, decltype(nullptr) y) { 116 // CHECK: %[[DEST:retval|agg.result]] 117 // CHECK: %cmp.eq = icmp eq i32* %{{.+}}, null 118 // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 [[NE]] 119 // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] 120 // CHECK: store i8 %sel.eq, i8* %__value_, align 1 121 return x <=> y; 122 } 123 124 // CHECK-LABEL: @_Z18unscoped_enum_testijxy 125 void unscoped_enum_test(int i, unsigned u, long long l, unsigned long long ul) { 126 enum EnumA : int { A }; 127 enum EnumB : unsigned { B }; 128 // CHECK: %[[I:.*]] = load {{.*}} %i.addr 129 // CHECK: icmp slt i32 {{.*}} %[[I]] 130 (void)(A <=> i); 131 132 // CHECK: %[[U:.*]] = load {{.*}} %u.addr 133 // CHECK: icmp ult i32 {{.*}} %[[U]] 134 (void)(A <=> u); 135 136 // CHECK: %[[L:.*]] = load {{.*}} %l.addr 137 // CHECK: icmp slt i64 {{.*}} %[[L]] 138 (void)(A <=> l); 139 140 // CHECK: %[[U2:.*]] = load {{.*}} %u.addr 141 // CHECK: icmp ult i32 {{.*}} %[[U2]] 142 (void)(B <=> u); 143 144 // CHECK: %[[UL:.*]] = load {{.*}} %ul.addr 145 // CHECK: icmp ult i64 {{.*}} %[[UL]] 146 (void)(B <=> ul); 147 } 148 149 namespace NullptrTest { 150 using nullptr_t = decltype(nullptr); 151 152 // CHECK-LABEL: @_ZN11NullptrTest4testEDnDn( 153 auto test(nullptr_t x, nullptr_t y) { 154 // CHECK: %[[DEST:retval|agg.result]] 155 // CHECK-NOT: select 156 // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] 157 // CHECK-NEXT: store i8 [[EQ]], i8* %__value_ 158 // CHECK: ret 159 return x <=> y; 160 } 161 } // namespace NullptrTest 162 163 namespace ComplexTest { 164 165 auto test_float(_Complex float x, _Complex float y) { 166 // CHECK: %[[DEST:retval|agg.result]] 167 // CHECK: %cmp.eq.r = fcmp oeq float %x.real, %y.real 168 // CHECK: %cmp.eq.i = fcmp oeq float %x.imag, %y.imag 169 // CHECK: %and.eq = and i1 %cmp.eq.r, %cmp.eq.i 170 // CHECK: %sel.eq = select i1 %and.eq, i8 [[EQ]], i8 [[NE]] 171 // CHECK: %__value_ = getelementptr inbounds %[[WE]], %[[WE]]* %[[DEST]] 172 // CHECK: store i8 %sel.eq, i8* %__value_, align 1 173 return x <=> y; 174 } 175 176 // CHECK-LABEL: @_ZN11ComplexTest8test_intECiS0_( 177 auto test_int(_Complex int x, _Complex int y) { 178 // CHECK: %[[DEST:retval|agg.result]] 179 // CHECK: %cmp.eq.r = icmp eq i32 %x.real, %y.real 180 // CHECK: %cmp.eq.i = icmp eq i32 %x.imag, %y.imag 181 // CHECK: %and.eq = and i1 %cmp.eq.r, %cmp.eq.i 182 // CHECK: %sel.eq = select i1 %and.eq, i8 [[EQ]], i8 [[NE]] 183 // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] 184 // CHECK: store i8 %sel.eq, i8* %__value_, align 1 185 return x <=> y; 186 } 187 188 } // namespace ComplexTest 189