/// TODO: Common w/ the version in AtomicExpandPass, and change the term used.
/// Idemptotent is confusing in this context.
bool isIdempotentRMW(AtomicRMWInst& RMWI) {
+ if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
+ switch(RMWI.getOperation()) {
+ case AtomicRMWInst::FAdd: // -0.0
+ return CF->isZero() && CF->isNegative();
+ case AtomicRMWInst::FSub: // +0.0
+ return CF->isZero() && !CF->isNegative();
+ default:
+ return false;
+ };
+
auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
if(!C)
- // TODO: Handle fadd, fsub?
return false;
switch(RMWI.getOperation()) {
// We chose to canonicalize all idempotent operations to an single
// operation code and constant. This makes it easier for the rest of the
- // optimizer to match easily. The choice of or w/zero is arbitrary.
+ // optimizer to match easily. The choices of or w/0 and fadd w/-0.0 are
+ // arbitrary.
if (RMWI.getType()->isIntegerTy() &&
RMWI.getOperation() != AtomicRMWInst::Or) {
RMWI.setOperation(AtomicRMWInst::Or);
RMWI.setOperand(1, ConstantInt::get(RMWI.getType(), 0));
return &RMWI;
+ } else if (RMWI.getType()->isFloatingPointTy() &&
+ RMWI.getOperation() != AtomicRMWInst::FAdd) {
+ RMWI.setOperation(AtomicRMWInst::FAdd);
+ RMWI.setOperand(1, ConstantFP::getNegativeZero(RMWI.getType()));
+ return &RMWI;
}
// Check if the required ordering is compatible with an atomic load.