[clang] [clang] Add sincos builtin using `llvm.sincos` intrinsic (PR #114086)

Benjamin Maxwell via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 29 10:02:16 PDT 2024


================
@@ -722,6 +722,36 @@ static Value *emitFrexpBuiltin(CodeGenFunction &CGF, const CallExpr *E,
   return CGF.Builder.CreateExtractValue(Call, 0);
 }
 
+static void emitSincosBuiltin(CodeGenFunction &CGF, const CallExpr *E,
+                              llvm::Intrinsic::ID IntrinsicID) {
+  llvm::Value *Val = CGF.EmitScalarExpr(E->getArg(0));
+  llvm::Value *Dest0 = CGF.EmitScalarExpr(E->getArg(1));
+  llvm::Value *Dest1 = CGF.EmitScalarExpr(E->getArg(2));
+
+  llvm::Function *F = CGF.CGM.getIntrinsic(IntrinsicID, {Val->getType()});
+  llvm::Value *Call = CGF.Builder.CreateCall(F, Val);
+
+  llvm::Value *SinResult = CGF.Builder.CreateExtractValue(Call, 0);
+  llvm::Value *CosResult = CGF.Builder.CreateExtractValue(Call, 1);
+
+  QualType DestPtrType = E->getArg(1)->getType()->getPointeeType();
+  LValue SinLV = CGF.MakeNaturalAlignAddrLValue(Dest0, DestPtrType);
+  LValue CosLV = CGF.MakeNaturalAlignAddrLValue(Dest1, DestPtrType);
+
+  llvm::StoreInst *StoreSin = CGF.Builder.CreateStore(SinResult, SinLV.getAddress());
+  llvm::StoreInst *StoreCos = CGF.Builder.CreateStore(CosResult, CosLV.getAddress());
+
+  // Mark the two stores as non-aliasing with eachother. The order of stores
+  // emitted by this builtin is arbitrary, enforcing a particular order will
+  // prevent optimizations later on.
+  llvm::MDBuilder MDHelper(CGF.getLLVMContext());
+  MDNode* Domain = MDHelper.createAnonymousAliasScopeDomain();
+  MDNode* AliasScope = MDHelper.createAnonymousAliasScope(Domain);
+  MDNode* AliasScopeList = MDNode::get(Call->getContext(), AliasScope);
+  StoreSin->setMetadata(LLVMContext::MD_alias_scope, AliasScopeList);
+  StoreCos->setMetadata(LLVMContext::MD_noalias, AliasScopeList);
----------------
MacDue wrote:

What do people think of this? Looking at various documentation for `sincos[f]` I've never seen the store order (sin, cos) or (cos, sin) specified, and I imagine they're assumed not to alias anyway making it a moot point. 

The issue is without adding this `noalias` metadata the order of stores emitted here becomes significant, and later they're chained together in SDAG. This means an unnecessary stack slot may be created to ensure stores follow the arbitrary order from this built-in lowering.

For example, for the store order (sin, cos) you get:
```
mov x19, x1
add x1, sp, #12
bl sincosf
ldr s0, [sp, #12]
str s0, [x19] 
```
and for (cos, sin):
```
mov x19, x0
add x0, sp, #12
bl sincosf
ldr s0, [sp, #12]
str s0, [x19]
```

https://github.com/llvm/llvm-project/pull/114086


More information about the cfe-commits mailing list