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