TARGET_HEADER_BUILTIN(_umul128, "ULLiULLiULLiULLi*", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__faststorefence, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__shiftleft128, "ULLiULLiULLiUc", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__shiftright128, "ULLiULLiULLiUc", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
llvm::SyncScope::System);
}
+ case X86::BI__shiftleft128:
+ case X86::BI__shiftright128: {
+ // FIXME: Once fshl/fshr no longer add an unneeded and and cmov, do this:
+ // llvm::Function *F = CGM.getIntrinsic(
+ // BuiltinID == X86::BI__shiftleft128 ? Intrinsic::fshl : Intrinsic::fshr,
+ // Int64Ty);
+ // Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
+ // return Builder.CreateCall(F, Ops);
+ llvm::Type *Int128Ty = Builder.getInt128Ty();
+ Value *Val = Builder.CreateOr(
+ Builder.CreateShl(Builder.CreateZExt(Ops[1], Int128Ty), 64),
+ Builder.CreateZExt(Ops[0], Int128Ty));
+ Value *Amt = Builder.CreateAnd(Builder.CreateZExt(Ops[2], Int128Ty),
+ llvm::ConstantInt::get(Int128Ty, 0x3f));
+ Value *Res;
+ if (BuiltinID == X86::BI__shiftleft128)
+ Res = Builder.CreateLShr(Builder.CreateShl(Val, Amt), 64);
+ else
+ Res = Builder.CreateLShr(Val, Amt);
+ return Builder.CreateTrunc(Res, Int64Ty);
+ }
case X86::BI_ReadWriteBarrier:
case X86::BI_ReadBarrier:
case X86::BI_WriteBarrier: {
__asm__ volatile ("nop");
}
#endif
-#if defined(__x86_64__)
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-__shiftleft128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) {
- unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l;
- unsigned __int128 __res = __val << (__d & 63);
- return (unsigned __int64)(__res >> 64);
-}
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-__shiftright128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) {
- unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l;
- unsigned __int128 __res = __val >> (__d & 63);
- return (unsigned __int64)__res;
-}
-#endif
/*----------------------------------------------------------------------------*\
|* Privileged intrinsics
// CHECK-X64: = mul nuw i128 %
// CHECK-X64: store i64 %
// CHECK-X64: ret i64 %
-#endif
+
+unsigned __int64 test__shiftleft128(unsigned __int64 l, unsigned __int64 h,
+ unsigned char d) {
+ return __shiftleft128(l, h, d);
+}
+// CHECK-X64-LABEL: define dso_local i64 @test__shiftleft128(i64 %l, i64 %h, i8 %d)
+// CHECK-X64 = zext i64 %h to i128
+// CHECK-X64 = shl nuw i128 %0, 64
+// CHECK-X64 = zext i64 %l to i128
+// CHECK-X64 = or i128 %1, %2
+// CHECK-X64 = and i8 %d, 63
+// CHECK-X64 = shl i128 %
+// CHECK-X64 = lshr i128 %
+// CHECK-X64 = trunc i128 %
+// CHECK-X64 ret i64 %
+
+unsigned __int64 test__shiftright128(unsigned __int64 l, unsigned __int64 h,
+ unsigned char d) {
+ return __shiftright128(l, h, d);
+}
+// CHECK-X64-LABEL: define dso_local i64 @test__shiftright128(i64 %l, i64 %h, i8 %d)
+// CHECK-X64 = zext i64 %h to i128
+// CHECK-X64 = shl nuw i128 %
+// CHECK-X64 = zext i64 %l to i128
+// CHECK-X64 = or i128 %
+// CHECK-X64 = and i8 %d, 63
+// CHECK-X64 = lshr i128 %
+// CHECK-X64 = trunc i128 %
+// CHECK-X64 ret i64 %
+
+#endif // defined(__x86_64__)
__stosw(0, 0, 0);
#ifdef _M_X64
- __shiftleft128(1, 2, 3);
- __shiftright128(1, 2, 3);
__movsq(0, 0, 0);
__stosq(0, 0, 0);
#endif