Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3914,10 +3914,14 @@ // Narrow any constants that need it. for (auto *LogicN : NodesWithConsts) { - auto *C = cast(LogicN->getOperand(1)); + unsigned OpNum = isa(LogicN->getOperand(1)) ? 1 : 0; + auto *C = cast(LogicN->getOperand(OpNum)); SDValue And = DAG.getNode(ISD::AND, SDLoc(C), C->getValueType(0), SDValue(C, 0), MaskOp); - DAG.UpdateNodeOperands(LogicN, LogicN->getOperand(0), And); + if (OpNum == 1) + DAG.UpdateNodeOperands(LogicN, LogicN->getOperand(0), And); + else + DAG.UpdateNodeOperands(LogicN, LogicN->getOperand(1), And); } // Create narrow loads. Index: test/CodeGen/X86/pr35761.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/pr35761.ll @@ -0,0 +1,71 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-unknown-linux %s -o - | FileCheck %s + +%"class.a::u" = type { i8 } +%"class.a::r" = type { i8 } +%struct.ah = type { %struct.z } +%struct.z = type { [3 x i8], i8 } + +@x = global i8 0, align 1 +@y = global i32 0, align 4 +@aj = global %"class.a::u" zeroinitializer, align 1 +@ak = global %"class.a::r" zeroinitializer, align 1 + +define void @PR35761() { +; CHECK-LABEL: PR35761: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: .cfi_def_cfa_offset 24 +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: .cfi_offset %rbx, -24 +; CHECK-NEXT: .cfi_offset %rbp, -16 +; CHECK-NEXT: movzbl {{.*}}(%rip), %ebx +; CHECK-NEXT: andl $1, %ebx +; CHECK-NEXT: movl $aj, %edi +; CHECK-NEXT: movl $3, %esi +; CHECK-NEXT: callq _ZN1a1uIiNS_2abIiEEE2afEi +; CHECK-NEXT: movzbl {{.*}}(%rip), %ebp +; CHECK-NEXT: xorl $255, %ebp +; CHECK-NEXT: orl %ebx, %ebp +; CHECK-NEXT: movl $ak, %edi +; CHECK-NEXT: movl $2, %esi +; CHECK-NEXT: callq _ZN1a1rI2ahEixEi +; CHECK-NEXT: movzbl 2(%rax), %ecx +; CHECK-NEXT: movw %bp, (%rax) +; CHECK-NEXT: andl $192, %ecx +; CHECK-NEXT: movb %cl, 2(%rax) +; CHECK-NEXT: addq $8, %rsp +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: popq %rbp +; CHECK-NEXT: retq +entry: + %0 = load i8, i8* @x, align 1 + %tobool = trunc i8 %0 to i1 + %conv = zext i1 %tobool to i32 + %call = call i32 @_ZN1a1uIiNS_2abIiEEE2afEi(%"class.a::u"* @aj, i32 3) + %or = or i32 32767, %call + %neg = xor i32 %or, -1 + %neg1 = xor i32 %neg, -1 + %1 = load i32, i32* @y, align 4 + %xor = xor i32 %neg1, %1 + %or2 = or i32 %conv, %xor + %conv3 = trunc i32 %or2 to i8 + %call4 = call dereferenceable(4) %struct.ah* @_ZN1a1rI2ahEixEi(%"class.a::r"* @ak, i32 2) + %ai = getelementptr inbounds %struct.ah, %struct.ah* %call4, i32 0, i32 0 + %2 = bitcast %struct.z* %ai to i24* + %3 = zext i8 %conv3 to i24 + %bf.load = load i24, i24* %2, align 2 + %bf.value = and i24 %3, 4194303 + %bf.clear = and i24 %bf.load, -4194304 + %bf.set = or i24 %bf.clear, %bf.value + store i24 %bf.set, i24* %2, align 2 + ret void +} + +declare i32 @_ZN1a1uIiNS_2abIiEEE2afEi(%"class.a::u"*, i32) + +declare dereferenceable(4) %struct.ah* @_ZN1a1rI2ahEixEi(%"class.a::r"*, i32) +