forked from OSchip/llvm-project
[InstCombine] Extend "idempotent" atomicrmw optimizations to floating point
An idempotent atomicrmw is one that does not change memory in the process of execution. We have already added handling for the various integer operations; this patch extends the same handling to floating point operations which were recently added to IR. Note: At the moment, we canonicalize idempotent fsub to fadd when ordering requirements prevent us from using a load. As discussed in the review, I will be replacing this with canonicalizing both floating point ops to integer ops in the near future. Differential Revision: https://reviews.llvm.org/D58251 llvm-svn: 355210
This commit is contained in:
parent
39f6d7e616
commit
77982868c5
|
@ -21,9 +21,18 @@ namespace {
|
|||
/// 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()) {
|
||||
|
@ -116,12 +125,18 @@ Instruction *InstCombiner::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
|
|||
|
||||
// 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.
|
||||
|
|
|
@ -67,6 +67,29 @@ define i8 @atomic_max_smin_char(i8* %addr) {
|
|||
ret i8 %res
|
||||
}
|
||||
|
||||
; CHECK-LABEL: atomic_fsub
|
||||
; CHECK-NEXT: %res = load atomic float, float* %addr monotonic, align 4
|
||||
; CHECK-NEXT: ret float %res
|
||||
define float @atomic_fsub_zero(float* %addr) {
|
||||
%res = atomicrmw fsub float* %addr, float 0.0 monotonic
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; CHECK-LABEL: atomic_fadd
|
||||
; CHECK-NEXT: %res = load atomic float, float* %addr monotonic, align 4
|
||||
; CHECK-NEXT: ret float %res
|
||||
define float @atomic_fadd_zero(float* %addr) {
|
||||
%res = atomicrmw fadd float* %addr, float -0.0 monotonic
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; CHECK-LABEL: atomic_fsub_canon
|
||||
; CHECK-NEXT: %res = atomicrmw fadd float* %addr, float -0.000000e+00 release
|
||||
; CHECK-NEXT: ret float %res
|
||||
define float @atomic_fsub_canon(float* %addr) {
|
||||
%res = atomicrmw fsub float* %addr, float 0.0 release
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Can't replace a volatile w/a load; this would eliminate a volatile store.
|
||||
; CHECK-LABEL: atomic_sub_zero_volatile
|
||||
|
|
Loading…
Reference in New Issue