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