@@ -197,11 +197,11 @@ namespace {
197
197
llvm::Value *getScalarRValValueOrNull (RValue RVal) const ;
198
198
199
199
// / Converts an rvalue to integer value if needed.
200
- llvm::Value *convertRValueToInt (RValue RVal, bool CastFP = true ) const ;
200
+ llvm::Value *convertRValueToInt (RValue RVal, bool CmpXchg = false ) const ;
201
201
202
202
RValue ConvertToValueOrAtomic (llvm::Value *IntVal, AggValueSlot ResultSlot,
203
203
SourceLocation Loc, bool AsValue,
204
- bool CastFP = true ) const ;
204
+ bool CmpXchg = false ) const ;
205
205
206
206
// / Copy an atomic r-value into atomic-layout memory.
207
207
void emitCopyIntoMemory (RValue rvalue) const ;
@@ -264,15 +264,17 @@ namespace {
264
264
llvm::AtomicOrdering AO, bool IsVolatile);
265
265
// / Emits atomic load as LLVM instruction.
266
266
llvm::Value *EmitAtomicLoadOp (llvm::AtomicOrdering AO, bool IsVolatile,
267
- bool CastFP = true );
267
+ bool CmpXchg = false );
268
268
// / Emits atomic compare-and-exchange op as a libcall.
269
269
llvm::Value *EmitAtomicCompareExchangeLibcall (
270
270
llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
271
271
llvm::AtomicOrdering Success =
272
272
llvm::AtomicOrdering::SequentiallyConsistent,
273
273
llvm::AtomicOrdering Failure =
274
274
llvm::AtomicOrdering::SequentiallyConsistent);
275
- // / Emits atomic compare-and-exchange op as LLVM instruction.
275
+ // / Emits atomic compare-and-exchange op as LLVM instruction. Operands
276
+ // / must be of integer or pointer type, so float must be casted.
277
+ // / TODO: this could change - see comment in AtomicExpandPass.cpp.
276
278
std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp (
277
279
llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
278
280
llvm::AtomicOrdering Success =
@@ -1399,13 +1401,22 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
1399
1401
LVal.getBaseInfo (), TBAAAccessInfo ()));
1400
1402
}
1401
1403
1404
+ static bool shouldCastToInt (llvm::Type *ValTy, bool CmpXchg) {
1405
+ // TODO: Also pass through non-ieee FP types.
1406
+ bool KeepType = (ValTy->isIntegerTy () || ValTy->isPointerTy () ||
1407
+ (ValTy->isIEEELikeFPTy () && !CmpXchg));
1408
+ return !KeepType;
1409
+ }
1410
+
1402
1411
RValue AtomicInfo::ConvertToValueOrAtomic (llvm::Value *Val,
1403
1412
AggValueSlot ResultSlot,
1404
1413
SourceLocation Loc, bool AsValue,
1405
- bool CastFP ) const {
1414
+ bool CmpXchg ) const {
1406
1415
// Try not to in some easy cases.
1407
- assert ((Val->getType ()->isIntegerTy () || Val->getType ()->isIEEELikeFPTy ()) &&
1408
- " Expected integer or floating point value" );
1416
+ assert ((Val->getType ()->isIntegerTy () || Val->getType ()->isPointerTy () ||
1417
+ Val->getType ()->isIEEELikeFPTy ()) &&
1418
+ " Expected integer, pointer or floating point value when converting "
1419
+ " result." );
1409
1420
if (getEvaluationKind () == TEK_Scalar &&
1410
1421
(((!LVal.isBitField () ||
1411
1422
LVal.getBitFieldInfo ().Size == ValueSizeInBits) &&
@@ -1414,13 +1425,11 @@ RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,
1414
1425
auto *ValTy = AsValue
1415
1426
? CGF.ConvertTypeForMem (ValueTy)
1416
1427
: getAtomicAddress ().getElementType ();
1417
- if (ValTy-> isIntegerTy () || (!CastFP && ValTy-> isIEEELikeFPTy () )) {
1428
+ if (! shouldCastToInt (ValTy, CmpXchg )) {
1418
1429
assert ((!ValTy->isIntegerTy () || Val->getType () == ValTy) &&
1419
1430
" Different integer types." );
1420
1431
return RValue::get (CGF.EmitFromMemory (Val, ValueTy));
1421
- } else if (ValTy->isPointerTy ())
1422
- return RValue::get (CGF.Builder .CreateIntToPtr (Val, ValTy));
1423
- else if (llvm::CastInst::isBitCastable (Val->getType (), ValTy))
1432
+ } else if (llvm::CastInst::isBitCastable (Val->getType (), ValTy))
1424
1433
return RValue::get (CGF.Builder .CreateBitCast (Val, ValTy));
1425
1434
}
1426
1435
@@ -1457,10 +1466,10 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
1457
1466
}
1458
1467
1459
1468
llvm::Value *AtomicInfo::EmitAtomicLoadOp (llvm::AtomicOrdering AO,
1460
- bool IsVolatile, bool CastFP ) {
1469
+ bool IsVolatile, bool CmpXchg ) {
1461
1470
// Okay, we're doing this natively.
1462
1471
Address Addr = getAtomicAddress ();
1463
- if (! (Addr.getElementType ()-> isIEEELikeFPTy () && !CastFP ))
1472
+ if (shouldCastToInt (Addr.getElementType (), CmpXchg ))
1464
1473
Addr = castToAtomicIntPointer (Addr);
1465
1474
llvm::LoadInst *Load = CGF.Builder .CreateLoad (Addr, " atomic-load" );
1466
1475
Load->setAtomic (AO);
@@ -1521,16 +1530,15 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
1521
1530
}
1522
1531
1523
1532
// Okay, we're doing this natively.
1524
- auto *Load = EmitAtomicLoadOp (AO, IsVolatile, /* CastFP= */ false );
1533
+ auto *Load = EmitAtomicLoadOp (AO, IsVolatile);
1525
1534
1526
1535
// If we're ignoring an aggregate return, don't do anything.
1527
1536
if (getEvaluationKind () == TEK_Aggregate && ResultSlot.isIgnored ())
1528
1537
return RValue::getAggregate (Address::invalid (), false );
1529
1538
1530
1539
// Okay, turn that back into the original value or atomic (for non-simple
1531
1540
// lvalues) type.
1532
- return ConvertToValueOrAtomic (Load, ResultSlot, Loc, AsValue,
1533
- /* CastFP=*/ false );
1541
+ return ConvertToValueOrAtomic (Load, ResultSlot, Loc, AsValue);
1534
1542
}
1535
1543
1536
1544
// / Emit a load from an l-value of atomic type. Note that the r-value
@@ -1599,20 +1607,17 @@ llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const {
1599
1607
return nullptr ;
1600
1608
}
1601
1609
1602
- llvm::Value *AtomicInfo::convertRValueToInt (RValue RVal, bool CastFP ) const {
1610
+ llvm::Value *AtomicInfo::convertRValueToInt (RValue RVal, bool CmpXchg ) const {
1603
1611
// If we've got a scalar value of the right size, try to avoid going
1604
1612
// through memory. Floats get casted if needed by AtomicExpandPass.
1605
1613
if (llvm::Value *Value = getScalarRValValueOrNull (RVal)) {
1606
- if (isa<llvm::IntegerType>(Value->getType ()) ||
1607
- (!CastFP && Value->getType ()->isIEEELikeFPTy ()))
1614
+ if (!shouldCastToInt (Value->getType (), CmpXchg))
1608
1615
return CGF.EmitToMemory (Value, ValueTy);
1609
1616
else {
1610
1617
llvm::IntegerType *InputIntTy = llvm::IntegerType::get (
1611
1618
CGF.getLLVMContext (),
1612
1619
LVal.isSimple () ? getValueSizeInBits () : getAtomicSizeInBits ());
1613
- if (isa<llvm::PointerType>(Value->getType ()))
1614
- return CGF.Builder .CreatePtrToInt (Value, InputIntTy);
1615
- else if (llvm::BitCastInst::isBitCastable (Value->getType (), InputIntTy))
1620
+ if (llvm::BitCastInst::isBitCastable (Value->getType (), InputIntTy))
1616
1621
return CGF.Builder .CreateBitCast (Value, InputIntTy);
1617
1622
}
1618
1623
}
@@ -1685,13 +1690,14 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
1685
1690
1686
1691
// If we've got a scalar value of the right size, try to avoid going
1687
1692
// through memory.
1688
- auto *ExpectedVal = convertRValueToInt (Expected);
1689
- auto *DesiredVal = convertRValueToInt (Desired);
1693
+ auto *ExpectedVal = convertRValueToInt (Expected, /* CmpXchg= */ true );
1694
+ auto *DesiredVal = convertRValueToInt (Desired, /* CmpXchg= */ true );
1690
1695
auto Res = EmitAtomicCompareExchangeOp (ExpectedVal, DesiredVal, Success,
1691
1696
Failure, IsWeak);
1692
1697
return std::make_pair (
1693
1698
ConvertToValueOrAtomic (Res.first , AggValueSlot::ignored (),
1694
- SourceLocation (), /* AsValue=*/ false ),
1699
+ SourceLocation (), /* AsValue=*/ false ,
1700
+ /* CmpXchg=*/ true ),
1695
1701
Res.second );
1696
1702
}
1697
1703
@@ -1785,7 +1791,7 @@ void AtomicInfo::EmitAtomicUpdateOp(
1785
1791
auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering (AO);
1786
1792
1787
1793
// Do the atomic load.
1788
- auto *OldVal = EmitAtomicLoadOp (Failure, IsVolatile);
1794
+ auto *OldVal = EmitAtomicLoadOp (Failure, IsVolatile, /* CmpXchg= */ true );
1789
1795
// For non-simple lvalues perform compare-and-swap procedure.
1790
1796
auto *ContBB = CGF.createBasicBlock (" atomic_cont" );
1791
1797
auto *ExitBB = CGF.createBasicBlock (" atomic_exit" );
@@ -1801,7 +1807,8 @@ void AtomicInfo::EmitAtomicUpdateOp(
1801
1807
CGF.Builder .CreateStore (PHI, NewAtomicIntAddr);
1802
1808
}
1803
1809
auto OldRVal = ConvertToValueOrAtomic (PHI, AggValueSlot::ignored (),
1804
- SourceLocation (), /* AsValue=*/ false );
1810
+ SourceLocation (), /* AsValue=*/ false ,
1811
+ /* CmpXchg=*/ true );
1805
1812
EmitAtomicUpdateValue (CGF, *this , OldRVal, UpdateOp, NewAtomicAddr);
1806
1813
auto *DesiredVal = CGF.Builder .CreateLoad (NewAtomicIntAddr);
1807
1814
// Try to write new value using cmpxchg operation.
@@ -1867,7 +1874,7 @@ void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal,
1867
1874
auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering (AO);
1868
1875
1869
1876
// Do the atomic load.
1870
- auto *OldVal = EmitAtomicLoadOp (Failure, IsVolatile);
1877
+ auto *OldVal = EmitAtomicLoadOp (Failure, IsVolatile, /* CmpXchg= */ true );
1871
1878
// For non-simple lvalues perform compare-and-swap procedure.
1872
1879
auto *ContBB = CGF.createBasicBlock (" atomic_cont" );
1873
1880
auto *ExitBB = CGF.createBasicBlock (" atomic_exit" );
@@ -1966,21 +1973,16 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
1966
1973
}
1967
1974
1968
1975
// Okay, we're doing this natively.
1969
- llvm::Value *ValToStore =
1970
- atomics.convertRValueToInt (rvalue, /* CastFP=*/ false );
1976
+ llvm::Value *ValToStore = atomics.convertRValueToInt (rvalue);
1971
1977
1972
1978
// Do the atomic store.
1973
1979
Address Addr = atomics.getAtomicAddress ();
1974
- bool ShouldCastToInt = true ;
1975
1980
if (llvm::Value *Value = atomics.getScalarRValValueOrNull (rvalue))
1976
- if (isa<llvm::IntegerType>(Value->getType ()) ||
1977
- Value->getType ()->isIEEELikeFPTy ())
1978
- ShouldCastToInt = false ;
1979
- if (ShouldCastToInt) {
1980
- Addr = atomics.castToAtomicIntPointer (Addr);
1981
- ValToStore = Builder.CreateIntCast (ValToStore, Addr.getElementType (),
1982
- /* isSigned=*/ false );
1983
- }
1981
+ if (shouldCastToInt (Value->getType (), /* CmpXchg=*/ false )) {
1982
+ Addr = atomics.castToAtomicIntPointer (Addr);
1983
+ ValToStore = Builder.CreateIntCast (ValToStore, Addr.getElementType (),
1984
+ /* isSigned=*/ false );
1985
+ }
1984
1986
llvm::StoreInst *store = Builder.CreateStore (ValToStore, Addr);
1985
1987
1986
1988
if (AO == llvm::AtomicOrdering::Acquire)
0 commit comments