Index: llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp @@ -404,6 +404,11 @@ } } +static bool isConstantOne(const Value* V) { + const ConstantInt *CI = dyn_cast(V); + return CI && CI->isOne(); +} + void AMDGPUAtomicOptimizer::optimizeAtomic(Instruction &I, AtomicRMWInst::BinOp Op, unsigned ValIdx, @@ -523,7 +528,7 @@ // old value times the number of active lanes. Value *const Ctpop = B.CreateIntCast( B.CreateUnaryIntrinsic(Intrinsic::ctpop, Ballot), Ty, false); - NewV = B.CreateMul(V, Ctpop); + NewV = isConstantOne(V) ? Ctpop : B.CreateMul(V, Ctpop); break; } @@ -543,7 +548,8 @@ // old value times the parity of the number of active lanes. Value *const Ctpop = B.CreateIntCast( B.CreateUnaryIntrinsic(Intrinsic::ctpop, Ballot), Ty, false); - NewV = B.CreateMul(V, B.CreateAnd(Ctpop, 1)); + NewV = isConstantOne(V) ? B.CreateAnd(Ctpop, 1) + : B.CreateMul(V, B.CreateAnd(Ctpop, 1)); break; } } @@ -622,7 +628,7 @@ llvm_unreachable("Unhandled atomic op"); case AtomicRMWInst::Add: case AtomicRMWInst::Sub: - LaneOffset = B.CreateMul(V, Mbcnt); + LaneOffset = isConstantOne(V) ? Mbcnt : B.CreateMul(V, Mbcnt); break; case AtomicRMWInst::And: case AtomicRMWInst::Or: @@ -633,7 +639,8 @@ LaneOffset = B.CreateSelect(Cond, Identity, V); break; case AtomicRMWInst::Xor: - LaneOffset = B.CreateMul(V, B.CreateAnd(Mbcnt, 1)); + LaneOffset = isConstantOne(V) ? B.CreateAnd(Mbcnt, 1) + : B.CreateMul(V, B.CreateAnd(Mbcnt, 1)); break; } } Index: llvm/test/CodeGen/AMDGPU/atomic_optimizations_mul_one.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/atomic_optimizations_mul_one.mir @@ -0,0 +1,55 @@ +# RUN: llc -O0 -mtriple=amdgcn -run-pass=amdgpu-atomic-optimizer %s -o - | FileCheck %s + +--- | + + declare i32 @llvm.amdgcn.struct.buffer.atomic.add.i32(i32, <4 x i32>, i32, i32, i32, i32 immarg) #0 + declare i32 @llvm.amdgcn.struct.buffer.atomic.sub.i32(i32, <4 x i32>, i32, i32, i32, i32 immarg) #0 + declare i32 @llvm.amdgcn.struct.buffer.atomic.xor.i32(i32, <4 x i32>, i32, i32, i32, i32 immarg) #0 + declare void @llvm.amdgcn.struct.buffer.store.format.v4i32(<4 x i32>, <4 x i32>, i32, i32, i32, i32 immarg) #1 + + ; CHECK-NOT: mul i32 1, %[[REG:[0-9]+]] + ; CHECK-NOT: mul i32 %[[REG:[0-9]+]], 1 + + define amdgpu_cs void @atomic_add(<4 x i32> inreg %arg1) { + .entry: + %0 = call i32 @llvm.amdgcn.struct.buffer.atomic.add.i32(i32 1, <4 x i32> %arg1, i32 0, i32 0, i32 0, i32 0) + ret void + } + + define amdgpu_cs void @atomic_add_and_format(<4 x i32> inreg %arg) { + .entry: + %a = call i32 @llvm.amdgcn.struct.buffer.atomic.add.i32(i32 1, <4 x i32> %arg, i32 0, i32 0, i32 0, i32 0) + call void @llvm.amdgcn.struct.buffer.store.format.v4i32(<4 x i32> %arg, <4 x i32> %arg, i32 %a, i32 0, i32 0, i32 0) + ret void + } + + define amdgpu_cs void @atomic_sub(<4 x i32> inreg %arg1) { + .entry: + %0 = call i32 @llvm.amdgcn.struct.buffer.atomic.sub.i32(i32 1, <4 x i32> %arg1, i32 0, i32 0, i32 0, i32 0) + ret void + } + + define amdgpu_cs void @atomic_sub_and_format(<4 x i32> inreg %arg) { + .entry: + %a = call i32 @llvm.amdgcn.struct.buffer.atomic.sub.i32(i32 1, <4 x i32> %arg, i32 0, i32 0, i32 0, i32 0) + call void @llvm.amdgcn.struct.buffer.store.format.v4i32(<4 x i32> %arg, <4 x i32> %arg, i32 %a, i32 0, i32 0, i32 0) + ret void + } + + define amdgpu_cs void @atomic_xor(<4 x i32> inreg %arg1) { + .entry: + %0 = call i32 @llvm.amdgcn.struct.buffer.atomic.xor.i32(i32 1, <4 x i32> %arg1, i32 0, i32 0, i32 0, i32 0) + ret void + } + + define amdgpu_cs void @atomic_xor_and_format(<4 x i32> inreg %arg) { + .entry: + %a = call i32 @llvm.amdgcn.struct.buffer.atomic.xor.i32(i32 1, <4 x i32> %arg, i32 0, i32 0, i32 0, i32 0) + call void @llvm.amdgcn.struct.buffer.store.format.v4i32(<4 x i32> %arg, <4 x i32> %arg, i32 %a, i32 0, i32 0, i32 0) + ret void + } + + attributes #0 = { nounwind willreturn } + attributes #1 = { nounwind willreturn writeonly } + +...